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