Consolidate generic pointer code
[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     short dptrInUse;
97     short dptr1InUse;
98     set *sendSet;
99   }
100 _G;
101
102 static char *rb1regs[] = {
103     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
104 };
105
106 static void saveRBank (int, iCode *, bool);
107
108 #define RESULTONSTACK(x) \
109                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
110                          IC_RESULT(x)->aop->type == AOP_STK )
111
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
115                  { \
116                     emitcode("mov","a,%s",_mova_tmp); \
117                  } \
118                  free(_mova_tmp); \
119                 }
120 #define CLRC    emitcode("clr","c")
121 #define SETC    emitcode("setb","c")
122
123 // A scratch register which will be used to hold
124 // result bytes from operands in far space via DPTR2.
125 #define DP2_RESULT_REG  "_ap"
126
127 static lineNode *lineHead = NULL;
128 static lineNode *lineCurr = NULL;
129
130 static unsigned char SLMask[] =
131 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
132  0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char SRMask[] =
134 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135  0x07, 0x03, 0x01, 0x00};
136
137 #define LSB     0
138 #define MSB16   1
139 #define MSB24   2
140 #define MSB32   3
141 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
142                                 symbol *lbl = newiTempLabel(NULL);              \
143                                 emitcode ("setb","F1");                         \
144                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
145                                 emitcode ("clr","F1");                          \
146                                 emitcode ("","!tlabeldef",lbl->key+100);        \
147                         }}
148 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
149                                 symbol *lbl = newiTempLabel(NULL);              \
150                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
151                                 emitcode ("setb","EA");                         \
152                                 emitcode ("","!tlabeldef",lbl->key+100);        \
153                         }}
154
155
156 /*-----------------------------------------------------------------*/
157 /* emitcode - writes the code into a file : for now it is simple    */
158 /*-----------------------------------------------------------------*/
159 static void
160 emitcode (char *inst, char *fmt,...)
161 {
162   va_list ap;
163   char lb[INITIAL_INLINEASM];
164   char *lbp = lb;
165
166   va_start (ap, fmt);
167
168   if (inst && *inst)
169     {
170       if (fmt && *fmt)
171         sprintf (lb, "%s\t", inst);
172       else
173         sprintf (lb, "%s", inst);
174       tvsprintf (lb + (strlen (lb)), fmt, ap);
175     }
176   else
177     tvsprintf (lb, fmt, ap);
178
179   while (isspace (*lbp))
180     lbp++;
181
182   if (lbp && *lbp)
183     lineCurr = (lineCurr ?
184                 connectLine (lineCurr, newLineNode (lb)) :
185                 (lineHead = newLineNode (lb)));
186   lineCurr->isInline = _G.inLine;
187   lineCurr->isDebug = _G.debugLine;
188   va_end (ap);
189 }
190
191 /*-----------------------------------------------------------------*/
192 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
193 /*-----------------------------------------------------------------*/
194 static regs *
195 getFreePtr (iCode * ic, asmop ** aopp, bool result)
196 {
197   bool r0iu = FALSE, r1iu = FALSE;
198   bool r0ou = FALSE, r1ou = FALSE;
199
200   /* the logic: if r0 & r1 used in the instruction
201      then we are in trouble otherwise */
202
203   /* first check if r0 & r1 are used by this
204      instruction, in which case we are in trouble */
205   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
206   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
207   if (r0iu && r1iu) {
208       goto endOfWorld;
209     }
210
211   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
212   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
213
214   /* if no usage of r0 then return it */
215   if (!r0iu && !r0ou)
216     {
217       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
218       (*aopp)->type = AOP_R0;
219
220       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
221     }
222
223   /* if no usage of r1 then return it */
224   if (!r1iu && !r1ou)
225     {
226       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
227       (*aopp)->type = AOP_R1;
228
229       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
230     }
231
232   /* now we know they both have usage */
233   /* if r0 not used in this instruction */
234   if (!r0iu)
235     {
236       /* push it if not already pushed */
237       if (!_G.r0Pushed)
238         {
239           emitcode ("push", "%s",
240                     ds390_regWithIdx (R0_IDX)->dname);
241           _G.r0Pushed++;
242         }
243
244       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
245       (*aopp)->type = AOP_R0;
246
247       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
248     }
249
250   /* if r1 not used then */
251
252   if (!r1iu)
253     {
254       /* push it if not already pushed */
255       if (!_G.r1Pushed)
256         {
257           emitcode ("push", "%s",
258                     ds390_regWithIdx (R1_IDX)->dname);
259           _G.r1Pushed++;
260         }
261
262       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
263       (*aopp)->type = AOP_R1;
264       return ds390_regWithIdx (R1_IDX);
265     }
266
267 endOfWorld:
268   /* I said end of world but not quite end of world yet */
269   /* if this is a result then we can push it on the stack */
270   if (result)
271     {
272       (*aopp)->type = AOP_STK;
273       return NULL;
274     }
275
276   /* other wise this is true end of the world */
277   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
278           "getFreePtr should never reach here");
279   exit (1);
280 }
281
282 /*-----------------------------------------------------------------*/
283 /* newAsmop - creates a new asmOp                                  */
284 /*-----------------------------------------------------------------*/
285 static asmop *
286 newAsmop (short type)
287 {
288   asmop *aop;
289
290   aop = Safe_calloc (1, sizeof (asmop));
291   aop->type = type;
292   return aop;
293 }
294
295 static int _currentDPS;         /* Current processor DPS. */
296 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
297 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
298
299 /*-----------------------------------------------------------------*/
300 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
301 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
302 /* alternate DPTR (DPL1/DPH1/DPX1).          */
303 /*-----------------------------------------------------------------*/
304 static void
305 genSetDPTR (int n)
306 {
307
308   /* If we are doing lazy evaluation, simply note the desired
309    * change, but don't emit any code yet.
310    */
311   if (_lazyDPS)
312     {
313       _desiredDPS = n;
314       return;
315     }
316
317   if (!n)
318     {
319       emitcode ("mov", "dps,#0");
320     }
321   else
322     {
323       TR_DPTR("#1");
324       emitcode ("mov", "dps,#1");
325     }
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
330 /*                   */
331 /* Any code that operates on DPTR (NB: not on the individual     */
332 /* components, like DPH) *must* call _flushLazyDPS() before using  */
333 /* DPTR within a lazy DPS evaluation block.        */
334 /*                   */
335 /* Note that aopPut and aopGet already contain the proper calls to */
336 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
337 /* DPS evaluation block.             */
338 /*                   */
339 /* Also, _flushLazyDPS must be called before any flow control      */
340 /* operations that could potentially branch out of the block.    */
341 /*                         */
342 /* Lazy DPS evaluation is simply an optimization (though an      */
343 /* important one), so if in doubt, leave it out.       */
344 /*-----------------------------------------------------------------*/
345 static void
346 _startLazyDPSEvaluation (void)
347 {
348   _currentDPS = 0;
349   _desiredDPS = 0;
350 #ifdef BETTER_LITERAL_SHIFT  
351   _lazyDPS++;
352 #else
353   _lazyDPS = 1;
354 #endif  
355 }
356
357 /*-----------------------------------------------------------------*/
358 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
359 /* desired one. Call before using DPTR within a lazy DPS evaluation */
360 /* block.                */
361 /*-----------------------------------------------------------------*/
362 static void
363 _flushLazyDPS (void)
364 {
365   if (!_lazyDPS)
366     {
367       /* nothing to do. */
368       return;
369     }
370
371   if (_desiredDPS != _currentDPS)
372     {
373       if (_desiredDPS)
374         {
375           emitcode ("inc", "dps");
376         }
377       else
378         {
379           emitcode ("dec", "dps");
380         }
381       _currentDPS = _desiredDPS;
382     }
383 }
384
385 /*-----------------------------------------------------------------*/
386 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
387 /*                   */
388 /* Forces us back to the safe state (standard DPTR selected).    */
389 /*-----------------------------------------------------------------*/
390 static void
391 _endLazyDPSEvaluation (void)
392 {
393 #ifdef BETTER_LITERAL_SHIFT  
394   _lazyDPS--;
395 #else
396   _lazyDPS = 0;
397 #endif    
398   if (!_lazyDPS)
399   {
400     if (_currentDPS)
401     {
402       genSetDPTR (0);
403       _flushLazyDPS ();
404     }
405     _currentDPS = 0;
406     _desiredDPS = 0;
407   }
408 }
409
410
411
412 /*-----------------------------------------------------------------*/
413 /* pointerCode - returns the code for a pointer type               */
414 /*-----------------------------------------------------------------*/
415 static int
416 pointerCode (sym_link * etype)
417 {
418
419   return PTR_TYPE (SPEC_OCLS (etype));
420
421 }
422
423 /*-----------------------------------------------------------------*/
424 /* aopForSym - for a true symbol                                   */
425 /*-----------------------------------------------------------------*/
426 static asmop *
427 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
428 {
429   asmop *aop;
430   memmap *space = SPEC_OCLS (sym->etype);
431
432   /* if already has one */
433   if (sym->aop)
434     return sym->aop;
435
436   /* assign depending on the storage class */
437   /* if it is on the stack or indirectly addressable */
438   /* space we need to assign either r0 or r1 to it   */
439   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
440     {
441       sym->aop = aop = newAsmop (0);
442       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
443       aop->size = getSize (sym->type);
444
445       /* now assign the address of the variable to
446          the pointer register */
447       if (aop->type != AOP_STK)
448         {
449
450           if (sym->onStack)
451             {
452               if (_G.accInUse)
453                 emitcode ("push", "acc");
454
455               if (_G.bInUse)
456                 emitcode ("push", "b");
457
458               emitcode ("mov", "a,_bp");
459               emitcode ("add", "a,#!constbyte",
460                         ((sym->stack < 0) ?
461                          ((char) (sym->stack - _G.nRegsSaved)) :
462                          ((char) sym->stack)) & 0xff);
463               emitcode ("mov", "%s,a",
464                         aop->aopu.aop_ptr->name);
465
466               if (_G.bInUse)
467                 emitcode ("pop", "b");
468
469               if (_G.accInUse)
470                 emitcode ("pop", "acc");
471             }
472           else
473             emitcode ("mov", "%s,#%s",
474                       aop->aopu.aop_ptr->name,
475                       sym->rname);
476           aop->paged = space->paged;
477         }
478       else
479         aop->aopu.aop_stk = sym->stack;
480       return aop;
481     }
482
483   if (sym->onStack && options.stack10bit)
484     {
485         short stack_val = -((sym->stack < 0) ?
486                             ((short) (sym->stack - _G.nRegsSaved)) :
487                             ((short) sym->stack)) ;
488         if (useDP2 && _G.dptr1InUse) {
489             emitcode ("push","dpl1");
490             emitcode ("push","dph1");
491             emitcode ("push","dpx1");
492         } else if (_G.dptrInUse ) {
493             emitcode ("push","dpl");
494             emitcode ("push","dph");
495             emitcode ("push","dpx");
496         }
497       /* It's on the 10 bit stack, which is located in
498        * far data space.
499        */           
500         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
501             if (useDP2) {
502                 if (options.model == MODEL_FLAT24)
503                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
504                 TR_DPTR("#2");
505                 emitcode ("mov", "dph1,_bpx+1");
506                 emitcode ("mov", "dpl1,_bpx");
507                 emitcode ("mov","dps,#1");
508             } else {
509                 if (options.model == MODEL_FLAT24)
510                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
511                 emitcode ("mov", "dph,_bpx+1");
512                 emitcode ("mov", "dpl,_bpx");
513             }
514             stack_val = -stack_val;
515             while (stack_val--) {
516                 emitcode ("inc","dptr");
517             }
518             if (useDP2) {
519                 emitcode("mov","dps,#0");
520             }
521         }  else {
522             if (_G.accInUse)
523                 emitcode ("push", "acc");
524             
525             if (_G.bInUse)
526                 emitcode ("push", "b");
527         
528             emitcode ("mov", "a,_bpx");
529             emitcode ("clr","c");
530             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
531             emitcode ("mov","b,a");
532             emitcode ("mov","a,_bpx+1");
533             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
534             if (useDP2) {
535                 if (options.model == MODEL_FLAT24)
536                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
537                 TR_DPTR("#2");
538                 emitcode ("mov", "dph1,a");
539                 emitcode ("mov", "dpl1,b");
540             } else {
541                 if (options.model == MODEL_FLAT24)
542                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
543                 emitcode ("mov", "dph,a");
544                 emitcode ("mov", "dpl,b");
545             }
546             
547             if (_G.bInUse)
548                 emitcode ("pop", "b");
549             
550             if (_G.accInUse)
551                 emitcode ("pop", "acc");
552         }
553         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
554         aop->size = getSize (sym->type);
555         return aop;
556     }
557
558   /* if in bit space */
559   if (IN_BITSPACE (space))
560     {
561       sym->aop = aop = newAsmop (AOP_CRY);
562       aop->aopu.aop_dir = sym->rname;
563       aop->size = getSize (sym->type);
564       return aop;
565     }
566   /* if it is in direct space */
567   if (IN_DIRSPACE (space))
568     {
569       sym->aop = aop = newAsmop (AOP_DIR);
570       aop->aopu.aop_dir = sym->rname;
571       aop->size = getSize (sym->type);
572       return aop;
573     }
574
575   /* special case for a function */
576   if (IS_FUNC (sym->type))
577     {
578       sym->aop = aop = newAsmop (AOP_IMMD);
579       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
580       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
581       aop->size = FPTRSIZE;
582       return aop;
583     }
584   
585   /* only remaining is far space */
586   /* in which case DPTR gets the address */
587   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
588   if (useDP2)
589     {
590       genSetDPTR (1);
591       _flushLazyDPS ();
592       emitcode ("mov", "dptr,#%s", sym->rname);
593       genSetDPTR (0);
594     }
595   else
596     {
597       emitcode ("mov", "dptr,#%s", sym->rname);
598     }
599   aop->size = getSize (sym->type);
600
601   /* if it is in code space */
602   if (IN_CODESPACE (space))
603     aop->code = 1;
604
605   return aop;
606 }
607
608 /*-----------------------------------------------------------------*/
609 /* aopForRemat - rematerialzes an object                           */
610 /*-----------------------------------------------------------------*/
611 static asmop *
612 aopForRemat (symbol * sym)
613 {
614   iCode *ic = sym->rematiCode;
615   asmop *aop = newAsmop (AOP_IMMD);
616   int ptr_type =0;
617   int val = 0;
618
619   for (;;)
620     {
621       if (ic->op == '+')
622         val += (int) operandLitValue (IC_RIGHT (ic));
623       else if (ic->op == '-')
624         val -= (int) operandLitValue (IC_RIGHT (ic));
625       else if (IS_CAST_ICODE(ic)) {
626               sym_link *from_type = operandType(IC_RIGHT(ic));
627               aop->aopu.aop_immd.from_cast_remat = 1;
628               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
629               ptr_type = DCL_TYPE(from_type);
630               if (ptr_type == IPOINTER) {
631                 // bug #481053
632                 ptr_type = POINTER;
633               }
634               continue ;
635       } else break;
636       
637       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
638     }
639
640   if (val)
641     sprintf (buffer, "(%s %c 0x%04x)",
642              OP_SYMBOL (IC_LEFT (ic))->rname,
643              val >= 0 ? '+' : '-',
644              abs (val) & 0xffff);
645   else {
646       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
647           sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
648       else
649           strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
650   }
651
652   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
653   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
654   /* set immd2 field if required */
655   if (aop->aopu.aop_immd.from_cast_remat) {
656           tsprintf(buffer,"#!constbyte",ptr_type);
657           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
658           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
659   }
660
661   return aop;
662 }
663
664 /*-----------------------------------------------------------------*/
665 /* aopHasRegs - returns true if aop has regs between from-to       */
666 /*-----------------------------------------------------------------*/
667 static int aopHasRegs(asmop *aop, int from, int to)
668 {
669     int size =0;
670
671     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
672
673     for (; size < aop->size ; size++) {
674         int reg;
675         for (reg = from ; reg <= to ; reg++)
676             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
677     }
678     return 0;
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* regsInCommon - two operands have some registers in common       */
683 /*-----------------------------------------------------------------*/
684 static bool
685 regsInCommon (operand * op1, operand * op2)
686 {
687   symbol *sym1, *sym2;
688   int i;
689
690   /* if they have registers in common */
691   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
692     return FALSE;
693
694   sym1 = OP_SYMBOL (op1);
695   sym2 = OP_SYMBOL (op2);
696
697   if (sym1->nRegs == 0 || sym2->nRegs == 0)
698     return FALSE;
699
700   for (i = 0; i < sym1->nRegs; i++)
701     {
702       int j;
703       if (!sym1->regs[i])
704         continue;
705
706       for (j = 0; j < sym2->nRegs; j++)
707         {
708           if (!sym2->regs[j])
709             continue;
710
711           if (sym2->regs[j] == sym1->regs[i])
712             return TRUE;
713         }
714     }
715
716   return FALSE;
717 }
718
719 /*-----------------------------------------------------------------*/
720 /* operandsEqu - equivalent                                        */
721 /*-----------------------------------------------------------------*/
722 static bool
723 operandsEqu (operand * op1, operand * op2)
724 {
725   symbol *sym1, *sym2;
726
727   /* if they not symbols */
728   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
729     return FALSE;
730
731   sym1 = OP_SYMBOL (op1);
732   sym2 = OP_SYMBOL (op2);
733
734   /* if both are itemps & one is spilt
735      and the other is not then false */
736   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
737       sym1->isspilt != sym2->isspilt)
738     return FALSE;
739
740   /* if they are the same */
741   if (sym1 == sym2)
742     return TRUE;
743
744   if (strcmp (sym1->rname, sym2->rname) == 0)
745     return TRUE;
746
747
748   /* if left is a tmp & right is not */
749   if (IS_ITEMP (op1) &&
750       !IS_ITEMP (op2) &&
751       sym1->isspilt &&
752       (sym1->usl.spillLoc == sym2))
753     return TRUE;
754
755   if (IS_ITEMP (op2) &&
756       !IS_ITEMP (op1) &&
757       sym2->isspilt &&
758       sym1->level > 0 &&
759       (sym2->usl.spillLoc == sym1))
760     return TRUE;
761
762   return FALSE;
763 }
764
765 /*-----------------------------------------------------------------*/
766 /* sameRegs - two asmops have the same registers                   */
767 /*-----------------------------------------------------------------*/
768 static bool
769 sameRegs (asmop * aop1, asmop * aop2)
770 {
771   int i;
772
773   if (aop1 == aop2)
774     {
775       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
776         {
777           return FALSE;
778         }
779       return TRUE;
780     }
781
782   if (aop1->type != AOP_REG ||
783       aop2->type != AOP_REG)
784     return FALSE;
785
786   if (aop1->size != aop2->size)
787     return FALSE;
788
789   for (i = 0; i < aop1->size; i++)
790     if (aop1->aopu.aop_reg[i] !=
791         aop2->aopu.aop_reg[i])
792       return FALSE;
793
794   return TRUE;
795 }
796
797 /*-----------------------------------------------------------------*/
798 /* aopOp - allocates an asmop for an operand  :                    */
799 /*-----------------------------------------------------------------*/
800 static void
801 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
802 {
803   asmop *aop;
804   symbol *sym;
805   int i;
806
807   if (!op)
808     return;
809
810   /* if this a literal */
811   if (IS_OP_LITERAL (op))
812     {
813       op->aop = aop = newAsmop (AOP_LIT);
814       aop->aopu.aop_lit = op->operand.valOperand;
815       aop->size = getSize (operandType (op));
816       return;
817     }
818
819   /* if already has a asmop then continue */
820   if (op->aop)
821     return;
822
823   /* if the underlying symbol has a aop */
824   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
825     {
826       op->aop = OP_SYMBOL (op)->aop;
827       return;
828     }
829
830   /* if this is a true symbol */
831   if (IS_TRUE_SYMOP (op))
832     {
833       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
834       return;
835     }
836
837   /* this is a temporary : this has
838      only four choices :
839      a) register
840      b) spillocation
841      c) rematerialize
842      d) conditional
843      e) can be a return use only */
844
845   sym = OP_SYMBOL (op);
846
847
848   /* if the type is a conditional */
849   if (sym->regType == REG_CND)
850     {
851       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
852       aop->size = 0;
853       return;
854     }
855
856   /* if it is spilt then two situations
857      a) is rematerialize
858      b) has a spill location */
859   if (sym->isspilt || sym->nRegs == 0)
860     {
861
862       /* rematerialize it NOW */
863       if (sym->remat)
864         {
865           sym->aop = op->aop = aop =
866             aopForRemat (sym);
867           aop->size = getSize (sym->type);
868           return;
869         }
870
871       if (sym->accuse)
872         {
873           int i;
874           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
875           aop->size = getSize (sym->type);
876           for (i = 0; i < 2; i++)
877             aop->aopu.aop_str[i] = accUse[i];
878           return;
879         }
880
881       if (sym->ruonly)
882         {
883           int i;
884
885           if (useDP2)
886             {
887               /* a AOP_STR uses DPTR, but DPTR is already in use;
888                * we're just hosed.
889                */
890                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
891             }
892
893           aop = op->aop = sym->aop = newAsmop (AOP_STR);
894           aop->size = getSize (sym->type);
895           for (i = 0; i < (int) fReturnSizeDS390; i++)
896             aop->aopu.aop_str[i] = fReturn[i];
897           return;
898         }
899       
900       if (sym->dptr) { /* has been allocated to a DPTRn */
901           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
902           aop->size = getSize (sym->type);
903           aop->aopu.dptr = sym->dptr;
904           return ;
905       }
906       /* else spill location  */
907       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
908           /* force a new aop if sizes differ */
909           sym->usl.spillLoc->aop = NULL;
910       }
911       sym->aop = op->aop = aop =
912         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
913       aop->size = getSize (sym->type);
914       return;
915     }
916
917   /* must be in a register */
918   sym->aop = op->aop = aop = newAsmop (AOP_REG);
919   aop->size = sym->nRegs;
920   for (i = 0; i < sym->nRegs; i++)
921     aop->aopu.aop_reg[i] = sym->regs[i];
922 }
923
924 /*-----------------------------------------------------------------*/
925 /* freeAsmop - free up the asmop given to an operand               */
926 /*----------------------------------------------------------------*/
927 static void
928 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
929 {
930   asmop *aop;
931
932   if (!op)
933     aop = aaop;
934   else
935     aop = op->aop;
936
937   if (!aop)
938     return;
939
940   if (aop->freed)
941     goto dealloc;
942
943   aop->freed = 1;
944
945   /* depending on the asmop type only three cases need work AOP_RO
946      , AOP_R1 && AOP_STK */
947   switch (aop->type)
948     {
949     case AOP_R0:
950       if (_G.r0Pushed)
951         {
952           if (pop)
953             {
954               emitcode ("pop", "ar0");
955               _G.r0Pushed--;
956             }
957         }
958       bitVectUnSetBit (ic->rUsed, R0_IDX);
959       break;
960
961     case AOP_R1:
962       if (_G.r1Pushed)
963         {
964           if (pop)
965             {
966               emitcode ("pop", "ar1");
967               _G.r1Pushed--;
968             }
969         }
970       bitVectUnSetBit (ic->rUsed, R1_IDX);
971       break;
972
973     case AOP_STK:
974       {
975         int sz = aop->size;
976         int stk = aop->aopu.aop_stk + aop->size;
977         bitVectUnSetBit (ic->rUsed, R0_IDX);
978         bitVectUnSetBit (ic->rUsed, R1_IDX);
979
980         getFreePtr (ic, &aop, FALSE);
981
982         if (options.stack10bit)
983           {
984             /* I'm not sure what to do here yet... */
985             /* #STUB */
986             fprintf (stderr,
987                      "*** Warning: probably generating bad code for "
988                      "10 bit stack mode.\n");
989           }
990
991         if (stk)
992           {
993             emitcode ("mov", "a,_bp");
994             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
995             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
996           }
997         else
998           {
999             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1000           }
1001
1002         while (sz--)
1003           {
1004             emitcode ("pop", "acc");
1005             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1006             if (!sz)
1007               break;
1008             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1009           }
1010         op->aop = aop;
1011         freeAsmop (op, NULL, ic, TRUE);
1012         if (_G.r0Pushed)
1013           {
1014             emitcode ("pop", "ar0");
1015             _G.r0Pushed--;
1016           }
1017
1018         if (_G.r1Pushed)
1019           {
1020             emitcode ("pop", "ar1");
1021             _G.r1Pushed--;
1022           }
1023       }
1024     case AOP_DPTR2:
1025         if (_G.dptr1InUse) {
1026             emitcode ("pop","dpx1");
1027             emitcode ("pop","dph1");
1028             emitcode ("pop","dpl1");
1029         }
1030         break;
1031     case AOP_DPTR:
1032         if (_G.dptrInUse) {
1033             emitcode ("pop","dpx");
1034             emitcode ("pop","dph");
1035             emitcode ("pop","dpl");
1036         }
1037         break;
1038     }
1039 dealloc:
1040   /* all other cases just dealloc */
1041   if (op)
1042     {
1043       op->aop = NULL;
1044       if (IS_SYMOP (op))
1045         {
1046           OP_SYMBOL (op)->aop = NULL;
1047           /* if the symbol has a spill */
1048           if (SPIL_LOC (op))
1049             SPIL_LOC (op)->aop = NULL;
1050         }
1051     }
1052 }
1053
1054 /*------------------------------------------------------------------*/
1055 /* aopGet - for fetching value of the aop                           */
1056 /*                    */
1057 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1058 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1059 /* just less efficient.               */
1060 /*------------------------------------------------------------------*/
1061
1062 static char *
1063 aopGet (asmop * aop,
1064         int offset,
1065         bool bit16,
1066         bool dname,
1067         bool canClobberACC)
1068 {
1069   char *s = buffer;
1070   char *rs;
1071
1072   /* offset is greater than
1073      size then zero */
1074   if (offset > (aop->size - 1) &&
1075       aop->type != AOP_LIT)
1076     return zero;
1077
1078   /* depending on type */
1079   switch (aop->type)
1080     {
1081
1082     case AOP_R0:
1083     case AOP_R1:
1084       /* if we need to increment it */
1085       while (offset > aop->coff)
1086         {
1087           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1088           aop->coff++;
1089         }
1090
1091       while (offset < aop->coff)
1092         {
1093           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1094           aop->coff--;
1095         }
1096
1097       aop->coff = offset;
1098       if (aop->paged)
1099         {
1100           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1101           return (dname ? "acc" : "a");
1102         }
1103       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1104       rs = Safe_calloc (1, strlen (s) + 1);
1105       strcpy (rs, s);
1106       return rs;
1107
1108     case AOP_DPTRn:
1109         assert(offset <= 3);
1110         return dptrn[aop->aopu.dptr][offset];
1111
1112     case AOP_DPTR:
1113     case AOP_DPTR2:
1114
1115       if (aop->type == AOP_DPTR2)
1116         {
1117           genSetDPTR (1);
1118           if (!canClobberACC)
1119             {
1120                     TR_AP("#1");
1121                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1122             }
1123         }
1124
1125       _flushLazyDPS ();
1126
1127       while (offset > aop->coff)
1128         {
1129           emitcode ("inc", "dptr");
1130           aop->coff++;
1131         }
1132
1133       while (offset < aop->coff)
1134         {
1135           emitcode ("lcall", "__decdptr");
1136           aop->coff--;
1137         }
1138
1139       aop->coff = offset;
1140       if (aop->code)
1141         {
1142           emitcode ("clr", "a");
1143           emitcode ("movc", "a,@a+dptr");
1144         }
1145       else
1146         {
1147           emitcode ("movx", "a,@dptr");
1148         }
1149
1150       if (aop->type == AOP_DPTR2)
1151         {
1152           genSetDPTR (0);
1153           if (!canClobberACC)
1154             {
1155        TR_AP("#2");
1156               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1157               return DP2_RESULT_REG;
1158             }
1159         }
1160       return (dname ? "acc" : "a");
1161
1162     case AOP_IMMD:
1163       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1164               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1165       } else if (bit16)
1166         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1167       else if (offset) {
1168           switch (offset) {
1169           case 1:
1170               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1171               break;
1172           case 2:
1173               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1174               break;
1175           case 3:
1176               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1177               break;
1178           default: /* should not need this (just in case) */
1179               sprintf (s, "#(%s >> %d)",
1180                        aop->aopu.aop_immd.aop_immd1,
1181                        offset * 8);
1182           }
1183       }
1184       else
1185         sprintf (s, "#%s",
1186                  aop->aopu.aop_immd.aop_immd1);
1187       rs = Safe_calloc (1, strlen (s) + 1);
1188       strcpy (rs, s);
1189       return rs;
1190
1191     case AOP_DIR:
1192       if (offset)
1193         sprintf (s, "(%s + %d)",
1194                  aop->aopu.aop_dir,
1195                  offset);
1196       else
1197         sprintf (s, "%s", aop->aopu.aop_dir);
1198       rs = Safe_calloc (1, strlen (s) + 1);
1199       strcpy (rs, s);
1200       return rs;
1201
1202     case AOP_REG:
1203       if (dname)
1204         return aop->aopu.aop_reg[offset]->dname;
1205       else
1206         return aop->aopu.aop_reg[offset]->name;
1207
1208     case AOP_CRY:
1209       emitcode ("clr", "a");
1210       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1211       emitcode ("rlc", "a");
1212       return (dname ? "acc" : "a");
1213
1214     case AOP_ACC:
1215       if (!offset && dname)
1216         return "acc";
1217       return aop->aopu.aop_str[offset];
1218
1219     case AOP_LIT:
1220       return aopLiteral (aop->aopu.aop_lit, offset);
1221
1222     case AOP_STR:
1223       aop->coff = offset;
1224       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1225           dname)
1226         return "acc";
1227
1228       return aop->aopu.aop_str[offset];
1229
1230     }
1231
1232   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1233           "aopget got unsupported aop->type");
1234   exit (1);
1235 }
1236 /*-----------------------------------------------------------------*/
1237 /* aopPut - puts a string for a aop                                */
1238 /*-----------------------------------------------------------------*/
1239 static void
1240 aopPut (asmop * aop, char *s, int offset)
1241 {
1242   char *d = buffer;
1243
1244   if (aop->size && offset > (aop->size - 1))
1245     {
1246       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1247               "aopPut got offset > aop->size");
1248       exit (1);
1249     }
1250
1251   /* will assign value to value */
1252   /* depending on where it is ofcourse */
1253   switch (aop->type)
1254     {
1255     case AOP_DIR:
1256       if (offset)
1257         sprintf (d, "(%s + %d)",
1258                  aop->aopu.aop_dir, offset);
1259       else
1260         sprintf (d, "%s", aop->aopu.aop_dir);
1261
1262       if (strcmp (d, s))
1263         emitcode ("mov", "%s,%s", d, s);
1264
1265       break;
1266
1267     case AOP_REG:
1268       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1269           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1270         {
1271           if (*s == '@' ||
1272               strcmp (s, "r0") == 0 ||
1273               strcmp (s, "r1") == 0 ||
1274               strcmp (s, "r2") == 0 ||
1275               strcmp (s, "r3") == 0 ||
1276               strcmp (s, "r4") == 0 ||
1277               strcmp (s, "r5") == 0 ||
1278               strcmp (s, "r6") == 0 ||
1279               strcmp (s, "r7") == 0)
1280             emitcode ("mov", "%s,%s",
1281                       aop->aopu.aop_reg[offset]->dname, s);
1282           else
1283             emitcode ("mov", "%s,%s",
1284                       aop->aopu.aop_reg[offset]->name, s);
1285         }
1286       break;
1287
1288     case AOP_DPTRn:
1289         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1290         break;
1291
1292     case AOP_DPTR:
1293     case AOP_DPTR2:
1294
1295       if (aop->type == AOP_DPTR2)
1296         {
1297           genSetDPTR (1);
1298         }
1299       _flushLazyDPS ();
1300
1301       if (aop->code)
1302         {
1303           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1304                   "aopPut writting to code space");
1305           exit (1);
1306         }
1307
1308       while (offset > aop->coff)
1309         {
1310           aop->coff++;
1311           emitcode ("inc", "dptr");
1312         }
1313
1314       while (offset < aop->coff)
1315         {
1316           aop->coff--;
1317           emitcode ("lcall", "__decdptr");
1318         }
1319
1320       aop->coff = offset;
1321
1322       /* if not in accumulater */
1323       MOVA (s);
1324
1325       emitcode ("movx", "@dptr,a");
1326
1327       if (aop->type == AOP_DPTR2)
1328         {
1329           genSetDPTR (0);
1330         }
1331       break;
1332
1333     case AOP_R0:
1334     case AOP_R1:
1335       while (offset > aop->coff)
1336         {
1337           aop->coff++;
1338           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1339         }
1340       while (offset < aop->coff)
1341         {
1342           aop->coff--;
1343           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1344         }
1345       aop->coff = offset;
1346
1347       if (aop->paged)
1348         {
1349           MOVA (s);
1350           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1351
1352         }
1353       else if (*s == '@')
1354         {
1355           MOVA (s);
1356           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1357         }
1358       else if (strcmp (s, "r0") == 0 ||
1359                strcmp (s, "r1") == 0 ||
1360                strcmp (s, "r2") == 0 ||
1361                strcmp (s, "r3") == 0 ||
1362                strcmp (s, "r4") == 0 ||
1363                strcmp (s, "r5") == 0 ||
1364                strcmp (s, "r6") == 0 ||
1365                strcmp (s, "r7") == 0)
1366         {
1367           char buffer[10];
1368           sprintf (buffer, "a%s", s);
1369           emitcode ("mov", "@%s,%s",
1370                     aop->aopu.aop_ptr->name, buffer);
1371         }
1372       else
1373         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1374
1375       break;
1376
1377     case AOP_STK:
1378       if (strcmp (s, "a") == 0)
1379         emitcode ("push", "acc");
1380       else
1381         if (*s=='@') {
1382           MOVA(s);
1383           emitcode ("push", "acc");
1384         } else {
1385           emitcode ("push", s);
1386         }
1387
1388       break;
1389
1390     case AOP_CRY:
1391       /* if bit variable */
1392       if (!aop->aopu.aop_dir)
1393         {
1394           emitcode ("clr", "a");
1395           emitcode ("rlc", "a");
1396         }
1397       else
1398         {
1399           if (s == zero)
1400             emitcode ("clr", "%s", aop->aopu.aop_dir);
1401           else if (s == one)
1402             emitcode ("setb", "%s", aop->aopu.aop_dir);
1403           else if (!strcmp (s, "c"))
1404             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1405           else
1406             {
1407               if (strcmp (s, "a"))
1408                 {
1409                   MOVA (s);
1410                 }
1411               {
1412                 /* set C, if a >= 1 */
1413                 emitcode ("add", "a,#!constbyte",0xff);
1414                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1415               }
1416             }
1417         }
1418       break;
1419
1420     case AOP_STR:
1421       aop->coff = offset;
1422       if (strcmp (aop->aopu.aop_str[offset], s))
1423         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1424       break;
1425
1426     case AOP_ACC:
1427       aop->coff = offset;
1428       if (!offset && (strcmp (s, "acc") == 0))
1429         break;
1430
1431       if (strcmp (aop->aopu.aop_str[offset], s))
1432         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1433       break;
1434
1435     default:
1436       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437               "aopPut got unsupported aop->type");
1438       exit (1);
1439     }
1440
1441 }
1442
1443
1444 /*--------------------------------------------------------------------*/
1445 /* reAdjustPreg - points a register back to where it should (coff==0) */
1446 /*--------------------------------------------------------------------*/
1447 static void
1448 reAdjustPreg (asmop * aop)
1449 {
1450   if ((aop->coff==0) || (aop->size <= 1)) {
1451     return;
1452   }
1453
1454   switch (aop->type)
1455     {
1456     case AOP_R0:
1457     case AOP_R1:
1458       while (aop->coff--)
1459         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1460       break;
1461     case AOP_DPTR:
1462     case AOP_DPTR2:
1463       if (aop->type == AOP_DPTR2)
1464         {
1465           genSetDPTR (1);
1466           _flushLazyDPS ();
1467         }
1468       while (aop->coff--)
1469         {
1470           emitcode ("lcall", "__decdptr");
1471         }
1472
1473       if (aop->type == AOP_DPTR2)
1474         {
1475           genSetDPTR (0);
1476         }
1477       break;
1478
1479     }
1480   aop->coff=0;
1481 }
1482
1483 #define AOP(op) op->aop
1484 #define AOP_TYPE(op) AOP(op)->type
1485 #define AOP_SIZE(op) AOP(op)->size
1486 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1487                        AOP_TYPE(x) == AOP_R0))
1488
1489 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1490                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1491                          AOP(x)->paged))
1492
1493 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1494                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1495                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1496 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1497 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1498
1499 /* Workaround for DS80C390 bug: div ab may return bogus results
1500  * if A is accessed in instruction immediately before the div.
1501  *
1502  * Will be fixed in B4 rev of processor, Dallas claims.
1503  */
1504
1505 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1506     if (!AOP_NEEDSACC(RIGHT))         \
1507     {               \
1508       /* We can load A first, then B, since     \
1509        * B (the RIGHT operand) won't clobber A,   \
1510        * thus avoiding touching A right before the div. \
1511        */             \
1512       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1513       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1514       MOVA(L);            \
1515       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1516     }               \
1517     else              \
1518     {               \
1519       /* Just stuff in a nop after loading A. */    \
1520       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1521       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1522       MOVA(L);            \
1523       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1524     }
1525
1526 /*-----------------------------------------------------------------*/
1527 /* genNotFloat - generates not for float operations              */
1528 /*-----------------------------------------------------------------*/
1529 static void
1530 genNotFloat (operand * op, operand * res)
1531 {
1532   int size, offset;
1533   char *l;
1534   symbol *tlbl;
1535
1536   D (emitcode (";", "genNotFloat ");
1537     );
1538
1539   /* we will put 127 in the first byte of
1540      the result */
1541   aopPut (AOP (res), "#127", 0);
1542   size = AOP_SIZE (op) - 1;
1543   offset = 1;
1544
1545   _startLazyDPSEvaluation ();
1546   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1547   MOVA (l);
1548
1549   while (size--)
1550     {
1551       emitcode ("orl", "a,%s",
1552                 aopGet (op->aop,
1553                         offset++, FALSE, FALSE, FALSE));
1554     }
1555   _endLazyDPSEvaluation ();
1556
1557   tlbl = newiTempLabel (NULL);
1558   aopPut (res->aop, one, 1);
1559   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1560   aopPut (res->aop, zero, 1);
1561   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1562
1563   size = res->aop->size - 2;
1564   offset = 2;
1565   /* put zeros in the rest */
1566   while (size--)
1567     aopPut (res->aop, zero, offset++);
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* opIsGptr: returns non-zero if the passed operand is       */
1572 /* a generic pointer type.             */
1573 /*-----------------------------------------------------------------*/
1574 static int
1575 opIsGptr (operand * op)
1576 {
1577   sym_link *type = operandType (op);
1578
1579   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1580     {
1581       return 1;
1582     }
1583   return 0;
1584 }
1585
1586 /*-----------------------------------------------------------------*/
1587 /* getDataSize - get the operand data size                         */
1588 /*-----------------------------------------------------------------*/
1589 static int
1590 getDataSize (operand * op)
1591 {
1592   int size;
1593   size = AOP_SIZE (op);
1594   if (size == GPTRSIZE)
1595     {
1596       sym_link *type = operandType (op);
1597       if (IS_GENPTR (type))
1598         {
1599           /* generic pointer; arithmetic operations
1600            * should ignore the high byte (pointer type).
1601            */
1602           size--;
1603         }
1604     }
1605   return size;
1606 }
1607
1608 /*-----------------------------------------------------------------*/
1609 /* outAcc - output Acc                                             */
1610 /*-----------------------------------------------------------------*/
1611 static void
1612 outAcc (operand * result)
1613 {
1614   int size, offset;
1615   size = getDataSize (result);
1616   if (size)
1617     {
1618       aopPut (AOP (result), "a", 0);
1619       size--;
1620       offset = 1;
1621       /* unsigned or positive */
1622       while (size--)
1623         {
1624           aopPut (AOP (result), zero, offset++);
1625         }
1626     }
1627 }
1628
1629 /*-----------------------------------------------------------------*/
1630 /* outBitC - output a bit C                                        */
1631 /*-----------------------------------------------------------------*/
1632 static void
1633 outBitC (operand * result)
1634 {
1635   /* if the result is bit */
1636   if (AOP_TYPE (result) == AOP_CRY)
1637     {
1638       aopPut (AOP (result), "c", 0);
1639     }
1640   else
1641     {
1642       emitcode ("clr", "a");
1643       emitcode ("rlc", "a");
1644       outAcc (result);
1645     }
1646 }
1647
1648 /*-----------------------------------------------------------------*/
1649 /* toBoolean - emit code for orl a,operator(sizeop)                */
1650 /*-----------------------------------------------------------------*/
1651 static void
1652 toBoolean (operand * oper)
1653 {
1654   int   size = AOP_SIZE (oper) - 1;
1655   int   offset = 1;
1656   bool usedB = FALSE;
1657
1658   /* The generic part of a generic pointer should
1659    * not participate in it's truth value.
1660    *
1661    * i.e. 0x10000000 is zero.
1662    */
1663   if (opIsGptr (oper))
1664     {
1665       D (emitcode (";", "toBoolean: generic ptr special case.");
1666         );
1667       size--;
1668     }
1669
1670   _startLazyDPSEvaluation ();
1671   if (AOP_NEEDSACC (oper) && size)
1672     {
1673       usedB = TRUE;
1674       emitcode ("push", "b");
1675       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1676     }
1677   else
1678     {
1679       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1680     }
1681   while (size--)
1682     {
1683       if (usedB)
1684         {
1685           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1686         }
1687       else
1688         {
1689           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1690         }
1691     }
1692   _endLazyDPSEvaluation ();
1693
1694   if (usedB)
1695     {
1696       emitcode ("mov", "a,b");
1697       emitcode ("pop", "b");
1698     }
1699 }
1700
1701
1702 /*-----------------------------------------------------------------*/
1703 /* genNot - generate code for ! operation                          */
1704 /*-----------------------------------------------------------------*/
1705 static void
1706 genNot (iCode * ic)
1707 {
1708   symbol *tlbl;
1709   sym_link *optype = operandType (IC_LEFT (ic));
1710
1711   D (emitcode (";", "genNot ");
1712     );
1713
1714   /* assign asmOps to operand & result */
1715   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1716   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1717
1718   /* if in bit space then a special case */
1719   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1720     {
1721       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1722       emitcode ("cpl", "c");
1723       outBitC (IC_RESULT (ic));
1724       goto release;
1725     }
1726
1727   /* if type float then do float */
1728   if (IS_FLOAT (optype))
1729     {
1730       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1731       goto release;
1732     }
1733
1734   toBoolean (IC_LEFT (ic));
1735
1736   tlbl = newiTempLabel (NULL);
1737   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1738   emitcode ("", "!tlabeldef", tlbl->key + 100);
1739   outBitC (IC_RESULT (ic));
1740
1741 release:
1742   /* release the aops */
1743   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1744   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1745 }
1746
1747
1748 /*-----------------------------------------------------------------*/
1749 /* genCpl - generate code for complement                           */
1750 /*-----------------------------------------------------------------*/
1751 static void
1752 genCpl (iCode * ic)
1753 {
1754   int offset = 0;
1755   int size;
1756   symbol *tlbl;
1757
1758   D (emitcode (";", "genCpl ");
1759     );
1760
1761
1762   /* assign asmOps to operand & result */
1763   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1765
1766   /* special case if in bit space */
1767   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1768     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1769       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770       emitcode ("cpl", "c");
1771       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1772       goto release;
1773     }
1774     tlbl=newiTempLabel(NULL);
1775     emitcode ("cjne", "%s,#0x01,%05d$", 
1776               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1777     emitcode ("", "%05d$:", tlbl->key+100);
1778     outBitC (IC_RESULT(ic));
1779     goto release;
1780   }
1781
1782   size = AOP_SIZE (IC_RESULT (ic));
1783   _startLazyDPSEvaluation ();
1784   while (size--)
1785     {
1786       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1787       MOVA (l);
1788       emitcode ("cpl", "a");
1789       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1790     }
1791   _endLazyDPSEvaluation ();
1792
1793
1794 release:
1795   /* release the aops */
1796   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1797   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1798 }
1799
1800 /*-----------------------------------------------------------------*/
1801 /* genUminusFloat - unary minus for floating points                */
1802 /*-----------------------------------------------------------------*/
1803 static void
1804 genUminusFloat (operand * op, operand * result)
1805 {
1806   int size, offset = 0;
1807   char *l;
1808   /* for this we just need to flip the
1809      first it then copy the rest in place */
1810   D (emitcode (";", "genUminusFloat");
1811     );
1812
1813   _startLazyDPSEvaluation ();
1814   size = AOP_SIZE (op) - 1;
1815   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1816   MOVA (l);
1817
1818   emitcode ("cpl", "acc.7");
1819   aopPut (AOP (result), "a", 3);
1820
1821   while (size--)
1822     {
1823       aopPut (AOP (result),
1824               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1825               offset);
1826       offset++;
1827     }
1828   _endLazyDPSEvaluation ();
1829 }
1830
1831 /*-----------------------------------------------------------------*/
1832 /* genUminus - unary minus code generation                         */
1833 /*-----------------------------------------------------------------*/
1834 static void
1835 genUminus (iCode * ic)
1836 {
1837   int offset, size;
1838   sym_link *optype, *rtype;
1839
1840   D (emitcode (";", "genUminus ");
1841     );
1842
1843
1844   /* assign asmops */
1845   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1847
1848   /* if both in bit space then special
1849      case */
1850   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1851       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1852     {
1853
1854       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1855       emitcode ("cpl", "c");
1856       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1857       goto release;
1858     }
1859
1860   optype = operandType (IC_LEFT (ic));
1861   rtype = operandType (IC_RESULT (ic));
1862
1863   /* if float then do float stuff */
1864   if (IS_FLOAT (optype))
1865     {
1866       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1867       goto release;
1868     }
1869
1870   /* otherwise subtract from zero */
1871   size = AOP_SIZE (IC_LEFT (ic));
1872   offset = 0;
1873   _startLazyDPSEvaluation ();
1874   while (size--)
1875     {
1876       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1877       if (!strcmp (l, "a"))
1878         {
1879           if (offset == 0)
1880             SETC;
1881           emitcode ("cpl", "a");
1882           emitcode ("addc", "a,#0");
1883         }
1884       else
1885         {
1886           if (offset == 0)
1887             CLRC;
1888           emitcode ("clr", "a");
1889           emitcode ("subb", "a,%s", l);
1890         }
1891       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1892     }
1893   _endLazyDPSEvaluation ();
1894
1895   /* if any remaining bytes in the result */
1896   /* we just need to propagate the sign   */
1897   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1898     {
1899       emitcode ("rlc", "a");
1900       emitcode ("subb", "a,acc");
1901       while (size--)
1902         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1903     }
1904
1905 release:
1906   /* release the aops */
1907   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1908   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1909 }
1910
1911 /*-----------------------------------------------------------------*/
1912 /* savermask - saves registers in the mask                         */
1913 /*-----------------------------------------------------------------*/
1914 static void savermask(bitVect *rs_mask)
1915 {
1916     int i;
1917     if (options.useXstack) {
1918         if (bitVectBitValue (rs_mask, R0_IDX))
1919             emitcode ("mov", "b,r0");
1920         emitcode ("mov", "r0,%s", spname);
1921         for (i = 0; i < ds390_nRegs; i++) {
1922             if (bitVectBitValue (rs_mask, i)) {
1923                 if (i == R0_IDX)
1924                     emitcode ("mov", "a,b");
1925                 else
1926                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1927                 emitcode ("movx", "@r0,a");
1928                 emitcode ("inc", "r0");
1929             }
1930         }
1931         emitcode ("mov", "%s,r0", spname);
1932         if (bitVectBitValue (rs_mask, R0_IDX))
1933             emitcode ("mov", "r0,b");
1934     } else {
1935         for (i = 0; i < ds390_nRegs; i++) {
1936             if (bitVectBitValue (rs_mask, i))
1937                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1938         }
1939     }
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* saveRegisters - will look for a call and save the registers     */
1944 /*-----------------------------------------------------------------*/
1945 static void
1946 saveRegisters (iCode * lic)
1947 {
1948   iCode *ic;
1949   bitVect *rsave;
1950
1951   /* look for call */
1952   for (ic = lic; ic; ic = ic->next)
1953     if (ic->op == CALL || ic->op == PCALL)
1954       break;
1955
1956   if (!ic)
1957     {
1958       fprintf (stderr, "found parameter push with no function call\n");
1959       return;
1960     }
1961
1962   /* if the registers have been saved already then
1963      do nothing */
1964   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1965
1966   /* special case if DPTR alive across a function call then must save it 
1967      even though callee saves */
1968   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1969       int i =0;
1970       rsave = newBitVect(ic->rMask->size);
1971       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1972           if (bitVectBitValue(ic->rMask,i))
1973               rsave = bitVectSetBit(rsave,i);
1974       }
1975       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1976   } else {
1977     /* safe the registers in use at this time but skip the
1978        ones for the result */
1979     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1980                            ds390_rUmaskForOp (IC_RESULT(ic)));
1981   }
1982   ic->regsSaved = 1;
1983   savermask(rsave);
1984 }
1985
1986 /*-----------------------------------------------------------------*/
1987 /* usavermask - restore registers with mask                        */
1988 /*-----------------------------------------------------------------*/
1989 static void unsavermask(bitVect *rs_mask)
1990 {
1991     int i;
1992     if (options.useXstack) {
1993         emitcode ("mov", "r0,%s", spname);
1994         for (i = ds390_nRegs; i >= 0; i--) {
1995             if (bitVectBitValue (rs_mask, i)) {
1996                 emitcode ("dec", "r0");
1997                 emitcode ("movx", "a,@r0");
1998                 if (i == R0_IDX)
1999                     emitcode ("mov", "b,a");
2000                 else
2001                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2002             }       
2003         }
2004         emitcode ("mov", "%s,r0", spname);
2005         if (bitVectBitValue (rs_mask, R0_IDX))
2006             emitcode ("mov", "r0,b");
2007     } else {
2008         for (i = ds390_nRegs; i >= 0; i--) {
2009             if (bitVectBitValue (rs_mask, i))
2010                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2011         }
2012     }
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* unsaveRegisters - pop the pushed registers                      */
2017 /*-----------------------------------------------------------------*/
2018 static void
2019 unsaveRegisters (iCode * ic)
2020 {
2021   bitVect *rsave;
2022
2023   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2024       int i =0;
2025       rsave = newBitVect(ic->rMask->size);
2026       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2027           if (bitVectBitValue(ic->rMask,i))
2028               rsave = bitVectSetBit(rsave,i);
2029       }
2030       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2031   } else {
2032     /* restore the registers in use at this time but skip the
2033        ones for the result */
2034     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2035                            ds390_rUmaskForOp (IC_RESULT(ic)));
2036   }
2037   unsavermask(rsave);
2038 }
2039
2040
2041 /*-----------------------------------------------------------------*/
2042 /* pushSide -                */
2043 /*-----------------------------------------------------------------*/
2044 static void
2045 pushSide (operand * oper, int size)
2046 {
2047   int offset = 0;
2048   _startLazyDPSEvaluation ();
2049   while (size--)
2050     {
2051       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2052       if (AOP_TYPE (oper) != AOP_REG &&
2053           AOP_TYPE (oper) != AOP_DIR &&
2054           strcmp (l, "a"))
2055         {
2056           emitcode ("mov", "a,%s", l);
2057           emitcode ("push", "acc");
2058         }
2059       else
2060         emitcode ("push", "%s", l);
2061     }
2062   _endLazyDPSEvaluation ();
2063 }
2064
2065 /*-----------------------------------------------------------------*/
2066 /* assignResultValue -               */
2067 /*-----------------------------------------------------------------*/
2068 static void
2069 assignResultValue (operand * oper)
2070 {
2071   int offset = 0;
2072   int size = AOP_SIZE (oper);
2073
2074   _startLazyDPSEvaluation ();
2075   while (size--)
2076     {
2077       aopPut (AOP (oper), fReturn[offset], offset);
2078       offset++;
2079     }
2080   _endLazyDPSEvaluation ();
2081 }
2082
2083
2084 /*-----------------------------------------------------------------*/
2085 /* genXpush - pushes onto the external stack                       */
2086 /*-----------------------------------------------------------------*/
2087 static void
2088 genXpush (iCode * ic)
2089 {
2090   asmop *aop = newAsmop (0);
2091   regs *r;
2092   int size, offset = 0;
2093
2094   D (emitcode (";", "genXpush ");
2095     );
2096
2097   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2098   r = getFreePtr (ic, &aop, FALSE);
2099
2100
2101   emitcode ("mov", "%s,_spx", r->name);
2102
2103   size = AOP_SIZE (IC_LEFT (ic));
2104   _startLazyDPSEvaluation ();
2105   while (size--)
2106     {
2107
2108       char *l = aopGet (AOP (IC_LEFT (ic)),
2109                         offset++, FALSE, FALSE, TRUE);
2110       MOVA (l);
2111       emitcode ("movx", "@%s,a", r->name);
2112       emitcode ("inc", "%s", r->name);
2113
2114     }
2115   _endLazyDPSEvaluation ();
2116
2117
2118   emitcode ("mov", "_spx,%s", r->name);
2119
2120   freeAsmop (NULL, aop, ic, TRUE);
2121   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* genIpush - genrate code for pushing this gets a little complex  */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 genIpush (iCode * ic)
2129 {
2130   int size, offset = 0;
2131   char *l;
2132
2133   D (emitcode (";", "genIpush ");
2134     );
2135
2136   /* if this is not a parm push : ie. it is spill push
2137      and spill push is always done on the local stack */
2138   if (!ic->parmPush)
2139     {
2140
2141       /* and the item is spilt then do nothing */
2142       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2143         return;
2144
2145       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2146       size = AOP_SIZE (IC_LEFT (ic));
2147       /* push it on the stack */
2148       _startLazyDPSEvaluation ();
2149       while (size--)
2150         {
2151           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2152           if (*l == '#')
2153             {
2154               MOVA (l);
2155               l = "acc";
2156             }
2157           emitcode ("push", "%s", l);
2158         }
2159       _endLazyDPSEvaluation ();
2160       return;
2161     }
2162
2163   /* this is a paramter push: in this case we call
2164      the routine to find the call and save those
2165      registers that need to be saved */
2166   saveRegisters (ic);
2167
2168   /* if use external stack then call the external
2169      stack pushing routine */
2170   if (options.useXstack)
2171     {
2172       genXpush (ic);
2173       return;
2174     }
2175
2176   /* then do the push */
2177   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2178
2179   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2180   size = AOP_SIZE (IC_LEFT (ic));
2181
2182   _startLazyDPSEvaluation ();
2183   while (size--)
2184     {
2185       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2186       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2187           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2188           strcmp (l, "a"))
2189         {
2190           emitcode ("mov", "a,%s", l);
2191           emitcode ("push", "acc");
2192         }
2193       else
2194         emitcode ("push", "%s", l);
2195     }
2196   _endLazyDPSEvaluation ();
2197
2198   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2199 }
2200
2201 /*-----------------------------------------------------------------*/
2202 /* genIpop - recover the registers: can happen only for spilling   */
2203 /*-----------------------------------------------------------------*/
2204 static void
2205 genIpop (iCode * ic)
2206 {
2207   int size, offset;
2208
2209   D (emitcode (";", "genIpop ");
2210     );
2211
2212
2213   /* if the temp was not pushed then */
2214   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2215     return;
2216
2217   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2218   size = AOP_SIZE (IC_LEFT (ic));
2219   offset = (size - 1);
2220   _startLazyDPSEvaluation ();
2221   while (size--)
2222     {
2223       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2224                                      FALSE, TRUE, TRUE));
2225     }
2226   _endLazyDPSEvaluation ();
2227
2228   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2229 }
2230
2231 /*-----------------------------------------------------------------*/
2232 /* unsaveRBank - restores the resgister bank from stack            */
2233 /*-----------------------------------------------------------------*/
2234 static void
2235 unsaveRBank (int bank, iCode * ic, bool popPsw)
2236 {
2237   int i;
2238   asmop *aop = NULL;
2239   regs *r = NULL;
2240
2241   if (options.useXstack)
2242   {
2243       if (!ic)
2244       {
2245           /* Assume r0 is available for use. */
2246           r = ds390_regWithIdx (R0_IDX);;          
2247       } 
2248       else
2249       {
2250           aop = newAsmop (0);
2251           r = getFreePtr (ic, &aop, FALSE);
2252       }
2253       emitcode ("mov", "%s,_spx", r->name);      
2254   }
2255   
2256   if (popPsw)
2257     {
2258       if (options.useXstack)
2259       {
2260           emitcode ("movx", "a,@%s", r->name);
2261           emitcode ("mov", "psw,a");
2262           emitcode ("dec", "%s", r->name);
2263         }
2264       else
2265       {
2266         emitcode ("pop", "psw");
2267       }
2268     }
2269
2270   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2271     {
2272       if (options.useXstack)
2273         {
2274           emitcode ("movx", "a,@%s", r->name);
2275           emitcode ("mov", "(%s+%d),a",
2276                     regs390[i].base, 8 * bank + regs390[i].offset);
2277           emitcode ("dec", "%s", r->name);
2278
2279         }
2280       else
2281         emitcode ("pop", "(%s+%d)",
2282                   regs390[i].base, 8 * bank + regs390[i].offset);
2283     }
2284
2285   if (options.useXstack)
2286     {
2287       emitcode ("mov", "_spx,%s", r->name);
2288     }
2289     
2290   if (aop)
2291   {
2292       freeAsmop (NULL, aop, ic, TRUE);  
2293   }    
2294 }
2295
2296 /*-----------------------------------------------------------------*/
2297 /* saveRBank - saves an entire register bank on the stack          */
2298 /*-----------------------------------------------------------------*/
2299 static void
2300 saveRBank (int bank, iCode * ic, bool pushPsw)
2301 {
2302   int i;
2303   asmop *aop = NULL;
2304   regs *r = NULL;
2305
2306   if (options.useXstack)
2307     {
2308         if (!ic)
2309         {
2310           /* Assume r0 is available for use. */
2311                   r = ds390_regWithIdx (R0_IDX);;
2312         }
2313         else
2314         {
2315           aop = newAsmop (0);
2316           r = getFreePtr (ic, &aop, FALSE);
2317         }
2318         emitcode ("mov", "%s,_spx", r->name);    
2319     }
2320
2321   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2322     {
2323       if (options.useXstack)
2324         {
2325           emitcode ("inc", "%s", r->name);
2326           emitcode ("mov", "a,(%s+%d)",
2327                     regs390[i].base, 8 * bank + regs390[i].offset);
2328           emitcode ("movx", "@%s,a", r->name);
2329         }
2330       else
2331         emitcode ("push", "(%s+%d)",
2332                   regs390[i].base, 8 * bank + regs390[i].offset);
2333     }
2334
2335   if (pushPsw)
2336     {
2337       if (options.useXstack)
2338         {
2339           emitcode ("mov", "a,psw");
2340           emitcode ("movx", "@%s,a", r->name);
2341           emitcode ("inc", "%s", r->name);
2342           emitcode ("mov", "_spx,%s", r->name);
2343         }
2344       else
2345       {
2346         emitcode ("push", "psw");
2347       }
2348
2349       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2350     }
2351   
2352   if (aop)
2353   {
2354        freeAsmop (NULL, aop, ic, TRUE);
2355   }    
2356     
2357   if (ic)
2358   {  
2359       ic->bankSaved = 1;
2360   }
2361 }
2362
2363 /*-----------------------------------------------------------------*/
2364 /* genSend - gen code for SEND                                     */
2365 /*-----------------------------------------------------------------*/
2366 static void genSend(set *sendSet)
2367 {
2368     iCode *sic;
2369     int sendCount = 0 ;
2370     static int rb1_count = 0;
2371
2372     for (sic = setFirstItem (sendSet); sic;
2373          sic = setNextItem (sendSet)) {     
2374         int size, offset = 0;
2375         
2376         size=getSize(operandType(IC_LEFT(sic)));
2377         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2378         if (sendCount == 0) { /* first parameter */
2379             // we know that dpl(hxb) is the result, so
2380             rb1_count = 0 ;
2381             _startLazyDPSEvaluation ();
2382             if (size>1) {
2383                 aopOp (IC_LEFT (sic), sic, FALSE, 
2384                        (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2385             } else {
2386                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2387             }
2388             while (size--) {
2389                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2390                                   FALSE, FALSE, TRUE);
2391                 if (strcmp (l, fReturn[offset])) {
2392                     emitcode ("mov", "%s,%s",
2393                               fReturn[offset],
2394                               l);
2395                 }
2396                 offset++;
2397             }
2398             _endLazyDPSEvaluation ();
2399             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2400             rb1_count =0;
2401         } else { /* if more parameter in registers */
2402             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2403             while (size--) {
2404                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2405                                                                 FALSE, FALSE, TRUE));
2406             }
2407             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2408         }
2409         sendCount++;
2410     }
2411 }
2412
2413 /*-----------------------------------------------------------------*/
2414 /* genCall - generates a call statement                            */
2415 /*-----------------------------------------------------------------*/
2416 static void
2417 genCall (iCode * ic)
2418 {
2419   sym_link *dtype;
2420   bool restoreBank = FALSE;
2421   bool swapBanks = FALSE;
2422
2423   D (emitcode (";", "genCall "););
2424
2425   /* if we are calling a not _naked function that is not using
2426      the same register bank then we need to save the
2427      destination registers on the stack */
2428   dtype = operandType (IC_LEFT (ic));
2429   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2430       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2431       IFFUNC_ISISR (currFunc->type))
2432   {
2433       if (!ic->bankSaved) 
2434       {
2435            /* This is unexpected; the bank should have been saved in
2436             * genFunction.
2437             */
2438            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2439            restoreBank = TRUE;
2440       }
2441       swapBanks = TRUE;
2442   }
2443   
2444     /* if caller saves & we have not saved then */
2445     if (!ic->regsSaved)
2446       saveRegisters (ic);
2447   
2448   /* if send set is not empty the assign */
2449   /* We've saved all the registers we care about;
2450   * therefore, we may clobber any register not used
2451   * in the calling convention (i.e. anything not in
2452   * fReturn.
2453   */
2454   if (_G.sendSet)
2455     {
2456         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2457             genSend(reverseSet(_G.sendSet));
2458         } else {
2459             genSend(_G.sendSet);
2460         }
2461       _G.sendSet = NULL;
2462     }  
2463     
2464   if (swapBanks)
2465   {
2466         emitcode ("mov", "psw,#!constbyte", 
2467            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2468   }
2469
2470   /* make the call */
2471   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2472                             OP_SYMBOL (IC_LEFT (ic))->rname :
2473                             OP_SYMBOL (IC_LEFT (ic))->name));
2474
2475   if (swapBanks)
2476   {
2477        emitcode ("mov", "psw,#!constbyte", 
2478           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2479   }
2480
2481   /* if we need assign a result value */
2482   if ((IS_ITEMP (IC_RESULT (ic)) &&
2483        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2484         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2485         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2486       IS_TRUE_SYMOP (IC_RESULT (ic)))
2487     {
2488       if (isOperandInFarSpace (IC_RESULT (ic))
2489           && getSize (operandType (IC_RESULT (ic))) <= 2)
2490         {
2491           int size = getSize (operandType (IC_RESULT (ic)));
2492
2493           /* Special case for 1 or 2 byte return in far space. */
2494           MOVA (fReturn[0]);
2495           if (size > 1)
2496             {
2497               emitcode ("mov", "b,%s", fReturn[1]);
2498             }
2499
2500           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2501           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2502
2503           if (size > 1)
2504             {
2505               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2506             }
2507           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2508         }
2509       else
2510         {
2511           _G.accInUse++;
2512           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2513           _G.accInUse--;
2514
2515           assignResultValue (IC_RESULT (ic));
2516
2517           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2518         }
2519     }
2520
2521   /* adjust the stack for parameters if
2522      required */
2523   if (ic->parmBytes) {
2524       int i;
2525       if (options.stack10bit) {
2526           if (ic->parmBytes <= 10) {
2527               emitcode(";","stack adjustment for parms");
2528               for (i=0; i < ic->parmBytes ; i++) {
2529                   emitcode("pop","acc");
2530               }
2531           } else {            
2532               PROTECT_SP;
2533               emitcode ("clr","c");
2534               emitcode ("mov","a,sp");
2535               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2536               emitcode ("mov","sp,a");
2537               emitcode ("mov","a,esp");
2538               emitcode ("anl","a,#3");
2539               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2540               emitcode ("mov","esp,a");   
2541               UNPROTECT_SP;
2542           }
2543       } else {
2544           if (ic->parmBytes > 3) {
2545               emitcode ("mov", "a,%s", spname);
2546               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2547               emitcode ("mov", "%s,a", spname);
2548           } else
2549               for (i = 0; i < ic->parmBytes; i++)
2550                   emitcode ("dec", "%s", spname);
2551       }
2552   }
2553
2554   /* if we hade saved some registers then unsave them */
2555   if (ic->regsSaved)
2556     unsaveRegisters (ic);
2557
2558   /* if register bank was saved then pop them */
2559   if (restoreBank)
2560     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2561 }
2562
2563 /*-----------------------------------------------------------------*/
2564 /* genPcall - generates a call by pointer statement                */
2565 /*-----------------------------------------------------------------*/
2566 static void
2567 genPcall (iCode * ic)
2568 {
2569   sym_link *dtype;
2570   symbol *rlbl = newiTempLabel (NULL);
2571   bool restoreBank=FALSE;
2572
2573   D (emitcode (";", "genPcall ");
2574     );
2575
2576
2577   /* if caller saves & we have not saved then */
2578   if (!ic->regsSaved)
2579     saveRegisters (ic);
2580
2581   /* if we are calling a function that is not using
2582      the same register bank then we need to save the
2583      destination registers on the stack */
2584   dtype = operandType (IC_LEFT (ic));
2585   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2586       IFFUNC_ISISR (currFunc->type) &&
2587       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2588     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2589     restoreBank=TRUE;
2590   }
2591
2592   /* push the return address on to the stack */
2593   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2594   emitcode ("push", "acc");
2595   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2596   emitcode ("push", "acc");
2597
2598   if (options.model == MODEL_FLAT24)
2599     {
2600       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2601       emitcode ("push", "acc");
2602     }
2603
2604   /* now push the calling address */
2605   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2606
2607   pushSide (IC_LEFT (ic), FPTRSIZE);
2608
2609   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2610
2611   /* if send set is not empty the assign */
2612   if (_G.sendSet)
2613     {
2614         genSend(reverseSet(_G.sendSet));
2615         _G.sendSet = NULL;
2616     }
2617
2618   emitcode ("ret", "");
2619   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2620
2621
2622   /* if we need assign a result value */
2623   if ((IS_ITEMP (IC_RESULT (ic)) &&
2624        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2625         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2626       IS_TRUE_SYMOP (IC_RESULT (ic)))
2627     {
2628
2629       _G.accInUse++;
2630       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2631       _G.accInUse--;
2632
2633       assignResultValue (IC_RESULT (ic));
2634
2635       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2636     }
2637
2638   /* adjust the stack for parameters if
2639      required */
2640   if (ic->parmBytes)
2641     {
2642       int i;
2643       if (options.stack10bit) {
2644           if (ic->parmBytes <= 10) {
2645               emitcode(";","stack adjustment for parms");
2646               for (i=0; i < ic->parmBytes ; i++) {
2647                   emitcode("pop","acc");
2648               }
2649           } else {            
2650               PROTECT_SP;
2651               emitcode ("clr","c");
2652               emitcode ("mov","a,sp");
2653               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2654               emitcode ("mov","sp,a");
2655               emitcode ("mov","a,esp");
2656               emitcode ("anl","a,#3");
2657               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2658               emitcode ("mov","esp,a");   
2659               UNPROTECT_SP;
2660           }
2661       } else {
2662           if (ic->parmBytes > 3) {
2663               emitcode ("mov", "a,%s", spname);
2664               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2665               emitcode ("mov", "%s,a", spname);
2666           }
2667           else
2668               for (i = 0; i < ic->parmBytes; i++)
2669                   emitcode ("dec", "%s", spname);
2670           
2671       }
2672     }
2673   /* if register bank was saved then unsave them */
2674   if (restoreBank)
2675     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2676   
2677   /* if we hade saved some registers then
2678      unsave them */
2679   if (ic->regsSaved)
2680     unsaveRegisters (ic);
2681
2682 }
2683
2684 /*-----------------------------------------------------------------*/
2685 /* resultRemat - result  is rematerializable                       */
2686 /*-----------------------------------------------------------------*/
2687 static int
2688 resultRemat (iCode * ic)
2689 {
2690   if (SKIP_IC (ic) || ic->op == IFX)
2691     return 0;
2692
2693   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2694     {
2695       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2696       if (sym->remat && !POINTER_SET (ic))
2697         return 1;
2698     }
2699
2700   return 0;
2701 }
2702
2703 #if defined(__BORLANDC__) || defined(_MSC_VER)
2704 #define STRCASECMP stricmp
2705 #else
2706 #define STRCASECMP strcasecmp
2707 #endif
2708
2709 /*-----------------------------------------------------------------*/
2710 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2711 /*-----------------------------------------------------------------*/
2712 static bool
2713 inExcludeList (char *s)
2714 {
2715   int i = 0;
2716
2717   if (options.excludeRegs[i] &&
2718       STRCASECMP (options.excludeRegs[i], "none") == 0)
2719     return FALSE;
2720
2721   for (i = 0; options.excludeRegs[i]; i++)
2722     {
2723       if (options.excludeRegs[i] &&
2724           STRCASECMP (s, options.excludeRegs[i]) == 0)
2725         return TRUE;
2726     }
2727   return FALSE;
2728 }
2729
2730 /*-----------------------------------------------------------------*/
2731 /* genFunction - generated code for function entry                 */
2732 /*-----------------------------------------------------------------*/
2733 static void
2734 genFunction (iCode * ic)
2735 {
2736   symbol *sym;
2737   sym_link *ftype;
2738   bool   switchedPSW = FALSE;
2739
2740   D (emitcode (";", "genFunction "););
2741
2742   _G.nRegsSaved = 0;
2743   /* create the function header */
2744   emitcode (";", "-----------------------------------------");
2745   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2746   emitcode (";", "-----------------------------------------");
2747
2748   emitcode ("", "%s:", sym->rname);
2749   ftype = operandType (IC_LEFT (ic));
2750
2751   if (IFFUNC_ISNAKED(ftype))
2752   {
2753       emitcode(";", "naked function: no prologue.");
2754       return;
2755   }
2756   
2757   if (options.stack_probe) 
2758       emitcode ("lcall","__stack_probe");
2759   /* if critical function then turn interrupts off */
2760   if (IFFUNC_ISCRITICAL (ftype))
2761     emitcode ("clr", "ea");
2762
2763   /* here we need to generate the equates for the
2764      register bank if required */
2765   if (FUNC_REGBANK (ftype) != rbank)
2766     {
2767       int i;
2768
2769       rbank = FUNC_REGBANK (ftype);
2770       for (i = 0; i < ds390_nRegs; i++)
2771         {
2772           if (regs390[i].print) {
2773               if (strcmp (regs390[i].base, "0") == 0)
2774                   emitcode ("", "%s !equ !constbyte",
2775                             regs390[i].dname,
2776                             8 * rbank + regs390[i].offset);
2777               else
2778                   emitcode ("", "%s !equ %s + !constbyte",
2779                             regs390[i].dname,
2780                             regs390[i].base,
2781                             8 * rbank + regs390[i].offset);
2782           }
2783         }
2784     }
2785
2786   /* if this is an interrupt service routine then
2787      save acc, b, dpl, dph  */
2788   if (IFFUNC_ISISR (sym->type))
2789       { /* is ISR */
2790       if (!inExcludeList ("acc"))
2791         emitcode ("push", "acc");
2792       if (!inExcludeList ("b"))
2793         emitcode ("push", "b");
2794       if (!inExcludeList ("dpl"))
2795         emitcode ("push", "dpl");
2796       if (!inExcludeList ("dph"))
2797         emitcode ("push", "dph");
2798       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2799         {
2800           emitcode ("push", "dpx");
2801           /* Make sure we're using standard DPTR */
2802           emitcode ("push", "dps");
2803           emitcode ("mov", "dps,#0");
2804           if (options.stack10bit)
2805             {
2806               /* This ISR could conceivably use DPTR2. Better save it. */
2807               emitcode ("push", "dpl1");
2808               emitcode ("push", "dph1");
2809               emitcode ("push", "dpx1");
2810               emitcode ("push",  DP2_RESULT_REG);
2811             }
2812         }
2813       /* if this isr has no bank i.e. is going to
2814          run with bank 0 , then we need to save more
2815          registers :-) */
2816       if (!FUNC_REGBANK (sym->type))
2817         {
2818             int i;
2819
2820           /* if this function does not call any other
2821              function then we can be economical and
2822              save only those registers that are used */
2823           if (!IFFUNC_HASFCALL(sym->type))
2824             {
2825
2826               /* if any registers used */
2827               if (sym->regsUsed)
2828                 {
2829                   /* save the registers used */
2830                   for (i = 0; i < sym->regsUsed->size; i++)
2831                     {
2832                       if (bitVectBitValue (sym->regsUsed, i) ||
2833                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2834                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2835                     }
2836                 }
2837
2838             }
2839           else
2840             {
2841               /* this function has  a function call cannot
2842                  determines register usage so we will have to push the
2843                  entire bank */
2844               saveRBank (0, ic, FALSE);
2845               if (options.parms_in_bank1) {
2846                   for (i=0; i < 8 ; i++ ) {
2847                       emitcode ("push","%s",rb1regs[i]);
2848                   }
2849               }
2850             }
2851         }
2852         else
2853         {
2854             /* This ISR uses a non-zero bank.
2855              *
2856              * We assume that the bank is available for our
2857              * exclusive use.
2858              *
2859              * However, if this ISR calls a function which uses some
2860              * other bank, we must save that bank entirely.
2861              */
2862             unsigned long banksToSave = 0;
2863             
2864             if (IFFUNC_HASFCALL(sym->type))
2865             {
2866
2867 #define MAX_REGISTER_BANKS 4
2868
2869                 iCode *i;
2870                 int ix;
2871
2872                 for (i = ic; i; i = i->next)
2873                 {
2874                     if (i->op == ENDFUNCTION)
2875                     {
2876                         /* we got to the end OK. */
2877                         break;
2878                     }
2879                     
2880                     if (i->op == CALL)
2881                     {
2882                         sym_link *dtype;
2883                         
2884                         dtype = operandType (IC_LEFT(i));
2885                         if (dtype 
2886                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2887                         {
2888                              /* Mark this bank for saving. */
2889                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2890                              {
2891                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2892                              }
2893                              else
2894                              {
2895                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2896                              }
2897                              
2898                              /* And note that we don't need to do it in 
2899                               * genCall.
2900                               */
2901                              i->bankSaved = 1;
2902                         }
2903                     }
2904                     if (i->op == PCALL)
2905                     {
2906                         /* This is a mess; we have no idea what
2907                          * register bank the called function might
2908                          * use.
2909                          *
2910                          * The only thing I can think of to do is
2911                          * throw a warning and hope.
2912                          */
2913                         werror(W_FUNCPTR_IN_USING_ISR);   
2914                     }
2915                 }
2916
2917                 if (banksToSave && options.useXstack)
2918                 {
2919                     /* Since we aren't passing it an ic, 
2920                      * saveRBank will assume r0 is available to abuse.
2921                      *
2922                      * So switch to our (trashable) bank now, so
2923                      * the caller's R0 isn't trashed.
2924                      */
2925                     emitcode ("push", "psw");
2926                     emitcode ("mov", "psw,#!constbyte", 
2927                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2928                     switchedPSW = TRUE;
2929                 }
2930                 
2931                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2932                 {
2933                      if (banksToSave & (1 << ix))
2934                      {
2935                          saveRBank(ix, NULL, FALSE);
2936                      }
2937                 }
2938             }
2939             // jwk: this needs a closer look
2940             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2941         }
2942     }
2943   else
2944     {
2945       /* if callee-save to be used for this function
2946          then save the registers being used in this function */
2947       if (IFFUNC_CALLEESAVES(sym->type))
2948         {
2949           int i;
2950
2951           /* if any registers used */
2952           if (sym->regsUsed)
2953             {
2954               /* save the registers used */
2955               for (i = 0; i < sym->regsUsed->size; i++)
2956                 {
2957                   if (bitVectBitValue (sym->regsUsed, i) ||
2958                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2959                     {
2960                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2961                       _G.nRegsSaved++;
2962                     }
2963                 }
2964             }
2965         }
2966     }
2967
2968   /* set the register bank to the desired value */
2969   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2970    && !switchedPSW)
2971     {
2972       emitcode ("push", "psw");
2973       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2974     }
2975
2976   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2977        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2978       if (options.stack10bit) {
2979           emitcode ("push","_bpx");
2980           emitcode ("push","_bpx+1");
2981           emitcode ("mov","_bpx,%s",spname);
2982           emitcode ("mov","_bpx+1,esp");
2983           emitcode ("anl","_bpx+1,#3");
2984       } else {
2985           if (options.useXstack) {
2986               emitcode ("mov", "r0,%s", spname);
2987               emitcode ("mov", "a,_bp");
2988               emitcode ("movx", "@r0,a");
2989               emitcode ("inc", "%s", spname);
2990           } else {
2991               /* set up the stack */
2992               emitcode ("push", "_bp"); /* save the callers stack  */
2993           }
2994           emitcode ("mov", "_bp,%s", spname);
2995       }
2996   }
2997
2998   /* adjust the stack for the function */
2999   if (sym->stack) {
3000       int i = sym->stack;
3001       if (options.stack10bit) {
3002           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3003           assert (sym->recvSize <= 4);
3004           if (sym->stack <= 8) {
3005               while (i--) emitcode ("push","acc");
3006           } else {
3007               PROTECT_SP;
3008               emitcode ("mov","a,sp");
3009               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3010               emitcode ("mov","sp,a");
3011               emitcode ("mov","a,esp");
3012               emitcode ("anl","a,#3");
3013               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3014               emitcode ("mov","esp,a");
3015               UNPROTECT_SP;
3016           }
3017       } else {
3018           if (i > 256)
3019               werror (W_STACK_OVERFLOW, sym->name);
3020           
3021           if (i > 3 && sym->recvSize < 4) {
3022               
3023               emitcode ("mov", "a,sp");
3024               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3025               emitcode ("mov", "sp,a");
3026               
3027           } else
3028               while (i--)
3029                   emitcode ("inc", "sp");
3030       }
3031   }
3032
3033   if (sym->xstack)
3034     {
3035
3036       emitcode ("mov", "a,_spx");
3037       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3038       emitcode ("mov", "_spx,a");
3039     }
3040
3041 }
3042
3043 /*-----------------------------------------------------------------*/
3044 /* genEndFunction - generates epilogue for functions               */
3045 /*-----------------------------------------------------------------*/
3046 static void
3047 genEndFunction (iCode * ic)
3048 {
3049   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3050
3051   D (emitcode (";", "genEndFunction "););
3052
3053   if (IFFUNC_ISNAKED(sym->type))
3054   {
3055       emitcode(";", "naked function: no epilogue.");
3056       return;
3057   }
3058
3059   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3060        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3061
3062       if (options.stack10bit) {
3063           PROTECT_SP;     
3064           emitcode ("mov", "sp,_bpx", spname);
3065           emitcode ("mov", "esp,_bpx+1", spname);
3066           UNPROTECT_SP;
3067       } else {
3068           emitcode ("mov", "%s,_bp", spname);
3069       }
3070   }
3071
3072   /* if use external stack but some variables were
3073      added to the local stack then decrement the
3074      local stack */
3075   if (options.useXstack && sym->stack) {
3076       emitcode ("mov", "a,sp");
3077       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3078       emitcode ("mov", "sp,a");
3079   }
3080
3081
3082   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3083        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3084
3085       if (options.useXstack) {
3086           emitcode ("mov", "r0,%s", spname);
3087           emitcode ("movx", "a,@r0");
3088           emitcode ("mov", "_bp,a");
3089           emitcode ("dec", "%s", spname);
3090       } else {
3091           if (options.stack10bit) {
3092               emitcode ("pop", "_bpx+1");
3093               emitcode ("pop", "_bpx");
3094           } else {
3095               emitcode ("pop", "_bp");
3096           }
3097       }
3098   }
3099
3100   /* restore the register bank  */
3101   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3102   {
3103     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3104      || !options.useXstack)
3105     {
3106         /* Special case of ISR using non-zero bank with useXstack
3107          * is handled below.
3108          */
3109         emitcode ("pop", "psw");
3110     }
3111   } 
3112
3113   if (IFFUNC_ISISR (sym->type))
3114       { /* is ISR */  
3115
3116       /* now we need to restore the registers */
3117       /* if this isr has no bank i.e. is going to
3118          run with bank 0 , then we need to save more
3119          registers :-) */
3120       if (!FUNC_REGBANK (sym->type))
3121         {
3122             int i;
3123           /* if this function does not call any other
3124              function then we can be economical and
3125              save only those registers that are used */
3126           if (!IFFUNC_HASFCALL(sym->type))
3127             {
3128
3129               /* if any registers used */
3130               if (sym->regsUsed)
3131                 {
3132                   /* save the registers used */
3133                   for (i = sym->regsUsed->size; i >= 0; i--)
3134                     {
3135                       if (bitVectBitValue (sym->regsUsed, i) ||
3136                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3137                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3138                     }
3139                 }
3140
3141             }
3142           else
3143             {
3144               /* this function has  a function call cannot
3145                  determines register usage so we will have to pop the
3146                  entire bank */
3147               if (options.parms_in_bank1) {
3148                   for (i = 7 ; i >= 0 ; i-- ) {
3149                       emitcode ("pop","%s",rb1regs[i]);
3150                   }
3151               }
3152               unsaveRBank (0, ic, FALSE);
3153             }
3154         }
3155         else
3156         {
3157             /* This ISR uses a non-zero bank.
3158              *
3159              * Restore any register banks saved by genFunction
3160              * in reverse order.
3161              */
3162           // jwk: this needs a closer look
3163             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3164             int ix;
3165           
3166             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3167             {
3168                 if (savedBanks & (1 << ix))
3169                 {
3170                     unsaveRBank(ix, NULL, FALSE);
3171                 }
3172             }
3173             
3174             if (options.useXstack)
3175             {
3176                 /* Restore bank AFTER calling unsaveRBank,
3177                  * since it can trash r0.
3178                  */
3179                 emitcode ("pop", "psw");
3180             }
3181         }
3182
3183       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3184         {
3185           if (options.stack10bit)
3186             {
3187               emitcode ("pop", DP2_RESULT_REG);
3188               emitcode ("pop", "dpx1");
3189               emitcode ("pop", "dph1");
3190               emitcode ("pop", "dpl1");
3191             }
3192           emitcode ("pop", "dps");
3193           emitcode ("pop", "dpx");
3194         }
3195       if (!inExcludeList ("dph"))
3196         emitcode ("pop", "dph");
3197       if (!inExcludeList ("dpl"))
3198         emitcode ("pop", "dpl");
3199       if (!inExcludeList ("b"))
3200         emitcode ("pop", "b");
3201       if (!inExcludeList ("acc"))
3202         emitcode ("pop", "acc");
3203
3204       if (IFFUNC_ISCRITICAL (sym->type))
3205         emitcode ("setb", "ea");
3206
3207       /* if debug then send end of function */
3208       if (options.debug && currFunc) {
3209           _G.debugLine = 1;
3210           emitcode ("", "C$%s$%d$%d$%d ==.",
3211                     FileBaseName (ic->filename), currFunc->lastLine,
3212                     ic->level, ic->block);
3213           if (IS_STATIC (currFunc->etype))
3214             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3215           else
3216             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3217           _G.debugLine = 0;
3218         }
3219
3220       emitcode ("reti", "");
3221     }
3222   else
3223     {
3224       if (IFFUNC_ISCRITICAL (sym->type))
3225         emitcode ("setb", "ea");
3226
3227       if (IFFUNC_CALLEESAVES(sym->type))
3228         {
3229           int i;
3230
3231           /* if any registers used */
3232           if (sym->regsUsed)
3233             {
3234               /* save the registers used */
3235               for (i = sym->regsUsed->size; i >= 0; i--)
3236                 {
3237                   if (bitVectBitValue (sym->regsUsed, i) ||
3238                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3239                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3240                 }
3241             }
3242
3243         }
3244
3245       /* if debug then send end of function */
3246       if (options.debug && currFunc)
3247         {
3248           _G.debugLine = 1;
3249           emitcode ("", "C$%s$%d$%d$%d ==.",
3250                     FileBaseName (ic->filename), currFunc->lastLine,
3251                     ic->level, ic->block);
3252           if (IS_STATIC (currFunc->etype))
3253             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3254           else
3255             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3256           _G.debugLine = 0;
3257         }
3258
3259       emitcode ("ret", "");
3260     }
3261
3262 }
3263
3264 /*-----------------------------------------------------------------*/
3265 /* genJavaNativeRet - generate code for return JavaNative          */
3266 /*-----------------------------------------------------------------*/
3267 static void genJavaNativeRet(iCode *ic)
3268 {
3269     int i, size;
3270
3271     aopOp (IC_LEFT (ic), ic, FALSE, 
3272            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3273     size = AOP_SIZE (IC_LEFT (ic));
3274
3275     assert (size <= 4);
3276
3277     /* it is assigned to GPR0-R3 then push them */
3278     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3279         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3280         for (i = 0 ; i < size ; i++ ) {
3281             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3282         }
3283         for (i = (size-1) ; i >= 0 ; i--) {
3284             emitcode ("pop","a%s",javaRet[i]);
3285         }
3286     } else {
3287         for (i = 0 ; i < size ; i++) 
3288             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3289     }
3290     for (i = size ; i < 4 ; i++ )
3291             emitcode ("mov","%s,#0",javaRet[i]);
3292     return;
3293 }
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genRet - generate code for return statement                     */
3297 /*-----------------------------------------------------------------*/
3298 static void
3299 genRet (iCode * ic)
3300 {
3301   int size, offset = 0, pushed = 0;
3302
3303   D (emitcode (";", "genRet ");
3304     );
3305
3306   /* if we have no return value then
3307      just generate the "ret" */
3308   if (!IC_LEFT (ic))
3309     goto jumpret;
3310
3311   /* if this is a JavaNative function then return 
3312      value in different register */
3313   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3314       genJavaNativeRet(ic);
3315       goto jumpret;
3316   }
3317   /* we have something to return then
3318      move the return value into place */
3319   aopOp (IC_LEFT (ic), ic, FALSE, 
3320          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3321   size = AOP_SIZE (IC_LEFT (ic));
3322
3323   _startLazyDPSEvaluation ();
3324   while (size--)
3325     {
3326       char *l;
3327       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3328         {
3329           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3330                       FALSE, TRUE, FALSE);
3331           emitcode ("push", "%s", l);
3332           pushed++;
3333         }
3334       else
3335         {
3336           /* Since A is the last element of fReturn,
3337            * is is OK to clobber it in the aopGet.
3338            */
3339           l = aopGet (AOP (IC_LEFT (ic)), offset,
3340                       FALSE, FALSE, TRUE);
3341           if (strcmp (fReturn[offset], l))
3342             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3343         }
3344     }
3345   _endLazyDPSEvaluation ();
3346
3347   if (pushed)
3348     {
3349       while (pushed)
3350         {
3351           pushed--;
3352           if (strcmp (fReturn[pushed], "a"))
3353             emitcode ("pop", fReturn[pushed]);
3354           else
3355             emitcode ("pop", "acc");
3356         }
3357     }
3358   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3359
3360 jumpret:
3361   /* generate a jump to the return label
3362      if the next is not the return statement */
3363   if (!(ic->next && ic->next->op == LABEL &&
3364         IC_LABEL (ic->next) == returnLabel))
3365
3366     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3367
3368 }
3369
3370 /*-----------------------------------------------------------------*/
3371 /* genLabel - generates a label                                    */
3372 /*-----------------------------------------------------------------*/
3373 static void
3374 genLabel (iCode * ic)
3375 {
3376   /* special case never generate */
3377   if (IC_LABEL (ic) == entryLabel)
3378     return;
3379
3380   D (emitcode (";", "genLabel ");
3381     );
3382
3383   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3384 }
3385
3386 /*-----------------------------------------------------------------*/
3387 /* genGoto - generates a ljmp                                      */
3388 /*-----------------------------------------------------------------*/
3389 static void
3390 genGoto (iCode * ic)
3391 {
3392   D (emitcode (";", "genGoto ");
3393     );
3394   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3395 }
3396
3397 /*-----------------------------------------------------------------*/
3398 /* findLabelBackwards: walks back through the iCode chain looking  */
3399 /* for the given label. Returns number of iCode instructions     */
3400 /* between that label and given ic.          */
3401 /* Returns zero if label not found.          */
3402 /*-----------------------------------------------------------------*/
3403 static int
3404 findLabelBackwards (iCode * ic, int key)
3405 {
3406   int count = 0;
3407
3408   while (ic->prev)
3409     {
3410       ic = ic->prev;
3411       count++;
3412
3413       /* If we have any pushes or pops, we cannot predict the distance.
3414          I don't like this at all, this should be dealt with in the 
3415          back-end */
3416       if (ic->op == IPUSH || ic->op == IPOP) {
3417         return 0;
3418       }
3419
3420       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3421         {
3422           /* printf("findLabelBackwards = %d\n", count); */
3423           return count;
3424         }
3425     }
3426
3427   return 0;
3428 }
3429
3430 /*-----------------------------------------------------------------*/
3431 /* genPlusIncr :- does addition with increment if possible         */
3432 /*-----------------------------------------------------------------*/
3433 static bool
3434 genPlusIncr (iCode * ic)
3435 {
3436   unsigned int icount;
3437   unsigned int size = getDataSize (IC_RESULT (ic));
3438
3439   /* will try to generate an increment */
3440   /* if the right side is not a literal
3441      we cannot */
3442   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3443     return FALSE;
3444
3445   /* if the literal value of the right hand side
3446      is greater than 4 then it is not worth it */
3447   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3448     return FALSE;
3449
3450   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3451       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3452       while (icount--) {
3453           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3454       }
3455       return TRUE;
3456   }
3457   /* if increment 16 bits in register */
3458   if (
3459        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3460        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3461        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3462        (size > 1) &&
3463        (icount == 1))
3464     {
3465       symbol *tlbl;
3466       int emitTlbl;
3467       int labelRange;
3468
3469       /* If the next instruction is a goto and the goto target
3470        * is <= 5 instructions previous to this, we can generate
3471        * jumps straight to that target.
3472        */
3473       if (ic->next && ic->next->op == GOTO
3474           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3475           && labelRange <= 5)
3476         {
3477           emitcode (";", "tail increment optimized (range %d)", labelRange);
3478           tlbl = IC_LABEL (ic->next);
3479           emitTlbl = 0;
3480         }
3481       else
3482         {
3483           tlbl = newiTempLabel (NULL);
3484           emitTlbl = 1;
3485         }
3486       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3487       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3488           IS_AOP_PREG (IC_RESULT (ic)))
3489         emitcode ("cjne", "%s,#0,!tlabel"
3490                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3491                   ,tlbl->key + 100);
3492       else
3493         {
3494           emitcode ("clr", "a");
3495           emitcode ("cjne", "a,%s,!tlabel"
3496                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3497                     ,tlbl->key + 100);
3498         }
3499
3500       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3501       if (size > 2)
3502         {
3503           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3504               IS_AOP_PREG (IC_RESULT (ic)))
3505             emitcode ("cjne", "%s,#0,!tlabel"
3506                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3507                       ,tlbl->key + 100);
3508           else
3509             emitcode ("cjne", "a,%s,!tlabel"
3510                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3511                       ,tlbl->key + 100);
3512
3513           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3514         }
3515       if (size > 3)
3516         {
3517           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3518               IS_AOP_PREG (IC_RESULT (ic)))
3519             emitcode ("cjne", "%s,#0,!tlabel"
3520                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3521                       ,tlbl->key + 100);
3522           else
3523             {
3524               emitcode ("cjne", "a,%s,!tlabel"
3525                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3526                         ,tlbl->key + 100);
3527             }
3528           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3529         }
3530
3531       if (emitTlbl)
3532         {
3533           emitcode ("", "!tlabeldef", tlbl->key + 100);
3534         }
3535       return TRUE;
3536     }
3537
3538   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3539       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3540       options.model == MODEL_FLAT24 ) {
3541
3542       switch (size) {
3543       case 3:
3544           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3545       case 2:
3546           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3547       case 1:
3548           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3549           break;
3550       }
3551       while (icount--) emitcode ("inc","dptr");      
3552       return TRUE;
3553   }
3554
3555   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3556       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3557       icount <= 5 ) {
3558       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3559       while (icount--) emitcode ("inc","dptr");
3560       emitcode ("mov","dps,#0");
3561       return TRUE;
3562   }
3563
3564   /* if the sizes are greater than 1 then we cannot */
3565   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3566       AOP_SIZE (IC_LEFT (ic)) > 1)
3567     return FALSE;
3568
3569   /* we can if the aops of the left & result match or
3570      if they are in registers and the registers are the
3571      same */
3572   if (
3573        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3574        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3575        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3576     {
3577
3578       if (icount > 3)
3579         {
3580           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3581           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3582           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3583         }
3584       else
3585         {
3586
3587           _startLazyDPSEvaluation ();
3588           while (icount--)
3589             {
3590               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3591             }
3592           _endLazyDPSEvaluation ();
3593         }
3594
3595       return TRUE;
3596     }
3597
3598   return FALSE;
3599 }
3600
3601 /*-----------------------------------------------------------------*/
3602 /* outBitAcc - output a bit in acc                                 */
3603 /*-----------------------------------------------------------------*/
3604 static void
3605 outBitAcc (operand * result)
3606 {
3607   symbol *tlbl = newiTempLabel (NULL);
3608   /* if the result is a bit */
3609   if (AOP_TYPE (result) == AOP_CRY)
3610     {
3611       aopPut (AOP (result), "a", 0);
3612     }
3613   else
3614     {
3615       emitcode ("jz", "!tlabel", tlbl->key + 100);
3616       emitcode ("mov", "a,%s", one);
3617       emitcode ("", "!tlabeldef", tlbl->key + 100);
3618       outAcc (result);
3619     }
3620 }
3621
3622 /*-----------------------------------------------------------------*/
3623 /* genPlusBits - generates code for addition of two bits           */
3624 /*-----------------------------------------------------------------*/
3625 static void
3626 genPlusBits (iCode * ic)
3627 {
3628   D (emitcode (";", "genPlusBits ");
3629     );
3630   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3631     {
3632       symbol *lbl = newiTempLabel (NULL);
3633       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3634       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3635       emitcode ("cpl", "c");
3636       emitcode ("", "!tlabeldef", (lbl->key + 100));
3637       outBitC (IC_RESULT (ic));
3638     }
3639   else
3640     {
3641       emitcode ("clr", "a");
3642       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3643       emitcode ("rlc", "a");
3644       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3645       emitcode ("addc", "a,#0");
3646       outAcc (IC_RESULT (ic));
3647     }
3648 }
3649
3650 static void
3651 adjustArithmeticResult (iCode * ic)
3652 {
3653   if (opIsGptr (IC_RESULT (ic)) &&
3654       opIsGptr (IC_LEFT (ic)) &&
3655       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3656     {
3657       aopPut (AOP (IC_RESULT (ic)),
3658               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3659               GPTRSIZE - 1);
3660     }
3661
3662   if (opIsGptr (IC_RESULT (ic)) &&
3663       opIsGptr (IC_RIGHT (ic)) &&
3664       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3665     {
3666       aopPut (AOP (IC_RESULT (ic)),
3667             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3668               GPTRSIZE - 1);
3669     }
3670
3671   if (opIsGptr (IC_RESULT (ic)) &&
3672       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3673       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3674       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3675       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3676     {
3677       char buffer[5];
3678       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3679       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3680     }
3681 }
3682
3683 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3684 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3685 // will be set TRUE. The caller must then handle the case specially, noting
3686 // that the IC_RESULT operand is not aopOp'd.
3687 #define AOP_OP_3_NOFATAL(ic, rc) \
3688     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3689     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3690                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3691     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3692         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3693     { \
3694        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3695        rc = TRUE; \
3696     }  \
3697     else \
3698     { \
3699        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3700                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3701        rc = FALSE; \
3702        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3703            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3704        { \
3705             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3706             fprintf(stderr,                                  \
3707                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3708        } \
3709     }
3710
3711 // aopOp the left & right operands of an ic.
3712 #define AOP_OP_2(ic) \
3713     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3714     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3715
3716 // convienience macro.
3717 #define AOP_SET_LOCALS(ic) \
3718     left = IC_LEFT(ic); \
3719     right = IC_RIGHT(ic); \
3720     result = IC_RESULT(ic);
3721
3722
3723 // Given an integer value of pushedSize bytes on the stack,
3724 // adjust it to be resultSize bytes, either by discarding
3725 // the most significant bytes or by zero-padding.
3726 //
3727 // On exit from this macro, pushedSize will have been adjusted to
3728 // equal resultSize, and ACC may be trashed.
3729 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3730       /* If the pushed data is bigger than the result,          \
3731        * simply discard unused bytes. Icky, but works.          \
3732        */                                                       \
3733       while (pushedSize > resultSize)                           \
3734       {                                                         \
3735           D (emitcode (";", "discarding unused result byte."););\
3736           emitcode ("pop", "acc");                              \
3737           pushedSize--;                                         \
3738       }                                                         \
3739       if (pushedSize < resultSize)                              \
3740       {                                                         \
3741           emitcode ("clr", "a");                                \
3742           /* Conversly, we haven't pushed enough here.          \
3743            * just zero-pad, and all is well.                    \
3744            */                                                   \
3745           while (pushedSize < resultSize)                       \
3746           {                                                     \
3747               emitcode("push", "acc");                          \
3748               pushedSize++;                                     \
3749           }                                                     \
3750       }                                                         \
3751       assert(pushedSize == resultSize);
3752
3753 /*-----------------------------------------------------------------*/
3754 /* genPlus - generates code for addition                           */
3755 /*-----------------------------------------------------------------*/
3756 static void
3757 genPlus (iCode * ic)
3758 {
3759   int size, offset = 0;
3760   bool pushResult = FALSE;
3761   int rSize;
3762
3763   D (emitcode (";", "genPlus "););
3764
3765   /* special cases :- */
3766   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3767       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3768       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3769       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3770       if (size <= 9) {
3771           while (size--) emitcode ("inc","dptr");
3772       } else {
3773           emitcode ("mov","a,dpl");
3774           emitcode ("add","a,#!constbyte",size & 0xff);
3775           emitcode ("mov","dpl,a");
3776           emitcode ("mov","a,dph");
3777           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3778           emitcode ("mov","dph,a");
3779           emitcode ("mov","a,dpx");
3780           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3781           emitcode ("mov","dpx,a");
3782       }
3783       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3784       return ;
3785   }
3786   if ( IS_SYMOP(IC_LEFT(ic)) && 
3787        OP_SYMBOL(IC_LEFT(ic))->remat &&
3788        isOperandInFarSpace(IC_RIGHT(ic))) {
3789       operand *op = IC_RIGHT(ic);
3790       IC_RIGHT(ic) = IC_LEFT(ic);
3791       IC_LEFT(ic) = op;
3792   }
3793                 
3794   AOP_OP_3_NOFATAL (ic, pushResult);
3795   if (pushResult)
3796     {
3797       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3798     }
3799
3800   if (!pushResult)
3801     {
3802       /* if literal, literal on the right or
3803          if left requires ACC or right is already
3804          in ACC */
3805       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3806        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3807           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3808         {
3809           operand *t = IC_RIGHT (ic);
3810           IC_RIGHT (ic) = IC_LEFT (ic);
3811           IC_LEFT (ic) = t;
3812           emitcode (";", "Swapped plus args.");
3813         }
3814
3815       /* if both left & right are in bit
3816          space */
3817       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3818           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3819         {
3820           genPlusBits (ic);
3821           goto release;
3822         }
3823
3824       /* if left in bit space & right literal */
3825       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3826           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3827         {
3828           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3829           /* if result in bit space */
3830           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3831             {
3832               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3833                 emitcode ("cpl", "c");
3834               outBitC (IC_RESULT (ic));
3835             }
3836           else
3837             {
3838               size = getDataSize (IC_RESULT (ic));
3839               _startLazyDPSEvaluation ();
3840               while (size--)
3841                 {
3842                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3843                   emitcode ("addc", "a,#0");
3844                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3845                 }
3846               _endLazyDPSEvaluation ();
3847             }
3848           goto release;
3849         }
3850
3851       /* if I can do an increment instead
3852          of add then GOOD for ME */
3853       if (genPlusIncr (ic) == TRUE)
3854         {
3855           emitcode (";", "did genPlusIncr");
3856           goto release;
3857         }
3858
3859     }
3860   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3861
3862   _startLazyDPSEvaluation ();
3863   while (size--)
3864     {
3865       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3866         {
3867           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3868           if (offset == 0)
3869             emitcode ("add", "a,%s",
3870                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3871           else
3872             emitcode ("addc", "a,%s",
3873                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3874         }
3875       else
3876         {
3877           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3878           {
3879               /* right is going to use ACC or we would have taken the
3880                * above branch.
3881                */
3882               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3883        TR_AP("#3");
3884               D(emitcode(";", "+ AOP_ACC special case."););
3885               emitcode("xch", "a, %s", DP2_RESULT_REG);
3886           }
3887           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3888           if (offset == 0)
3889           {
3890             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3891             {
3892          TR_AP("#4");
3893                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3894             }
3895             else
3896             {
3897                 emitcode ("add", "a,%s",
3898                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3899             }
3900           }
3901           else
3902           {
3903             emitcode ("addc", "a,%s",
3904                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3905           }
3906         }
3907       if (!pushResult)
3908         {
3909           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3910         }
3911       else
3912         {
3913           emitcode ("push", "acc");
3914         }
3915       offset++;
3916     }
3917   _endLazyDPSEvaluation ();
3918
3919   if (pushResult)
3920     {
3921       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3922
3923       size = getDataSize (IC_LEFT (ic));
3924       rSize = getDataSize (IC_RESULT (ic));
3925
3926       ADJUST_PUSHED_RESULT(size, rSize);
3927
3928       _startLazyDPSEvaluation ();
3929       while (size--)
3930         {
3931           emitcode ("pop", "acc");
3932           aopPut (AOP (IC_RESULT (ic)), "a", size);
3933         }
3934       _endLazyDPSEvaluation ();
3935     }
3936
3937   adjustArithmeticResult (ic);
3938
3939 release:
3940   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3943 }
3944
3945 /*-----------------------------------------------------------------*/
3946 /* genMinusDec :- does subtraction with deccrement if possible     */
3947 /*-----------------------------------------------------------------*/
3948 static bool
3949 genMinusDec (iCode * ic)
3950 {
3951   unsigned int icount;
3952   unsigned int size = getDataSize (IC_RESULT (ic));
3953
3954   /* will try to generate an increment */
3955   /* if the right side is not a literal
3956      we cannot */
3957   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3958     return FALSE;
3959
3960   /* if the literal value of the right hand side
3961      is greater than 4 then it is not worth it */
3962   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3963     return FALSE;
3964
3965   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3966       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3967       while (icount--) {
3968           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3969       }
3970       return TRUE;
3971   }
3972   /* if decrement 16 bits in register */
3973   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3974       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3975       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3976       (size > 1) &&
3977       (icount == 1))
3978     {
3979       symbol *tlbl;
3980       int emitTlbl;
3981       int labelRange;
3982
3983       /* If the next instruction is a goto and the goto target
3984          * is <= 5 instructions previous to this, we can generate
3985          * jumps straight to that target.
3986        */
3987       if (ic->next && ic->next->op == GOTO
3988           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3989           && labelRange <= 5)
3990         {
3991           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3992           tlbl = IC_LABEL (ic->next);
3993           emitTlbl = 0;
3994         }
3995       else
3996         {
3997           tlbl = newiTempLabel (NULL);
3998           emitTlbl = 1;
3999         }
4000
4001       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4002       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4003           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4004           IS_AOP_PREG (IC_RESULT (ic)))
4005         emitcode ("cjne", "%s,#!constbyte,!tlabel"
4006                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4007                   ,tlbl->key + 100);
4008       else
4009         {
4010           emitcode ("mov", "a,#!constbyte",0xff);
4011           emitcode ("cjne", "a,%s,!tlabel"
4012                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4013                     ,tlbl->key + 100);
4014         }
4015       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4016       if (size > 2)
4017         {
4018           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4019               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4020               IS_AOP_PREG (IC_RESULT (ic)))
4021             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4022                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4023                       ,tlbl->key + 100);
4024           else
4025             {
4026               emitcode ("cjne", "a,%s,!tlabel"
4027                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4028                         ,tlbl->key + 100);
4029             }
4030           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4031         }
4032       if (size > 3)
4033         {
4034           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4035               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4036               IS_AOP_PREG (IC_RESULT (ic)))
4037             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4038                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4039                       ,tlbl->key + 100);
4040           else
4041             {
4042               emitcode ("cjne", "a,%s,!tlabel"
4043                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4044                         ,tlbl->key + 100);
4045             }
4046           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4047         }
4048       if (emitTlbl)
4049         {
4050           emitcode ("", "!tlabeldef", tlbl->key + 100);
4051         }
4052       return TRUE;
4053     }
4054
4055   /* if the sizes are greater than 1 then we cannot */
4056   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4057       AOP_SIZE (IC_LEFT (ic)) > 1)
4058     return FALSE;
4059
4060   /* we can if the aops of the left & result match or
4061      if they are in registers and the registers are the
4062      same */
4063   if (
4064        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4065        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4066        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4067     {
4068
4069       _startLazyDPSEvaluation ();
4070       while (icount--)
4071         {
4072           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4073         }
4074       _endLazyDPSEvaluation ();
4075
4076       return TRUE;
4077     }
4078
4079   return FALSE;
4080 }
4081
4082 /*-----------------------------------------------------------------*/
4083 /* addSign - complete with sign                                    */
4084 /*-----------------------------------------------------------------*/
4085 static void
4086 addSign (operand * result, int offset, int sign)
4087 {
4088   int size = (getDataSize (result) - offset);
4089   if (size > 0)
4090     {
4091       _startLazyDPSEvaluation();
4092       if (sign)
4093         {
4094           emitcode ("rlc", "a");
4095           emitcode ("subb", "a,acc");
4096           while (size--)
4097           {
4098             aopPut (AOP (result), "a", offset++);
4099           }
4100         }
4101       else
4102       {
4103         while (size--)
4104         {
4105           aopPut (AOP (result), zero, offset++);
4106         }
4107       }
4108       _endLazyDPSEvaluation();
4109     }
4110 }
4111
4112 /*-----------------------------------------------------------------*/
4113 /* genMinusBits - generates code for subtraction  of two bits      */
4114 /*-----------------------------------------------------------------*/
4115 static void
4116 genMinusBits (iCode * ic)
4117 {
4118   symbol *lbl = newiTempLabel (NULL);
4119
4120   D (emitcode (";", "genMinusBits "););
4121
4122   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4123     {
4124       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4125       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4126       emitcode ("cpl", "c");
4127       emitcode ("", "!tlabeldef", (lbl->key + 100));
4128       outBitC (IC_RESULT (ic));
4129     }
4130   else
4131     {
4132       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4133       emitcode ("subb", "a,acc");
4134       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4135       emitcode ("inc", "a");
4136       emitcode ("", "!tlabeldef", (lbl->key + 100));
4137       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4138       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4139     }
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /* genMinus - generates code for subtraction                       */
4144 /*-----------------------------------------------------------------*/
4145 static void
4146 genMinus (iCode * ic)
4147 {
4148   int size, offset = 0;
4149   int rSize;
4150   unsigned long lit = 0L;
4151   bool pushResult = FALSE;
4152
4153   D (emitcode (";", "genMinus "););
4154
4155   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4156   aopOp (IC_RIGHT (ic), ic, FALSE, 
4157          (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4158   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4159       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4160     {
4161       pushResult = TRUE;
4162     }
4163   else
4164     {
4165       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4166
4167       /* special cases :- */
4168       /* if both left & right are in bit space */
4169       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4170           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4171         {
4172           genMinusBits (ic);
4173           goto release;
4174         }
4175
4176       /* if I can do an decrement instead
4177          of subtract then GOOD for ME */
4178       if (genMinusDec (ic) == TRUE)
4179         goto release;
4180
4181     }
4182
4183   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4184
4185   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4186     {
4187       CLRC;
4188     }
4189   else
4190     {
4191       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4192       lit = -(long) lit;
4193     }
4194
4195
4196   /* if literal, add a,#-lit, else normal subb */
4197   _startLazyDPSEvaluation ();
4198   while (size--) {
4199       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4200       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4201           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4202               emitcode ("mov","b,a");
4203               MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4204               emitcode ("xch","a,b");
4205               emitcode ("subb","a,b");
4206           } else {
4207               emitcode ("subb", "a,%s",
4208                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4209           }
4210       } else {
4211           /* first add without previous c */
4212           if (!offset) {
4213               if (!size && lit==-1) {
4214                   emitcode ("dec", "a");
4215               } else {
4216                   emitcode ("add", "a,#!constbyte",
4217                             (unsigned int) (lit & 0x0FFL));
4218               }
4219           } else {
4220               emitcode ("addc", "a,#!constbyte",
4221                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4222           }
4223       }
4224       
4225       if (pushResult) {
4226           emitcode ("push", "acc");
4227       } else {
4228           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4229       }
4230       offset++;
4231   }
4232   _endLazyDPSEvaluation ();
4233   
4234   if (pushResult)
4235     {
4236       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4237
4238       size = getDataSize (IC_LEFT (ic));
4239       rSize = getDataSize (IC_RESULT (ic));
4240
4241       ADJUST_PUSHED_RESULT(size, rSize);
4242
4243       _startLazyDPSEvaluation ();
4244       while (size--)
4245         {
4246           emitcode ("pop", "acc");
4247           aopPut (AOP (IC_RESULT (ic)), "a", size);
4248         }
4249       _endLazyDPSEvaluation ();
4250     }
4251
4252   adjustArithmeticResult (ic);
4253
4254 release:
4255   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4256   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4258 }
4259
4260
4261 /*-----------------------------------------------------------------*/
4262 /* genMultbits :- multiplication of bits                           */
4263 /*-----------------------------------------------------------------*/
4264 static void
4265 genMultbits (operand * left,
4266              operand * right,
4267              operand * result,
4268              iCode   * ic)
4269 {
4270   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4271   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4272   aopOp(result, ic, TRUE, FALSE);
4273   outBitC (result);
4274 }
4275
4276
4277 /*-----------------------------------------------------------------*/
4278 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4279 /*-----------------------------------------------------------------*/
4280 static void
4281 genMultOneByte (operand * left,
4282                 operand * right,
4283                 operand * result,
4284                 iCode   * ic)
4285 {
4286   sym_link *opetype = operandType (result);
4287   symbol *lbl;
4288
4289
4290   /* (if two literals: the value is computed before) */
4291   /* if one literal, literal on the right */
4292   if (AOP_TYPE (left) == AOP_LIT)
4293     {
4294       operand *t = right;
4295       right = left;
4296       left = t;
4297       emitcode (";", "swapped left and right");
4298     }
4299
4300   if (SPEC_USIGN(opetype)
4301       // ignore the sign of left and right, what else can we do?
4302       || (SPEC_USIGN(operandType(left)) && 
4303           SPEC_USIGN(operandType(right)))) {
4304     // just an unsigned 8*8=8/16 multiply
4305     //emitcode (";","unsigned");
4306     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4307     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4308     emitcode ("mul", "ab");
4309    
4310     _G.accInUse++; _G.bInUse++;
4311     aopOp(result, ic, TRUE, FALSE);
4312       
4313       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4314       {
4315           // this should never happen
4316           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4317                    AOP_SIZE(result), __FILE__, lineno);
4318           exit (1);
4319       }      
4320       
4321     aopPut (AOP (result), "a", 0);
4322     _G.accInUse--; _G.bInUse--;
4323     if (AOP_SIZE(result)==2) 
4324     {
4325       aopPut (AOP (result), "b", 1);
4326     }
4327     return;
4328   }
4329
4330   // we have to do a signed multiply
4331
4332   emitcode (";", "signed");
4333   emitcode ("clr", "F0"); // reset sign flag
4334   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4335
4336   lbl=newiTempLabel(NULL);
4337   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4338   // left side is negative, 8-bit two's complement, this fails for -128
4339   emitcode ("setb", "F0"); // set sign flag
4340   emitcode ("cpl", "a");
4341   emitcode ("inc", "a");
4342
4343   emitcode ("", "!tlabeldef", lbl->key+100);
4344
4345   /* if literal */
4346   if (AOP_TYPE(right)==AOP_LIT) {
4347     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4348     /* AND literal negative */
4349     if ((int) val < 0) {
4350       emitcode ("cpl", "F0"); // complement sign flag
4351       emitcode ("mov", "b,#!constbyte", -val);
4352     } else {
4353       emitcode ("mov", "b,#!constbyte", val);
4354     }
4355   } else {
4356     lbl=newiTempLabel(NULL);
4357     emitcode ("mov", "b,a");
4358     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4359     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4360     // right side is negative, 8-bit two's complement
4361     emitcode ("cpl", "F0"); // complement sign flag
4362     emitcode ("cpl", "a");
4363     emitcode ("inc", "a");
4364     emitcode ("", "!tlabeldef", lbl->key+100);
4365   }
4366   emitcode ("mul", "ab");
4367     
4368   _G.accInUse++;_G.bInUse++;
4369   aopOp(result, ic, TRUE, FALSE);
4370     
4371   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4372   {
4373     // this should never happen
4374       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4375                AOP_SIZE(result), __FILE__, lineno);
4376       exit (1);
4377   }    
4378     
4379   lbl=newiTempLabel(NULL);
4380   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4381   // only ONE op was negative, we have to do a 8/16-bit two's complement
4382   emitcode ("cpl", "a"); // lsb
4383   if (AOP_SIZE(result)==1) {
4384     emitcode ("inc", "a");
4385   } else {
4386     emitcode ("add", "a,#1");
4387     emitcode ("xch", "a,b");
4388     emitcode ("cpl", "a"); // msb
4389     emitcode ("addc", "a,#0");
4390     emitcode ("xch", "a,b");
4391   }
4392
4393   emitcode ("", "!tlabeldef", lbl->key+100);
4394   aopPut (AOP (result), "a", 0);
4395   _G.accInUse--;_G.bInUse--;
4396   if (AOP_SIZE(result)==2) {
4397     aopPut (AOP (result), "b", 1);
4398   }
4399 }
4400
4401 /*-----------------------------------------------------------------*/
4402 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4403 /*-----------------------------------------------------------------*/
4404 static void genMultTwoByte (operand *left, operand *right, 
4405                             operand *result, iCode *ic)
4406 {
4407         sym_link *retype = getSpec(operandType(right));
4408         sym_link *letype = getSpec(operandType(left));
4409         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4410         symbol *lbl;
4411
4412         if (AOP_TYPE (left) == AOP_LIT) {
4413                 operand *t = right;
4414                 right = left;
4415                 left = t;
4416         }
4417         /* save EA bit in F1 */
4418         lbl = newiTempLabel(NULL);
4419         emitcode ("setb","F1");
4420         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4421         emitcode ("clr","F1");
4422         emitcode("","!tlabeldef",lbl->key+100);
4423
4424         /* load up MB with right */
4425         if (!umult) {
4426                 emitcode("clr","F0");
4427                 if (AOP_TYPE(right) == AOP_LIT) {
4428                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4429                         if (val < 0) {
4430                                 emitcode("setb","F0");
4431                                 val = -val;
4432                         }
4433                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4434                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4435                 } else {
4436                         lbl = newiTempLabel(NULL);
4437                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4438                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4439                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4440                         emitcode ("xch", "a,b");
4441                         emitcode ("cpl","a");
4442                         emitcode ("add", "a,#1");
4443                         emitcode ("xch", "a,b");
4444                         emitcode ("cpl", "a"); // msb
4445                         emitcode ("addc", "a,#0");
4446                         emitcode ("setb","F0");
4447                         emitcode ("","!tlabeldef",lbl->key+100);
4448                         emitcode ("mov","mb,b");
4449                         emitcode ("mov","mb,a");
4450                 }
4451         } else {
4452                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4453                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4454         }
4455         /* load up MA with left */
4456         if (!umult) {
4457                 lbl = newiTempLabel(NULL);
4458                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4459                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4460                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4461                 emitcode ("xch", "a,b");
4462                 emitcode ("cpl","a");
4463                 emitcode ("add", "a,#1");
4464                 emitcode ("xch", "a,b");
4465                 emitcode ("cpl", "a"); // msb
4466                 emitcode ("addc","a,#0");
4467                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4468                 emitcode ("setb","F0");
4469                 emitcode ("","!tlabeldef",lbl->key+100);
4470                 emitcode ("mov","ma,b");
4471                 emitcode ("mov","ma,a");
4472         } else {
4473                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4474                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4475         }
4476         /* wait for multiplication to finish */
4477         lbl = newiTempLabel(NULL);
4478         emitcode("","!tlabeldef", lbl->key+100);
4479         emitcode("mov","a,mcnt1");
4480         emitcode("anl","a,#!constbyte",0x80);
4481         emitcode("jnz","!tlabel",lbl->key+100);
4482         
4483         freeAsmop (left, NULL, ic, TRUE);
4484         freeAsmop (right, NULL, ic,TRUE);
4485         aopOp(result, ic, TRUE, FALSE);
4486
4487         /* if unsigned then simple */   
4488         if (umult) {
4489                 emitcode ("mov","a,ma");
4490                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4491                 emitcode ("mov","a,ma");
4492                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4493                 aopPut(AOP(result),"ma",1);
4494                 aopPut(AOP(result),"ma",0);
4495         } else {
4496                 emitcode("push","ma");
4497                 emitcode("push","ma");
4498                 emitcode("push","ma");
4499                 MOVA("ma");
4500                 /* negate result if needed */
4501                 lbl = newiTempLabel(NULL);      
4502                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4503                 emitcode("cpl","a");
4504                 emitcode("add","a,#1");
4505                 emitcode("","!tlabeldef", lbl->key+100);
4506                 if (AOP_TYPE(result) == AOP_ACC)
4507                 {
4508                     D(emitcode(";", "ACC special case."););
4509                     /* We know result is the only live aop, and 
4510                      * it's obviously not a DPTR2, so AP is available.
4511                      */
4512                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4513                 }
4514                 else
4515                 {
4516                     aopPut(AOP(result),"a",0);
4517                 }
4518             
4519                 emitcode("pop","acc");
4520                 lbl = newiTempLabel(NULL);      
4521                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4522                 emitcode("cpl","a");
4523                 emitcode("addc","a,#0");
4524                 emitcode("","!tlabeldef", lbl->key+100);
4525                 aopPut(AOP(result),"a",1);
4526                 emitcode("pop","acc");
4527                 if (AOP_SIZE(result) >= 3) {
4528                         lbl = newiTempLabel(NULL);      
4529                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4530                         emitcode("cpl","a");
4531                         emitcode("addc","a,#0");                        
4532                         emitcode("","!tlabeldef", lbl->key+100);
4533                         aopPut(AOP(result),"a",2);
4534                 }
4535                 emitcode("pop","acc");
4536                 if (AOP_SIZE(result) >= 4) {
4537                         lbl = newiTempLabel(NULL);      
4538                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4539                         emitcode("cpl","a");
4540                         emitcode("addc","a,#0");                        
4541                         emitcode("","!tlabeldef", lbl->key+100);
4542                         aopPut(AOP(result),"a",3);
4543                 }
4544                 if (AOP_TYPE(result) == AOP_ACC)
4545                 {
4546                     /* We stashed the result away above. */
4547                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4548                 }           
4549                 
4550         }
4551         freeAsmop (result, NULL, ic, TRUE);
4552
4553         /* restore EA bit in F1 */
4554         lbl = newiTempLabel(NULL);
4555         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4556         emitcode ("setb","EA");
4557         emitcode("","!tlabeldef",lbl->key+100);
4558         return ;
4559 }
4560
4561 /*-----------------------------------------------------------------*/
4562 /* genMult - generates code for multiplication                     */
4563 /*-----------------------------------------------------------------*/
4564 static void
4565 genMult (iCode * ic)
4566 {
4567   operand *left = IC_LEFT (ic);
4568   operand *right = IC_RIGHT (ic);
4569   operand *result = IC_RESULT (ic);
4570
4571   D (emitcode (";", "genMult "););
4572
4573   /* assign the amsops */
4574   AOP_OP_2 (ic);
4575
4576   /* special cases first */
4577   /* both are bits */
4578   if (AOP_TYPE (left) == AOP_CRY &&
4579       AOP_TYPE (right) == AOP_CRY)
4580     {
4581       genMultbits (left, right, result, ic);
4582       goto release;
4583     }
4584
4585   /* if both are of size == 1 */
4586   if (AOP_SIZE (left) == 1 &&
4587       AOP_SIZE (right) == 1)
4588     {
4589       genMultOneByte (left, right, result, ic);
4590       goto release;
4591     }
4592
4593   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4594           /* use the ds390 ARITHMETIC accel UNIT */
4595           genMultTwoByte (left, right, result, ic);
4596           return ;
4597   }
4598   /* should have been converted to function call */
4599   assert (0);
4600
4601 release:
4602   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604   freeAsmop (result, NULL, ic, TRUE);
4605 }
4606
4607 /*-----------------------------------------------------------------*/
4608 /* genDivbits :- division of bits                                  */
4609 /*-----------------------------------------------------------------*/
4610 static void
4611 genDivbits (operand * left,
4612             operand * right,
4613             operand * result,
4614             iCode   * ic)
4615 {
4616
4617   char *l;
4618
4619   /* the result must be bit */
4620   LOAD_AB_FOR_DIV (left, right, l);
4621   emitcode ("div", "ab");
4622   emitcode ("rrc", "a");
4623   aopOp(result, ic, TRUE, FALSE);
4624     
4625   aopPut (AOP (result), "c", 0);
4626 }
4627
4628 /*-----------------------------------------------------------------*/
4629 /* genDivOneByte : 8 bit division                                  */
4630 /*-----------------------------------------------------------------*/
4631 static void
4632 genDivOneByte (operand * left,
4633                operand * right,
4634                operand * result,
4635                iCode   * ic)
4636 {
4637   sym_link *opetype = operandType (result);
4638   char *l;
4639   symbol *lbl;
4640   int size, offset;
4641
4642   offset = 1;
4643   /* signed or unsigned */
4644   if (SPEC_USIGN (opetype))
4645     {
4646         /* unsigned is easy */
4647         LOAD_AB_FOR_DIV (left, right, l);
4648         emitcode ("div", "ab");
4649
4650         _G.accInUse++;
4651         aopOp(result, ic, TRUE, FALSE);
4652         aopPut (AOP (result), "a", 0);
4653         _G.accInUse--;
4654
4655         size = AOP_SIZE (result) - 1;
4656         
4657         while (size--)
4658         {
4659             aopPut (AOP (result), zero, offset++);
4660         }
4661       return;
4662     }
4663
4664   /* signed is a little bit more difficult */
4665
4666   /* save the signs of the operands */
4667   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4668   MOVA (l);
4669   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4670   emitcode ("push", "acc");     /* save it on the stack */
4671
4672   /* now sign adjust for both left & right */
4673   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4674   MOVA (l);
4675   lbl = newiTempLabel (NULL);
4676   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4677   emitcode ("cpl", "a");
4678   emitcode ("inc", "a");
4679   emitcode ("", "!tlabeldef", (lbl->key + 100));
4680   emitcode ("mov", "b,a");
4681
4682   /* sign adjust left side */
4683   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4684   MOVA (l);
4685
4686   lbl = newiTempLabel (NULL);
4687   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4688   emitcode ("cpl", "a");
4689   emitcode ("inc", "a");
4690   emitcode ("", "!tlabeldef", (lbl->key + 100));
4691
4692   /* now the division */
4693   emitcode ("nop", "; workaround for DS80C390 div bug.");
4694   emitcode ("div", "ab");
4695   /* we are interested in the lower order
4696      only */
4697   emitcode ("mov", "b,a");
4698   lbl = newiTempLabel (NULL);
4699   emitcode ("pop", "acc");
4700   /* if there was an over flow we don't
4701      adjust the sign of the result */
4702   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4703   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4704   CLRC;
4705   emitcode ("clr", "a");
4706   emitcode ("subb", "a,b");
4707   emitcode ("mov", "b,a");
4708   emitcode ("", "!tlabeldef", (lbl->key + 100));
4709
4710   /* now we are done */
4711   _G.accInUse++;     _G.bInUse++;
4712     aopOp(result, ic, TRUE, FALSE);
4713     
4714     aopPut (AOP (result), "b", 0);
4715     
4716     size = AOP_SIZE (result) - 1;
4717     
4718     if (size > 0)
4719     {
4720       emitcode ("mov", "c,b.7");
4721       emitcode ("subb", "a,acc");
4722     }
4723     while (size--)
4724     {
4725         aopPut (AOP (result), "a", offset++);
4726     }
4727     _G.accInUse--;     _G.bInUse--;
4728
4729 }
4730
4731 /*-----------------------------------------------------------------*/
4732 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4733 /*-----------------------------------------------------------------*/
4734 static void genDivTwoByte (operand *left, operand *right, 
4735                             operand *result, iCode *ic)
4736 {
4737         sym_link *retype = getSpec(operandType(right));
4738         sym_link *letype = getSpec(operandType(left));
4739         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4740         symbol *lbl;
4741
4742         /* save EA bit in F1 */
4743         lbl = newiTempLabel(NULL);
4744         emitcode ("setb","F1");
4745         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4746         emitcode ("clr","F1");
4747         emitcode("","!tlabeldef",lbl->key+100);
4748
4749         /* load up MA with left */
4750         if (!umult) {
4751                 emitcode("clr","F0");
4752                 lbl = newiTempLabel(NULL);
4753                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4754                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4755                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4756                 emitcode ("xch", "a,b");
4757                 emitcode ("cpl","a");
4758                 emitcode ("add", "a,#1");
4759                 emitcode ("xch", "a,b");
4760                 emitcode ("cpl", "a"); // msb
4761                 emitcode ("addc","a,#0");
4762                 emitcode ("setb","F0");
4763                 emitcode ("","!tlabeldef",lbl->key+100);
4764                 emitcode ("mov","ma,b");
4765                 emitcode ("mov","ma,a");
4766         } else {
4767                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4768                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4769         }
4770
4771         /* load up MB with right */
4772         if (!umult) {
4773                 if (AOP_TYPE(right) == AOP_LIT) {
4774                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4775                         if (val < 0) {
4776                                 lbl = newiTempLabel(NULL);
4777                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4778                                 emitcode("setb","F0");
4779                                 emitcode ("","!tlabeldef",lbl->key+100);
4780                                 val = -val;
4781                         } 
4782                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4783                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4784                 } else {
4785                         lbl = newiTempLabel(NULL);
4786                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4787                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4788                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4789                         emitcode ("xch", "a,b");
4790                         emitcode ("cpl","a");
4791                         emitcode ("add", "a,#1");
4792                         emitcode ("xch", "a,b");
4793                         emitcode ("cpl", "a"); // msb
4794                         emitcode ("addc", "a,#0");
4795                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4796                         emitcode ("setb","F0");
4797                         emitcode ("","!tlabeldef",lbl->key+100);
4798                         emitcode ("mov","mb,b");
4799                         emitcode ("mov","mb,a");
4800                 }
4801         } else {
4802                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4803                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4804         }
4805
4806         /* wait for multiplication to finish */
4807         lbl = newiTempLabel(NULL);
4808         emitcode("","!tlabeldef", lbl->key+100);
4809         emitcode("mov","a,mcnt1");
4810         emitcode("anl","a,#!constbyte",0x80);
4811         emitcode("jnz","!tlabel",lbl->key+100);
4812         
4813         freeAsmop (left, NULL, ic, TRUE);
4814         freeAsmop (right, NULL, ic,TRUE);
4815         aopOp(result, ic, TRUE, FALSE);
4816
4817         /* if unsigned then simple */   
4818         if (umult) {
4819                 aopPut(AOP(result),"ma",1);
4820                 aopPut(AOP(result),"ma",0);
4821         } else {
4822                 emitcode("push","ma");
4823                 MOVA("ma");
4824                 /* negate result if needed */
4825                 lbl = newiTempLabel(NULL);      
4826                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4827                 emitcode("cpl","a");
4828                 emitcode("add","a,#1");
4829                 emitcode("","!tlabeldef", lbl->key+100);
4830                 aopPut(AOP(result),"a",0);
4831                 emitcode("pop","acc");
4832                 lbl = newiTempLabel(NULL);      
4833                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4834                 emitcode("cpl","a");
4835                 emitcode("addc","a,#0");
4836                 emitcode("","!tlabeldef", lbl->key+100);
4837                 aopPut(AOP(result),"a",1);
4838         }
4839         freeAsmop (result, NULL, ic, TRUE);
4840         /* restore EA bit in F1 */
4841         lbl = newiTempLabel(NULL);
4842         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4843         emitcode ("setb","EA");
4844         emitcode("","!tlabeldef",lbl->key+100);
4845         return ;
4846 }
4847
4848 /*-----------------------------------------------------------------*/
4849 /* genDiv - generates code for division                            */
4850 /*-----------------------------------------------------------------*/
4851 static void
4852 genDiv (iCode * ic)
4853 {
4854   operand *left = IC_LEFT (ic);
4855   operand *right = IC_RIGHT (ic);
4856   operand *result = IC_RESULT (ic);
4857
4858   D (emitcode (";", "genDiv "););
4859
4860   /* assign the amsops */
4861   AOP_OP_2 (ic);
4862
4863   /* special cases first */
4864   /* both are bits */
4865   if (AOP_TYPE (left) == AOP_CRY &&
4866       AOP_TYPE (right) == AOP_CRY)
4867     {
4868       genDivbits (left, right, result, ic);
4869       goto release;
4870     }
4871
4872   /* if both are of size == 1 */
4873   if (AOP_SIZE (left) == 1 &&
4874       AOP_SIZE (right) == 1)
4875     {
4876       genDivOneByte (left, right, result, ic);
4877       goto release;
4878     }
4879
4880   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4881           /* use the ds390 ARITHMETIC accel UNIT */
4882           genDivTwoByte (left, right, result, ic);
4883           return ;
4884   }
4885   /* should have been converted to function call */
4886   assert (0);
4887 release:
4888   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4890   freeAsmop (result, NULL, ic, TRUE);
4891 }
4892
4893 /*-----------------------------------------------------------------*/
4894 /* genModbits :- modulus of bits                                   */
4895 /*-----------------------------------------------------------------*/
4896 static void
4897 genModbits (operand * left,
4898             operand * right,
4899             operand * result,
4900             iCode   * ic)
4901 {
4902
4903   char *l;
4904
4905   /* the result must be bit */
4906   LOAD_AB_FOR_DIV (left, right, l);
4907   emitcode ("div", "ab");
4908   emitcode ("mov", "a,b");
4909   emitcode ("rrc", "a");
4910   aopOp(result, ic, TRUE, FALSE);
4911   aopPut (AOP (result), "c", 0);
4912 }
4913
4914 /*-----------------------------------------------------------------*/
4915 /* genModOneByte : 8 bit modulus                                   */
4916 /*-----------------------------------------------------------------*/
4917 static void
4918 genModOneByte (operand * left,
4919                operand * right,
4920                operand * result,
4921                iCode   * ic)
4922 {
4923   sym_link *opetype = operandType (result);
4924   char *l;
4925   symbol *lbl;
4926
4927   /* signed or unsigned */
4928   if (SPEC_USIGN (opetype))
4929     {
4930       /* unsigned is easy */
4931       LOAD_AB_FOR_DIV (left, right, l);
4932       emitcode ("div", "ab");
4933       aopOp(result, ic, TRUE, FALSE);   
4934       aopPut (AOP (result), "b", 0);
4935       return;
4936     }
4937
4938   /* signed is a little bit more difficult */
4939
4940   /* save the signs of the operands */
4941   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4942   MOVA (l);
4943
4944   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4945   emitcode ("push", "acc");     /* save it on the stack */
4946
4947   /* now sign adjust for both left & right */
4948   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4949   MOVA (l);
4950
4951   lbl = newiTempLabel (NULL);
4952   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4953   emitcode ("cpl", "a");
4954   emitcode ("inc", "a");
4955   emitcode ("", "!tlabeldef", (lbl->key + 100));
4956   emitcode ("mov", "b,a");
4957
4958   /* sign adjust left side */
4959   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4960   MOVA (l);
4961
4962   lbl = newiTempLabel (NULL);
4963   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4964   emitcode ("cpl", "a");
4965   emitcode ("inc", "a");
4966   emitcode ("", "!tlabeldef", (lbl->key + 100));
4967
4968   /* now the multiplication */
4969   emitcode ("nop", "; workaround for DS80C390 div bug.");
4970   emitcode ("div", "ab");
4971   /* we are interested in the lower order
4972      only */
4973   lbl = newiTempLabel (NULL);
4974   emitcode ("pop", "acc");
4975   /* if there was an over flow we don't
4976      adjust the sign of the result */
4977   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4978   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4979   CLRC;
4980   emitcode ("clr", "a");
4981   emitcode ("subb", "a,b");
4982   emitcode ("mov", "b,a");
4983   emitcode ("", "!tlabeldef", (lbl->key + 100));
4984   
4985   _G.bInUse++;
4986   /* now we are done */
4987   aopOp(result, ic, TRUE, FALSE);    
4988   aopPut (AOP (result), "b", 0);
4989   _G.bInUse--;
4990
4991 }
4992
4993 /*-----------------------------------------------------------------*/
4994 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4995 /*-----------------------------------------------------------------*/
4996 static void genModTwoByte (operand *left, operand *right, 
4997                             operand *result, iCode *ic)
4998 {
4999         sym_link *retype = getSpec(operandType(right));
5000         sym_link *letype = getSpec(operandType(left));
5001         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5002         symbol *lbl;
5003
5004         /* load up MA with left */
5005         /* save EA bit in F1 */
5006         lbl = newiTempLabel(NULL);
5007         emitcode ("setb","F1");
5008         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5009         emitcode ("clr","F1");
5010         emitcode("","!tlabeldef",lbl->key+100);
5011
5012         if (!umult) {
5013                 lbl = newiTempLabel(NULL);
5014                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5015                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5016                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5017                 emitcode ("xch", "a,b");
5018                 emitcode ("cpl","a");
5019                 emitcode ("add", "a,#1");
5020                 emitcode ("xch", "a,b");
5021                 emitcode ("cpl", "a"); // msb
5022                 emitcode ("addc","a,#0");
5023                 emitcode ("","!tlabeldef",lbl->key+100);
5024                 emitcode ("mov","ma,b");
5025                 emitcode ("mov","ma,a");
5026         } else {
5027                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5028                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5029         }
5030
5031         /* load up MB with right */
5032         if (!umult) {
5033                 if (AOP_TYPE(right) == AOP_LIT) {
5034                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5035                         if (val < 0) {
5036                                 val = -val;
5037                         } 
5038                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5039                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5040                 } else {
5041                         lbl = newiTempLabel(NULL);
5042                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5043                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5044                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5045                         emitcode ("xch", "a,b");
5046                         emitcode ("cpl","a");
5047                         emitcode ("add", "a,#1");
5048                         emitcode ("xch", "a,b");
5049                         emitcode ("cpl", "a"); // msb
5050                         emitcode ("addc", "a,#0");
5051                         emitcode ("","!tlabeldef",lbl->key+100);
5052                         emitcode ("mov","mb,b");
5053                         emitcode ("mov","mb,a");
5054                 }
5055         } else {
5056                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5057                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5058         }
5059
5060         /* wait for multiplication to finish */
5061         lbl = newiTempLabel(NULL);
5062         emitcode("","!tlabeldef", lbl->key+100);
5063         emitcode("mov","a,mcnt1");
5064         emitcode("anl","a,#!constbyte",0x80);
5065         emitcode("jnz","!tlabel",lbl->key+100);
5066         
5067         freeAsmop (left, NULL, ic, TRUE);
5068         freeAsmop (right, NULL, ic,TRUE);
5069         aopOp(result, ic, TRUE, FALSE);
5070
5071         aopPut(AOP(result),"mb",1);
5072         aopPut(AOP(result),"mb",0);
5073         freeAsmop (result, NULL, ic, TRUE);
5074
5075         /* restore EA bit in F1 */
5076         lbl = newiTempLabel(NULL);
5077         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5078         emitcode ("setb","EA");
5079         emitcode("","!tlabeldef",lbl->key+100);
5080         return ;
5081 }
5082
5083 /*-----------------------------------------------------------------*/
5084 /* genMod - generates code for division                            */
5085 /*-----------------------------------------------------------------*/
5086 static void
5087 genMod (iCode * ic)
5088 {
5089   operand *left = IC_LEFT (ic);
5090   operand *right = IC_RIGHT (ic);
5091   operand *result = IC_RESULT (ic);
5092
5093   D (emitcode (";", "genMod "); );
5094
5095   /* assign the amsops */
5096   AOP_OP_2 (ic);
5097
5098   /* special cases first */
5099   /* both are bits */
5100   if (AOP_TYPE (left) == AOP_CRY &&
5101       AOP_TYPE (right) == AOP_CRY)
5102     {
5103       genModbits (left, right, result, ic);
5104       goto release;
5105     }
5106
5107   /* if both are of size == 1 */
5108   if (AOP_SIZE (left) == 1 &&
5109       AOP_SIZE (right) == 1)
5110     {
5111       genModOneByte (left, right, result, ic);
5112       goto release;
5113     }
5114
5115   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5116           /* use the ds390 ARITHMETIC accel UNIT */
5117           genModTwoByte (left, right, result, ic);
5118           return ;
5119   }
5120
5121   /* should have been converted to function call */
5122   assert (0);
5123
5124 release:
5125   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127   freeAsmop (result, NULL, ic, TRUE);
5128 }
5129
5130 /*-----------------------------------------------------------------*/
5131 /* genIfxJump :- will create a jump depending on the ifx           */
5132 /*-----------------------------------------------------------------*/
5133 static void
5134 genIfxJump (iCode * ic, char *jval)
5135 {
5136   symbol *jlbl;
5137   symbol *tlbl = newiTempLabel (NULL);
5138   char *inst;
5139
5140   D (emitcode (";", "genIfxJump ");
5141     );
5142
5143   /* if true label then we jump if condition
5144      supplied is true */
5145   if (IC_TRUE (ic))
5146     {
5147       jlbl = IC_TRUE (ic);
5148       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5149                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5150     }
5151   else
5152     {
5153       /* false label is present */
5154       jlbl = IC_FALSE (ic);
5155       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5156                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5157     }
5158   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5159     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5160   else
5161     emitcode (inst, "!tlabel", tlbl->key + 100);
5162   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5163   emitcode ("", "!tlabeldef", tlbl->key + 100);
5164
5165   /* mark the icode as generated */
5166   ic->generated = 1;
5167 }
5168
5169 /*-----------------------------------------------------------------*/
5170 /* genCmp :- greater or less than comparison                       */
5171 /*-----------------------------------------------------------------*/
5172 static void
5173 genCmp (operand * left, operand * right,
5174         iCode * ic, iCode * ifx, int sign)
5175 {
5176   int size, offset = 0;
5177   unsigned long lit = 0L;
5178   operand *result;
5179
5180   D (emitcode (";", "genCmp");
5181     );
5182
5183   result = IC_RESULT (ic);
5184
5185   /* if left & right are bit variables */
5186   if (AOP_TYPE (left) == AOP_CRY &&
5187       AOP_TYPE (right) == AOP_CRY)
5188     {
5189       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5190       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5191     }
5192   else
5193     {
5194       /* subtract right from left if at the
5195          end the carry flag is set then we know that
5196          left is greater than right */
5197       size = max (AOP_SIZE (left), AOP_SIZE (right));
5198
5199       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5200       if ((size == 1) && !sign &&
5201           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5202         {
5203           symbol *lbl = newiTempLabel (NULL);
5204           emitcode ("cjne", "%s,%s,!tlabel",
5205                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5206                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5207                     lbl->key + 100);
5208           emitcode ("", "!tlabeldef", lbl->key + 100);
5209         }
5210       else
5211         {
5212           if (AOP_TYPE (right) == AOP_LIT)
5213             {
5214               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5215               /* optimize if(x < 0) or if(x >= 0) */
5216               if (lit == 0L)
5217                 {
5218                   if (!sign)
5219                     {
5220                       CLRC;
5221                     }
5222                   else
5223                     {
5224                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5225
5226                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5228
5229                       aopOp (result, ic, FALSE, FALSE);
5230
5231                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5232                         {
5233                           freeAsmop (result, NULL, ic, TRUE);
5234                           genIfxJump (ifx, "acc.7");
5235                           return;
5236                         }
5237                       else
5238                         {
5239                           emitcode ("rlc", "a");
5240                         }
5241                       goto release_freedLR;
5242                     }
5243                   goto release;
5244                 }
5245             }
5246           CLRC;
5247           while (size--)
5248             {
5249               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5250               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5251               //emitcode (";", "genCmp #2");
5252               if (sign && (size == 0))
5253                 {
5254                     //emitcode (";", "genCmp #3");
5255                   emitcode ("xrl", "a,#!constbyte",0x80);
5256                   if (AOP_TYPE (right) == AOP_LIT)
5257                     {
5258                       unsigned long lit = (unsigned long)
5259                       floatFromVal (AOP (right)->aopu.aop_lit);
5260                       //emitcode (";", "genCmp #3.1");
5261                       emitcode ("subb", "a,#!constbyte",
5262                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5263                     }
5264                   else
5265                     {
5266                       //emitcode (";", "genCmp #3.2");
5267                       if (AOP_NEEDSACC (right))
5268                         {
5269                           emitcode ("push", "acc");
5270                         }
5271                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5272                                                        FALSE, FALSE, FALSE));
5273                       emitcode ("xrl", "b,#!constbyte",0x80);
5274                       if (AOP_NEEDSACC (right))
5275                         {
5276                           emitcode ("pop", "acc");
5277                         }
5278                       emitcode ("subb", "a,b");
5279                     }
5280                 }
5281               else
5282                 {
5283                   const char *s;
5284
5285                   //emitcode (";", "genCmp #4");
5286                   if (AOP_NEEDSACC (right))
5287                     {
5288                       /* Yuck!! */
5289                       //emitcode (";", "genCmp #4.1");
5290                       emitcode ("xch", "a, b");
5291                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5292                       emitcode ("xch", "a, b");
5293                       s = "b";
5294                     }
5295                   else
5296                     {
5297                       //emitcode (";", "genCmp #4.2");
5298                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5299                     }
5300
5301                   emitcode ("subb", "a,%s", s);
5302                 }
5303             }
5304         }
5305     }
5306
5307 release:
5308 /* Don't need the left & right operands any more; do need the result. */
5309   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5310   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5311
5312   aopOp (result, ic, FALSE, FALSE);
5313
5314 release_freedLR:
5315
5316   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5317     {
5318       outBitC (result);
5319     }
5320   else
5321     {
5322       /* if the result is used in the next
5323          ifx conditional branch then generate
5324          code a little differently */
5325       if (ifx)
5326         {
5327           genIfxJump (ifx, "c");
5328         }
5329       else
5330         {
5331           outBitC (result);
5332         }
5333       /* leave the result in acc */
5334     }
5335   freeAsmop (result, NULL, ic, TRUE);
5336 }
5337
5338 /*-----------------------------------------------------------------*/
5339 /* genCmpGt :- greater than comparison                             */
5340 /*-----------------------------------------------------------------*/
5341 static void
5342 genCmpGt (iCode * ic, iCode * ifx)
5343 {
5344   operand *left, *right;
5345   sym_link *letype, *retype;
5346   int sign;
5347
5348   D (emitcode (";", "genCmpGt ");
5349     );
5350
5351   left = IC_LEFT (ic);
5352   right = IC_RIGHT (ic);
5353
5354   letype = getSpec (operandType (left));
5355   retype = getSpec (operandType (right));
5356   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5357
5358   /* assign the left & right amsops */
5359   AOP_OP_2 (ic);
5360
5361   genCmp (right, left, ic, ifx, sign);
5362 }
5363
5364 /*-----------------------------------------------------------------*/
5365 /* genCmpLt - less than comparisons                                */
5366 /*-----------------------------------------------------------------*/
5367 static void
5368 genCmpLt (iCode * ic, iCode * ifx)
5369 {
5370   operand *left, *right;
5371   sym_link *letype, *retype;
5372   int sign;
5373
5374   D (emitcode (";", "genCmpLt "););
5375
5376   left = IC_LEFT (ic);
5377   right = IC_RIGHT (ic);
5378
5379   letype = getSpec (operandType (left));
5380   retype = getSpec (operandType (right));
5381   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5382
5383   /* assign the left & right amsops */
5384   AOP_OP_2 (ic);
5385
5386   genCmp (left, right, ic, ifx, sign);
5387 }
5388
5389 /*-----------------------------------------------------------------*/
5390 /* gencjneshort - compare and jump if not equal                    */
5391 /*-----------------------------------------------------------------*/
5392 static void
5393 gencjneshort (operand * left, operand * right, symbol * lbl)
5394 {
5395   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5396   int offset = 0;
5397   unsigned long lit = 0L;
5398
5399   D (emitcode (";", "gencjneshort");
5400     );
5401
5402   /* if the left side is a literal or
5403      if the right is in a pointer register and left
5404      is not */
5405   if ((AOP_TYPE (left) == AOP_LIT) ||
5406       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5407     {
5408       operand *t = right;
5409       right = left;
5410       left = t;
5411     }
5412
5413   if (AOP_TYPE (right) == AOP_LIT)
5414     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5415
5416   if (opIsGptr (left) || opIsGptr (right))
5417     {
5418       /* We are comparing a generic pointer to something.
5419        * Exclude the generic type byte from the comparison.
5420        */
5421       size--;
5422       D (emitcode (";", "cjneshort: generic ptr special case.");
5423         )
5424     }
5425
5426
5427   /* if the right side is a literal then anything goes */
5428   if (AOP_TYPE (right) == AOP_LIT &&
5429       AOP_TYPE (left) != AOP_DIR)
5430     {
5431       while (size--)
5432         {
5433           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5434           MOVA (l);
5435           emitcode ("cjne", "a,%s,!tlabel",
5436                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5437                     lbl->key + 100);
5438           offset++;
5439         }
5440     }
5441
5442   /* if the right side is in a register or in direct space or
5443      if the left is a pointer register & right is not */
5444   else if (AOP_TYPE (right) == AOP_REG ||
5445            AOP_TYPE (right) == AOP_DIR ||
5446            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5447            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5448     {
5449       while (size--)
5450         {
5451           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5452           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5453               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5454             emitcode ("jnz", "!tlabel", lbl->key + 100);
5455           else
5456             emitcode ("cjne", "a,%s,!tlabel",
5457                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5458                       lbl->key + 100);
5459           offset++;
5460         }
5461     }
5462   else
5463     {
5464       /* right is a pointer reg need both a & b */
5465       while (size--)
5466         {
5467           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5468           if (strcmp (l, "b"))
5469             emitcode ("mov", "b,%s", l);
5470           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5471           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5472           offset++;
5473         }
5474     }
5475 }
5476
5477 /*-----------------------------------------------------------------*/
5478 /* gencjne - compare and jump if not equal                         */
5479 /*-----------------------------------------------------------------*/
5480 static void
5481 gencjne (operand * left, operand * right, symbol * lbl)
5482 {
5483   symbol *tlbl = newiTempLabel (NULL);
5484
5485   D (emitcode (";", "gencjne");
5486     );
5487
5488   gencjneshort (left, right, lbl);
5489
5490   emitcode ("mov", "a,%s", one);
5491   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5492   emitcode ("", "!tlabeldef", lbl->key + 100);
5493   emitcode ("clr", "a");
5494   emitcode ("", "!tlabeldef", tlbl->key + 100);
5495 }
5496
5497 /*-----------------------------------------------------------------*/
5498 /* genCmpEq - generates code for equal to                          */
5499 /*-----------------------------------------------------------------*/
5500 static void
5501 genCmpEq (iCode * ic, iCode * ifx)
5502 {
5503   operand *left, *right, *result;
5504
5505   D (emitcode (";", "genCmpEq ");
5506     );
5507
5508   AOP_OP_2 (ic);
5509   AOP_SET_LOCALS (ic);
5510
5511   /* if literal, literal on the right or
5512      if the right is in a pointer register and left
5513      is not */
5514   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5515       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5516     {
5517       operand *t = IC_RIGHT (ic);
5518       IC_RIGHT (ic) = IC_LEFT (ic);
5519       IC_LEFT (ic) = t;
5520     }
5521
5522   if (ifx &&                    /* !AOP_SIZE(result) */
5523       OP_SYMBOL (result) &&
5524       OP_SYMBOL (result)->regType == REG_CND)
5525     {
5526       symbol *tlbl;
5527       /* if they are both bit variables */
5528       if (AOP_TYPE (left) == AOP_CRY &&
5529           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5530         {
5531           if (AOP_TYPE (right) == AOP_LIT)
5532             {
5533               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5534               if (lit == 0L)
5535                 {
5536                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5537                   emitcode ("cpl", "c");
5538                 }
5539               else if (lit == 1L)
5540                 {
5541                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5542                 }
5543               else
5544                 {
5545                   emitcode ("clr", "c");
5546                 }
5547               /* AOP_TYPE(right) == AOP_CRY */
5548             }
5549           else
5550             {
5551               symbol *lbl = newiTempLabel (NULL);
5552               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5553               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5554               emitcode ("cpl", "c");
5555               emitcode ("", "!tlabeldef", (lbl->key + 100));
5556             }
5557           /* if true label then we jump if condition
5558              supplied is true */
5559           tlbl = newiTempLabel (NULL);
5560           if (IC_TRUE (ifx))
5561             {
5562               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5563               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5564             }
5565           else
5566             {
5567               emitcode ("jc", "!tlabel", tlbl->key + 100);
5568               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5569             }
5570           emitcode ("", "!tlabeldef", tlbl->key + 100);
5571         }
5572       else
5573         {
5574           tlbl = newiTempLabel (NULL);
5575           gencjneshort (left, right, tlbl);
5576           if (IC_TRUE (ifx))
5577             {
5578               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5579               emitcode ("", "!tlabeldef", tlbl->key + 100);
5580             }
5581           else
5582             {
5583               symbol *lbl = newiTempLabel (NULL);
5584               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5585               emitcode ("", "!tlabeldef", tlbl->key + 100);
5586               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5587               emitcode ("", "!tlabeldef", lbl->key + 100);
5588             }
5589         }
5590       /* mark the icode as generated */
5591       ifx->generated = 1;
5592
5593       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5594       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5595       return;
5596     }
5597
5598   /* if they are both bit variables */
5599   if (AOP_TYPE (left) == AOP_CRY &&
5600       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5601     {
5602       if (AOP_TYPE (right) == AOP_LIT)
5603         {
5604           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5605           if (lit == 0L)
5606             {
5607               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5608               emitcode ("cpl", "c");
5609             }
5610           else if (lit == 1L)
5611             {
5612               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5613             }
5614           else
5615             {
5616               emitcode ("clr", "c");
5617             }
5618           /* AOP_TYPE(right) == AOP_CRY */
5619         }
5620       else
5621         {
5622           symbol *lbl = newiTempLabel (NULL);
5623           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5624           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5625           emitcode ("cpl", "c");
5626           emitcode ("", "!tlabeldef", (lbl->key + 100));
5627         }
5628
5629       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5630       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5631
5632       aopOp (result, ic, TRUE, FALSE);
5633
5634       /* c = 1 if egal */
5635       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5636         {
5637           outBitC (result);
5638           goto release;
5639         }
5640       if (ifx)
5641         {
5642           genIfxJump (ifx, "c");
5643           goto release;
5644         }
5645       /* if the result is used in an arithmetic operation
5646          then put the result in place */
5647       outBitC (result);
5648     }
5649   else
5650     {
5651       gencjne (left, right, newiTempLabel (NULL));
5652
5653       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5654       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5655
5656       aopOp (result, ic, TRUE, FALSE);
5657
5658       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5659         {
5660           aopPut (AOP (result), "a", 0);
5661           goto release;
5662         }
5663       if (ifx)
5664         {
5665           genIfxJump (ifx, "a");
5666           goto release;
5667         }
5668       /* if the result is used in an arithmetic operation
5669          then put the result in place */
5670       if (AOP_TYPE (result) != AOP_CRY)
5671         outAcc (result);
5672       /* leave the result in acc */
5673     }
5674
5675 release:
5676   freeAsmop (result, NULL, ic, TRUE);
5677 }
5678
5679 /*-----------------------------------------------------------------*/
5680 /* ifxForOp - returns the icode containing the ifx for operand     */
5681 /*-----------------------------------------------------------------*/
5682 static iCode *
5683 ifxForOp (operand * op, iCode * ic)
5684 {
5685   /* if true symbol then needs to be assigned */
5686   if (IS_TRUE_SYMOP (op))
5687     return NULL;
5688
5689   /* if this has register type condition and
5690      the next instruction is ifx with the same operand
5691      and live to of the operand is upto the ifx only then */
5692   if (ic->next &&
5693       ic->next->op == IFX &&
5694       IC_COND (ic->next)->key == op->key &&
5695       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5696     return ic->next;
5697
5698   return NULL;
5699 }
5700 /*-----------------------------------------------------------------*/
5701 /* hasInc - operand is incremented before any other use            */
5702 /*-----------------------------------------------------------------*/
5703 static iCode *
5704 hasInc (operand *op, iCode *ic, int osize)
5705 {
5706   sym_link *type = operandType(op);
5707   sym_link *retype = getSpec (type);
5708   iCode *lic = ic->next;
5709   int isize ;
5710   
5711   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5712   if (!IS_SYMOP(op)) return NULL;
5713
5714   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5715   if (IS_AGGREGATE(type->next)) return NULL;
5716   if (osize != (isize = getSize(type->next))) return NULL;
5717
5718   while (lic) {
5719       /* if operand of the form op = op + <sizeof *op> */
5720       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5721           isOperandEqual(IC_RESULT(lic),op) && 
5722           isOperandLiteral(IC_RIGHT(lic)) &&
5723           operandLitValue(IC_RIGHT(lic)) == isize) {
5724           return lic;
5725       }
5726       /* if the operand used or deffed */
5727       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5728           return NULL;
5729       }
5730       /* if GOTO or IFX */
5731       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5732       lic = lic->next;
5733   }
5734   return NULL;
5735 }
5736
5737 /*-----------------------------------------------------------------*/
5738 /* genAndOp - for && operation                                     */
5739 /*-----------------------------------------------------------------*/
5740 static void
5741 genAndOp (iCode * ic)
5742 {
5743   operand *left, *right, *result;
5744   symbol *tlbl;
5745
5746   D (emitcode (";", "genAndOp "););
5747
5748   /* note here that && operations that are in an
5749      if statement are taken away by backPatchLabels
5750      only those used in arthmetic operations remain */
5751   AOP_OP_2 (ic);
5752   AOP_SET_LOCALS (ic);
5753
5754   /* if both are bit variables */
5755   if (AOP_TYPE (left) == AOP_CRY &&
5756       AOP_TYPE (right) == AOP_CRY)
5757     {
5758       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5759       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5760       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5762   
5763       aopOp (result,ic,FALSE, FALSE);
5764       outBitC (result);
5765     }
5766   else
5767     {
5768       tlbl = newiTempLabel (NULL);
5769       toBoolean (left);
5770       emitcode ("jz", "!tlabel", tlbl->key + 100);
5771       toBoolean (right);
5772       emitcode ("", "!tlabeldef", tlbl->key + 100);
5773       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5775   
5776       aopOp (result,ic,FALSE, FALSE);
5777       outBitAcc (result);
5778     }
5779     freeAsmop (result, NULL, ic, TRUE);
5780 }
5781
5782
5783 /*-----------------------------------------------------------------*/
5784 /* genOrOp - for || operation                                      */
5785 /*-----------------------------------------------------------------*/
5786 static void
5787 genOrOp (iCode * ic)
5788 {
5789   operand *left, *right, *result;
5790   symbol *tlbl;
5791
5792   D (emitcode (";", "genOrOp "););
5793
5794   /* note here that || operations that are in an
5795      if statement are taken away by backPatchLabels
5796      only those used in arthmetic operations remain */
5797   AOP_OP_2 (ic);
5798   AOP_SET_LOCALS (ic);
5799
5800   /* if both are bit variables */
5801   if (AOP_TYPE (left) == AOP_CRY &&
5802       AOP_TYPE (right) == AOP_CRY)
5803     {
5804       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5805       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5806       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5808   
5809       aopOp (result,ic,FALSE, FALSE);
5810       
5811       outBitC (result);
5812     }
5813   else
5814     {
5815       tlbl = newiTempLabel (NULL);
5816       toBoolean (left);
5817       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5818       toBoolean (right);
5819       emitcode ("", "!tlabeldef", tlbl->key + 100);
5820       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5821       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5822   
5823       aopOp (result,ic,FALSE, FALSE);
5824       
5825       outBitAcc (result);
5826     }
5827
5828   freeAsmop (result, NULL, ic, TRUE);
5829 }
5830
5831 /*-----------------------------------------------------------------*/
5832 /* isLiteralBit - test if lit == 2^n                               */
5833 /*-----------------------------------------------------------------*/
5834 static int
5835 isLiteralBit (unsigned long lit)
5836 {
5837   unsigned long pw[32] =
5838   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5839    0x100L, 0x200L, 0x400L, 0x800L,
5840    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5841    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5842    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5843    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5844    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5845   int idx;
5846
5847   for (idx = 0; idx < 32; idx++)
5848     if (lit == pw[idx])
5849       return idx + 1;
5850   return 0;
5851 }
5852
5853 /*-----------------------------------------------------------------*/
5854 /* continueIfTrue -                                                */
5855 /*-----------------------------------------------------------------*/
5856 static void
5857 continueIfTrue (iCode * ic)
5858 {
5859   if (IC_TRUE (ic))
5860     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5861   ic->generated = 1;
5862 }
5863
5864 /*-----------------------------------------------------------------*/
5865 /* jmpIfTrue -                                                     */
5866 /*-----------------------------------------------------------------*/
5867 static void
5868 jumpIfTrue (iCode * ic)
5869 {
5870   if (!IC_TRUE (ic))
5871     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5872   ic->generated = 1;
5873 }
5874
5875 /*-----------------------------------------------------------------*/
5876 /* jmpTrueOrFalse -                                                */
5877 /*-----------------------------------------------------------------*/
5878 static void
5879 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5880 {
5881   // ugly but optimized by peephole
5882   if (IC_TRUE (ic))
5883     {
5884       symbol *nlbl = newiTempLabel (NULL);
5885       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5886       emitcode ("", "!tlabeldef", tlbl->key + 100);
5887       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5888       emitcode ("", "!tlabeldef", nlbl->key + 100);
5889     }
5890   else
5891     {
5892       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5893       emitcode ("", "!tlabeldef", tlbl->key + 100);
5894     }
5895   ic->generated = 1;
5896 }
5897
5898 // Generate code to perform a bit-wise logic operation
5899 // on two operands in far space (assumed to already have been 
5900 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5901 // in far space. This requires pushing the result on the stack
5902 // then popping it into the result.
5903 static void
5904 genFarFarLogicOp(iCode *ic, char *logicOp)
5905 {
5906       int size, resultSize, compSize;
5907       int offset = 0;
5908       
5909       TR_AP("#5");
5910       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5911       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5912                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5913       
5914       _startLazyDPSEvaluation();
5915       for (size = compSize; (size--); offset++)
5916       {
5917           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5918           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5919           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5920           
5921           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5922           emitcode ("push", "acc");
5923       }
5924       _endLazyDPSEvaluation();
5925      
5926       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5927       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5928       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5929      
5930       resultSize = AOP_SIZE(IC_RESULT(ic));
5931
5932       ADJUST_PUSHED_RESULT(compSize, resultSize);
5933
5934       _startLazyDPSEvaluation();
5935       while (compSize--)
5936       {
5937           emitcode ("pop", "acc");
5938           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5939       }
5940       _endLazyDPSEvaluation();
5941       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5942 }
5943
5944
5945 /*-----------------------------------------------------------------*/
5946 /* genAnd  - code for and                                          */
5947 /*-----------------------------------------------------------------*/
5948 static void
5949 genAnd (iCode * ic, iCode * ifx)
5950 {
5951   operand *left, *right, *result;
5952   int size, offset = 0;
5953   unsigned long lit = 0L;
5954   int bytelit = 0;
5955   char buffer[10];
5956   bool pushResult;
5957
5958   D (emitcode (";", "genAnd "););
5959
5960   AOP_OP_3_NOFATAL (ic, pushResult);
5961   AOP_SET_LOCALS (ic);
5962
5963   if (pushResult)
5964   {
5965       genFarFarLogicOp(ic, "anl");
5966       return;
5967   }  
5968
5969 #ifdef DEBUG_TYPE
5970   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5971             AOP_TYPE (result),
5972             AOP_TYPE (left), AOP_TYPE (right));
5973   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5974             AOP_SIZE (result),
5975             AOP_SIZE (left), AOP_SIZE (right));
5976 #endif
5977
5978   /* if left is a literal & right is not then exchange them */
5979   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5980 #ifdef LOGIC_OPS_BROKEN      
5981     ||  AOP_NEEDSACC (left)
5982 #endif
5983     )
5984     {
5985       operand *tmp = right;
5986       right = left;
5987       left = tmp;
5988     }
5989
5990   /* if result = right then exchange them */
5991   if (sameRegs (AOP (result), AOP (right)))
5992     {
5993       operand *tmp = right;
5994       right = left;
5995       left = tmp;
5996     }
5997
5998   /* if right is bit then exchange them */
5999   if (AOP_TYPE (right) == AOP_CRY &&
6000       AOP_TYPE (left) != AOP_CRY)
6001     {
6002       operand *tmp = right;
6003       right = left;
6004       left = tmp;
6005     }
6006   if (AOP_TYPE (right) == AOP_LIT)
6007     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6008
6009   size = AOP_SIZE (result);
6010
6011   // if(bit & yy)
6012   // result = bit & yy;
6013   if (AOP_TYPE (left) == AOP_CRY)
6014     {
6015       // c = bit & literal;
6016       if (AOP_TYPE (right) == AOP_LIT)
6017         {
6018           if (lit & 1)
6019             {
6020               if (size && sameRegs (AOP (result), AOP (left)))
6021                 // no change
6022                 goto release;
6023               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6024             }
6025           else
6026             {
6027               // bit(result) = 0;
6028               if (size && (AOP_TYPE (result) == AOP_CRY))
6029                 {
6030                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6031                   goto release;
6032                 }
6033               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6034                 {
6035                   jumpIfTrue (ifx);
6036                   goto release;
6037                 }
6038               emitcode ("clr", "c");
6039             }
6040         }
6041       else
6042         {
6043           if (AOP_TYPE (right) == AOP_CRY)
6044             {
6045               // c = bit & bit;
6046               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6047               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6048             }
6049           else
6050             {
6051               // c = bit & val;
6052               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6053               // c = lsb
6054               emitcode ("rrc", "a");
6055               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6056             }
6057         }
6058       // bit = c
6059       // val = c
6060       if (size)
6061         outBitC (result);
6062       // if(bit & ...)
6063       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6064         genIfxJump (ifx, "c");
6065       goto release;
6066     }
6067
6068   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6069   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6070   if ((AOP_TYPE (right) == AOP_LIT) &&
6071       (AOP_TYPE (result) == AOP_CRY) &&
6072       (AOP_TYPE (left) != AOP_CRY))
6073     {
6074       int posbit = isLiteralBit (lit);
6075       /* left &  2^n */
6076       if (posbit)
6077         {
6078           posbit--;
6079           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6080           // bit = left & 2^n
6081           if (size)
6082             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6083           // if(left &  2^n)
6084           else
6085             {
6086               if (ifx)
6087                 {
6088                   sprintf (buffer, "acc.%d", posbit & 0x07);
6089                   genIfxJump (ifx, buffer);
6090                 }
6091               else 
6092                   {
6093                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6094                   }
6095               goto release;
6096             }
6097         }
6098       else
6099         {
6100           symbol *tlbl = newiTempLabel (NULL);
6101           int sizel = AOP_SIZE (left);
6102           if (size)
6103             emitcode ("setb", "c");
6104           while (sizel--)
6105             {
6106               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6107                 {
6108                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6109                   // byte ==  2^n ?
6110                   if ((posbit = isLiteralBit (bytelit)) != 0)
6111                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6112                   else
6113                     {
6114                       if (bytelit != 0x0FFL)
6115                         emitcode ("anl", "a,%s",
6116                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6117                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6118                     }
6119                 }
6120               offset++;
6121             }
6122           // bit = left & literal
6123           if (size)
6124             {
6125               emitcode ("clr", "c");
6126               emitcode ("", "!tlabeldef", tlbl->key + 100);
6127             }
6128           // if(left & literal)
6129           else
6130             {
6131               if (ifx)
6132                 jmpTrueOrFalse (ifx, tlbl);
6133               goto release;
6134             }
6135         }
6136       outBitC (result);
6137       goto release;
6138     }
6139
6140   /* if left is same as result */
6141   if (sameRegs (AOP (result), AOP (left)))
6142     {
6143       for (; size--; offset++)
6144         {
6145           if (AOP_TYPE (right) == AOP_LIT)
6146             {
6147               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6148                 continue;
6149               else if (bytelit == 0)
6150                 aopPut (AOP (result), zero, offset);
6151               else if (IS_AOP_PREG (result))
6152                 {
6153                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6154                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6155                   aopPut (AOP (result), "a", offset);
6156                 }
6157               else
6158                 emitcode ("anl", "%s,%s",
6159                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6160                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6161             }
6162           else
6163             {
6164               if (AOP_TYPE (left) == AOP_ACC)
6165                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6166               else
6167                 {
6168                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6169                   if (IS_AOP_PREG (result))
6170                     {
6171                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6172                       aopPut (AOP (result), "a", offset);
6173
6174                     }
6175                   else
6176                     emitcode ("anl", "%s,a",
6177                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6178                 }
6179             }
6180         }
6181     }
6182   else
6183     {
6184       // left & result in different registers
6185       if (AOP_TYPE (result) == AOP_CRY)
6186         {
6187           // result = bit
6188           // if(size), result in bit
6189           // if(!size && ifx), conditional oper: if(left & right)
6190           symbol *tlbl = newiTempLabel (NULL);
6191           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6192           if (size)
6193             emitcode ("setb", "c");
6194           while (sizer--)
6195             {
6196               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6197                 emitcode ("anl", "a,%s",
6198                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6199               } else {
6200                 if (AOP_TYPE(left)==AOP_ACC) {
6201                   emitcode("mov", "b,a");
6202                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6203                   emitcode("anl", "a,b");
6204                 }else {
6205                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6206                   emitcode ("anl", "a,%s",
6207                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6208                 }
6209               }
6210               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6211               offset++;
6212             }
6213           if (size)
6214             {
6215               CLRC;
6216               emitcode ("", "!tlabeldef", tlbl->key + 100);
6217               outBitC (result);
6218             }
6219           else if (ifx)
6220             jmpTrueOrFalse (ifx, tlbl);
6221         }
6222       else
6223         {
6224           for (; (size--); offset++)
6225             {
6226               // normal case
6227               // result = left & right
6228               if (AOP_TYPE (right) == AOP_LIT)
6229                 {
6230                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6231                     {
6232                       aopPut (AOP (result),
6233                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6234                               offset);
6235                       continue;
6236                     }
6237                   else if (bytelit == 0)
6238                     {
6239                       aopPut (AOP (result), zero, offset);
6240                       continue;
6241                     }
6242                   D (emitcode (";", "better literal AND."););
6243                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6244                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6245                                                     FALSE, FALSE, FALSE));
6246
6247                 }
6248               else
6249                 {
6250                   // faster than result <- left, anl result,right
6251                   // and better if result is SFR
6252                   if (AOP_TYPE (left) == AOP_ACC)
6253                     {
6254                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6255                                                        FALSE, FALSE, FALSE));
6256                     }
6257                   else
6258                     {
6259                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6260                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6261                       {
6262                           emitcode("mov", "b,a");
6263                           rOp = "b";
6264                       }
6265                         
6266                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6267                       emitcode ("anl", "a,%s", rOp);
6268                     }                   
6269                 }
6270               aopPut (AOP (result), "a", offset);
6271             }
6272         }
6273     }
6274
6275 release:
6276   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6277   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6278   freeAsmop (result, NULL, ic, TRUE);
6279 }
6280
6281
6282 /*-----------------------------------------------------------------*/
6283 /* genOr  - code for or                                            */
6284 /*-----------------------------------------------------------------*/
6285 static void
6286 genOr (iCode * ic, iCode * ifx)
6287 {
6288   operand *left, *right, *result;
6289   int size, offset = 0;
6290   unsigned long lit = 0L;
6291   bool     pushResult;
6292
6293   D (emitcode (";", "genOr "););
6294
6295   AOP_OP_3_NOFATAL (ic, pushResult);
6296   AOP_SET_LOCALS (ic);
6297
6298   if (pushResult)
6299   {
6300       genFarFarLogicOp(ic, "orl");
6301       return;
6302   }
6303
6304
6305 #ifdef DEBUG_TYPE
6306   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6307             AOP_TYPE (result),
6308             AOP_TYPE (left), AOP_TYPE (right));
6309   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6310             AOP_SIZE (result),
6311             AOP_SIZE (left), AOP_SIZE (right));
6312 #endif
6313
6314   /* if left is a literal & right is not then exchange them */
6315   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6316 #ifdef LOGIC_OPS_BROKEN
6317    || AOP_NEEDSACC (left) // I think this is a net loss now.
6318 #endif      
6319       )
6320     {
6321       operand *tmp = right;
6322       right = left;
6323       left = tmp;
6324     }
6325
6326   /* if result = right then exchange them */
6327   if (sameRegs (AOP (result), AOP (right)))
6328     {
6329       operand *tmp = right;
6330       right = left;
6331       left = tmp;
6332     }
6333
6334   /* if right is bit then exchange them */
6335   if (AOP_TYPE (right) == AOP_CRY &&
6336       AOP_TYPE (left) != AOP_CRY)
6337     {
6338       operand *tmp = right;
6339       right = left;
6340       left = tmp;
6341     }
6342   if (AOP_TYPE (right) == AOP_LIT)
6343     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6344
6345   size = AOP_SIZE (result);
6346
6347   // if(bit | yy)
6348   // xx = bit | yy;
6349   if (AOP_TYPE (left) == AOP_CRY)
6350     {
6351       if (AOP_TYPE (right) == AOP_LIT)
6352         {
6353           // c = bit & literal;
6354           if (lit)
6355             {
6356               // lit != 0 => result = 1
6357               if (AOP_TYPE (result) == AOP_CRY)
6358                 {
6359                   if (size)
6360                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6361                   else if (ifx)
6362                     continueIfTrue (ifx);
6363                   goto release;
6364                 }
6365               emitcode ("setb", "c");
6366             }
6367           else
6368             {
6369               // lit == 0 => result = left
6370               if (size && sameRegs (AOP (result), AOP (left)))
6371                 goto release;
6372               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6373             }
6374         }
6375       else
6376         {
6377           if (AOP_TYPE (right) == AOP_CRY)
6378             {
6379               // c = bit | bit;
6380               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6381               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6382             }
6383           else
6384             {
6385               // c = bit | val;
6386               symbol *tlbl = newiTempLabel (NULL);
6387               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6388                 emitcode ("setb", "c");
6389               emitcode ("jb", "%s,!tlabel",
6390                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6391               toBoolean (right);
6392               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6393               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6394                 {
6395                   jmpTrueOrFalse (ifx, tlbl);
6396                   goto release;
6397                 }
6398               else
6399                 {
6400                   CLRC;
6401                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6402                 }
6403             }
6404         }
6405       // bit = c
6406       // val = c
6407       if (size)
6408         outBitC (result);
6409       // if(bit | ...)
6410       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6411         genIfxJump (ifx, "c");
6412       goto release;
6413     }
6414
6415   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6416   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6417   if ((AOP_TYPE (right) == AOP_LIT) &&
6418       (AOP_TYPE (result) == AOP_CRY) &&
6419       (AOP_TYPE (left) != AOP_CRY))
6420     {
6421       if (lit)
6422         {
6423           // result = 1
6424           if (size)
6425             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6426           else
6427             continueIfTrue (ifx);
6428           goto release;
6429         }
6430       else
6431         {
6432           // lit = 0, result = boolean(left)
6433           if (size)
6434             emitcode ("setb", "c");
6435           toBoolean (right);
6436           if (size)
6437             {
6438               symbol *tlbl = newiTempLabel (NULL);
6439               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6440               CLRC;
6441               emitcode ("", "!tlabeldef", tlbl->key + 100);
6442             }
6443           else
6444             {
6445               genIfxJump (ifx, "a");
6446               goto release;
6447             }
6448         }
6449       outBitC (result);
6450       goto release;
6451     }
6452
6453   /* if left is same as result */
6454   if (sameRegs (AOP (result), AOP (left)))
6455     {
6456       for (; size--; offset++)
6457         {
6458           if (AOP_TYPE (right) == AOP_LIT)
6459             {
6460               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6461                 {
6462                   continue;
6463                 }
6464               else
6465                 {
6466                   if (IS_AOP_PREG (left))
6467                     {
6468                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6469                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6470                       aopPut (AOP (result), "a", offset);
6471                     }
6472                   else
6473                     {
6474                       emitcode ("orl", "%s,%s",
6475                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6476                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6477                     }
6478                 }
6479             }
6480           else
6481             {
6482               if (AOP_TYPE (left) == AOP_ACC)
6483                 {
6484                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6485                 }
6486               else
6487                 {
6488                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6489                   if (IS_AOP_PREG (left))
6490                     {
6491                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6492                       aopPut (AOP (result), "a", offset);
6493                     }
6494                   else
6495                     {
6496                       emitcode ("orl", "%s,a",
6497                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6498                     }
6499                 }
6500             }
6501         }
6502     }
6503   else
6504     {
6505       // left & result in different registers
6506       if (AOP_TYPE (result) == AOP_CRY)
6507         {
6508           // result = bit
6509           // if(size), result in bit
6510           // if(!size && ifx), conditional oper: if(left | right)
6511           symbol *tlbl = newiTempLabel (NULL);
6512           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6513           if (size)
6514             emitcode ("setb", "c");
6515           while (sizer--)
6516             {
6517               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6518                 emitcode ("orl", "a,%s",
6519                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6520               } else {
6521                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6522                 emitcode ("orl", "a,%s",
6523                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6524               }
6525               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6526               offset++;
6527             }
6528           if (size)
6529             {
6530               CLRC;
6531               emitcode ("", "!tlabeldef", tlbl->key + 100);
6532               outBitC (result);
6533             }
6534           else if (ifx)
6535             jmpTrueOrFalse (ifx, tlbl);
6536         }
6537       else
6538         {
6539             _startLazyDPSEvaluation();
6540           for (; (size--); offset++)
6541             {
6542               // normal case
6543               // result = left & right
6544               if (AOP_TYPE (right) == AOP_LIT)
6545                 {
6546                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6547                     {
6548                       aopPut (AOP (result),
6549                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6550                               offset);
6551                       continue;
6552                     }
6553                   D (emitcode (";", "better literal OR."););
6554                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6555                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6556                                                     FALSE, FALSE, FALSE));
6557
6558                 }
6559               else
6560                 {
6561                   // faster than result <- left, anl result,right
6562                   // and better if result is SFR
6563                   if (AOP_TYPE (left) == AOP_ACC)
6564                     {
6565                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6566                                                        FALSE, FALSE, FALSE));
6567                     }
6568                   else
6569                     {
6570                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6571                         
6572                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6573                       {
6574                           emitcode("mov", "b,a");
6575                           rOp = "b";
6576                       }
6577                         
6578                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6579                       emitcode ("orl", "a,%s", rOp);
6580                     }
6581                 }
6582               aopPut (AOP (result), "a", offset);
6583             }
6584             _endLazyDPSEvaluation();
6585         }
6586     }
6587
6588 release:
6589   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6590   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6591   freeAsmop (result, NULL, ic, TRUE);
6592 }
6593
6594 /*-----------------------------------------------------------------*/
6595 /* genXor - code for xclusive or                                   */
6596 /*-----------------------------------------------------------------*/
6597 static void
6598 genXor (iCode * ic, iCode * ifx)
6599 {
6600   operand *left, *right, *result;
6601   int size, offset = 0;
6602   unsigned long lit = 0L;
6603   bool pushResult;
6604
6605   D (emitcode (";", "genXor "););
6606
6607   AOP_OP_3_NOFATAL (ic, pushResult);
6608   AOP_SET_LOCALS (ic);
6609
6610   if (pushResult)
6611   {
6612       genFarFarLogicOp(ic, "xrl");
6613       return;
6614   }  
6615
6616 #ifdef DEBUG_TYPE
6617   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6618             AOP_TYPE (result),
6619             AOP_TYPE (left), AOP_TYPE (right));
6620   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6621             AOP_SIZE (result),
6622             AOP_SIZE (left), AOP_SIZE (right));
6623 #endif
6624
6625   /* if left is a literal & right is not ||
6626      if left needs acc & right does not */
6627   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6628 #ifdef LOGIC_OPS_BROKEN      
6629       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6630 #endif
6631      )
6632     {
6633       operand *tmp = right;
6634       right = left;
6635       left = tmp;
6636     }
6637
6638   /* if result = right then exchange them */
6639   if (sameRegs (AOP (result), AOP (right)))
6640     {
6641       operand *tmp = right;
6642       right = left;
6643       left = tmp;
6644     }
6645
6646   /* if right is bit then exchange them */
6647   if (AOP_TYPE (right) == AOP_CRY &&
6648       AOP_TYPE (left) != AOP_CRY)
6649     {
6650       operand *tmp = right;
6651       right = left;
6652       left = tmp;
6653     }
6654   if (AOP_TYPE (right) == AOP_LIT)
6655     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6656
6657   size = AOP_SIZE (result);
6658
6659   // if(bit ^ yy)
6660   // xx = bit ^ yy;
6661   if (AOP_TYPE (left) == AOP_CRY)
6662     {
6663       if (AOP_TYPE (right) == AOP_LIT)
6664         {
6665           // c = bit & literal;
6666           if (lit >> 1)
6667             {
6668               // lit>>1  != 0 => result = 1
6669               if (AOP_TYPE (result) == AOP_CRY)
6670                 {
6671                   if (size)
6672                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6673                   else if (ifx)
6674                     continueIfTrue (ifx);
6675                   goto release;
6676                 }
6677               emitcode ("setb", "c");
6678             }
6679           else
6680             {
6681               // lit == (0 or 1)
6682               if (lit == 0)
6683                 {
6684                   // lit == 0, result = left
6685                   if (size && sameRegs (AOP (result), AOP (left)))
6686                     goto release;
6687                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6688                 }
6689               else
6690                 {
6691                   // lit == 1, result = not(left)
6692                   if (size && sameRegs (AOP (result), AOP (left)))
6693                     {
6694                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6695                       goto release;
6696                     }
6697                   else
6698                     {
6699                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6700                       emitcode ("cpl", "c");
6701                     }
6702                 }
6703             }
6704
6705         }
6706       else
6707         {
6708           // right != literal
6709           symbol *tlbl = newiTempLabel (NULL);
6710           if (AOP_TYPE (right) == AOP_CRY)
6711             {
6712               // c = bit ^ bit;
6713               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6714             }
6715           else
6716             {
6717               int sizer = AOP_SIZE (right);
6718               // c = bit ^ val
6719               // if val>>1 != 0, result = 1
6720               emitcode ("setb", "c");
6721               while (sizer)
6722                 {
6723                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6724                   if (sizer == 1)
6725                     // test the msb of the lsb
6726                     emitcode ("anl", "a,#!constbyte",0xfe);
6727                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6728                   sizer--;
6729                 }
6730               // val = (0,1)
6731               emitcode ("rrc", "a");
6732             }
6733           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6734           emitcode ("cpl", "c");
6735           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6736         }
6737       // bit = c
6738       // val = c
6739       if (size)
6740         outBitC (result);
6741       // if(bit | ...)
6742       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6743         genIfxJump (ifx, "c");
6744       goto release;
6745     }
6746
6747   if (sameRegs (AOP (result), AOP (left)))
6748     {
6749       /* if left is same as result */
6750       for (; size--; offset++)
6751         {
6752           if (AOP_TYPE (right) == AOP_LIT)
6753             {
6754               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6755                 continue;
6756               else if (IS_AOP_PREG (left))
6757                 {
6758                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6759                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6760                   aopPut (AOP (result), "a", offset);
6761                 }
6762               else
6763                 emitcode ("xrl", "%s,%s",
6764                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6765                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6766             }
6767           else
6768             {
6769               if (AOP_TYPE (left) == AOP_ACC)
6770                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6771               else
6772                 {
6773                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6774                   if (IS_AOP_PREG (left))
6775                     {
6776                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6777                       aopPut (AOP (result), "a", offset);
6778                     }
6779                   else
6780                     emitcode ("xrl", "%s,a",
6781                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6782                 }
6783             }
6784         }
6785     }
6786   else
6787     {
6788       // left & result in different registers
6789       if (AOP_TYPE (result) == AOP_CRY)
6790         {
6791           // result = bit
6792           // if(size), result in bit
6793           // if(!size && ifx), conditional oper: if(left ^ right)
6794           symbol *tlbl = newiTempLabel (NULL);
6795           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6796                   
6797           if (size)
6798             emitcode ("setb", "c");
6799           while (sizer--)
6800             {
6801               if ((AOP_TYPE (right) == AOP_LIT) &&
6802                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6803                 {
6804                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6805                 }
6806               else
6807                 {
6808                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6809                     emitcode ("xrl", "a,%s",
6810                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6811                   } else {
6812                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6813                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6814                       {
6815                           emitcode("mov", "b,a");
6816                           rOp = "b";
6817                       }
6818                         
6819                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6820                       emitcode ("xrl", "a,%s", rOp);                  
6821                   }
6822                 }
6823               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6824               offset++;
6825             }
6826           if (size)
6827             {
6828               CLRC;
6829               emitcode ("", "!tlabeldef", tlbl->key + 100);
6830               outBitC (result);
6831             }
6832           else if (ifx)
6833             jmpTrueOrFalse (ifx, tlbl);
6834         }
6835       else
6836         {
6837         for (; (size--); offset++)
6838           {
6839             // normal case
6840             // result = left & right
6841             if (AOP_TYPE (right) == AOP_LIT)
6842               {
6843                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6844                   {
6845                     aopPut (AOP (result),
6846                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6847                             offset);
6848                     continue;
6849                   }
6850                 D (emitcode (";", "better literal XOR."););
6851                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6852                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6853                                                   FALSE, FALSE, FALSE));
6854               }
6855             else
6856               {
6857                 // faster than result <- left, anl result,right
6858                 // and better if result is SFR
6859                 if (AOP_TYPE (left) == AOP_ACC)
6860                   {
6861                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6862                                                      FALSE, FALSE, FALSE));
6863                   }
6864                 else
6865                   {
6866                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6867                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6868                       {
6869                           emitcode("mov", "b,a");
6870                           rOp = "b";
6871                       }
6872                         
6873                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6874                       emitcode ("xrl", "a,%s", rOp);
6875                   }
6876               }
6877             aopPut (AOP (result), "a", offset);
6878           }
6879         }
6880         
6881     }
6882
6883 release:
6884   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6885   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6886   freeAsmop (result, NULL, ic, TRUE);
6887 }
6888
6889 /*-----------------------------------------------------------------*/
6890 /* genInline - write the inline code out                           */
6891 /*-----------------------------------------------------------------*/
6892 static void
6893 genInline (iCode * ic)
6894 {
6895   char *buffer, *bp, *bp1;
6896
6897   D (emitcode (";", "genInline ");
6898     );
6899
6900   _G.inLine += (!options.asmpeep);
6901
6902   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6903   strcpy (buffer, IC_INLINE (ic));
6904
6905   /* emit each line as a code */
6906   while (*bp)
6907     {
6908       if (*bp == '\n')
6909         {
6910           *bp++ = '\0';
6911           emitcode (bp1, "");
6912           bp1 = bp;
6913         }
6914       else
6915         {
6916           if (*bp == ':')
6917             {
6918               bp++;
6919               *bp = '\0';
6920               bp++;
6921               emitcode (bp1, "");
6922               bp1 = bp;
6923             }
6924           else
6925             bp++;
6926         }
6927     }
6928   if (bp1 != bp)
6929     emitcode (bp1, "");
6930   /*     emitcode("",buffer); */
6931   _G.inLine -= (!options.asmpeep);
6932 }
6933
6934 /*-----------------------------------------------------------------*/
6935 /* genRRC - rotate right with carry                                */
6936 /*-----------------------------------------------------------------*/
6937 static void
6938 genRRC (iCode * ic)
6939 {
6940   operand *left, *result;
6941   int size, offset = 0;
6942   char *l;
6943
6944   D (emitcode (";", "genRRC ");
6945     );
6946
6947   /* rotate right with carry */
6948   left = IC_LEFT (ic);
6949   result = IC_RESULT (ic);
6950   aopOp (left, ic, FALSE, FALSE);
6951   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6952
6953   /* move it to the result */
6954   size = AOP_SIZE (result);
6955   offset = size - 1;
6956   CLRC;
6957
6958   _startLazyDPSEvaluation ();
6959   while (size--)
6960     {
6961       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6962       MOVA (l);
6963       emitcode ("rrc", "a");
6964       if (AOP_SIZE (result) > 1)
6965         aopPut (AOP (result), "a", offset--);
6966     }
6967   _endLazyDPSEvaluation ();
6968
6969   /* now we need to put the carry into the
6970      highest order byte of the result */
6971   if (AOP_SIZE (result) > 1)
6972     {
6973       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6974       MOVA (l);
6975     }
6976   emitcode ("mov", "acc.7,c");
6977   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6978   freeAsmop (left, NULL, ic, TRUE);
6979   freeAsmop (result, NULL, ic, TRUE);
6980 }
6981
6982 /*-----------------------------------------------------------------*/
6983 /* genRLC - generate code for rotate left with carry               */
6984 /*-----------------------------------------------------------------*/
6985 static void
6986 genRLC (iCode * ic)
6987 {
6988   operand *left, *result;
6989   int size, offset = 0;
6990   char *l;
6991
6992   D (emitcode (";", "genRLC ");
6993     );
6994
6995   /* rotate right with carry */
6996   left = IC_LEFT (ic);
6997   result = IC_RESULT (ic);
6998   aopOp (left, ic, FALSE, FALSE);
6999   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7000
7001   /* move it to the result */
7002   size = AOP_SIZE (result);
7003   offset = 0;
7004   if (size--)
7005     {
7006       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7007       MOVA (l);
7008       emitcode ("add", "a,acc");
7009       if (AOP_SIZE (result) > 1)
7010         {
7011           aopPut (AOP (result), "a", offset++);
7012         }
7013
7014       _startLazyDPSEvaluation ();
7015       while (size--)
7016         {
7017           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7018           MOVA (l);
7019           emitcode ("rlc", "a");
7020           if (AOP_SIZE (result) > 1)
7021             aopPut (AOP (result), "a", offset++);
7022         }
7023       _endLazyDPSEvaluation ();
7024     }
7025   /* now we need to put the carry into the
7026      highest order byte of the result */
7027   if (AOP_SIZE (result) > 1)
7028     {
7029       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7030       MOVA (l);
7031     }
7032   emitcode ("mov", "acc.0,c");
7033   aopPut (AOP (result), "a", 0);
7034   freeAsmop (left, NULL, ic, TRUE);
7035   freeAsmop (result, NULL, ic, TRUE);
7036 }
7037
7038 /*-----------------------------------------------------------------*/
7039 /* genGetHbit - generates code get highest order bit               */
7040 /*-----------------------------------------------------------------*/
7041 static void
7042 genGetHbit (iCode * ic)
7043 {
7044   operand *left, *result;
7045   left = IC_LEFT (ic);
7046   result = IC_RESULT (ic);
7047   aopOp (left, ic, FALSE, FALSE);
7048   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7049
7050   D (emitcode (";", "genGetHbit ");
7051     );
7052
7053   /* get the highest order byte into a */
7054   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7055   if (AOP_TYPE (result) == AOP_CRY)
7056     {
7057       emitcode ("rlc", "a");
7058       outBitC (result);
7059     }
7060   else
7061     {
7062       emitcode ("rl", "a");
7063       emitcode ("anl", "a,#1");
7064       outAcc (result);
7065     }
7066
7067
7068   freeAsmop (left, NULL, ic, TRUE);
7069   freeAsmop (result, NULL, ic, TRUE);
7070 }
7071
7072 /*-----------------------------------------------------------------*/
7073 /* AccRol - rotate left accumulator by known count                 */
7074 /*-----------------------------------------------------------------*/
7075 static void
7076 AccRol (int shCount)
7077 {
7078   shCount &= 0x0007;            // shCount : 0..7
7079
7080   switch (shCount)
7081     {
7082     case 0:
7083       break;
7084     case 1:
7085       emitcode ("rl", "a");
7086       break;
7087     case 2:
7088       emitcode ("rl", "a");
7089       emitcode ("rl", "a");
7090       break;
7091     case 3:
7092       emitcode ("swap", "a");
7093       emitcode ("rr", "a");
7094       break;
7095     case 4:
7096       emitcode ("swap", "a");
7097       break;
7098     case 5:
7099       emitcode ("swap", "a");
7100       emitcode ("rl", "a");
7101       break;
7102     case 6:
7103       emitcode ("rr", "a");
7104       emitcode ("rr", "a");
7105       break;
7106     case 7:
7107       emitcode ("rr", "a");
7108       break;
7109     }
7110 }
7111
7112 /*-----------------------------------------------------------------*/
7113 /* AccLsh - left shift accumulator by known count                  */
7114 /*-----------------------------------------------------------------*/
7115 static void
7116 AccLsh (int shCount)
7117 {
7118   if (shCount != 0)
7119     {
7120       if (shCount == 1)
7121         emitcode ("add", "a,acc");
7122       else if (shCount == 2)
7123         {
7124           emitcode ("add", "a,acc");
7125           emitcode ("add", "a,acc");
7126         }
7127       else
7128         {
7129           /* rotate left accumulator */
7130           AccRol (shCount);
7131           /* and kill the lower order bits */
7132           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7133         }
7134     }
7135 }
7136
7137 /*-----------------------------------------------------------------*/
7138 /* AccRsh - right shift accumulator by known count                 */
7139 /*-----------------------------------------------------------------*/
7140 static void
7141 AccRsh (int shCount)
7142 {
7143   if (shCount != 0)
7144     {
7145       if (shCount == 1)
7146         {
7147           CLRC;
7148           emitcode ("rrc", "a");
7149         }
7150       else
7151         {
7152           /* rotate right accumulator */
7153           AccRol (8 - shCount);
7154           /* and kill the higher order bits */
7155           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7156         }
7157     }
7158 }
7159
7160 #ifdef BETTER_LITERAL_SHIFT
7161 /*-----------------------------------------------------------------*/
7162 /* AccSRsh - signed right shift accumulator by known count                 */
7163 /*-----------------------------------------------------------------*/
7164 static void
7165 AccSRsh (int shCount)
7166 {
7167   symbol *tlbl;
7168   if (shCount != 0)
7169     {
7170       if (shCount == 1)
7171         {
7172           emitcode ("mov", "c,acc.7");
7173           emitcode ("rrc", "a");
7174         }
7175       else if (shCount == 2)
7176         {
7177           emitcode ("mov", "c,acc.7");
7178           emitcode ("rrc", "a");
7179           emitcode ("mov", "c,acc.7");
7180           emitcode ("rrc", "a");
7181         }
7182       else
7183         {
7184           tlbl = newiTempLabel (NULL);
7185           /* rotate right accumulator */
7186           AccRol (8 - shCount);
7187           /* and kill the higher order bits */
7188           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7189           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7190           emitcode ("orl", "a,#!constbyte",
7191                     (unsigned char) ~SRMask[shCount]);
7192           emitcode ("", "!tlabeldef", tlbl->key + 100);
7193         }
7194     }
7195 }
7196 #endif
7197
7198 #ifdef BETTER_LITERAL_SHIFT
7199 /*-----------------------------------------------------------------*/
7200 /* shiftR1Left2Result - shift right one byte from left to result   */
7201 /*-----------------------------------------------------------------*/
7202 static void
7203 shiftR1Left2Result (operand * left, int offl,
7204                     operand * result, int offr,
7205                     int shCount, int sign)
7206 {
7207   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7208   /* shift right accumulator */
7209   if (sign)
7210     AccSRsh (shCount);
7211   else
7212     AccRsh (shCount);
7213   aopPut (AOP (result), "a", offr);
7214 }
7215 #endif
7216
7217 #ifdef BETTER_LITERAL_SHIFT
7218 /*-----------------------------------------------------------------*/
7219 /* shiftL1Left2Result - shift left one byte from left to result    */
7220 /*-----------------------------------------------------------------*/
7221 static void
7222 shiftL1Left2Result (operand * left, int offl,
7223                     operand * result, int offr, int shCount)
7224 {
7225   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7226   /* shift left accumulator */
7227   AccLsh (shCount);
7228   aopPut (AOP (result), "a", offr);
7229 }
7230 #endif
7231
7232 #ifdef BETTER_LITERAL_SHIFT
7233 /*-----------------------------------------------------------------*/
7234 /* movLeft2Result - move byte from left to result                  */
7235 /*-----------------------------------------------------------------*/
7236 static void
7237 movLeft2Result (operand * left, int offl,
7238                 operand * result, int offr, int sign)
7239 {
7240   char *l;
7241   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7242   {
7243       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7244
7245       if (*l == '@' && (IS_AOP_PREG (result)))
7246       {
7247           emitcode ("mov", "a,%s", l);
7248           aopPut (AOP (result), "a", offr);
7249       }
7250       else
7251       {
7252           if (!sign)
7253           {
7254             aopPut (AOP (result), l, offr);
7255           }
7256           else
7257             {
7258               /* MSB sign in acc.7 ! */
7259               if (getDataSize (left) == offl + 1)
7260                 {
7261                   emitcode ("mov", "a,%s", l);
7262                   aopPut (AOP (result), "a", offr);
7263                 }
7264             }
7265       }
7266   }
7267 }
7268 #endif
7269
7270 #ifdef BETTER_LITERAL_SHIFT
7271 /*-----------------------------------------------------------------*/
7272 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7273 /*-----------------------------------------------------------------*/
7274 static void
7275 AccAXRrl1 (char *x)
7276 {
7277   emitcode ("rrc", "a");
7278   emitcode ("xch", "a,%s", x);
7279   emitcode ("rrc", "a");
7280   emitcode ("xch", "a,%s", x);
7281 }
7282 #endif
7283
7284 #ifdef BETTER_LITERAL_SHIFT
7285 //REMOVE ME!!!
7286 /*-----------------------------------------------------------------*/
7287 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7288 /*-----------------------------------------------------------------*/
7289 static void
7290 AccAXLrl1 (char *x)
7291 {
7292   emitcode ("xch", "a,%s", x);
7293   emitcode ("rlc", "a");
7294   emitcode ("xch", "a,%s", x);
7295   emitcode ("rlc", "a");
7296 }
7297 #endif
7298
7299 #ifdef BETTER_LITERAL_SHIFT
7300 /*-----------------------------------------------------------------*/
7301 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7302 /*-----------------------------------------------------------------*/
7303 static void
7304 AccAXLsh1 (char *x)
7305 {
7306   emitcode ("xch", "a,%s", x);
7307   emitcode ("add", "a,acc");
7308   emitcode ("xch", "a,%s", x);
7309   emitcode ("rlc", "a");
7310 }
7311 #endif
7312
7313 #ifdef BETTER_LITERAL_SHIFT
7314 /*-----------------------------------------------------------------*/
7315 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7316 /*-----------------------------------------------------------------*/
7317 static void
7318 AccAXLsh (char *x, int shCount)
7319 {
7320   switch (shCount)
7321     {
7322     case 0:
7323       break;
7324     case 1:
7325       AccAXLsh1 (x);
7326       break;
7327     case 2:
7328       AccAXLsh1 (x);
7329       AccAXLsh1 (x);
7330       break;
7331     case 3:
7332     case 4:
7333     case 5:                     // AAAAABBB:CCCCCDDD
7334
7335       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7336
7337       emitcode ("anl", "a,#!constbyte",
7338                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7339
7340       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7341
7342       AccRol (shCount);         // DDDCCCCC:BBB00000
7343
7344       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7345
7346       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7347
7348       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7349
7350       emitcode ("anl", "a,#!constbyte",
7351                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7352
7353       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7354
7355       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7356
7357       break;
7358     case 6:                     // AAAAAABB:CCCCCCDD
7359       emitcode ("anl", "a,#!constbyte",
7360                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7361       emitcode ("mov", "c,acc.0");      // c = B
7362       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7363 #if 0
7364       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7365       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7366 #else
7367       emitcode("rrc","a"); 
7368       emitcode("xch","a,%s", x); 
7369       emitcode("rrc","a"); 
7370       emitcode("mov","c,acc.0"); //<< get correct bit 
7371       emitcode("xch","a,%s", x); 
7372
7373       emitcode("rrc","a"); 
7374       emitcode("xch","a,%s", x); 
7375       emitcode("rrc","a"); 
7376       emitcode("xch","a,%s", x); 
7377 #endif
7378       break;
7379     case 7:                     // a:x <<= 7
7380
7381       emitcode ("anl", "a,#!constbyte",
7382                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7383
7384       emitcode ("mov", "c,acc.0");      // c = B
7385
7386       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7387
7388       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7389
7390       break;
7391     default:
7392       break;
7393     }
7394 }
7395 #endif
7396
7397 #ifdef BETTER_LITERAL_SHIFT
7398 //REMOVE ME!!!
7399 /*-----------------------------------------------------------------*/
7400 /* AccAXRsh - right shift a:x known count (0..7)                   */
7401 /*-----------------------------------------------------------------*/
7402 static void
7403 AccAXRsh (char *x, int shCount)
7404 {
7405   switch (shCount)
7406     {
7407     case 0:
7408       break;
7409     case 1:
7410       CLRC;
7411       AccAXRrl1 (x);            // 0->a:x
7412
7413       break;
7414     case 2:
7415       CLRC;
7416       AccAXRrl1 (x);            // 0->a:x
7417
7418       CLRC;
7419       AccAXRrl1 (x);            // 0->a:x
7420
7421       break;
7422     case 3:
7423     case 4:
7424     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7425
7426       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7427
7428       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7429
7430       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7431
7432       emitcode ("anl", "a,#!constbyte",
7433                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7434
7435       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7436
7437       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7438
7439       emitcode ("anl", "a,#!constbyte",
7440                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7441
7442       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7443
7444       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7445
7446       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7447
7448       break;
7449     case 6:                     // AABBBBBB:CCDDDDDD
7450
7451       emitcode ("mov", "c,acc.7");
7452       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7453
7454       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7455
7456       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7457
7458       emitcode ("anl", "a,#!constbyte",
7459                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7460
7461       break;
7462     case 7:                     // ABBBBBBB:CDDDDDDD
7463
7464       emitcode ("mov", "c,acc.7");      // c = A
7465
7466       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7467
7468       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7469
7470       emitcode ("anl", "a,#!constbyte",
7471                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7472
7473       break;
7474     default:
7475       break;
7476     }
7477 }
7478 #endif
7479
7480 #ifdef BETTER_LITERAL_SHIFT
7481 /*-----------------------------------------------------------------*/
7482 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7483 /*-----------------------------------------------------------------*/
7484 static void
7485 AccAXRshS (char *x, int shCount)
7486 {
7487   symbol *tlbl;
7488   switch (shCount)
7489     {
7490     case 0:
7491       break;
7492     case 1:
7493       emitcode ("mov", "c,acc.7");
7494       AccAXRrl1 (x);            // s->a:x
7495
7496       break;
7497     case 2:
7498       emitcode ("mov", "c,acc.7");
7499       AccAXRrl1 (x);            // s->a:x
7500
7501       emitcode ("mov", "c,acc.7");
7502       AccAXRrl1 (x);            // s->a:x
7503
7504       break;
7505     case 3:
7506     case 4:
7507     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7508
7509       tlbl = newiTempLabel (NULL);
7510       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7511
7512       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7513
7514       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7515
7516       emitcode ("anl", "a,#!constbyte",
7517                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7518
7519       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7520
7521       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7522
7523       emitcode ("anl", "a,#!constbyte",
7524                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7525
7526       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7527
7528       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7529
7530       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7531
7532       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7533       emitcode ("orl", "a,#!constbyte",
7534                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7535
7536       emitcode ("", "!tlabeldef", tlbl->key + 100);
7537       break;                    // SSSSAAAA:BBBCCCCC
7538
7539     case 6:                     // AABBBBBB:CCDDDDDD
7540
7541       tlbl = newiTempLabel (NULL);
7542       emitcode ("mov", "c,acc.7");
7543       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7544
7545       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7546
7547       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7548
7549       emitcode ("anl", "a,#!constbyte",
7550                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7551
7552       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7553       emitcode ("orl", "a,#!constbyte",
7554                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7555
7556       emitcode ("", "!tlabeldef", tlbl->key + 100);
7557       break;
7558     case 7:                     // ABBBBBBB:CDDDDDDD
7559
7560       tlbl = newiTempLabel (NULL);
7561       emitcode ("mov", "c,acc.7");      // c = A
7562
7563       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7564
7565       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7566
7567       emitcode ("anl", "a,#!constbyte",
7568                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7569
7570       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7571       emitcode ("orl", "a,#!constbyte",
7572                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7573
7574       emitcode ("", "!tlabeldef", tlbl->key + 100);
7575       break;
7576     default:
7577       break;
7578     }
7579 }
7580 #endif
7581
7582 #ifdef BETTER_LITERAL_SHIFT
7583 static void
7584 _loadLeftIntoAx(char    **lsb, 
7585                 operand *left, 
7586                 operand *result,
7587                 int     offl,
7588                 int     offr)
7589 {
7590   // Get the initial value from left into a pair of registers.
7591   // MSB must be in A, LSB can be any register.
7592   //
7593   // If the result is held in registers, it is an optimization
7594   // if the LSB can be held in the register which will hold the,
7595   // result LSB since this saves us from having to copy it into
7596   // the result following AccAXLsh.
7597   //
7598   // If the result is addressed indirectly, this is not a gain.
7599   if (AOP_NEEDSACC(result))
7600   {
7601        char *leftByte;
7602        
7603        _startLazyDPSEvaluation();
7604       if (AOP_TYPE(left) == AOP_DPTR2)
7605        {
7606            // Get MSB in A.
7607            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7608            // get LSB in DP2_RESULT_REG.
7609            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7610            assert(!strcmp(leftByte, DP2_RESULT_REG));
7611        }
7612        else
7613        {
7614            // get LSB into DP2_RESULT_REG
7615            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7616            if (strcmp(leftByte, DP2_RESULT_REG))
7617            {
7618                TR_AP("#7");
7619                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7620            }
7621            // And MSB in A.
7622            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7623            assert(strcmp(leftByte, DP2_RESULT_REG));
7624            MOVA(leftByte);
7625        }
7626        _endLazyDPSEvaluation();
7627        *lsb = DP2_RESULT_REG;
7628   }
7629   else
7630   {
7631       if (sameRegs (AOP (result), AOP (left)) &&
7632         ((offl + MSB16) == offr))
7633       {
7634           /* don't crash result[offr] */
7635           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7636           emitcode ("xch", "a,%s", 
7637                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7638       }
7639       else
7640       {
7641           movLeft2Result (left, offl, result, offr, 0);
7642           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7643       }
7644       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7645       assert(strcmp(*lsb,"a"));      
7646   }
7647 }
7648
7649 static void
7650 _storeAxResults(char    *lsb,
7651                 operand *result,
7652                 int     offr)
7653 {
7654   _startLazyDPSEvaluation();
7655   if (AOP_NEEDSACC(result))
7656   {
7657       /* We have to explicitly update the result LSB.
7658        */
7659       emitcode("xch","a,%s", lsb);
7660       aopPut(AOP(result), "a", offr);
7661       emitcode("mov","a,%s", lsb);
7662   }
7663   if (getDataSize (result) > 1)
7664   {
7665       aopPut (AOP (result), "a", offr + MSB16);
7666   }
7667   _endLazyDPSEvaluation();
7668 }
7669
7670 /*-----------------------------------------------------------------*/
7671 /* shiftL2Left2Result - shift left two bytes from left to result   */
7672 /*-----------------------------------------------------------------*/
7673 static void
7674 shiftL2Left2Result (operand * left, int offl,
7675                     operand * result, int offr, int shCount)
7676 {
7677   char *lsb;
7678
7679   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7680   
7681   AccAXLsh (lsb, shCount);
7682   
7683   _storeAxResults(lsb, result, offr);
7684 }
7685 #endif
7686
7687 #ifdef BETTER_LITERAL_SHIFT
7688 /*-----------------------------------------------------------------*/
7689 /* shiftR2Left2Result - shift right two bytes from left to result  */
7690 /*-----------------------------------------------------------------*/
7691 static void
7692 shiftR2Left2Result (operand * left, int offl,
7693                     operand * result, int offr,
7694                     int shCount, int sign)
7695 {
7696   char *lsb;
7697   
7698   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7699   
7700   /* a:x >> shCount (x = lsb(result)) */
7701   if (sign)
7702   {
7703      AccAXRshS(lsb, shCount);
7704   }
7705   else
7706   {
7707     AccAXRsh(lsb, shCount);
7708   }
7709   
7710   _storeAxResults(lsb, result, offr);
7711 }
7712 #endif
7713
7714 #if 0
7715 //REMOVE ME!!!
7716 /*-----------------------------------------------------------------*/
7717 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7718 /*-----------------------------------------------------------------*/
7719 static void
7720 shiftLLeftOrResult (operand * left, int offl,
7721                     operand * result, int offr, int shCount)
7722 {
7723   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7724   /* shift left accumulator */
7725   AccLsh (shCount);
7726   /* or with result */
7727   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7728   /* back to result */
7729   aopPut (AOP (result), "a", offr);
7730 }
7731 #endif
7732
7733 #if 0
7734 //REMOVE ME!!!
7735 /*-----------------------------------------------------------------*/
7736 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7737 /*-----------------------------------------------------------------*/
7738 static void
7739 shiftRLeftOrResult (operand * left, int offl,
7740                     operand * result, int offr, int shCount)
7741 {
7742   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7743   /* shift right accumulator */
7744   AccRsh (shCount);
7745   /* or with result */
7746   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7747   /* back to result */
7748   aopPut (AOP (result), "a", offr);
7749 }
7750 #endif
7751
7752 #ifdef BETTER_LITERAL_SHIFT
7753 /*-----------------------------------------------------------------*/
7754 /* genlshOne - left shift a one byte quantity by known count       */
7755 /*-----------------------------------------------------------------*/
7756 static void
7757 genlshOne (operand * result, operand * left, int shCount)
7758 {
7759   D (emitcode (";", "genlshOne "););
7760   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7761 }
7762 #endif
7763
7764 #ifdef BETTER_LITERAL_SHIFT
7765 /*-----------------------------------------------------------------*/
7766 /* genlshTwo - left shift two bytes by known amount != 0           */
7767 /*-----------------------------------------------------------------*/
7768 static void
7769 genlshTwo (operand * result, operand * left, int shCount)
7770 {
7771   int size;
7772
7773   D (emitcode (";", "genlshTwo "););
7774
7775   size = getDataSize (result);
7776
7777   /* if shCount >= 8 */
7778   if (shCount >= 8)
7779   {
7780       shCount -= 8;
7781
7782       _startLazyDPSEvaluation();
7783
7784       if (size > 1)
7785         {
7786           if (shCount)
7787           {
7788             _endLazyDPSEvaluation();
7789             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7790             aopPut (AOP (result), zero, LSB);       
7791           }
7792           else
7793           {
7794             movLeft2Result (left, LSB, result, MSB16, 0);
7795             aopPut (AOP (result), zero, LSB);
7796             _endLazyDPSEvaluation();
7797           }
7798         }
7799         else
7800         {
7801           aopPut (AOP (result), zero, LSB);
7802           _endLazyDPSEvaluation();
7803         }
7804   }
7805
7806   /*  1 <= shCount <= 7 */
7807   else
7808     {
7809       if (size == 1)
7810       {
7811         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7812       }
7813       else
7814       {
7815         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7816       }
7817     }
7818 }
7819 #endif
7820
7821 #if 0
7822 //REMOVE ME!!!
7823 /*-----------------------------------------------------------------*/
7824 /* shiftLLong - shift left one long from left to result            */
7825 /* offl = LSB or MSB16                                             */
7826 /*-----------------------------------------------------------------*/
7827 static void
7828 shiftLLong (operand * left, operand * result, int offr)
7829 {
7830   char *l;
7831   int size = AOP_SIZE (result);
7832
7833   if (size >= LSB + offr)
7834     {
7835       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7836       MOVA (l);
7837       emitcode ("add", "a,acc");
7838       if (sameRegs (AOP (left), AOP (result)) &&
7839           size >= MSB16 + offr && offr != LSB)
7840         emitcode ("xch", "a,%s",
7841                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7842       else
7843         aopPut (AOP (result), "a", LSB + offr);
7844     }
7845
7846   if (size >= MSB16 + offr)
7847     {
7848       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7849         {
7850           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7851           MOVA (l);
7852         }
7853       emitcode ("rlc", "a");
7854       if (sameRegs (AOP (left), AOP (result)) &&
7855           size >= MSB24 + offr && offr != LSB)
7856         emitcode ("xch", "a,%s",
7857                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7858       else
7859         aopPut (AOP (result), "a", MSB16 + offr);
7860     }
7861
7862   if (size >= MSB24 + offr)
7863     {
7864       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7865         {
7866           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7867           MOVA (l);
7868         }
7869       emitcode ("rlc", "a");
7870       if (sameRegs (AOP (left), AOP (result)) &&
7871           size >= MSB32 + offr && offr != LSB)
7872         emitcode ("xch", "a,%s",
7873                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7874       else
7875         aopPut (AOP (result), "a", MSB24 + offr);
7876     }
7877
7878   if (size > MSB32 + offr)
7879     {
7880       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7881         {
7882           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7883           MOVA (l);
7884         }
7885       emitcode ("rlc", "a");
7886       aopPut (AOP (result), "a", MSB32 + offr);
7887     }
7888   if (offr != LSB)
7889     aopPut (AOP (result), zero, LSB);
7890 }
7891 #endif
7892
7893 #if 0
7894 //REMOVE ME!!!
7895 /*-----------------------------------------------------------------*/
7896 /* genlshFour - shift four byte by a known amount != 0             */
7897 /*-----------------------------------------------------------------*/
7898 static void
7899 genlshFour (operand * result, operand * left, int shCount)
7900 {
7901   int size;
7902
7903   D (emitcode (";", "genlshFour ");
7904     );
7905
7906   size = AOP_SIZE (result);
7907
7908   /* if shifting more that 3 bytes */
7909   if (shCount >= 24)
7910     {
7911       shCount -= 24;
7912       if (shCount)
7913         /* lowest order of left goes to the highest
7914            order of the destination */
7915         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7916       else
7917         movLeft2Result (left, LSB, result, MSB32, 0);
7918       aopPut (AOP (result), zero, LSB);
7919       aopPut (AOP (result), zero, MSB16);
7920       aopPut (AOP (result), zero, MSB24);
7921       return;
7922     }
7923
7924   /* more than two bytes */
7925   else if (shCount >= 16)
7926     {
7927       /* lower order two bytes goes to higher order two bytes */
7928       shCount -= 16;
7929       /* if some more remaining */
7930       if (shCount)
7931         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7932       else
7933         {
7934           movLeft2Result (left, MSB16, result, MSB32, 0);
7935           movLeft2Result (left, LSB, result, MSB24, 0);
7936         }
7937       aopPut (AOP (result), zero, MSB16);
7938       aopPut (AOP (result), zero, LSB);
7939       return;
7940     }
7941
7942   /* if more than 1 byte */
7943   else if (shCount >= 8)
7944     {
7945       /* lower order three bytes goes to higher order  three bytes */
7946       shCount -= 8;
7947       if (size == 2)
7948         {
7949           if (shCount)
7950             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7951           else
7952             movLeft2Result (left, LSB, result, MSB16, 0);
7953         }
7954       else
7955         {                       /* size = 4 */
7956           if (shCount == 0)
7957             {
7958               movLeft2Result (left, MSB24, result, MSB32, 0);
7959               movLeft2Result (left, MSB16, result, MSB24, 0);
7960               movLeft2Result (left, LSB, result, MSB16, 0);
7961               aopPut (AOP (result), zero, LSB);
7962             }
7963           else if (shCount == 1)
7964             shiftLLong (left, result, MSB16);
7965           else
7966             {
7967               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7968               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7969               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7970               aopPut (AOP (result), zero, LSB);
7971             }
7972         }
7973     }
7974
7975   /* 1 <= shCount <= 7 */
7976   else if (shCount <= 2)
7977     {
7978       shiftLLong (left, result, LSB);
7979       if (shCount == 2)
7980         shiftLLong (result, result, LSB);
7981     }
7982   /* 3 <= shCount <= 7, optimize */
7983   else
7984     {
7985       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7986       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7987       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7988     }
7989 }
7990 #endif
7991
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* genLeftShiftLiteral - left shifting by known count              */
7995 /*-----------------------------------------------------------------*/
7996 static bool
7997 genLeftShiftLiteral (operand * left,
7998                      operand * right,
7999                      operand * result,
8000                      iCode * ic)
8001 {
8002   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8003   int size;
8004
8005   size = getSize (operandType (result));
8006
8007   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8008
8009   /* We only handle certain easy cases so far. */
8010   if ((shCount != 0)
8011    && (shCount < (size * 8))
8012    && (size != 1)
8013    && (size != 2))
8014   {
8015       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8016       return FALSE;
8017   }
8018
8019   freeAsmop (right, NULL, ic, TRUE);
8020
8021   aopOp(left, ic, FALSE, FALSE);
8022   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8023
8024 #if 0 // debug spew
8025   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8026   {
8027         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8028         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8029         {
8030            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8031         }
8032   }
8033   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8034   {
8035         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8036         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8037         {
8038            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8039         }       
8040   }  
8041 #endif
8042   
8043 #if VIEW_SIZE
8044   emitcode ("; shift left ", "result %d, left %d", size,
8045             AOP_SIZE (left));
8046 #endif
8047
8048   /* I suppose that the left size >= result size */
8049   if (shCount == 0)
8050   {
8051         _startLazyDPSEvaluation();
8052         while (size--)
8053         {
8054           movLeft2Result (left, size, result, size, 0);
8055         }
8056         _endLazyDPSEvaluation();
8057   }
8058   else if (shCount >= (size * 8))
8059   {
8060     _startLazyDPSEvaluation();
8061     while (size--)
8062     {
8063       aopPut (AOP (result), zero, size);
8064     }
8065     _endLazyDPSEvaluation();
8066   }
8067   else
8068   {
8069       switch (size)
8070         {
8071         case 1:
8072           genlshOne (result, left, shCount);
8073           break;
8074
8075         case 2:
8076           genlshTwo (result, left, shCount);
8077           break;
8078 #if 0
8079         case 4:
8080           genlshFour (result, left, shCount);
8081           break;
8082 #endif
8083         default:
8084           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8085           break;
8086         }
8087     }
8088   freeAsmop (left, NULL, ic, TRUE);
8089   freeAsmop (result, NULL, ic, TRUE);
8090   return TRUE;
8091 }
8092 #endif
8093
8094 /*-----------------------------------------------------------------*/
8095 /* genLeftShift - generates code for left shifting                 */
8096 /*-----------------------------------------------------------------*/
8097 static void
8098 genLeftShift (iCode * ic)
8099 {
8100   operand *left, *right, *result;
8101   int size, offset;
8102   char *l;
8103   symbol *tlbl, *tlbl1;
8104
8105   D (emitcode (";", "genLeftShift "););
8106
8107   right = IC_RIGHT (ic);
8108   left = IC_LEFT (ic);
8109   result = IC_RESULT (ic);
8110
8111   aopOp (right, ic, FALSE, FALSE);
8112
8113
8114 #ifdef BETTER_LITERAL_SHIFT
8115   /* if the shift count is known then do it
8116      as efficiently as possible */
8117   if (AOP_TYPE (right) == AOP_LIT)
8118     {
8119       if (genLeftShiftLiteral (left, right, result, ic))
8120       {
8121         return;
8122       }
8123     }
8124 #endif
8125
8126   /* shift count is unknown then we have to form
8127      a loop get the loop count in B : Note: we take
8128      only the lower order byte since shifting
8129      more that 32 bits make no sense anyway, ( the
8130      largest size of an object can be only 32 bits ) */
8131
8132   if (AOP_TYPE (right) == AOP_LIT)
8133   {
8134       /* Really should be handled by genLeftShiftLiteral,
8135        * but since I'm too lazy to fix that today, at least we can make
8136        * some small improvement.
8137        */
8138        emitcode("mov", "b,#!constbyte",
8139                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8140   }
8141   else
8142   {
8143         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8144         emitcode ("inc", "b");
8145   }
8146   freeAsmop (right, NULL, ic, TRUE);
8147   aopOp (left, ic, FALSE, FALSE);
8148   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8149
8150   /* now move the left to the result if they are not the
8151      same */
8152   if (!sameRegs (AOP (left), AOP (result)) &&
8153       AOP_SIZE (result) > 1)
8154     {
8155
8156       size = AOP_SIZE (result);
8157       offset = 0;
8158       _startLazyDPSEvaluation ();
8159       while (size--)
8160         {
8161           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8162           if (*l == '@' && (IS_AOP_PREG (result)))
8163             {
8164
8165               emitcode ("mov", "a,%s", l);
8166               aopPut (AOP (result), "a", offset);
8167             }
8168           else
8169             aopPut (AOP (result), l, offset);
8170           offset++;
8171         }
8172       _endLazyDPSEvaluation ();
8173     }
8174
8175   tlbl = newiTempLabel (NULL);
8176   size = AOP_SIZE (result);
8177   offset = 0;
8178   tlbl1 = newiTempLabel (NULL);
8179
8180   /* if it is only one byte then */
8181   if (size == 1)
8182     {
8183       symbol *tlbl1 = newiTempLabel (NULL);
8184
8185       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8186       MOVA (l);
8187       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8188       emitcode ("", "!tlabeldef", tlbl->key + 100);
8189       emitcode ("add", "a,acc");
8190       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8191       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8192       aopPut (AOP (result), "a", 0);
8193       goto release;
8194     }
8195
8196   reAdjustPreg (AOP (result));
8197
8198   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8199   emitcode ("", "!tlabeldef", tlbl->key + 100);
8200   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8201   MOVA (l);
8202   emitcode ("add", "a,acc");
8203   aopPut (AOP (result), "a", offset++);
8204   _startLazyDPSEvaluation ();
8205   while (--size)
8206     {
8207       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8208       MOVA (l);
8209       emitcode ("rlc", "a");
8210       aopPut (AOP (result), "a", offset++);
8211     }
8212   _endLazyDPSEvaluation ();
8213   reAdjustPreg (AOP (result));
8214
8215   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8216   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8217 release:
8218   freeAsmop (left, NULL, ic, TRUE);
8219   freeAsmop (result, NULL, ic, TRUE);
8220 }
8221
8222 #ifdef BETTER_LITERAL_SHIFT
8223 /*-----------------------------------------------------------------*/
8224 /* genrshOne - right shift a one byte quantity by known count      */
8225 /*-----------------------------------------------------------------*/
8226 static void
8227 genrshOne (operand * result, operand * left,
8228            int shCount, int sign)
8229 {
8230   D (emitcode (";", "genrshOne"););
8231   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8232 }
8233 #endif
8234
8235 #ifdef BETTER_LITERAL_SHIFT
8236 /*-----------------------------------------------------------------*/
8237 /* genrshTwo - right shift two bytes by known amount != 0          */
8238 /*-----------------------------------------------------------------*/
8239 static void
8240 genrshTwo (operand * result, operand * left,
8241            int shCount, int sign)
8242 {
8243   D (emitcode (";", "genrshTwo"););
8244
8245   /* if shCount >= 8 */
8246   if (shCount >= 8)
8247     {
8248       shCount -= 8;
8249       _startLazyDPSEvaluation();
8250       if (shCount)
8251       {
8252         shiftR1Left2Result (left, MSB16, result, LSB,
8253                             shCount, sign);
8254       }                     
8255       else
8256       {
8257         movLeft2Result (left, MSB16, result, LSB, sign);
8258       }
8259       addSign (result, MSB16, sign);
8260       _endLazyDPSEvaluation();
8261     }
8262
8263   /*  1 <= shCount <= 7 */
8264   else
8265   {
8266     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8267   }
8268 }
8269 #endif
8270
8271 #if 0
8272 //REMOVE ME!!!
8273 /*-----------------------------------------------------------------*/
8274 /* shiftRLong - shift right one long from left to result           */
8275 /* offl = LSB or MSB16                                             */
8276 /*-----------------------------------------------------------------*/
8277 static void
8278 shiftRLong (operand * left, int offl,
8279             operand * result, int sign)
8280 {
8281   int isSameRegs=sameRegs(AOP(left),AOP(result));
8282
8283   if (isSameRegs && offl>1) {
8284     // we are in big trouble, but this shouldn't happen
8285     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8286   }
8287
8288   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8289   
8290   if (offl==MSB16) {
8291     // shift is > 8
8292     if (sign) {
8293       emitcode ("rlc", "a");
8294       emitcode ("subb", "a,acc");
8295       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8296     } else {
8297       aopPut (AOP(result), zero, MSB32);
8298     }
8299   }
8300
8301   if (!sign) {
8302     emitcode ("clr", "c");
8303   } else {
8304     emitcode ("mov", "c,acc.7");
8305   }
8306
8307   emitcode ("rrc", "a");
8308
8309   if (isSameRegs && offl==MSB16) {
8310     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8311   } else {
8312     aopPut (AOP (result), "a", MSB32);
8313     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8314   }
8315
8316   emitcode ("rrc", "a");
8317   if (isSameRegs && offl==1) {
8318     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8319   } else {
8320     aopPut (AOP (result), "a", MSB24);
8321     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8322   }
8323   emitcode ("rrc", "a");
8324   aopPut (AOP (result), "a", MSB16 - offl);
8325
8326   if (offl == LSB)
8327     {
8328       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8329       emitcode ("rrc", "a");
8330       aopPut (AOP (result), "a", LSB);
8331     }
8332 }
8333 #endif
8334
8335 #if 0
8336 //REMOVE ME!!!
8337 /*-----------------------------------------------------------------*/
8338 /* genrshFour - shift four byte by a known amount != 0             */
8339 /*-----------------------------------------------------------------*/
8340 static void
8341 genrshFour (operand * result, operand * left,
8342             int shCount, int sign)
8343 {
8344   D (emitcode (";", "genrshFour");
8345     );
8346
8347   /* if shifting more that 3 bytes */
8348   if (shCount >= 24)
8349     {
8350       shCount -= 24;
8351       if (shCount)
8352         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8353       else
8354         movLeft2Result (left, MSB32, result, LSB, sign);
8355       addSign (result, MSB16, sign);
8356     }
8357   else if (shCount >= 16)
8358     {
8359       shCount -= 16;
8360       if (shCount)
8361         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8362       else
8363         {
8364           movLeft2Result (left, MSB24, result, LSB, 0);
8365           movLeft2Result (left, MSB32, result, MSB16, sign);
8366         }
8367       addSign (result, MSB24, sign);
8368     }
8369   else if (shCount >= 8)
8370     {
8371       shCount -= 8;
8372       if (shCount == 1)
8373         shiftRLong (left, MSB16, result, sign);
8374       else if (shCount == 0)
8375         {
8376           movLeft2Result (left, MSB16, result, LSB, 0);
8377           movLeft2Result (left, MSB24, result, MSB16, 0);
8378           movLeft2Result (left, MSB32, result, MSB24, sign);
8379           addSign (result, MSB32, sign);
8380         }
8381       else
8382         {
8383           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8384           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8385           /* the last shift is signed */
8386           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8387           addSign (result, MSB32, sign);
8388         }
8389     }
8390   else
8391     {                           /* 1 <= shCount <= 7 */
8392       if (shCount <= 2)
8393         {
8394           shiftRLong (left, LSB, result, sign);
8395           if (shCount == 2)
8396             shiftRLong (result, LSB, result, sign);
8397         }
8398       else
8399         {
8400           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8401           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8402           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8403         }
8404     }
8405 }
8406 #endif
8407
8408 #ifdef BETTER_LITERAL_SHIFT
8409 /*-----------------------------------------------------------------*/
8410 /* genRightShiftLiteral - right shifting by known count            */
8411 /*-----------------------------------------------------------------*/
8412 static bool
8413 genRightShiftLiteral (operand * left,
8414                       operand * right,
8415                       operand * result,
8416                       iCode * ic,
8417                       int sign)
8418 {
8419   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8420   int size;
8421
8422   size = getSize (operandType (result));
8423
8424   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8425
8426   /* We only handle certain easy cases so far. */
8427   if ((shCount != 0)
8428    && (shCount < (size * 8))
8429    && (size != 1)
8430    && (size != 2))
8431   {
8432       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8433       return FALSE;
8434   }
8435
8436   freeAsmop (right, NULL, ic, TRUE);
8437
8438   aopOp (left, ic, FALSE, FALSE);
8439   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8440
8441 #if VIEW_SIZE
8442   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8443             AOP_SIZE (left));
8444 #endif
8445
8446   /* test the LEFT size !!! */
8447
8448   /* I suppose that the left size >= result size */
8449   if (shCount == 0)
8450   {
8451       size = getDataSize (result);
8452       _startLazyDPSEvaluation();
8453       while (size--)
8454       {
8455         movLeft2Result (left, size, result, size, 0);
8456       }
8457       _endLazyDPSEvaluation();
8458   }
8459   else if (shCount >= (size * 8))
8460     {
8461       if (sign)
8462       {
8463         /* get sign in acc.7 */
8464         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8465       }
8466       addSign (result, LSB, sign);
8467     }
8468   else
8469     {
8470       switch (size)
8471         {
8472         case 1:
8473           genrshOne (result, left, shCount, sign);
8474           break;
8475
8476         case 2:
8477           genrshTwo (result, left, shCount, sign);
8478           break;
8479 #if 0
8480         case 4:
8481           genrshFour (result, left, shCount, sign);
8482           break;
8483 #endif    
8484         default:
8485           break;
8486         }
8487
8488       freeAsmop (left, NULL, ic, TRUE);
8489       freeAsmop (result, NULL, ic, TRUE);
8490     }
8491     return TRUE;
8492 }
8493 #endif
8494
8495 /*-----------------------------------------------------------------*/
8496 /* genSignedRightShift - right shift of signed number              */
8497 /*-----------------------------------------------------------------*/
8498 static void
8499 genSignedRightShift (iCode * ic)
8500 {
8501   operand *right, *left, *result;
8502   int size, offset;
8503   char *l;
8504   symbol *tlbl, *tlbl1;
8505
8506   D (emitcode (";", "genSignedRightShift "););
8507
8508   /* we do it the hard way put the shift count in b
8509      and loop thru preserving the sign */
8510
8511   right = IC_RIGHT (ic);
8512   left = IC_LEFT (ic);
8513   result = IC_RESULT (ic);
8514
8515   aopOp (right, ic, FALSE, FALSE);
8516
8517 #ifdef BETTER_LITERAL_SHIFT
8518   if (AOP_TYPE (right) == AOP_LIT)
8519     {
8520       if (genRightShiftLiteral (left, right, result, ic, 1))
8521       {
8522         return;
8523       }
8524     }
8525 #endif
8526   /* shift count is unknown then we have to form
8527      a loop get the loop count in B : Note: we take
8528      only the lower order byte since shifting
8529      more that 32 bits make no sense anyway, ( the
8530      largest size of an object can be only 32 bits ) */
8531
8532   if (AOP_TYPE (right) == AOP_LIT)
8533   {
8534       /* Really should be handled by genRightShiftLiteral,
8535        * but since I'm too lazy to fix that today, at least we can make
8536        * some small improvement.
8537        */
8538        emitcode("mov", "b,#!constbyte",
8539                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8540   }
8541   else
8542   {
8543         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8544         emitcode ("inc", "b");
8545   }
8546   freeAsmop (right, NULL, ic, TRUE);
8547   aopOp (left, ic, FALSE, FALSE);
8548   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8549
8550   /* now move the left to the result if they are not the
8551      same */
8552   if (!sameRegs (AOP (left), AOP (result)) &&
8553       AOP_SIZE (result) > 1)
8554     {
8555
8556       size = AOP_SIZE (result);
8557       offset = 0;
8558       _startLazyDPSEvaluation ();
8559       while (size--)
8560         {
8561           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8562           if (*l == '@' && IS_AOP_PREG (result))
8563             {
8564
8565               emitcode ("mov", "a,%s", l);
8566               aopPut (AOP (result), "a", offset);
8567             }
8568           else
8569             aopPut (AOP (result), l, offset);
8570           offset++;
8571         }
8572       _endLazyDPSEvaluation ();
8573     }
8574
8575   /* mov the highest order bit to OVR */
8576   tlbl = newiTempLabel (NULL);
8577   tlbl1 = newiTempLabel (NULL);
8578
8579   size = AOP_SIZE (result);
8580   offset = size - 1;
8581   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8582   emitcode ("rlc", "a");
8583   emitcode ("mov", "ov,c");
8584   /* if it is only one byte then */
8585   if (size == 1)
8586     {
8587       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8588       MOVA (l);
8589       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8590       emitcode ("", "!tlabeldef", tlbl->key + 100);
8591       emitcode ("mov", "c,ov");
8592       emitcode ("rrc", "a");
8593       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8594       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8595       aopPut (AOP (result), "a", 0);
8596       goto release;
8597     }
8598
8599   reAdjustPreg (AOP (result));
8600   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8601   emitcode ("", "!tlabeldef", tlbl->key + 100);
8602   emitcode ("mov", "c,ov");
8603   _startLazyDPSEvaluation ();
8604   while (size--)
8605     {
8606       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8607       MOVA (l);
8608       emitcode ("rrc", "a");
8609       aopPut (AOP (result), "a", offset--);
8610     }
8611   _endLazyDPSEvaluation ();
8612   reAdjustPreg (AOP (result));
8613   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8614   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8615
8616 release:
8617   freeAsmop (left, NULL, ic, TRUE);
8618   freeAsmop (result, NULL, ic, TRUE);
8619 }
8620
8621 /*-----------------------------------------------------------------*/
8622 /* genRightShift - generate code for right shifting                */
8623 /*-----------------------------------------------------------------*/
8624 static void
8625 genRightShift (iCode * ic)
8626 {
8627   operand *right, *left, *result;
8628   sym_link *retype;
8629   int size, offset;
8630   char *l;
8631   symbol *tlbl, *tlbl1;
8632
8633   D (emitcode (";", "genRightShift "););
8634
8635   /* if signed then we do it the hard way preserve the
8636      sign bit moving it inwards */
8637   retype = getSpec (operandType (IC_RESULT (ic)));
8638
8639   if (!SPEC_USIGN (retype))
8640     {
8641       genSignedRightShift (ic);
8642       return;
8643     }
8644
8645   /* signed & unsigned types are treated the same : i.e. the
8646      signed is NOT propagated inwards : quoting from the
8647      ANSI - standard : "for E1 >> E2, is equivalent to division
8648      by 2**E2 if unsigned or if it has a non-negative value,
8649      otherwise the result is implementation defined ", MY definition
8650      is that the sign does not get propagated */
8651
8652   right = IC_RIGHT (ic);
8653   left = IC_LEFT (ic);
8654   result = IC_RESULT (ic);
8655
8656   aopOp (right, ic, FALSE, FALSE);
8657
8658 #ifdef BETTER_LITERAL_SHIFT
8659   /* if the shift count is known then do it
8660      as efficiently as possible */
8661   if (AOP_TYPE (right) == AOP_LIT)
8662     {
8663       if (genRightShiftLiteral (left, right, result, ic, 0))
8664       {
8665         return;
8666       }
8667     }
8668 #endif
8669
8670   /* shift count is unknown then we have to form
8671      a loop get the loop count in B : Note: we take
8672      only the lower order byte since shifting
8673      more that 32 bits make no sense anyway, ( the
8674      largest size of an object can be only 32 bits ) */
8675   
8676   if (AOP_TYPE (right) == AOP_LIT)
8677   {
8678       /* Really should be handled by genRightShiftLiteral,
8679        * but since I'm too lazy to fix that today, at least we can make
8680        * some small improvement.
8681        */
8682        emitcode("mov", "b,#!constbyte",
8683                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8684   }
8685   else
8686   {
8687         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8688         emitcode ("inc", "b");
8689   }
8690   freeAsmop (right, NULL, ic, TRUE);
8691   aopOp (left, ic, FALSE, FALSE);
8692   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8693
8694   /* now move the left to the result if they are not the
8695      same */
8696   if (!sameRegs (AOP (left), AOP (result)) &&
8697       AOP_SIZE (result) > 1)
8698     {
8699
8700       size = AOP_SIZE (result);
8701       offset = 0;
8702       _startLazyDPSEvaluation ();
8703       while (size--)
8704         {
8705           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8706           if (*l == '@' && IS_AOP_PREG (result))
8707             {
8708
8709               emitcode ("mov", "a,%s", l);
8710               aopPut (AOP (result), "a", offset);
8711             }
8712           else
8713             aopPut (AOP (result), l, offset);
8714           offset++;
8715         }
8716       _endLazyDPSEvaluation ();
8717     }
8718
8719   tlbl = newiTempLabel (NULL);
8720   tlbl1 = newiTempLabel (NULL);
8721   size = AOP_SIZE (result);
8722   offset = size - 1;
8723
8724   /* if it is only one byte then */
8725   if (size == 1)
8726     {
8727       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8728       MOVA (l);
8729       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8730       emitcode ("", "!tlabeldef", tlbl->key + 100);
8731       CLRC;
8732       emitcode ("rrc", "a");
8733       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8734       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8735       aopPut (AOP (result), "a", 0);
8736       goto release;
8737     }
8738
8739   reAdjustPreg (AOP (result));
8740   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8741   emitcode ("", "!tlabeldef", tlbl->key + 100);
8742   CLRC;
8743   _startLazyDPSEvaluation ();
8744   while (size--)
8745     {
8746       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8747       MOVA (l);
8748       emitcode ("rrc", "a");
8749       aopPut (AOP (result), "a", offset--);
8750     }
8751   _endLazyDPSEvaluation ();
8752   reAdjustPreg (AOP (result));
8753
8754   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8755   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8756
8757 release:
8758   freeAsmop (left, NULL, ic, TRUE);
8759   freeAsmop (result, NULL, ic, TRUE);
8760 }
8761
8762 /*-----------------------------------------------------------------*/
8763 /* genUnpackBits - generates code for unpacking bits               */
8764 /*-----------------------------------------------------------------*/
8765 static void
8766 genUnpackBits (operand * result, char *rname, int ptype)
8767 {
8768   int shCnt;
8769   int rlen = 0;
8770   sym_link *etype;
8771   int offset = 0;
8772
8773   D (emitcode (";", "genUnpackBits ");
8774     );
8775
8776   etype = getSpec (operandType (result));
8777
8778   /* read the first byte  */
8779   switch (ptype)
8780     {
8781
8782     case POINTER:
8783     case IPOINTER:
8784       emitcode ("mov", "a,@%s", rname);
8785       break;
8786
8787     case PPOINTER:
8788       emitcode ("movx", "a,@%s", rname);
8789       break;
8790
8791     case FPOINTER:
8792       emitcode ("movx", "a,@dptr");
8793       break;
8794
8795     case CPOINTER:
8796       emitcode ("clr", "a");
8797       emitcode ("movc", "a,@a+dptr");
8798       break;
8799
8800     case GPOINTER:
8801       emitcode ("lcall", "__gptrget");
8802       break;
8803     }
8804
8805   /* if we have bitdisplacement then it fits   */
8806   /* into this byte completely or if length is */
8807   /* less than a byte                          */
8808   if ((shCnt = SPEC_BSTR (etype)) ||
8809       (SPEC_BLEN (etype) <= 8))
8810     {
8811
8812       /* shift right acc */
8813       AccRsh (shCnt);
8814
8815       emitcode ("anl", "a,#!constbyte",
8816                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8817       aopPut (AOP (result), "a", offset);
8818       return;
8819     }
8820
8821   /* bit field did not fit in a byte  */
8822   rlen = SPEC_BLEN (etype) - 8;
8823   aopPut (AOP (result), "a", offset++);
8824
8825   while (1)
8826     {
8827
8828       switch (ptype)
8829         {
8830         case POINTER:
8831         case IPOINTER:
8832           emitcode ("inc", "%s", rname);
8833           emitcode ("mov", "a,@%s", rname);
8834           break;
8835
8836         case PPOINTER:
8837           emitcode ("inc", "%s", rname);
8838           emitcode ("movx", "a,@%s", rname);
8839           break;
8840
8841         case FPOINTER:
8842           emitcode ("inc", "dptr");
8843           emitcode ("movx", "a,@dptr");
8844           break;
8845
8846         case CPOINTER:
8847           emitcode ("clr", "a");
8848           emitcode ("inc", "dptr");
8849           emitcode ("movc", "a,@a+dptr");
8850           break;
8851
8852         case GPOINTER:
8853           emitcode ("inc", "dptr");
8854           emitcode ("lcall", "__gptrget");
8855           break;
8856         }
8857
8858       rlen -= 8;
8859       /* if we are done */
8860       if (rlen < 8)
8861         break;
8862
8863       aopPut (AOP (result), "a", offset++);
8864
8865     }
8866
8867   if (rlen)
8868     {
8869       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8870       aopPut (AOP (result), "a", offset);
8871     }
8872
8873   return;
8874 }
8875
8876
8877 /*-----------------------------------------------------------------*/
8878 /* genDataPointerGet - generates code when ptr offset is known     */
8879 /*-----------------------------------------------------------------*/
8880 static void
8881 genDataPointerGet (operand * left,
8882                    operand * result,
8883                    iCode * ic)
8884 {
8885   char *l;
8886   char buffer[256];
8887   int size, offset = 0;
8888   aopOp (result, ic, TRUE, FALSE);
8889
8890   /* get the string representation of the name */
8891   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8892   size = AOP_SIZE (result);
8893   _startLazyDPSEvaluation ();
8894   while (size--)
8895     {
8896       if (offset)
8897         sprintf (buffer, "(%s + %d)", l + 1, offset);
8898       else
8899         sprintf (buffer, "%s", l + 1);
8900       aopPut (AOP (result), buffer, offset++);
8901     }
8902   _endLazyDPSEvaluation ();
8903
8904   freeAsmop (left, NULL, ic, TRUE);
8905   freeAsmop (result, NULL, ic, TRUE);
8906 }
8907
8908 /*-----------------------------------------------------------------*/
8909 /* genNearPointerGet - emitcode for near pointer fetch             */
8910 /*-----------------------------------------------------------------*/
8911 static void
8912 genNearPointerGet (operand * left,
8913                    operand * result,
8914                    iCode * ic,
8915                    iCode *pi)
8916 {
8917   asmop *aop = NULL;
8918   regs *preg = NULL;
8919   char *rname;
8920   sym_link *rtype, *retype, *letype;
8921   sym_link *ltype = operandType (left);
8922   char buffer[80];
8923
8924   rtype = operandType (result);
8925   retype = getSpec (rtype);
8926   letype = getSpec (ltype);
8927
8928   aopOp (left, ic, FALSE, FALSE);
8929
8930   /* if left is rematerialisable and
8931      result is not bit variable type and
8932      the left is pointer to data space i.e
8933      lower 128 bytes of space */
8934   if (AOP_TYPE (left) == AOP_IMMD &&
8935       !IS_BITVAR (retype) &&
8936       !IS_BITVAR (letype) &&
8937       DCL_TYPE (ltype) == POINTER)
8938     {
8939       genDataPointerGet (left, result, ic);
8940       return;
8941     }
8942
8943   /* if the value is already in a pointer register
8944      then don't need anything more */
8945   if (!AOP_INPREG (AOP (left)))
8946     {
8947       /* otherwise get a free pointer register */
8948       aop = newAsmop (0);
8949       preg = getFreePtr (ic, &aop, FALSE);
8950       emitcode ("mov", "%s,%s",
8951                 preg->name,
8952                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8953       rname = preg->name;
8954     }
8955   else
8956     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8957
8958   freeAsmop (left, NULL, ic, TRUE);
8959   aopOp (result, ic, FALSE, FALSE);
8960
8961   /* if bitfield then unpack the bits */
8962   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8963     genUnpackBits (result, rname, POINTER);
8964   else
8965     {
8966       /* we have can just get the values */
8967       int size = AOP_SIZE (result);
8968       int offset = 0;
8969
8970       while (size--)
8971         {
8972           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8973             {
8974
8975               emitcode ("mov", "a,@%s", rname);
8976               aopPut (AOP (result), "a", offset);
8977             }
8978           else
8979             {
8980               sprintf (buffer, "@%s", rname);
8981               aopPut (AOP (result), buffer, offset);
8982             }
8983           offset++;
8984           if (size || pi)
8985             emitcode ("inc", "%s", rname);
8986         }
8987     }
8988
8989   /* now some housekeeping stuff */
8990   if (aop)
8991     {
8992       /* we had to allocate for this iCode */
8993       if (pi) { /* post increment present */
8994         aopPut(AOP ( left ),rname,0);
8995       }
8996       freeAsmop (NULL, aop, ic, TRUE);
8997     }
8998   else
8999     {
9000       /* we did not allocate which means left
9001          already in a pointer register, then
9002          if size > 0 && this could be used again
9003          we have to point it back to where it
9004          belongs */
9005       if (AOP_SIZE (result) > 1 &&
9006           !OP_SYMBOL (left)->remat &&
9007           (OP_SYMBOL (left)->liveTo > ic->seq ||
9008            ic->depth) &&
9009           !pi)
9010         {
9011           int size = AOP_SIZE (result) - 1;
9012           while (size--)
9013             emitcode ("dec", "%s", rname);
9014         }
9015     }
9016
9017   /* done */
9018   freeAsmop (result, NULL, ic, TRUE);
9019   if (pi) pi->generated = 1;
9020 }
9021
9022 /*-----------------------------------------------------------------*/
9023 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9024 /*-----------------------------------------------------------------*/
9025 static void
9026 genPagedPointerGet (operand * left,
9027                     operand * result,
9028                     iCode * ic,
9029                     iCode * pi)
9030 {
9031   asmop *aop = NULL;
9032   regs *preg = NULL;
9033   char *rname;
9034   sym_link *rtype, *retype, *letype;
9035
9036   rtype = operandType (result);
9037   retype = getSpec (rtype);
9038   letype = getSpec (operandType (left));
9039   aopOp (left, ic, FALSE, FALSE);
9040
9041   /* if the value is already in a pointer register
9042      then don't need anything more */
9043   if (!AOP_INPREG (AOP (left)))
9044     {
9045       /* otherwise get a free pointer register */
9046       aop = newAsmop (0);
9047       preg = getFreePtr (ic, &aop, FALSE);
9048       emitcode ("mov", "%s,%s",
9049                 preg->name,
9050                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9051       rname = preg->name;
9052     }
9053   else
9054     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9055
9056   freeAsmop (left, NULL, ic, TRUE);
9057   aopOp (result, ic, FALSE, FALSE);
9058
9059   /* if bitfield then unpack the bits */
9060   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9061     genUnpackBits (result, rname, PPOINTER);
9062   else
9063     {
9064       /* we have can just get the values */
9065       int size = AOP_SIZE (result);
9066       int offset = 0;
9067
9068       while (size--)
9069         {
9070
9071           emitcode ("movx", "a,@%s", rname);
9072           aopPut (AOP (result), "a", offset);
9073
9074           offset++;
9075
9076           if (size || pi)
9077             emitcode ("inc", "%s", rname);
9078         }
9079     }
9080
9081   /* now some housekeeping stuff */
9082   if (aop)
9083     {
9084       /* we had to allocate for this iCode */
9085       if (pi) aopPut ( AOP (left), rname, 0);
9086       freeAsmop (NULL, aop, ic, TRUE);
9087     }
9088   else
9089     {
9090       /* we did not allocate which means left
9091          already in a pointer register, then
9092          if size > 0 && this could be used again
9093          we have to point it back to where it
9094          belongs */
9095       if (AOP_SIZE (result) > 1 &&
9096           !OP_SYMBOL (left)->remat &&
9097           (OP_SYMBOL (left)->liveTo > ic->seq ||
9098            ic->depth) &&
9099           !pi)
9100         {
9101           int size = AOP_SIZE (result) - 1;
9102           while (size--)
9103             emitcode ("dec", "%s", rname);
9104         }
9105     }
9106
9107   /* done */
9108   freeAsmop (result, NULL, ic, TRUE);
9109   if (pi) pi->generated = 1;
9110 }
9111
9112 /*-----------------------------------------------------------------*/
9113 /* genFarPointerGet - gget value from far space                    */
9114 /*-----------------------------------------------------------------*/
9115 static void
9116 genFarPointerGet (operand * left,
9117                   operand * result, iCode * ic, iCode *pi)
9118 {
9119     int size, offset, dopi=1;
9120   sym_link *retype = getSpec (operandType (result));
9121   sym_link *letype = getSpec (operandType (left));
9122   D (emitcode (";", "genFarPointerGet");
9123     );
9124
9125   aopOp (left, ic, FALSE, FALSE);
9126
9127   /* if the operand is already in dptr
9128      then we do nothing else we move the value to dptr */
9129   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9130     {
9131       /* if this is remateriazable */
9132       if (AOP_TYPE (left) == AOP_IMMD)
9133         {
9134           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9135         }
9136       else
9137         {
9138           /* we need to get it byte by byte */
9139           _startLazyDPSEvaluation ();
9140           if (AOP_TYPE (left) != AOP_DPTR)
9141             {
9142               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9143               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9144               if (options.model == MODEL_FLAT24)
9145                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9146             }
9147           else
9148             {
9149               /* We need to generate a load to DPTR indirect through DPTR. */
9150               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9151                 );
9152               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9153               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9154               if (options.model == MODEL_FLAT24)
9155                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9156               emitcode ("pop", "dph");
9157               emitcode ("pop", "dpl");
9158               dopi =0;
9159             }
9160           _endLazyDPSEvaluation ();
9161         }
9162     }
9163   /* so dptr know contains the address */
9164   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9165
9166   /* if bit then unpack */
9167   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9168       if (AOP_INDPTRn(left)) {
9169           genSetDPTR(AOP(left)->aopu.dptr);
9170       }
9171       genUnpackBits (result, "dptr", FPOINTER);
9172       if (AOP_INDPTRn(left)) {
9173           genSetDPTR(0);
9174       }
9175   } else
9176     {
9177       size = AOP_SIZE (result);
9178       offset = 0;
9179
9180       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9181           while (size--) {
9182               genSetDPTR(AOP(left)->aopu.dptr);
9183               emitcode ("movx", "a,@dptr");
9184               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9185                   emitcode ("inc", "dptr");
9186               genSetDPTR (0);
9187               aopPut (AOP (result), "a", offset++);
9188           }
9189       } else {
9190           _startLazyDPSEvaluation ();
9191           while (size--) {
9192               if (AOP_INDPTRn(left)) {
9193                   genSetDPTR(AOP(left)->aopu.dptr);
9194               } else {
9195                   genSetDPTR (0);
9196               }
9197               _flushLazyDPS ();
9198               
9199               emitcode ("movx", "a,@dptr");
9200               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9201                   emitcode ("inc", "dptr");
9202               
9203               aopPut (AOP (result), "a", offset++);
9204           }
9205           _endLazyDPSEvaluation ();
9206       }
9207     }
9208   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9209       if (!AOP_INDPTRn(left)) {
9210           aopPut ( AOP (left), "dpl", 0);
9211           aopPut ( AOP (left), "dph", 1);
9212           if (options.model == MODEL_FLAT24)
9213               aopPut ( AOP (left), "dpx", 2);
9214       }
9215     pi->generated = 1;
9216   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9217              AOP_SIZE(result) > 1 &&
9218              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9219       
9220       size = AOP_SIZE (result) - 1;
9221       if (AOP_INDPTRn(left)) {
9222           genSetDPTR(AOP(left)->aopu.dptr);
9223       }
9224       while (size--) emitcode ("lcall","__decdptr");
9225       if (AOP_INDPTRn(left)) {
9226           genSetDPTR(0);
9227       }
9228   }
9229
9230   freeAsmop (left, NULL, ic, TRUE);
9231   freeAsmop (result, NULL, ic, TRUE);
9232 }
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genCodePointerGet - get value from code space                  */
9236 /*-----------------------------------------------------------------*/
9237 static void
9238 genCodePointerGet (operand * left,
9239                     operand * result, iCode * ic, iCode *pi)
9240 {
9241   int size, offset, dopi=1;
9242   sym_link *retype = getSpec (operandType (result));
9243
9244   aopOp (left, ic, FALSE, FALSE);
9245
9246   /* if the operand is already in dptr
9247      then we do nothing else we move the value to dptr */
9248   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9249     {
9250       /* if this is remateriazable */
9251       if (AOP_TYPE (left) == AOP_IMMD)
9252         {
9253           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9254         }
9255       else
9256         {                       /* we need to get it byte by byte */
9257           _startLazyDPSEvaluation ();
9258           if (AOP_TYPE (left) != AOP_DPTR)
9259             {
9260               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9261               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9262               if (options.model == MODEL_FLAT24)
9263                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9264             }
9265           else
9266             {
9267               /* We need to generate a load to DPTR indirect through DPTR. */
9268               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9269                 );
9270               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9271               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9272               if (options.model == MODEL_FLAT24)
9273                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9274               emitcode ("pop", "dph");
9275               emitcode ("pop", "dpl");
9276               dopi=0;
9277             }
9278           _endLazyDPSEvaluation ();
9279         }
9280     }
9281   /* so dptr know contains the address */
9282   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9283
9284   /* if bit then unpack */
9285   if (IS_BITVAR (retype)) {
9286       if (AOP_INDPTRn(left)) {
9287           genSetDPTR(AOP(left)->aopu.dptr);
9288       }
9289       genUnpackBits (result, "dptr", CPOINTER);
9290       if (AOP_INDPTRn(left)) {
9291           genSetDPTR(0);
9292       }
9293   } else
9294     {
9295       size = AOP_SIZE (result);
9296       offset = 0;
9297       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9298           while (size--) {
9299               genSetDPTR(AOP(left)->aopu.dptr);
9300               emitcode ("clr", "a");
9301               emitcode ("movc", "a,@a+dptr");
9302               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9303                   emitcode ("inc", "dptr");
9304               genSetDPTR (0);
9305               aopPut (AOP (result), "a", offset++);
9306           }
9307       } else {
9308           _startLazyDPSEvaluation ();
9309           while (size--)
9310               {
9311                   if (AOP_INDPTRn(left)) {
9312                       genSetDPTR(AOP(left)->aopu.dptr);
9313                   } else {
9314                       genSetDPTR (0);
9315                   }
9316                   _flushLazyDPS ();
9317                   
9318                   emitcode ("clr", "a");
9319                   emitcode ("movc", "a,@a+dptr");
9320                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9321                       emitcode ("inc", "dptr");
9322                   aopPut (AOP (result), "a", offset++);
9323               }
9324           _endLazyDPSEvaluation ();
9325       }
9326     }
9327   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9328       if (!AOP_INDPTRn(left)) {
9329           aopPut ( AOP (left), "dpl", 0);
9330           aopPut ( AOP (left), "dph", 1);
9331           if (options.model == MODEL_FLAT24)
9332               aopPut ( AOP (left), "dpx", 2);
9333       }
9334       pi->generated = 1;
9335   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9336              AOP_SIZE(result) > 1 &&
9337              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9338       
9339       size = AOP_SIZE (result) - 1;
9340       if (AOP_INDPTRn(left)) {
9341           genSetDPTR(AOP(left)->aopu.dptr);
9342       }
9343       while (size--) emitcode ("lcall","__decdptr");
9344       if (AOP_INDPTRn(left)) {
9345           genSetDPTR(0);
9346       }
9347   }
9348   
9349   freeAsmop (left, NULL, ic, TRUE);
9350   freeAsmop (result, NULL, ic, TRUE);
9351 }
9352
9353 /*-----------------------------------------------------------------*/
9354 /* genGenPointerGet - gget value from generic pointer space        */
9355 /*-----------------------------------------------------------------*/
9356 static void
9357 genGenPointerGet (operand * left,
9358                   operand * result, iCode * ic, iCode * pi)
9359 {
9360   int size, offset;
9361   sym_link *retype = getSpec (operandType (result));
9362   sym_link *letype = getSpec (operandType (left));
9363
9364   D (emitcode (";", "genGenPointerGet "); );
9365
9366   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9367
9368   /* if the operand is already in dptr
9369      then we do nothing else we move the value to dptr */
9370   if (AOP_TYPE (left) != AOP_STR)
9371     {
9372       /* if this is remateriazable */
9373       if (AOP_TYPE (left) == AOP_IMMD)
9374         {
9375           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9376           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9377                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9378           else
9379                   emitcode ("mov", "b,#%d", pointerCode (retype));
9380         }
9381       else
9382         {                       /* we need to get it byte by byte */
9383           _startLazyDPSEvaluation ();
9384 #if 1   // I see no point at all to this code and will likely yank it soon.
9385           if (AOP(left)->type==AOP_DPTR2) {
9386             char *l;
9387             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9388             genSetDPTR(0);
9389             _flushLazyDPS();
9390             emitcode ("mov", "dpl,%s", l);
9391             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9392             genSetDPTR(0);
9393             _flushLazyDPS();
9394             emitcode ("mov", "dph,%s", l);
9395             if (options.model == MODEL_FLAT24) {
9396               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9397               genSetDPTR(0);
9398               _flushLazyDPS();
9399               emitcode ("mov", "dpx,%s", l);
9400               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9401             } else {
9402               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9403             }
9404           } 
9405           else 
9406 #endif          
9407           {
9408             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9409             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9410             if (options.model == MODEL_FLAT24) {
9411               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9412               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9413             } else {
9414               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9415             }
9416           }
9417           _endLazyDPSEvaluation ();
9418         }
9419     }
9420   /* so dptr know contains the address */
9421   aopOp (result, ic, FALSE, TRUE);
9422
9423   /* if bit then unpack */
9424   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9425     genUnpackBits (result, "dptr", GPOINTER);
9426   else
9427     {
9428       size = AOP_SIZE (result);
9429       offset = 0;
9430
9431       while (size--)
9432         {
9433           emitcode ("lcall", "__gptrget");
9434           aopPut (AOP (result), "a", offset++);
9435           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9436             emitcode ("inc", "dptr");
9437         }
9438     }
9439
9440   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9441     aopPut ( AOP (left), "dpl", 0);
9442     aopPut ( AOP (left), "dph", 1);
9443     if (options.model == MODEL_FLAT24) {
9444         aopPut ( AOP (left), "dpx", 2);
9445         aopPut ( AOP (left), "b", 3);   
9446     } else  aopPut ( AOP (left), "b", 2);       
9447     pi->generated = 1;
9448   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9449              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9450       
9451       size = AOP_SIZE (result) - 1;
9452       while (size--) emitcode ("lcall","__decdptr");
9453   }
9454
9455   freeAsmop (left, NULL, ic, TRUE);
9456   freeAsmop (result, NULL, ic, TRUE);
9457 }
9458
9459 /*-----------------------------------------------------------------*/
9460 /* genPointerGet - generate code for pointer get                   */
9461 /*-----------------------------------------------------------------*/
9462 static void
9463 genPointerGet (iCode * ic, iCode *pi)
9464 {
9465   operand *left, *result;
9466   sym_link *type, *etype;
9467   int p_type;
9468
9469   D (emitcode (";", "genPointerGet ");
9470     );
9471
9472   left = IC_LEFT (ic);
9473   result = IC_RESULT (ic);
9474
9475   /* depending on the type of pointer we need to
9476      move it to the correct pointer register */
9477   type = operandType (left);
9478   etype = getSpec (type);
9479   /* if left is of type of pointer then it is simple */
9480   if (IS_PTR (type) && !IS_FUNC (type->next))
9481     p_type = DCL_TYPE (type);
9482   else
9483     {
9484       /* we have to go by the storage class */
9485       p_type = PTR_TYPE (SPEC_OCLS (etype));
9486     }
9487   /* special case when cast remat */
9488   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9489       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9490           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9491           type =   type = operandType (left);
9492           p_type = DCL_TYPE (type);
9493   }
9494   /* now that we have the pointer type we assign
9495      the pointer values */
9496   switch (p_type)
9497     {
9498
9499     case POINTER:
9500     case IPOINTER:
9501       genNearPointerGet (left, result, ic, pi);
9502       break;
9503
9504     case PPOINTER:
9505       genPagedPointerGet (left, result, ic, pi);
9506       break;
9507
9508     case FPOINTER:
9509       genFarPointerGet (left, result, ic, pi);
9510       break;
9511
9512     case CPOINTER:
9513       genCodePointerGet (left, result, ic, pi);
9514       break;
9515
9516     case GPOINTER:
9517       genGenPointerGet (left, result, ic, pi);
9518       break;
9519     }
9520
9521 }
9522
9523 /*-----------------------------------------------------------------*/
9524 /* genPackBits - generates code for packed bit storage             */
9525 /*-----------------------------------------------------------------*/
9526 static void
9527 genPackBits (sym_link * etype,
9528              operand * right,
9529              char *rname, int p_type)
9530 {
9531   int shCount = 0;
9532   int offset = 0;
9533   int rLen = 0;
9534   int blen, bstr;
9535   char *l;
9536
9537   blen = SPEC_BLEN (etype);
9538   bstr = SPEC_BSTR (etype);
9539
9540   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9541   MOVA (l);
9542
9543   /* if the bit lenth is less than or    */
9544   /* it exactly fits a byte then         */
9545   if (SPEC_BLEN (etype) <= 8)
9546     {
9547       shCount = SPEC_BSTR (etype);
9548
9549       /* shift left acc */
9550       AccLsh (shCount);
9551
9552       if (SPEC_BLEN (etype) < 8)
9553         {                       /* if smaller than a byte */
9554
9555
9556           switch (p_type)
9557             {
9558             case POINTER:
9559               emitcode ("mov", "b,a");
9560               emitcode ("mov", "a,@%s", rname);
9561               break;
9562
9563             case FPOINTER:
9564               emitcode ("mov", "b,a");
9565               emitcode ("movx", "a,@dptr");
9566               break;
9567
9568             case GPOINTER:
9569               emitcode ("push", "b");
9570               emitcode ("push", "acc");
9571               emitcode ("lcall", "__gptrget");
9572               emitcode ("pop", "b");
9573               break;
9574             }
9575
9576           emitcode ("anl", "a,#!constbyte", (unsigned char)
9577                     ((unsigned char) (0xFF << (blen + bstr)) |
9578                      (unsigned char) (0xFF >> (8 - bstr))));
9579           emitcode ("orl", "a,b");
9580           if (p_type == GPOINTER)
9581             emitcode ("pop", "b");
9582         }
9583     }
9584
9585   switch (p_type)
9586     {
9587     case POINTER:
9588       emitcode ("mov", "@%s,a", rname);
9589       break;
9590
9591     case FPOINTER:
9592       emitcode ("movx", "@dptr,a");
9593       break;
9594
9595     case GPOINTER:
9596       emitcode ("lcall", "__gptrput");
9597       break;
9598     }
9599
9600   /* if we r done */
9601   if (SPEC_BLEN (etype) <= 8)
9602     return;
9603
9604   emitcode ("inc", "%s", rname);
9605   rLen = SPEC_BLEN (etype);
9606
9607   /* now generate for lengths greater than one byte */
9608   while (1)
9609     {
9610
9611       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9612
9613       rLen -= 8;
9614       if (rLen < 8)
9615         break;
9616
9617       switch (p_type)
9618         {
9619         case POINTER:
9620           if (*l == '@')
9621             {
9622               MOVA (l);
9623               emitcode ("mov", "@%s,a", rname);
9624             }
9625           else
9626             emitcode ("mov", "@%s,%s", rname, l);
9627           break;
9628
9629         case FPOINTER:
9630           MOVA (l);
9631           emitcode ("movx", "@dptr,a");
9632           break;
9633
9634         case GPOINTER:
9635           MOVA (l);
9636           emitcode ("lcall", "__gptrput");
9637           break;
9638         }
9639       emitcode ("inc", "%s", rname);
9640     }
9641
9642   MOVA (l);
9643
9644   /* last last was not complete */
9645   if (rLen)
9646     {
9647       /* save the byte & read byte */
9648       switch (p_type)
9649         {
9650         case POINTER:
9651           emitcode ("mov", "b,a");
9652           emitcode ("mov", "a,@%s", rname);
9653           break;
9654
9655         case FPOINTER:
9656           emitcode ("mov", "b,a");
9657           emitcode ("movx", "a,@dptr");
9658           break;
9659
9660         case GPOINTER:
9661           emitcode ("push", "b");
9662           emitcode ("push", "acc");
9663           emitcode ("lcall", "__gptrget");
9664           emitcode ("pop", "b");
9665           break;
9666         }
9667
9668       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9669       emitcode ("orl", "a,b");
9670     }
9671
9672   if (p_type == GPOINTER)
9673     emitcode ("pop", "b");
9674
9675   switch (p_type)
9676     {
9677
9678     case POINTER:
9679       emitcode ("mov", "@%s,a", rname);
9680       break;
9681
9682     case FPOINTER:
9683       emitcode ("movx", "@dptr,a");
9684       break;
9685
9686     case GPOINTER:
9687       emitcode ("lcall", "__gptrput");
9688       break;
9689     }
9690 }
9691 /*-----------------------------------------------------------------*/
9692 /* genDataPointerSet - remat pointer to data space                 */
9693 /*-----------------------------------------------------------------*/
9694 static void
9695 genDataPointerSet (operand * right,
9696                    operand * result,
9697                    iCode * ic)
9698 {
9699   int size, offset = 0;
9700   char *l, buffer[256];
9701
9702   aopOp (right, ic, FALSE, FALSE);
9703
9704   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9705   size = AOP_SIZE (right);
9706   while (size--)
9707     {
9708       if (offset)
9709         sprintf (buffer, "(%s + %d)", l + 1, offset);
9710       else
9711         sprintf (buffer, "%s", l + 1);
9712       emitcode ("mov", "%s,%s", buffer,
9713                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9714     }
9715
9716   freeAsmop (right, NULL, ic, TRUE);
9717   freeAsmop (result, NULL, ic, TRUE);
9718 }
9719
9720 /*-----------------------------------------------------------------*/
9721 /* genNearPointerSet - emitcode for near pointer put                */
9722 /*-----------------------------------------------------------------*/
9723 static void
9724 genNearPointerSet (operand * right,
9725                    operand * result,
9726                    iCode * ic,
9727                    iCode * pi)
9728 {
9729   asmop *aop = NULL;
9730   regs *preg = NULL;
9731   char *rname, *l;
9732   sym_link *retype, *letype;
9733   sym_link *ptype = operandType (result);
9734
9735   retype = getSpec (operandType (right));
9736   letype = getSpec (ptype);
9737
9738   aopOp (result, ic, FALSE, FALSE);
9739
9740   /* if the result is rematerializable &
9741      in data space & not a bit variable */
9742   if (AOP_TYPE (result) == AOP_IMMD &&
9743       DCL_TYPE (ptype) == POINTER &&
9744       !IS_BITVAR (retype) &&
9745       !IS_BITVAR (letype))
9746     {
9747       genDataPointerSet (right, result, ic);
9748       return;
9749     }
9750
9751   /* if the value is already in a pointer register
9752      then don't need anything more */
9753   if (!AOP_INPREG (AOP (result)))
9754     {
9755       /* otherwise get a free pointer register */
9756       aop = newAsmop (0);
9757       preg = getFreePtr (ic, &aop, FALSE);
9758       emitcode ("mov", "%s,%s",
9759                 preg->name,
9760                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9761       rname = preg->name;
9762     }
9763   else
9764     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9765
9766   aopOp (right, ic, FALSE, FALSE);
9767
9768   /* if bitfield then unpack the bits */
9769   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9770     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9771   else
9772     {
9773       /* we have can just get the values */
9774       int size = AOP_SIZE (right);
9775       int offset = 0;
9776
9777       while (size--)
9778         {
9779           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9780           if (*l == '@')
9781             {
9782               MOVA (l);
9783               emitcode ("mov", "@%s,a", rname);
9784             }
9785           else
9786             emitcode ("mov", "@%s,%s", rname, l);
9787           if (size || pi)
9788             emitcode ("inc", "%s", rname);
9789           offset++;
9790         }
9791     }
9792
9793   /* now some housekeeping stuff */
9794   if (aop)
9795     {
9796       /* we had to allocate for this iCode */
9797       if (pi) aopPut (AOP (result),rname,0);
9798       freeAsmop (NULL, aop, ic, TRUE);
9799     }
9800   else
9801     {
9802       /* we did not allocate which means left
9803          already in a pointer register, then
9804          if size > 0 && this could be used again
9805          we have to point it back to where it
9806          belongs */
9807       if (AOP_SIZE (right) > 1 &&
9808           !OP_SYMBOL (result)->remat &&
9809           (OP_SYMBOL (result)->liveTo > ic->seq ||
9810            ic->depth) &&
9811           !pi)
9812         {
9813           int size = AOP_SIZE (right) - 1;
9814           while (size--)
9815             emitcode ("dec", "%s", rname);
9816         }
9817     }
9818
9819   /* done */
9820   if (pi) pi->generated = 1;
9821   freeAsmop (result, NULL, ic, TRUE);
9822   freeAsmop (right, NULL, ic, TRUE);
9823
9824
9825 }
9826
9827 /*-----------------------------------------------------------------*/
9828 /* genPagedPointerSet - emitcode for Paged pointer put             */
9829 /*-----------------------------------------------------------------*/
9830 static void
9831 genPagedPointerSet (operand * right,
9832                     operand * result,
9833                     iCode * ic,
9834                     iCode *pi)
9835 {
9836   asmop *aop = NULL;
9837   regs *preg = NULL;
9838   char *rname, *l;
9839   sym_link *retype, *letype;
9840
9841   retype = getSpec (operandType (right));
9842   letype = getSpec (operandType (result));
9843
9844   aopOp (result, ic, FALSE, FALSE);
9845
9846   /* if the value is already in a pointer register
9847      then don't need anything more */
9848   if (!AOP_INPREG (AOP (result)))
9849     {
9850       /* otherwise get a free pointer register */
9851       aop = newAsmop (0);
9852       preg = getFreePtr (ic, &aop, FALSE);
9853       emitcode ("mov", "%s,%s",
9854                 preg->name,
9855                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9856       rname = preg->name;
9857     }
9858   else
9859     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9860
9861   aopOp (right, ic, FALSE, FALSE);
9862
9863   /* if bitfield then unpack the bits */
9864   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9865     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9866   else
9867     {
9868       /* we have can just get the values */
9869       int size = AOP_SIZE (right);
9870       int offset = 0;
9871
9872       while (size--)
9873         {
9874           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9875
9876           MOVA (l);
9877           emitcode ("movx", "@%s,a", rname);
9878
9879           if (size || pi)
9880             emitcode ("inc", "%s", rname);
9881
9882           offset++;
9883         }
9884     }
9885
9886   /* now some housekeeping stuff */
9887   if (aop)
9888     {
9889       if (pi) aopPut (AOP (result),rname,0);
9890       /* we had to allocate for this iCode */
9891       freeAsmop (NULL, aop, ic, TRUE);
9892     }
9893   else
9894     {
9895       /* we did not allocate which means left
9896          already in a pointer register, then
9897          if size > 0 && this could be used again
9898          we have to point it back to where it
9899          belongs */
9900       if (AOP_SIZE (right) > 1 &&
9901           !OP_SYMBOL (result)->remat &&
9902           (OP_SYMBOL (result)->liveTo > ic->seq ||
9903            ic->depth) &&
9904           !pi)
9905         {
9906           int size = AOP_SIZE (right) - 1;
9907           while (size--)
9908             emitcode ("dec", "%s", rname);
9909         }
9910     }
9911
9912   /* done */
9913   if (pi) pi->generated = 1;
9914   freeAsmop (result, NULL, ic, TRUE);
9915   freeAsmop (right, NULL, ic, TRUE);
9916
9917
9918 }
9919
9920 /*-----------------------------------------------------------------*/
9921 /* genFarPointerSet - set value from far space                     */
9922 /*-----------------------------------------------------------------*/
9923 static void
9924 genFarPointerSet (operand * right,
9925                   operand * result, iCode * ic, iCode *pi)
9926 {
9927   int size, offset, dopi=1;
9928   sym_link *retype = getSpec (operandType (right));
9929   sym_link *letype = getSpec (operandType (result));
9930
9931   aopOp (result, ic, FALSE, FALSE);
9932
9933   /* if the operand is already in dptr
9934      then we do nothing else we move the value to dptr */
9935   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
9936     {
9937       /* if this is remateriazable */
9938       if (AOP_TYPE (result) == AOP_IMMD)
9939         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9940       else
9941         {
9942           /* we need to get it byte by byte */
9943           _startLazyDPSEvaluation ();
9944           if (AOP_TYPE (result) != AOP_DPTR)
9945             {
9946               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9947               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9948               if (options.model == MODEL_FLAT24)
9949                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9950             }
9951           else
9952             {
9953               /* We need to generate a load to DPTR indirect through DPTR. */
9954               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9955                 );
9956               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9957               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9958               if (options.model == MODEL_FLAT24)
9959                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9960               emitcode ("pop", "dph");
9961               emitcode ("pop", "dpl");
9962               dopi=0;
9963             }
9964           _endLazyDPSEvaluation ();
9965         }
9966     }
9967   /* so dptr know contains the address */
9968   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
9969
9970   /* if bit then unpack */
9971   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9972       if (AOP_INDPTRn(result)) {
9973           genSetDPTR(AOP(result)->aopu.dptr);
9974       }
9975       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9976       if (AOP_INDPTRn(result)) {
9977           genSetDPTR(0);
9978       }
9979   } else {
9980       size = AOP_SIZE (right);
9981       offset = 0;
9982       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
9983           while (size--) {
9984               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9985               MOVA (l);
9986               
9987               genSetDPTR(AOP(result)->aopu.dptr);
9988               emitcode ("movx", "@dptr,a");
9989               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9990                   emitcode ("inc", "dptr");
9991               genSetDPTR (0);
9992           }
9993       } else {
9994           _startLazyDPSEvaluation ();
9995           while (size--) {
9996               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9997               MOVA (l);
9998               
9999               if (AOP_INDPTRn(result)) {
10000                   genSetDPTR(AOP(result)->aopu.dptr);
10001               } else {
10002                   genSetDPTR (0);
10003               }
10004               _flushLazyDPS ();
10005               
10006               emitcode ("movx", "@dptr,a");
10007               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10008                   emitcode ("inc", "dptr");
10009           }
10010           _endLazyDPSEvaluation ();
10011       }
10012   }
10013   
10014   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10015       if (!AOP_INDPTRn(result)) {
10016           aopPut (AOP(result),"dpl",0);
10017           aopPut (AOP(result),"dph",1);
10018           if (options.model == MODEL_FLAT24)
10019               aopPut (AOP(result),"dpx",2);
10020       }
10021       pi->generated=1;
10022   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10023              AOP_SIZE(right) > 1 &&
10024              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10025       
10026       size = AOP_SIZE (right) - 1;
10027       if (AOP_INDPTRn(result)) {
10028           genSetDPTR(AOP(result)->aopu.dptr);
10029       } 
10030       while (size--) emitcode ("lcall","__decdptr");
10031       if (AOP_INDPTRn(result)) {
10032           genSetDPTR(0);
10033       }
10034   }
10035   freeAsmop (result, NULL, ic, TRUE);
10036   freeAsmop (right, NULL, ic, TRUE);
10037 }
10038
10039 /*-----------------------------------------------------------------*/
10040 /* genGenPointerSet - set value from generic pointer space         */
10041 /*-----------------------------------------------------------------*/
10042 static void
10043 genGenPointerSet (operand * right,
10044                   operand * result, iCode * ic, iCode *pi)
10045 {
10046   int size, offset;
10047   sym_link *retype = getSpec (operandType (right));
10048   sym_link *letype = getSpec (operandType (result));
10049
10050   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10051
10052   /* if the operand is already in dptr
10053      then we do nothing else we move the value to dptr */
10054   if (AOP_TYPE (result) != AOP_STR)
10055     {
10056       _startLazyDPSEvaluation ();
10057       /* if this is remateriazable */
10058       if (AOP_TYPE (result) == AOP_IMMD)
10059         {
10060           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10061           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10062                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10063           else
10064                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10065         }
10066       else
10067         {                       /* we need to get it byte by byte */
10068           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10069           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10070           if (options.model == MODEL_FLAT24) {
10071             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10072             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10073           } else {
10074             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10075           }
10076         }
10077       _endLazyDPSEvaluation ();
10078     }
10079   /* so dptr know contains the address */
10080   aopOp (right, ic, FALSE, TRUE);
10081
10082   /* if bit then unpack */
10083   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10084     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10085   else
10086     {
10087       size = AOP_SIZE (right);
10088       offset = 0;
10089
10090       _startLazyDPSEvaluation ();
10091       while (size--)
10092         {
10093           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10094           MOVA (l);
10095
10096           genSetDPTR (0);
10097           _flushLazyDPS ();
10098
10099           emitcode ("lcall", "__gptrput");
10100           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10101             emitcode ("inc", "dptr");
10102         }
10103       _endLazyDPSEvaluation ();
10104     }
10105
10106   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10107       aopPut (AOP(result),"dpl",0);
10108       aopPut (AOP(result),"dph",1);
10109       if (options.model == MODEL_FLAT24) {
10110           aopPut (AOP(result),"dpx",2);
10111           aopPut (AOP(result),"b",3);
10112       } else {
10113           aopPut (AOP(result),"b",2);
10114       }
10115       pi->generated=1;
10116   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10117              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10118       
10119       size = AOP_SIZE (right) - 1;
10120       while (size--) emitcode ("lcall","__decdptr");
10121   }
10122   freeAsmop (result, NULL, ic, TRUE);
10123   freeAsmop (right, NULL, ic, TRUE);
10124 }
10125
10126 /*-----------------------------------------------------------------*/
10127 /* genPointerSet - stores the value into a pointer location        */
10128 /*-----------------------------------------------------------------*/
10129 static void
10130 genPointerSet (iCode * ic, iCode *pi)
10131 {
10132   operand *right, *result;
10133   sym_link *type, *etype;
10134   int p_type;
10135
10136   D (emitcode (";", "genPointerSet ");
10137     );
10138
10139   right = IC_RIGHT (ic);
10140   result = IC_RESULT (ic);
10141
10142   /* depending on the type of pointer we need to
10143      move it to the correct pointer register */
10144   type = operandType (result);
10145   etype = getSpec (type);
10146   /* if left is of type of pointer then it is simple */
10147   if (IS_PTR (type) && !IS_FUNC (type->next))
10148     {
10149       p_type = DCL_TYPE (type);
10150     }
10151   else
10152     {
10153       /* we have to go by the storage class */
10154       p_type = PTR_TYPE (SPEC_OCLS (etype));
10155     }
10156   /* special case when cast remat */
10157   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10158       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10159           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10160           type =   type = operandType (result);
10161           p_type = DCL_TYPE (type);
10162   }
10163
10164   /* now that we have the pointer type we assign
10165      the pointer values */
10166   switch (p_type)
10167     {
10168
10169     case POINTER:
10170     case IPOINTER:
10171       genNearPointerSet (right, result, ic, pi);
10172       break;
10173
10174     case PPOINTER:
10175       genPagedPointerSet (right, result, ic, pi);
10176       break;
10177
10178     case FPOINTER:
10179       genFarPointerSet (right, result, ic, pi);
10180       break;
10181
10182     case GPOINTER:
10183       genGenPointerSet (right, result, ic, pi);
10184       break;
10185
10186     default:
10187       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10188               "genPointerSet: illegal pointer type");
10189     }
10190
10191 }
10192
10193 /*-----------------------------------------------------------------*/
10194 /* genIfx - generate code for Ifx statement                        */
10195 /*-----------------------------------------------------------------*/
10196 static void
10197 genIfx (iCode * ic, iCode * popIc)
10198 {
10199   operand *cond = IC_COND (ic);
10200   int isbit = 0;
10201
10202   D (emitcode (";", "genIfx "););
10203
10204   aopOp (cond, ic, FALSE, FALSE);
10205
10206   /* get the value into acc */
10207   if (AOP_TYPE (cond) != AOP_CRY)
10208     toBoolean (cond);
10209   else
10210     isbit = 1;
10211   /* the result is now in the accumulator */
10212   freeAsmop (cond, NULL, ic, TRUE);
10213
10214   /* if there was something to be popped then do it */
10215   if (popIc)
10216     genIpop (popIc);
10217
10218   /* if the condition is  a bit variable */
10219   if (isbit && IS_ITEMP (cond) &&
10220       SPIL_LOC (cond))
10221     genIfxJump (ic, SPIL_LOC (cond)->rname);
10222   else if (isbit && !IS_ITEMP (cond))
10223     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10224   else
10225     genIfxJump (ic, "a");
10226
10227   ic->generated = 1;
10228 }
10229
10230 /*-----------------------------------------------------------------*/
10231 /* genAddrOf - generates code for address of                       */
10232 /*-----------------------------------------------------------------*/
10233 static void
10234 genAddrOf (iCode * ic)
10235 {
10236   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10237   int size, offset;
10238
10239   D (emitcode (";", "genAddrOf ");
10240     );
10241
10242   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10243
10244   /* if the operand is on the stack then we
10245      need to get the stack offset of this
10246      variable */
10247   if (sym->onStack) {
10248       
10249       /* if 10 bit stack */
10250       if (options.stack10bit) {
10251           char buff[10];
10252           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10253           /* if it has an offset then we need to compute it */
10254 /*        emitcode ("subb", "a,#!constbyte", */
10255 /*                  -((sym->stack < 0) ? */
10256 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10257 /*                    ((short) sym->stack)) & 0xff); */
10258 /*        emitcode ("mov","b,a"); */
10259 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10260 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10261 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10262           if (sym->stack) {
10263               emitcode ("mov", "a,_bpx");
10264               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10265                                              ((char) (sym->stack - _G.nRegsSaved)) :
10266                                              ((char) sym->stack )) & 0xff);
10267               emitcode ("mov", "b,a");
10268               emitcode ("mov", "a,_bpx+1");
10269               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10270                                               ((short) (sym->stack - _G.nRegsSaved)) :
10271                                               ((short) sym->stack )) >> 8) & 0xff);
10272               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10273               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10274               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10275           } else {
10276               /* we can just move _bp */
10277               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10278               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10279               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10280           }       
10281       } else {
10282           /* if it has an offset then we need to compute it */
10283           if (sym->stack) {
10284               emitcode ("mov", "a,_bp");
10285               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10286               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10287           } else {
10288               /* we can just move _bp */
10289               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10290           }
10291           /* fill the result with zero */
10292           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10293           
10294           
10295           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10296               fprintf (stderr,
10297                        "*** warning: pointer to stack var truncated.\n");
10298           }
10299
10300           offset = 1;
10301           while (size--) {
10302               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10303           }      
10304       }
10305       goto release;
10306   }
10307
10308   /* object not on stack then we need the name */
10309   size = AOP_SIZE (IC_RESULT (ic));
10310   offset = 0;
10311
10312   while (size--)
10313     {
10314       char s[SDCC_NAME_MAX];
10315       if (offset) {
10316           switch (offset) {
10317           case 1:
10318               tsprintf(s,"!his",sym->rname);
10319               break;
10320           case 2:
10321               tsprintf(s,"!hihis",sym->rname);
10322               break;
10323           case 3:
10324               tsprintf(s,"!hihihis",sym->rname);
10325               break;
10326           default: /* should not need this (just in case) */
10327               sprintf (s, "#(%s >> %d)",
10328                        sym->rname,
10329                        offset * 8);
10330           }
10331       } else
10332           sprintf (s, "#%s", sym->rname);
10333       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10334     }
10335
10336 release:
10337   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10338
10339 }
10340
10341 /*-----------------------------------------------------------------*/
10342 /* genArrayInit - generates code for address of                       */
10343 /*-----------------------------------------------------------------*/
10344 static void
10345 genArrayInit (iCode * ic)
10346 {
10347     literalList *iLoop;
10348     int         ix, count;
10349     int         elementSize = 0, eIndex;
10350     unsigned    val, lastVal;
10351     sym_link    *type;
10352     operand     *left=IC_LEFT(ic);
10353     
10354     D (emitcode (";", "genArrayInit "););
10355
10356     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10357     
10358     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10359     {
10360         // Load immediate value into DPTR.
10361         emitcode("mov", "dptr, %s",
10362              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10363     }
10364     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10365     {
10366 #if 0
10367       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10368               "Unexpected operand to genArrayInit.\n");
10369       exit(1);
10370 #else
10371       // a regression because of SDCCcse.c:1.52
10372       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10373       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10374       if (options.model == MODEL_FLAT24)
10375         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10376 #endif
10377     }
10378     
10379     type = operandType(IC_LEFT(ic));
10380     
10381     if (type && type->next)
10382     {
10383         elementSize = getSize(type->next);
10384     }
10385     else
10386     {
10387         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10388                                 "can't determine element size in genArrayInit.\n");
10389         exit(1);
10390     }
10391     
10392     iLoop = IC_ARRAYILIST(ic);
10393     lastVal = 0xffff;
10394     
10395     while (iLoop)
10396     {
10397         bool firstpass = TRUE;
10398         
10399         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10400                  iLoop->count, (int)iLoop->literalValue, elementSize);
10401         
10402         ix = iLoop->count;
10403         
10404         while (ix)
10405         {
10406             symbol *tlbl = NULL;
10407             
10408             count = ix > 256 ? 256 : ix;
10409             
10410             if (count > 1)
10411             {
10412                 tlbl = newiTempLabel (NULL);
10413                 if (firstpass || (count & 0xff))
10414                 {
10415                     emitcode("mov", "b, #!constbyte", count & 0xff);
10416                 }
10417                 
10418                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10419             }
10420             
10421             firstpass = FALSE;
10422                 
10423             for (eIndex = 0; eIndex < elementSize; eIndex++)
10424             {
10425                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10426                 if (val != lastVal)
10427                 {
10428                     emitcode("mov", "a, #!constbyte", val);
10429                     lastVal = val;
10430                 }
10431                 
10432                 emitcode("movx", "@dptr, a");
10433                 emitcode("inc", "dptr");
10434             }
10435             
10436             if (count > 1)
10437             {
10438                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10439             }
10440             
10441             ix -= count;
10442         }
10443         
10444         iLoop = iLoop->next;
10445     }
10446     
10447     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10448 }
10449
10450 /*-----------------------------------------------------------------*/
10451 /* genFarFarAssign - assignment when both are in far space         */
10452 /*-----------------------------------------------------------------*/
10453 static void
10454 genFarFarAssign (operand * result, operand * right, iCode * ic)
10455 {
10456   int size = AOP_SIZE (right);
10457   int offset = 0;
10458   symbol *rSym = NULL;
10459
10460   if (size == 1)
10461   {
10462       /* quick & easy case. */
10463       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10464       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10465       freeAsmop (right, NULL, ic, FALSE);
10466       /* now assign DPTR to result */
10467       _G.accInUse++;
10468       aopOp(result, ic, FALSE, FALSE);
10469       _G.accInUse--;
10470       aopPut(AOP(result), "a", 0);
10471       freeAsmop(result, NULL, ic, FALSE);
10472       return;
10473   }
10474   
10475   /* See if we've got an underlying symbol to abuse. */
10476   if (IS_SYMOP(result) && OP_SYMBOL(result))
10477   {
10478       if (IS_TRUE_SYMOP(result))
10479       {
10480           rSym = OP_SYMBOL(result);
10481       }
10482       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10483       {
10484           rSym = OP_SYMBOL(result)->usl.spillLoc;
10485       }
10486   }
10487              
10488   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10489   {
10490       /* We can use the '390 auto-toggle feature to good effect here. */
10491       
10492       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10493       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10494       emitcode ("mov", "dptr,#%s", rSym->rname); 
10495       /* DP2 = result, DP1 = right, DP1 is current. */
10496       while (size)
10497       {
10498           emitcode("movx", "a,@dptr");
10499           emitcode("movx", "@dptr,a");
10500           if (--size)
10501           {
10502                emitcode("inc", "dptr");
10503                emitcode("inc", "dptr");
10504           }
10505       }
10506       emitcode("mov", "dps,#0");
10507       freeAsmop (right, NULL, ic, FALSE);
10508 #if 0
10509 some alternative code for processors without auto-toggle
10510 no time to test now, so later well put in...kpb
10511         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10512         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10513         emitcode ("mov", "dptr,#%s", rSym->rname); 
10514         /* DP2 = result, DP1 = right, DP1 is current. */
10515         while (size)
10516         {
10517           --size;
10518           emitcode("movx", "a,@dptr");
10519           if (size)
10520             emitcode("inc", "dptr");
10521           emitcode("inc", "dps");
10522           emitcode("movx", "@dptr,a");
10523           if (size)
10524             emitcode("inc", "dptr");
10525           emitcode("inc", "dps");
10526         }
10527         emitcode("mov", "dps,#0");
10528         freeAsmop (right, NULL, ic, FALSE);
10529 #endif
10530   }
10531   else
10532   {
10533       D (emitcode (";", "genFarFarAssign"););
10534       aopOp (result, ic, TRUE, TRUE);
10535
10536       _startLazyDPSEvaluation ();
10537       
10538       while (size--)
10539         {
10540           aopPut (AOP (result),
10541                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10542           offset++;
10543         }
10544       _endLazyDPSEvaluation ();
10545       freeAsmop (result, NULL, ic, FALSE);
10546       freeAsmop (right, NULL, ic, FALSE);
10547   }
10548 }
10549
10550 /*-----------------------------------------------------------------*/
10551 /* genAssign - generate code for assignment                        */
10552 /*-----------------------------------------------------------------*/
10553 static void
10554 genAssign (iCode * ic)
10555 {
10556   operand *result, *right;
10557   int size, offset;
10558   unsigned long lit = 0L;
10559
10560   D (emitcode (";", "genAssign ");
10561     );
10562
10563   result = IC_RESULT (ic);
10564   right = IC_RIGHT (ic);
10565
10566   /* if they are the same */
10567   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10568     return;
10569
10570   aopOp (right, ic, FALSE, FALSE);
10571
10572   emitcode (";", "genAssign: resultIsFar = %s",
10573             isOperandInFarSpace (result) ?
10574             "TRUE" : "FALSE");
10575
10576   /* special case both in far space */
10577   if ((AOP_TYPE (right) == AOP_DPTR ||
10578        AOP_TYPE (right) == AOP_DPTR2) &&
10579   /* IS_TRUE_SYMOP(result)       && */
10580       isOperandInFarSpace (result))
10581     {
10582       genFarFarAssign (result, right, ic);
10583       return;
10584     }
10585
10586   aopOp (result, ic, TRUE, FALSE);
10587
10588   /* if they are the same registers */
10589   if (sameRegs (AOP (right), AOP (result)))
10590     goto release;
10591
10592   /* if the result is a bit */
10593   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10594     {
10595       /* if the right size is a literal then
10596          we know what the value is */
10597       if (AOP_TYPE (right) == AOP_LIT)
10598         {
10599           if (((int) operandLitValue (right)))
10600             aopPut (AOP (result), one, 0);
10601           else
10602             aopPut (AOP (result), zero, 0);
10603           goto release;
10604         }
10605
10606       /* the right is also a bit variable */
10607       if (AOP_TYPE (right) == AOP_CRY)
10608         {
10609           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10610           aopPut (AOP (result), "c", 0);
10611           goto release;
10612         }
10613
10614       /* we need to or */
10615       toBoolean (right);
10616       aopPut (AOP (result), "a", 0);
10617       goto release;
10618     }
10619
10620   /* bit variables done */
10621   /* general case */
10622   size = AOP_SIZE (result);
10623   offset = 0;
10624   if (AOP_TYPE (right) == AOP_LIT)
10625     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10626
10627   if ((size > 1) &&
10628       (AOP_TYPE (result) != AOP_REG) &&
10629       (AOP_TYPE (right) == AOP_LIT) &&
10630       !IS_FLOAT (operandType (right)))
10631     {
10632       _startLazyDPSEvaluation ();
10633       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10634         {
10635           aopPut (AOP (result),
10636                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10637                   offset);
10638           offset++;
10639           size--;
10640         }
10641       /* And now fill the rest with zeros. */
10642       if (size)
10643         {
10644           emitcode ("clr", "a");
10645         }
10646       while (size--)
10647         {
10648           aopPut (AOP (result), "a", offset++);
10649         }
10650       _endLazyDPSEvaluation ();
10651     }
10652   else
10653     {
10654       _startLazyDPSEvaluation ();
10655       while (size--)
10656         {
10657           aopPut (AOP (result),
10658                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10659                   offset);
10660           offset++;
10661         }
10662       _endLazyDPSEvaluation ();
10663     }
10664
10665 release:
10666   freeAsmop (right, NULL, ic, FALSE);
10667   freeAsmop (result, NULL, ic, TRUE);
10668 }
10669
10670 /*-----------------------------------------------------------------*/
10671 /* genJumpTab - generates code for jump table                      */
10672 /*-----------------------------------------------------------------*/
10673 static void
10674 genJumpTab (iCode * ic)
10675 {
10676   symbol *jtab;
10677   char *l;
10678
10679   D (emitcode (";", "genJumpTab ");
10680     );
10681
10682   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10683   /* get the condition into accumulator */
10684   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10685   MOVA (l);
10686   /* multiply by four! */
10687   emitcode ("add", "a,acc");
10688   emitcode ("add", "a,acc");
10689   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10690
10691   jtab = newiTempLabel (NULL);
10692   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10693   emitcode ("jmp", "@a+dptr");
10694   emitcode ("", "!tlabeldef", jtab->key + 100);
10695   /* now generate the jump labels */
10696   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10697        jtab = setNextItem (IC_JTLABELS (ic)))
10698     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10699
10700 }
10701
10702 /*-----------------------------------------------------------------*/
10703 /* genCast - gen code for casting                                  */
10704 /*-----------------------------------------------------------------*/
10705 static void
10706 genCast (iCode * ic)
10707 {
10708   operand *result = IC_RESULT (ic);
10709   sym_link *ctype = operandType (IC_LEFT (ic));
10710   sym_link *rtype = operandType (IC_RIGHT (ic));
10711   operand *right = IC_RIGHT (ic);
10712   int size, offset;
10713
10714   D (emitcode (";", "genCast ");
10715     );
10716
10717   /* if they are equivalent then do nothing */
10718   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10719     return;
10720
10721   aopOp (right, ic, FALSE, FALSE);
10722   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10723
10724   /* if the result is a bit */
10725   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10726   if (IS_BITVAR(OP_SYMBOL(result)->type))
10727     {
10728       /* if the right size is a literal then
10729          we know what the value is */
10730       if (AOP_TYPE (right) == AOP_LIT)
10731         {
10732           if (((int) operandLitValue (right)))
10733             aopPut (AOP (result), one, 0);
10734           else
10735             aopPut (AOP (result), zero, 0);
10736
10737           goto release;
10738         }
10739
10740       /* the right is also a bit variable */
10741       if (AOP_TYPE (right) == AOP_CRY)
10742         {
10743           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10744           aopPut (AOP (result), "c", 0);
10745           goto release;
10746         }
10747
10748       /* we need to or */
10749       toBoolean (right);
10750       aopPut (AOP (result), "a", 0);
10751       goto release;
10752     }
10753
10754   /* if they are the same size : or less */
10755   if (AOP_SIZE (result) <= AOP_SIZE (right))
10756     {
10757
10758       /* if they are in the same place */
10759       if (sameRegs (AOP (right), AOP (result)))
10760         goto release;
10761
10762       /* if they in different places then copy */
10763       size = AOP_SIZE (result);
10764       offset = 0;
10765       _startLazyDPSEvaluation ();
10766       while (size--)
10767         {
10768           aopPut (AOP (result),
10769                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10770                   offset);
10771           offset++;
10772         }
10773       _endLazyDPSEvaluation ();
10774       goto release;
10775     }
10776
10777
10778   /* if the result is of type pointer */
10779   if (IS_PTR (ctype))
10780     {
10781
10782       int p_type;
10783       sym_link *type = operandType (right);
10784
10785       /* pointer to generic pointer */
10786       if (IS_GENPTR (ctype))
10787         {
10788           if (IS_PTR (type))
10789             {
10790               p_type = DCL_TYPE (type);
10791             }
10792           else
10793             {
10794 #if OLD_CAST_BEHAVIOR
10795               /* KV: we are converting a non-pointer type to
10796                * a generic pointer. This (ifdef'd out) code
10797                * says that the resulting generic pointer
10798                * should have the same class as the storage
10799                * location of the non-pointer variable.
10800                *
10801                * For example, converting an int (which happens
10802                * to be stored in DATA space) to a pointer results
10803                * in a DATA generic pointer; if the original int
10804                * in XDATA space, so will be the resulting pointer.
10805                *
10806                * I don't like that behavior, and thus this change:
10807                * all such conversions will be forced to XDATA and
10808                * throw a warning. If you want some non-XDATA
10809                * type, or you want to suppress the warning, you
10810                * must go through an intermediate cast, like so:
10811                *
10812                * char _generic *gp = (char _xdata *)(intVar);
10813                */
10814               sym_link *etype = getSpec (type);
10815
10816               /* we have to go by the storage class */
10817               if (SPEC_OCLS (etype) != generic)
10818                 {
10819                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10820                 }
10821               else
10822 #endif
10823                 {
10824                   /* Converting unknown class (i.e. register variable)
10825                    * to generic pointer. This is not good, but
10826                    * we'll make a guess (and throw a warning).
10827                    */
10828                   p_type = FPOINTER;
10829                   werror (W_INT_TO_GEN_PTR_CAST);
10830                 }
10831             }
10832
10833           /* the first two bytes are known */
10834           size = GPTRSIZE - 1;
10835           offset = 0;
10836           _startLazyDPSEvaluation ();
10837           while (size--)
10838             {
10839               aopPut (AOP (result),
10840                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10841                       offset);
10842               offset++;
10843             }
10844           _endLazyDPSEvaluation ();
10845
10846           /* the last byte depending on type */
10847             {
10848                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10849                 char gpValStr[10];
10850             
10851                 if (gpVal == -1)
10852                 {
10853                     // pointerTypeToGPByte will have bitched.
10854                     exit(1);
10855                 }
10856             
10857                 sprintf(gpValStr, "#0x%d", gpVal);
10858                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
10859             }
10860           goto release;
10861         }
10862
10863       /* just copy the pointers */
10864       size = AOP_SIZE (result);
10865       offset = 0;
10866       _startLazyDPSEvaluation ();
10867       while (size--)
10868         {
10869           aopPut (AOP (result),
10870                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10871                   offset);
10872           offset++;
10873         }
10874       _endLazyDPSEvaluation ();
10875       goto release;
10876     }
10877
10878   /* so we now know that the size of destination is greater
10879      than the size of the source */
10880   /* we move to result for the size of source */
10881   size = AOP_SIZE (right);
10882   offset = 0;
10883   _startLazyDPSEvaluation ();
10884   while (size--)
10885     {
10886       aopPut (AOP (result),
10887               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10888               offset);
10889       offset++;
10890     }
10891   _endLazyDPSEvaluation ();
10892
10893   /* now depending on the sign of the source && destination */
10894   size = AOP_SIZE (result) - AOP_SIZE (right);
10895   /* if unsigned or not an integral type */
10896   /* also, if the source is a bit, we don't need to sign extend, because
10897    * it can't possibly have set the sign bit.
10898    */
10899   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10900     {
10901       while (size--)
10902         {
10903           aopPut (AOP (result), zero, offset++);
10904         }
10905     }
10906   else
10907     {
10908       /* we need to extend the sign :{ */
10909       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10910                         FALSE, FALSE, TRUE);
10911       MOVA (l);
10912       emitcode ("rlc", "a");
10913       emitcode ("subb", "a,acc");
10914       while (size--)
10915         aopPut (AOP (result), "a", offset++);
10916     }
10917
10918   /* we are done hurray !!!! */
10919
10920 release:
10921   freeAsmop (right, NULL, ic, TRUE);
10922   freeAsmop (result, NULL, ic, TRUE);
10923
10924 }
10925
10926 /*-----------------------------------------------------------------*/
10927 /* genDjnz - generate decrement & jump if not zero instrucion      */
10928 /*-----------------------------------------------------------------*/
10929 static int
10930 genDjnz (iCode * ic, iCode * ifx)
10931 {
10932   symbol *lbl, *lbl1;
10933   if (!ifx)
10934     return 0;
10935
10936   /* if the if condition has a false label
10937      then we cannot save */
10938   if (IC_FALSE (ifx))
10939     return 0;
10940
10941   /* if the minus is not of the form
10942      a = a - 1 */
10943   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10944       !IS_OP_LITERAL (IC_RIGHT (ic)))
10945     return 0;
10946
10947   if (operandLitValue (IC_RIGHT (ic)) != 1)
10948     return 0;
10949
10950   /* if the size of this greater than one then no
10951      saving */
10952   if (getSize (operandType (IC_RESULT (ic))) > 1)
10953     return 0;
10954
10955   /* otherwise we can save BIG */
10956   D(emitcode(";", "genDjnz"););
10957
10958   lbl = newiTempLabel (NULL);
10959   lbl1 = newiTempLabel (NULL);
10960
10961   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10962
10963   if (AOP_NEEDSACC(IC_RESULT(ic)))
10964   {
10965       /* If the result is accessed indirectly via
10966        * the accumulator, we must explicitly write
10967        * it back after the decrement.
10968        */
10969       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10970       
10971       if (strcmp(rByte, "a"))
10972       {
10973            /* Something is hopelessly wrong */
10974            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10975                    __FILE__, __LINE__);
10976            /* We can just give up; the generated code will be inefficient,
10977             * but what the hey.
10978             */
10979            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10980            return 0;
10981       }
10982       emitcode ("dec", "%s", rByte);
10983       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10984       emitcode ("jnz", "!tlabel", lbl->key + 100);
10985   }
10986   else if (IS_AOP_PREG (IC_RESULT (ic)))
10987     {
10988       emitcode ("dec", "%s",
10989                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10990       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10991       emitcode ("jnz", "!tlabel", lbl->key + 100);
10992     }
10993   else
10994     {
10995       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10996                 lbl->key + 100);
10997     }
10998   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10999   emitcode ("", "!tlabeldef", lbl->key + 100);
11000   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11001   emitcode ("", "!tlabeldef", lbl1->key + 100);
11002
11003   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11004   ifx->generated = 1;
11005   return 1;
11006 }
11007
11008 /*-----------------------------------------------------------------*/
11009 /* genReceive - generate code for a receive iCode                  */
11010 /*-----------------------------------------------------------------*/
11011 static void
11012 genReceive (iCode * ic)
11013 {
11014
11015     int size = getSize (operandType (IC_RESULT (ic)));
11016     int offset = 0;
11017     int rb1off ;
11018     
11019     D (emitcode (";", "genReceive ");
11020        );
11021
11022   if (ic->argreg == 1) { /* first parameter */
11023       if (isOperandInFarSpace (IC_RESULT (ic)) &&
11024           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11025            IS_TRUE_SYMOP (IC_RESULT (ic))))
11026           {
11027               offset = fReturnSizeDS390 - size;
11028               while (size--)
11029                   {
11030                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11031                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11032                       offset++;
11033                   }
11034               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11035               size = AOP_SIZE (IC_RESULT (ic));
11036               offset = 0;
11037               while (size--)
11038                   {
11039                       emitcode ("pop", "acc");
11040                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11041                   }
11042               
11043           } else {
11044               _G.accInUse++;
11045               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11046               _G.accInUse--;
11047               assignResultValue (IC_RESULT (ic));
11048           }
11049   } else { /* second receive onwards */
11050       /* this gets a little tricky since unused recevies will be
11051          eliminated, we have saved the reg in the type field . and
11052          we use that to figure out which register to use */
11053       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11054       rb1off = ic->argreg;
11055       while (size--) {
11056           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11057       }
11058       
11059   }
11060   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11061 }
11062
11063 /*-----------------------------------------------------------------*/
11064 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11065 /*-----------------------------------------------------------------*/
11066 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11067 {
11068     operand *from , *to , *count;
11069     symbol *lbl;
11070     bitVect *rsave;
11071     int i;
11072
11073     /* we know it has to be 3 parameters */
11074     assert (nparms == 3);
11075     
11076     rsave = newBitVect(16);
11077     /* save DPTR if it needs to be saved */
11078     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11079             if (bitVectBitValue(ic->rMask,i))
11080                     rsave = bitVectSetBit(rsave,i);
11081     }
11082     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11083                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11084     savermask(rsave);
11085     
11086     to = parms[0];
11087     from = parms[1];
11088     count = parms[2];
11089
11090     aopOp (from, ic->next, FALSE, FALSE);
11091
11092     /* get from into DPTR1 */
11093     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11094     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11095     if (options.model == MODEL_FLAT24) {
11096         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11097     }
11098
11099     freeAsmop (from, NULL, ic, FALSE);
11100     aopOp (to, ic, FALSE, FALSE);
11101     /* get "to" into DPTR */
11102     /* if the operand is already in dptr
11103        then we do nothing else we move the value to dptr */
11104     if (AOP_TYPE (to) != AOP_STR) {
11105         /* if already in DPTR then we need to push */
11106         if (AOP_TYPE(to) == AOP_DPTR) {
11107             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11108             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11109             if (options.model == MODEL_FLAT24)
11110                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11111             emitcode ("pop", "dph");
11112             emitcode ("pop", "dpl");        
11113         } else {
11114             _startLazyDPSEvaluation ();
11115             /* if this is remateriazable */
11116             if (AOP_TYPE (to) == AOP_IMMD) {
11117                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11118             } else {                    /* we need to get it byte by byte */
11119                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11120                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11121                 if (options.model == MODEL_FLAT24) {
11122                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11123                 }
11124             }
11125             _endLazyDPSEvaluation ();
11126         }
11127     }
11128     freeAsmop (to, NULL, ic, FALSE);
11129     _G.dptrInUse = _G.dptr1InUse = 1;
11130     aopOp (count, ic->next->next, FALSE,FALSE);
11131     lbl =newiTempLabel(NULL);
11132
11133     /* now for the actual copy */
11134     if (AOP_TYPE(count) == AOP_LIT && 
11135         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11136         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11137         if (fromc) {
11138             emitcode ("lcall","__bi_memcpyc2x_s");
11139         } else {
11140             emitcode ("lcall","__bi_memcpyx2x_s");
11141         }
11142         freeAsmop (count, NULL, ic, FALSE);
11143     } else {
11144         symbol *lbl1 = newiTempLabel(NULL);
11145         
11146         emitcode (";"," Auto increment but no djnz");
11147         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11148         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11149         freeAsmop (count, NULL, ic, FALSE);
11150         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11151         emitcode ("","!tlabeldef",lbl->key+100);
11152         if (fromc) {
11153             emitcode ("clr","a");
11154             emitcode ("movc", "a,@a+dptr");
11155         } else 
11156             emitcode ("movx", "a,@dptr");
11157         emitcode ("movx", "@dptr,a");
11158         emitcode ("inc", "dptr");
11159         emitcode ("inc", "dptr");
11160         emitcode ("mov","a,b");
11161         emitcode ("orl","a,_ap");
11162         emitcode ("jz","!tlabel",lbl1->key+100);
11163         emitcode ("mov","a,_ap");
11164         emitcode ("add","a,#!constbyte",0xFF);
11165         emitcode ("mov","_ap,a");
11166         emitcode ("mov","a,b");
11167         emitcode ("addc","a,#!constbyte",0xFF);
11168         emitcode ("mov","b,a");
11169         emitcode ("sjmp","!tlabel",lbl->key+100);
11170         emitcode ("","!tlabeldef",lbl1->key+100);
11171     }
11172     emitcode ("mov", "dps,#0"); 
11173     _G.dptrInUse = _G.dptr1InUse = 0;
11174     unsavermask(rsave);
11175
11176 }
11177
11178 /*-----------------------------------------------------------------*/
11179 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11180 /*-----------------------------------------------------------------*/
11181 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11182 {
11183     operand *from , *to , *count;
11184     symbol *lbl,*lbl2;
11185     bitVect *rsave;
11186     int i;
11187
11188     /* we know it has to be 3 parameters */
11189     assert (nparms == 3);
11190     
11191     rsave = newBitVect(16);
11192     /* save DPTR if it needs to be saved */
11193     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11194             if (bitVectBitValue(ic->rMask,i))
11195                     rsave = bitVectSetBit(rsave,i);
11196     }
11197     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11198                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11199     savermask(rsave);
11200     
11201     to = parms[0];
11202     from = parms[1];
11203     count = parms[2];
11204
11205     aopOp (from, ic->next, FALSE, FALSE);
11206
11207     /* get from into DPTR1 */
11208     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11209     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11210     if (options.model == MODEL_FLAT24) {
11211         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11212     }
11213
11214     freeAsmop (from, NULL, ic, FALSE);
11215     aopOp (to, ic, FALSE, FALSE);
11216     /* get "to" into DPTR */
11217     /* if the operand is already in dptr
11218        then we do nothing else we move the value to dptr */
11219     if (AOP_TYPE (to) != AOP_STR) {
11220         /* if already in DPTR then we need to push */
11221         if (AOP_TYPE(to) == AOP_DPTR) {
11222             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11223             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11224             if (options.model == MODEL_FLAT24)
11225                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11226             emitcode ("pop", "dph");
11227             emitcode ("pop", "dpl");        
11228         } else {
11229             _startLazyDPSEvaluation ();
11230             /* if this is remateriazable */
11231             if (AOP_TYPE (to) == AOP_IMMD) {
11232                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11233             } else {                    /* we need to get it byte by byte */
11234                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11235                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11236                 if (options.model == MODEL_FLAT24) {
11237                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11238                 }
11239             }
11240             _endLazyDPSEvaluation ();
11241         }
11242     }
11243     freeAsmop (to, NULL, ic, FALSE);
11244     _G.dptrInUse = _G.dptr1InUse = 1;
11245     aopOp (count, ic->next->next, FALSE,FALSE);
11246     lbl =newiTempLabel(NULL);
11247     lbl2 =newiTempLabel(NULL);
11248
11249     /* now for the actual compare */
11250     if (AOP_TYPE(count) == AOP_LIT && 
11251         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11252         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11253         if (fromc)
11254             emitcode("lcall","__bi_memcmpc2x_s");
11255         else
11256             emitcode("lcall","__bi_memcmpx2x_s");
11257         freeAsmop (count, NULL, ic, FALSE);
11258         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11259         aopPut(AOP(IC_RESULT(ic)),"a",0);
11260         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11261     } else {
11262         symbol *lbl1 = newiTempLabel(NULL);
11263
11264         emitcode("push","ar0");         
11265         emitcode (";"," Auto increment but no djnz");
11266         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11267         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11268         freeAsmop (count, NULL, ic, FALSE);
11269         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11270         emitcode ("","!tlabeldef",lbl->key+100);
11271         if (fromc) {
11272             emitcode ("clr","a");
11273             emitcode ("movc", "a,@a+dptr");
11274         } else 
11275             emitcode ("movx", "a,@dptr");
11276         emitcode ("mov","r0,a");
11277         emitcode ("movx", "a,@dptr");
11278         emitcode ("clr","c");
11279         emitcode ("subb","a,r0");
11280         emitcode ("jnz","!tlabel",lbl2->key+100);
11281         emitcode ("inc", "dptr");
11282         emitcode ("inc", "dptr");
11283         emitcode ("mov","a,b");
11284         emitcode ("orl","a,_ap");
11285         emitcode ("jz","!tlabel",lbl1->key+100);
11286         emitcode ("mov","a,_ap");
11287         emitcode ("add","a,#!constbyte",0xFF);
11288         emitcode ("mov","_ap,a");
11289         emitcode ("mov","a,b");
11290         emitcode ("addc","a,#!constbyte",0xFF);
11291         emitcode ("mov","b,a");
11292         emitcode ("sjmp","!tlabel",lbl->key+100);
11293         emitcode ("","!tlabeldef",lbl1->key+100);
11294         emitcode ("clr","a");
11295         emitcode ("","!tlabeldef",lbl2->key+100);
11296         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11297         aopPut(AOP(IC_RESULT(ic)),"a",0);
11298         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11299         emitcode("pop","ar0");
11300         emitcode ("mov", "dps,#0");      
11301     }
11302     _G.dptrInUse = _G.dptr1InUse = 0;
11303     unsavermask(rsave);
11304
11305 }
11306
11307 /*-----------------------------------------------------------------*/
11308 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11309 /* port, first parameter output area second parameter pointer to   */
11310 /* port third parameter count                                      */
11311 /*-----------------------------------------------------------------*/
11312 static void genInp( iCode *ic, int nparms, operand **parms)
11313 {
11314     operand *from , *to , *count;
11315     symbol *lbl;
11316     bitVect *rsave;
11317     int i;
11318
11319     /* we know it has to be 3 parameters */
11320     assert (nparms == 3);
11321     
11322     rsave = newBitVect(16);
11323     /* save DPTR if it needs to be saved */
11324     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11325             if (bitVectBitValue(ic->rMask,i))
11326                     rsave = bitVectSetBit(rsave,i);
11327     }
11328     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11329                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11330     savermask(rsave);
11331     
11332     to = parms[0];
11333     from = parms[1];
11334     count = parms[2];
11335
11336     aopOp (from, ic->next, FALSE, FALSE);
11337
11338     /* get from into DPTR1 */
11339     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11340     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11341     if (options.model == MODEL_FLAT24) {
11342         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11343     }
11344
11345     freeAsmop (from, NULL, ic, FALSE);
11346     aopOp (to, ic, FALSE, FALSE);
11347     /* get "to" into DPTR */
11348     /* if the operand is already in dptr
11349        then we do nothing else we move the value to dptr */
11350     if (AOP_TYPE (to) != AOP_STR) {
11351         /* if already in DPTR then we need to push */
11352         if (AOP_TYPE(to) == AOP_DPTR) {
11353             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11354             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11355             if (options.model == MODEL_FLAT24)
11356                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11357             emitcode ("pop", "dph");
11358             emitcode ("pop", "dpl");        
11359         } else {
11360             _startLazyDPSEvaluation ();
11361             /* if this is remateriazable */
11362             if (AOP_TYPE (to) == AOP_IMMD) {
11363                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11364             } else {                    /* we need to get it byte by byte */
11365                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11366                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11367                 if (options.model == MODEL_FLAT24) {
11368                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11369                 }
11370             }
11371             _endLazyDPSEvaluation ();
11372         }
11373     }
11374     freeAsmop (to, NULL, ic, FALSE);
11375
11376     _G.dptrInUse = _G.dptr1InUse = 1;
11377     aopOp (count, ic->next->next, FALSE,FALSE);
11378     lbl =newiTempLabel(NULL);
11379
11380     /* now for the actual copy */
11381     if (AOP_TYPE(count) == AOP_LIT && 
11382         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11383         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11384         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11385         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11386         freeAsmop (count, NULL, ic, FALSE);
11387         emitcode ("","!tlabeldef",lbl->key+100);
11388         emitcode ("movx", "a,@dptr");   /* read data from port */
11389         emitcode ("dec","dps");         /* switch to DPTR */
11390         emitcode ("movx", "@dptr,a");   /* save into location */
11391         emitcode ("inc", "dptr");       /* point to next area */
11392         emitcode ("inc","dps");         /* switch to DPTR2 */
11393         emitcode ("djnz","b,!tlabel",lbl->key+100);
11394     } else {
11395         symbol *lbl1 = newiTempLabel(NULL);
11396         
11397         emitcode (";"," Auto increment but no djnz");
11398         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11399         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11400         freeAsmop (count, NULL, ic, FALSE);
11401         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11402         emitcode ("","!tlabeldef",lbl->key+100);
11403         emitcode ("movx", "a,@dptr");
11404         emitcode ("dec","dps");         /* switch to DPTR */
11405         emitcode ("movx", "@dptr,a");
11406         emitcode ("inc", "dptr");
11407         emitcode ("inc","dps");         /* switch to DPTR2 */
11408 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11409 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11410         emitcode ("mov","a,b");
11411         emitcode ("orl","a,_ap");
11412         emitcode ("jz","!tlabel",lbl1->key+100);
11413         emitcode ("mov","a,_ap");
11414         emitcode ("add","a,#!constbyte",0xFF);
11415         emitcode ("mov","_ap,a");
11416         emitcode ("mov","a,b");
11417         emitcode ("addc","a,#!constbyte",0xFF);
11418         emitcode ("mov","b,a");
11419         emitcode ("sjmp","!tlabel",lbl->key+100);
11420         emitcode ("","!tlabeldef",lbl1->key+100);
11421     }
11422     emitcode ("mov", "dps,#0"); 
11423     _G.dptrInUse = _G.dptr1InUse = 0;
11424     unsavermask(rsave);
11425
11426 }
11427
11428 /*-----------------------------------------------------------------*/
11429 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11430 /* port, first parameter output area second parameter pointer to   */
11431 /* port third parameter count                                      */
11432 /*-----------------------------------------------------------------*/
11433 static void genOutp( iCode *ic, int nparms, operand **parms)
11434 {
11435     operand *from , *to , *count;
11436     symbol *lbl;
11437     bitVect *rsave;
11438     int i;
11439
11440     /* we know it has to be 3 parameters */
11441     assert (nparms == 3);
11442     
11443     rsave = newBitVect(16);
11444     /* save DPTR if it needs to be saved */
11445     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11446             if (bitVectBitValue(ic->rMask,i))
11447                     rsave = bitVectSetBit(rsave,i);
11448     }
11449     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11450                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11451     savermask(rsave);
11452     
11453     to = parms[0];
11454     from = parms[1];
11455     count = parms[2];
11456
11457     aopOp (from, ic->next, FALSE, FALSE);
11458
11459     /* get from into DPTR1 */
11460     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11461     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11462     if (options.model == MODEL_FLAT24) {
11463         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11464     }
11465
11466     freeAsmop (from, NULL, ic, FALSE);
11467     aopOp (to, ic, FALSE, FALSE);
11468     /* get "to" into DPTR */
11469     /* if the operand is already in dptr
11470        then we do nothing else we move the value to dptr */
11471     if (AOP_TYPE (to) != AOP_STR) {
11472         /* if already in DPTR then we need to push */
11473         if (AOP_TYPE(to) == AOP_DPTR) {
11474             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11475             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11476             if (options.model == MODEL_FLAT24)
11477                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11478             emitcode ("pop", "dph");
11479             emitcode ("pop", "dpl");        
11480         } else {
11481             _startLazyDPSEvaluation ();
11482             /* if this is remateriazable */
11483             if (AOP_TYPE (to) == AOP_IMMD) {
11484                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11485             } else {                    /* we need to get it byte by byte */
11486                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11487                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11488                 if (options.model == MODEL_FLAT24) {
11489                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11490                 }
11491             }
11492             _endLazyDPSEvaluation ();
11493         }
11494     }
11495     freeAsmop (to, NULL, ic, FALSE);
11496
11497     _G.dptrInUse = _G.dptr1InUse = 1;
11498     aopOp (count, ic->next->next, FALSE,FALSE);
11499     lbl =newiTempLabel(NULL);
11500
11501     /* now for the actual copy */
11502     if (AOP_TYPE(count) == AOP_LIT && 
11503         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11504         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11505         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11506         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11507         emitcode ("","!tlabeldef",lbl->key+100);
11508         emitcode ("movx", "a,@dptr");   /* read data from port */
11509         emitcode ("inc","dps");         /* switch to DPTR2 */
11510         emitcode ("movx", "@dptr,a");   /* save into location */
11511         emitcode ("inc", "dptr");       /* point to next area */
11512         emitcode ("dec","dps");         /* switch to DPTR */
11513         emitcode ("djnz","b,!tlabel",lbl->key+100);
11514         freeAsmop (count, NULL, ic, FALSE);
11515     } else {
11516         symbol *lbl1 = newiTempLabel(NULL);
11517         
11518         emitcode (";"," Auto increment but no djnz");
11519         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11520         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11521         freeAsmop (count, NULL, ic, FALSE);
11522         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11523         emitcode ("","!tlabeldef",lbl->key+100);
11524         emitcode ("movx", "a,@dptr");
11525         emitcode ("inc", "dptr");
11526         emitcode ("inc","dps");         /* switch to DPTR2 */
11527         emitcode ("movx", "@dptr,a");
11528         emitcode ("dec","dps");         /* switch to DPTR */
11529         emitcode ("mov","a,b");
11530         emitcode ("orl","a,_ap");
11531         emitcode ("jz","!tlabel",lbl1->key+100);
11532         emitcode ("mov","a,_ap");
11533         emitcode ("add","a,#!constbyte",0xFF);
11534         emitcode ("mov","_ap,a");
11535         emitcode ("mov","a,b");
11536         emitcode ("addc","a,#!constbyte",0xFF);
11537         emitcode ("mov","b,a");
11538         emitcode ("sjmp","!tlabel",lbl->key+100);
11539         emitcode ("","!tlabeldef",lbl1->key+100);
11540     }
11541     emitcode ("mov", "dps,#0"); 
11542     _G.dptrInUse = _G.dptr1InUse = 0;
11543     unsavermask(rsave);
11544
11545 }
11546
11547 /*-----------------------------------------------------------------*/
11548 /* genSwapW - swap lower & high order bytes                        */
11549 /*-----------------------------------------------------------------*/
11550 static void genSwapW(iCode *ic, int nparms, operand **parms)
11551 {
11552     operand *dest;
11553     operand *src;
11554     assert (nparms==1);
11555
11556     src = parms[0];
11557     dest=IC_RESULT(ic);
11558
11559     assert(getSize(operandType(src))==2);
11560
11561     aopOp (src, ic, FALSE, FALSE);
11562     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11563     _G.accInUse++;
11564     emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11565     _G.accInUse--;
11566     freeAsmop (src, NULL, ic, FALSE);
11567     
11568     aopOp (dest,ic, FALSE, FALSE);
11569     aopPut(AOP(dest),"b",0);
11570     aopPut(AOP(dest),"a",1);
11571     freeAsmop (dest, NULL, ic, FALSE);    
11572 }
11573
11574 /*-----------------------------------------------------------------*/
11575 /* genMemsetX - gencode for memSetX data                           */
11576 /*-----------------------------------------------------------------*/
11577 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11578 {
11579     operand *to , *val , *count;
11580     symbol *lbl;
11581     char *l;
11582     int i;
11583     bitVect *rsave = NULL;
11584
11585     /* we know it has to be 3 parameters */
11586     assert (nparms == 3);
11587     
11588     to = parms[0];
11589     val = parms[1];
11590     count = parms[2];
11591         
11592     /* save DPTR if it needs to be saved */
11593     rsave = newBitVect(16);
11594     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11595             if (bitVectBitValue(ic->rMask,i))
11596                     rsave = bitVectSetBit(rsave,i);
11597     }
11598     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11599                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11600     savermask(rsave);
11601
11602     aopOp (to, ic, FALSE, FALSE);
11603     /* get "to" into DPTR */
11604     /* if the operand is already in dptr
11605        then we do nothing else we move the value to dptr */
11606     if (AOP_TYPE (to) != AOP_STR) {
11607         /* if already in DPTR then we need to push */
11608         if (AOP_TYPE(to) == AOP_DPTR) {
11609             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11610             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11611             if (options.model == MODEL_FLAT24)
11612                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11613             emitcode ("pop", "dph");
11614             emitcode ("pop", "dpl");        
11615         } else {
11616             _startLazyDPSEvaluation ();
11617             /* if this is remateriazable */
11618             if (AOP_TYPE (to) == AOP_IMMD) {
11619                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11620             } else {                    /* we need to get it byte by byte */
11621                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11622                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11623                 if (options.model == MODEL_FLAT24) {
11624                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11625                 }
11626             }
11627             _endLazyDPSEvaluation ();
11628         }
11629     }
11630     freeAsmop (to, NULL, ic, FALSE);
11631
11632     aopOp (val, ic->next->next, FALSE,FALSE);
11633     aopOp (count, ic->next->next, FALSE,FALSE);    
11634     lbl =newiTempLabel(NULL);
11635     /* now for the actual copy */
11636     if (AOP_TYPE(count) == AOP_LIT && 
11637         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11638         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11639         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11640         MOVA(l);
11641         emitcode ("","!tlabeldef",lbl->key+100);
11642         emitcode ("movx", "@dptr,a");
11643         emitcode ("inc", "dptr");
11644         emitcode ("djnz","b,!tlabel",lbl->key+100);
11645     } else {
11646         symbol *lbl1 = newiTempLabel(NULL);
11647         
11648         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11649         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11650         emitcode ("","!tlabeldef",lbl->key+100);
11651         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11652         MOVA(l);
11653         emitcode ("movx", "@dptr,a");
11654         emitcode ("inc", "dptr");
11655         emitcode ("mov","a,b");
11656         emitcode ("orl","a,_ap");
11657         emitcode ("jz","!tlabel",lbl1->key+100);
11658         emitcode ("mov","a,_ap");
11659         emitcode ("add","a,#!constbyte",0xFF);
11660         emitcode ("mov","_ap,a");
11661         emitcode ("mov","a,b");
11662         emitcode ("addc","a,#!constbyte",0xFF);
11663         emitcode ("mov","b,a");
11664         emitcode ("sjmp","!tlabel",lbl->key+100);
11665         emitcode ("","!tlabeldef",lbl1->key+100);
11666     }
11667     freeAsmop (count, NULL, ic, FALSE);
11668     unsavermask(rsave);
11669 }
11670
11671 /*-----------------------------------------------------------------*/
11672 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11673 /*-----------------------------------------------------------------*/
11674 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11675 {
11676         bitVect *rsave ;
11677         operand *pnum, *result;
11678         int i;
11679     
11680         assert (nparms==1);
11681         /* save registers that need to be saved */
11682         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11683                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11684     
11685         pnum = parms[0]; 
11686         aopOp (pnum, ic, FALSE, FALSE);
11687         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11688         freeAsmop (pnum, NULL, ic, FALSE);
11689         emitcode ("lcall","NatLib_LoadPrimitive");
11690         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11691         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11692             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11693                 for (i = (size-1) ; i >= 0 ; i-- ) {
11694                         emitcode ("push","a%s",javaRet[i]);
11695                 }
11696                 for (i=0; i < size ; i++ ) {
11697                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11698                 }
11699         } else {
11700                 for (i = 0 ; i < size ; i++ ) {
11701                         aopPut(AOP(result),javaRet[i],i);
11702                 }
11703         }    
11704         freeAsmop (result, NULL, ic, FALSE);
11705         unsavermask(rsave);
11706 }
11707
11708 /*-----------------------------------------------------------------*/
11709 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11710 /*-----------------------------------------------------------------*/
11711 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11712 {
11713         bitVect *rsave ;
11714         operand *pnum, *result;
11715         int size = 3;
11716         int i;
11717     
11718         assert (nparms==1);
11719         /* save registers that need to be saved */
11720         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11721                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11722     
11723         pnum = parms[0]; 
11724         aopOp (pnum, ic, FALSE, FALSE);
11725         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11726         freeAsmop (pnum, NULL, ic, FALSE);
11727         emitcode ("lcall","NatLib_LoadPointer");
11728         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11729         if (AOP_TYPE(result)!=AOP_STR) {
11730                 for (i = 0 ; i < size ; i++ ) {
11731                         aopPut(AOP(result),fReturn[i],i);
11732                 }
11733         }    
11734         freeAsmop (result, NULL, ic, FALSE);
11735         unsavermask(rsave);
11736 }
11737
11738 /*-----------------------------------------------------------------*/
11739 /* genNatLibInstallStateBlock -                                    */
11740 /*-----------------------------------------------------------------*/
11741 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11742                                        operand **parms, const char *name)
11743 {
11744         bitVect *rsave ;
11745         operand *psb, *handle;
11746         assert (nparms==2);
11747
11748         /* save registers that need to be saved */
11749         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11750                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11751         psb = parms[0];
11752         handle = parms[1];
11753
11754         /* put pointer to state block into DPTR1 */
11755         aopOp (psb, ic, FALSE, FALSE);
11756         if (AOP_TYPE (psb) == AOP_IMMD) {
11757                 emitcode ("mov","dps,#1");
11758                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11759                 emitcode ("mov","dps,#0");
11760         } else {
11761                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11762                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11763                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11764         }
11765         freeAsmop (psb, NULL, ic, FALSE);
11766
11767         /* put libraryID into DPTR */
11768         emitcode ("mov","dptr,#LibraryID");
11769
11770         /* put handle into r3:r2 */
11771         aopOp (handle, ic, FALSE, FALSE);
11772         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11773                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11774                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11775                 emitcode ("pop","ar3");
11776                 emitcode ("pop","ar2");
11777         } else {        
11778                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11779                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11780         }
11781         freeAsmop (psb, NULL, ic, FALSE);
11782
11783         /* make the call */
11784         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11785
11786         /* put return value into place*/
11787         _G.accInUse++;
11788         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11789         _G.accInUse--;
11790         aopPut(AOP(IC_RESULT(ic)),"a",0);
11791         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11792         unsavermask(rsave);
11793 }
11794
11795 /*-----------------------------------------------------------------*/
11796 /* genNatLibRemoveStateBlock -                                     */
11797 /*-----------------------------------------------------------------*/
11798 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11799 {
11800         bitVect *rsave ;
11801
11802         assert(nparms==0);
11803
11804         /* save registers that need to be saved */
11805         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11806                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11807
11808         /* put libraryID into DPTR */
11809         emitcode ("mov","dptr,#LibraryID");
11810         /* make the call */
11811         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11812         unsavermask(rsave);
11813 }
11814
11815 /*-----------------------------------------------------------------*/
11816 /* genNatLibGetStateBlock -                                        */
11817 /*-----------------------------------------------------------------*/
11818 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11819                                    operand **parms,const char *name)
11820 {
11821         bitVect *rsave ;
11822         symbol *lbl = newiTempLabel(NULL);
11823         
11824         assert(nparms==0);
11825         /* save registers that need to be saved */
11826         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11827                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11828
11829         /* put libraryID into DPTR */
11830         emitcode ("mov","dptr,#LibraryID");
11831         /* make the call */
11832         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11833         emitcode ("jnz","!tlabel",lbl->key+100);
11834
11835         /* put return value into place */
11836         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11837         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11838                 emitcode ("push","ar3");
11839                 emitcode ("push","ar2");
11840                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11841                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11842         } else {
11843                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11844                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11845         }
11846         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11847         emitcode ("","!tlabeldef",lbl->key+100);
11848         unsavermask(rsave);
11849 }
11850
11851 /*-----------------------------------------------------------------*/
11852 /* genMMMalloc -                                                   */
11853 /*-----------------------------------------------------------------*/
11854 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11855                          int size, const char *name)
11856 {
11857         bitVect *rsave ;
11858         operand *bsize;
11859         symbol *rsym;
11860         symbol *lbl = newiTempLabel(NULL);
11861
11862         assert (nparms == 1);
11863         /* save registers that need to be saved */
11864         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11865                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11866         
11867         bsize=parms[0];
11868         aopOp (bsize,ic,FALSE,FALSE);
11869
11870         /* put the size in R4-R2 */
11871         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11872                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11873                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11874                 if (size==3) {
11875                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11876                         emitcode("pop","ar4");
11877                 }
11878                 emitcode("pop","ar3");
11879                 emitcode("pop","ar2");          
11880         } else {
11881                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11882                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11883                 if (size==3) {
11884                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11885                 }
11886         }
11887         freeAsmop (bsize, NULL, ic, FALSE);
11888
11889         /* make the call */
11890         emitcode ("lcall","MM_%s",name);
11891         emitcode ("jz","!tlabel",lbl->key+100);
11892         emitcode ("mov","r2,#!constbyte",0xff);
11893         emitcode ("mov","r3,#!constbyte",0xff);
11894         emitcode ("","!tlabeldef",lbl->key+100);
11895         /* we don't care about the pointer : we just save the handle */
11896         rsym = OP_SYMBOL(IC_RESULT(ic));
11897         if (rsym->liveFrom != rsym->liveTo) {
11898                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11899                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11900                         emitcode ("push","ar3");
11901                         emitcode ("push","ar2");
11902                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11903                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11904                 } else {
11905                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11906                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11907                 }
11908                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11909         }
11910         unsavermask(rsave);
11911 }
11912
11913 /*-----------------------------------------------------------------*/
11914 /* genMMDeref -                                                    */
11915 /*-----------------------------------------------------------------*/
11916 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11917 {
11918         bitVect *rsave ;
11919         operand *handle;
11920
11921         assert (nparms == 1);
11922         /* save registers that need to be saved */
11923         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11924                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11925         
11926         handle=parms[0];
11927         aopOp (handle,ic,FALSE,FALSE);
11928
11929         /* put the size in R4-R2 */
11930         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11931                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11932                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11933                 emitcode("pop","ar3");
11934                 emitcode("pop","ar2");          
11935         } else {
11936                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11937                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11938         }
11939         freeAsmop (handle, NULL, ic, FALSE);
11940
11941         /* make the call */
11942         emitcode ("lcall","MM_Deref");
11943         
11944         {
11945                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11946                 if (rsym->liveFrom != rsym->liveTo) {                   
11947                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11948                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11949                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11950                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11951                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11952                         }
11953                 }
11954         }
11955         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11956         unsavermask(rsave);
11957 }
11958
11959 /*-----------------------------------------------------------------*/
11960 /* genMMUnrestrictedPersist -                                      */
11961 /*-----------------------------------------------------------------*/
11962 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11963 {
11964         bitVect *rsave ;
11965         operand *handle;
11966
11967         assert (nparms == 1);
11968         /* save registers that need to be saved */
11969         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11970                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11971         
11972         handle=parms[0];
11973         aopOp (handle,ic,FALSE,FALSE);
11974
11975         /* put the size in R3-R2 */
11976         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11977                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11978                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11979                 emitcode("pop","ar3");
11980                 emitcode("pop","ar2");          
11981         } else {
11982                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11983                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11984         }
11985         freeAsmop (handle, NULL, ic, FALSE);
11986
11987         /* make the call */
11988         emitcode ("lcall","MM_UnrestrictedPersist");
11989
11990         {
11991                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11992                 if (rsym->liveFrom != rsym->liveTo) {   
11993                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11994                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11995                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11996                 }
11997         }
11998         unsavermask(rsave);
11999 }
12000
12001 /*-----------------------------------------------------------------*/
12002 /* genSystemExecJavaProcess -                                      */
12003 /*-----------------------------------------------------------------*/
12004 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12005 {
12006         bitVect *rsave ;
12007         operand *handle, *pp;
12008
12009         assert (nparms==2);
12010         /* save registers that need to be saved */
12011         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12012                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12013         
12014         pp = parms[0];
12015         handle = parms[1];
12016         
12017         /* put the handle in R3-R2 */
12018         aopOp (handle,ic,FALSE,FALSE);
12019         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12020                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12021                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12022                 emitcode("pop","ar3");
12023                 emitcode("pop","ar2");          
12024         } else {
12025                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12026                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12027         }
12028         freeAsmop (handle, NULL, ic, FALSE);
12029         
12030         /* put pointer in DPTR */
12031         aopOp (pp,ic,FALSE,FALSE);
12032         if (AOP_TYPE(pp) == AOP_IMMD) {
12033                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
12034         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12035                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12036                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12037                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12038         }
12039         freeAsmop (handle, NULL, ic, FALSE);
12040
12041         /* make the call */
12042         emitcode ("lcall","System_ExecJavaProcess");
12043         
12044         /* put result in place */
12045         {
12046                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12047                 if (rsym->liveFrom != rsym->liveTo) {   
12048                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12049                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12050                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12051                 }
12052         }
12053         
12054         unsavermask(rsave);
12055 }
12056
12057 /*-----------------------------------------------------------------*/
12058 /* genSystemRTCRegisters -                                         */
12059 /*-----------------------------------------------------------------*/
12060 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12061                                   char *name)
12062 {
12063         bitVect *rsave ;
12064         operand *pp;
12065
12066         assert (nparms==1);
12067         /* save registers that need to be saved */
12068         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12069                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12070         
12071         pp=parms[0];
12072         /* put pointer in DPTR */
12073         aopOp (pp,ic,FALSE,FALSE);
12074         if (AOP_TYPE (pp) == AOP_IMMD) {
12075                 emitcode ("mov","dps,#1");
12076                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12077                 emitcode ("mov","dps,#0");
12078         } else {
12079                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12080                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12081                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12082         }
12083         freeAsmop (pp, NULL, ic, FALSE);
12084
12085         /* make the call */
12086         emitcode ("lcall","System_%sRTCRegisters",name);
12087
12088         unsavermask(rsave);
12089 }
12090
12091 /*-----------------------------------------------------------------*/
12092 /* genSystemThreadSleep -                                          */
12093 /*-----------------------------------------------------------------*/
12094 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12095 {
12096         bitVect *rsave ;
12097         operand *to, *s;
12098
12099         assert (nparms==1);
12100         /* save registers that need to be saved */
12101         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12102                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12103
12104         to = parms[0];
12105         aopOp(to,ic,FALSE,FALSE);
12106         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12107             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12108                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12109                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12110                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12111                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12112                 emitcode ("pop","ar3");
12113                 emitcode ("pop","ar2");
12114                 emitcode ("pop","ar1");
12115                 emitcode ("pop","ar0");
12116         } else {
12117                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12118                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12119                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12120                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12121         }
12122         freeAsmop (to, NULL, ic, FALSE);
12123
12124         /* suspend in acc */
12125         s = parms[1];
12126         aopOp(s,ic,FALSE,FALSE);
12127         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12128         freeAsmop (s, NULL, ic, FALSE);
12129
12130         /* make the call */
12131         emitcode ("lcall","System_%s",name);
12132
12133         unsavermask(rsave);
12134 }
12135
12136 /*-----------------------------------------------------------------*/
12137 /* genSystemThreadResume -                                         */
12138 /*-----------------------------------------------------------------*/
12139 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12140 {
12141         bitVect *rsave ;
12142         operand *tid,*pid;
12143
12144         assert (nparms==2);
12145         /* save registers that need to be saved */
12146         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12147                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12148         
12149         tid = parms[0];
12150         pid = parms[1];
12151         
12152         /* PID in R0 */
12153         aopOp(pid,ic,FALSE,FALSE);
12154         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12155         freeAsmop (pid, NULL, ic, FALSE);
12156         
12157         /* tid into ACC */
12158         aopOp(tid,ic,FALSE,FALSE);
12159         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12160         freeAsmop (tid, NULL, ic, FALSE);
12161         
12162         emitcode ("lcall","System_ThreadResume");
12163
12164         /* put result into place */
12165         {
12166                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12167                 if (rsym->liveFrom != rsym->liveTo) {   
12168                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12169                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12170                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12171                 }
12172         }
12173         unsavermask(rsave);
12174 }
12175
12176 /*-----------------------------------------------------------------*/
12177 /* genSystemProcessResume -                                        */
12178 /*-----------------------------------------------------------------*/
12179 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12180 {
12181         bitVect *rsave ;
12182         operand *pid;
12183
12184         assert (nparms==1);
12185         /* save registers that need to be saved */
12186         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12188         
12189         pid = parms[0];
12190         
12191         /* pid into ACC */
12192         aopOp(pid,ic,FALSE,FALSE);
12193         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12194         freeAsmop (pid, NULL, ic, FALSE);
12195         
12196         emitcode ("lcall","System_ProcessResume");
12197
12198         unsavermask(rsave);
12199 }
12200
12201 /*-----------------------------------------------------------------*/
12202 /* genSystem -                                                     */
12203 /*-----------------------------------------------------------------*/
12204 static void genSystem (iCode *ic,int nparms,char *name)
12205 {
12206         assert(nparms == 0);
12207
12208         emitcode ("lcall","System_%s",name);
12209 }
12210
12211 /*-----------------------------------------------------------------*/
12212 /* genSystemPoll -                                                  */
12213 /*-----------------------------------------------------------------*/
12214 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12215 {
12216         bitVect *rsave ;
12217         operand *fp;
12218
12219         assert (nparms==1);
12220         /* save registers that need to be saved */
12221         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12222                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12223
12224         fp = parms[0];
12225         aopOp (fp,ic,FALSE,FALSE);
12226         if (AOP_TYPE (fp) == AOP_IMMD) {
12227                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12228         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12229                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12230                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12231                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12232         }
12233         freeAsmop (fp, NULL, ic, FALSE);
12234
12235         emitcode ("lcall","System_%sPoll",name);
12236
12237         /* put result into place */
12238         {
12239                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12240                 if (rsym->liveFrom != rsym->liveTo) {   
12241                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12242                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12243                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12244                 }
12245         }
12246         unsavermask(rsave);
12247 }
12248
12249 /*-----------------------------------------------------------------*/
12250 /* genSystemGetCurrentID -                                         */
12251 /*-----------------------------------------------------------------*/
12252 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12253 {
12254         assert (nparms==0);
12255
12256         emitcode ("lcall","System_GetCurrent%sId",name);
12257         /* put result into place */
12258         {
12259                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12260                 if (rsym->liveFrom != rsym->liveTo) {   
12261                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12262                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12263                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12264                 }
12265         }
12266 }
12267
12268 /*-----------------------------------------------------------------*/
12269 /* genBuiltIn - calls the appropriate function to  generating code */
12270 /* for a built in function                                         */
12271 /*-----------------------------------------------------------------*/
12272 static void genBuiltIn (iCode *ic)
12273 {
12274         operand *bi_parms[MAX_BUILTIN_ARGS];
12275         int nbi_parms;
12276         iCode *bi_iCode;
12277         symbol *bif;
12278
12279         /* get all the arguments for a built in function */
12280         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12281
12282         /* which function is it */
12283         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12284         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12285                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12286         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12287                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12288         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12289                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12290         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12291                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12292         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12293                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12294         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12295                 genInp(bi_iCode,nbi_parms,bi_parms);
12296         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12297                 genOutp(bi_iCode,nbi_parms,bi_parms);
12298         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12299                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12300                 /* JavaNative builtIns */               
12301         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12302                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12303         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12304                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12305         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12306                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12307         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12308                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12309         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12310                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12311         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12312                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12313         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12314                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12315         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12316                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12317         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12318                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12319         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12320                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12321         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12322                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12323         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12324                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12325         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12326                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12327         } else if (strcmp(bif->name,"MM_Free")==0) {
12328                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12329         } else if (strcmp(bif->name,"MM_Deref")==0) {
12330                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12331         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12332                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12333         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12334                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12335         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12336                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12337         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12338                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12339         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12340                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12341         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12342                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12343         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12344                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12345         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12346                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12347         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12348                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12349         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12350                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12351         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12352                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12353         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12354                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12355         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12356                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12357         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12358                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12359         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12360                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12361         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12362                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12363         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12364                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12365         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12366                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12367         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12368                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12369         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12370                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12371         } else {
12372                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12373                 return ;
12374         }
12375         return ;    
12376 }
12377
12378 /*-----------------------------------------------------------------*/
12379 /* gen390Code - generate code for Dallas 390 based controllers     */
12380 /*-----------------------------------------------------------------*/
12381 void
12382 gen390Code (iCode * lic)
12383 {
12384   iCode *ic;
12385   int cln = 0;
12386
12387   lineHead = lineCurr = NULL;
12388   dptrn[1][0] = "dpl1";
12389   dptrn[1][1] = "dph1";
12390   dptrn[1][2] = "dpx1";
12391   
12392   if (options.model == MODEL_FLAT24) {
12393     fReturnSizeDS390 = 5;
12394     fReturn = fReturn24;
12395   } else {
12396     fReturnSizeDS390 = 4;
12397     fReturn = fReturn16;
12398     options.stack10bit=0;
12399   }
12400 #if 1
12401   /* print the allocation information */
12402   if (allocInfo)
12403     printAllocInfo (currFunc, codeOutFile);
12404 #endif
12405   /* if debug information required */
12406   if (options.debug && currFunc)
12407     {
12408       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12409       _G.debugLine = 1;
12410       if (IS_STATIC (currFunc->etype))
12411         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12412       else
12413         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12414       _G.debugLine = 0;
12415     }
12416   /* stack pointer name */
12417   if (options.useXstack)
12418     spname = "_spx";
12419   else
12420     spname = "sp";
12421
12422
12423   for (ic = lic; ic; ic = ic->next)
12424     {
12425
12426       if (ic->lineno && cln != ic->lineno)
12427         {
12428           if (options.debug)
12429             {
12430               _G.debugLine = 1;
12431               emitcode ("", "C$%s$%d$%d$%d ==.",
12432                         FileBaseName (ic->filename), ic->lineno,
12433                         ic->level, ic->block);
12434               _G.debugLine = 0;
12435             }
12436           emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12437                     printCLine(ic->filename, ic->lineno));
12438           cln = ic->lineno;
12439         }
12440       /* if the result is marked as
12441          spilt and rematerializable or code for
12442          this has already been generated then
12443          do nothing */
12444       if (resultRemat (ic) || ic->generated)
12445         continue;
12446
12447       /* depending on the operation */
12448       switch (ic->op)
12449         {
12450         case '!':
12451           genNot (ic);
12452           break;
12453
12454         case '~':
12455           genCpl (ic);
12456           break;
12457
12458         case UNARYMINUS:
12459           genUminus (ic);
12460           break;
12461
12462         case IPUSH:
12463           genIpush (ic);
12464           break;
12465
12466         case IPOP:
12467           /* IPOP happens only when trying to restore a
12468              spilt live range, if there is an ifx statement
12469              following this pop then the if statement might
12470              be using some of the registers being popped which
12471              would destory the contents of the register so
12472              we need to check for this condition and handle it */
12473           if (ic->next &&
12474               ic->next->op == IFX &&
12475               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12476             genIfx (ic->next, ic);
12477           else
12478             genIpop (ic);
12479           break;
12480
12481         case CALL:
12482           genCall (ic);
12483           break;
12484
12485         case PCALL:
12486           genPcall (ic);
12487           break;
12488
12489         case FUNCTION:
12490           genFunction (ic);
12491           break;
12492
12493         case ENDFUNCTION:
12494           genEndFunction (ic);
12495           break;
12496
12497         case RETURN:
12498           genRet (ic);
12499           break;
12500
12501         case LABEL:
12502           genLabel (ic);
12503           break;
12504
12505         case GOTO:
12506           genGoto (ic);
12507           break;
12508
12509         case '+':
12510           genPlus (ic);
12511           break;
12512
12513         case '-':
12514           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12515             genMinus (ic);
12516           break;
12517
12518         case '*':
12519           genMult (ic);
12520           break;
12521
12522         case '/':
12523           genDiv (ic);
12524           break;
12525
12526         case '%':
12527           genMod (ic);
12528           break;
12529
12530         case '>':
12531           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12532           break;
12533
12534         case '<':
12535           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12536           break;
12537
12538         case LE_OP:
12539         case GE_OP:
12540         case NE_OP:
12541
12542           /* note these two are xlated by algebraic equivalence
12543              during parsing SDCC.y */
12544           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12545                   "got '>=' or '<=' shouldn't have come here");
12546           break;
12547
12548         case EQ_OP:
12549           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12550           break;
12551
12552         case AND_OP:
12553           genAndOp (ic);
12554           break;
12555
12556         case OR_OP:
12557           genOrOp (ic);
12558           break;
12559
12560         case '^':
12561           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12562           break;
12563
12564         case '|':
12565           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12566           break;
12567
12568         case BITWISEAND:
12569           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12570           break;
12571
12572         case INLINEASM:
12573           genInline (ic);
12574           break;
12575
12576         case RRC:
12577           genRRC (ic);
12578           break;
12579
12580         case RLC:
12581           genRLC (ic);
12582           break;
12583
12584         case GETHBIT:
12585           genGetHbit (ic);
12586           break;
12587
12588         case LEFT_OP:
12589           genLeftShift (ic);
12590           break;
12591
12592         case RIGHT_OP:
12593           genRightShift (ic);
12594           break;
12595
12596         case GET_VALUE_AT_ADDRESS:
12597           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12598           break;
12599
12600         case '=':
12601           if (POINTER_SET (ic))
12602             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12603           else
12604             genAssign (ic);
12605           break;
12606
12607         case IFX:
12608           genIfx (ic, NULL);
12609           break;
12610
12611         case ADDRESS_OF:
12612           genAddrOf (ic);
12613           break;
12614
12615         case JUMPTABLE:
12616           genJumpTab (ic);
12617           break;
12618
12619         case CAST:
12620           genCast (ic);
12621           break;
12622
12623         case RECEIVE:
12624           genReceive (ic);
12625           break;
12626
12627         case SEND:
12628           if (ic->builtinSEND) genBuiltIn(ic);
12629           else addSet (&_G.sendSet, ic);
12630           break;
12631
12632         case ARRAYINIT:
12633             genArrayInit(ic);
12634             break;
12635             
12636         default:
12637           ic = ic;
12638         }
12639     }
12640
12641
12642   /* now we are ready to call the
12643      peep hole optimizer */
12644   if (!options.nopeep)
12645     peepHole (&lineHead);
12646
12647   /* now do the actual printing */
12648   printLine (lineHead, codeOutFile);
12649   return;
12650 }