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