Improved genReceive, write two bytes at a time in genGenPointerPut, cleaned up some...
[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) { \
114                  char *_mova_tmp = strdup(x); \
115                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
116                  { \
117                     emitcode("mov","a,%s",_mova_tmp); \
118                  } \
119                  free(_mova_tmp); \
120                 }
121 #define MOVB(x) { char *_movb_tmp = strdup(x); \
122                  if (strcmp(_movb_tmp,"b")) \
123                  { \
124                     emitcode("mov","b,%s",_movb_tmp); \
125                  } \
126                  free(_movb_tmp); \
127                 }
128 #define CLRC    emitcode("clr","c")
129 #define SETC    emitcode("setb","c")
130
131 // A scratch register which will be used to hold
132 // result bytes from operands in far space via DPTR2.
133 #define DP2_RESULT_REG  "_ap"
134
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
137
138 static unsigned char SLMask[] =
139 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
140  0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char SRMask[] =
142 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
143  0x07, 0x03, 0x01, 0x00};
144
145 #define LSB     0
146 #define MSB16   1
147 #define MSB24   2
148 #define MSB32   3
149 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
150                                 symbol *lbl = newiTempLabel(NULL);              \
151                                 emitcode ("setb","F1");                         \
152                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
153                                 emitcode ("clr","F1");                          \
154                                 emitcode ("","!tlabeldef",lbl->key+100);        \
155                         }}
156 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
157                                 symbol *lbl = newiTempLabel(NULL);              \
158                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
159                                 emitcode ("setb","EA");                         \
160                                 emitcode ("","!tlabeldef",lbl->key+100);        \
161                         }}
162
163
164 /*-----------------------------------------------------------------*/
165 /* emitcode - writes the code into a file : for now it is simple    */
166 /*-----------------------------------------------------------------*/
167 static void
168 emitcode (char *inst, char *fmt,...)
169 {
170     va_list ap;
171     char lb[INITIAL_INLINEASM];
172     char *lbp = lb;
173     
174     va_start (ap, fmt);
175     
176     if (inst && *inst)
177     {
178         if (fmt && *fmt)
179         {
180             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
181         }
182         else
183         {
184             SNPRINTF (lb, sizeof(lb), "%s", inst);
185         }
186         
187         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
188                    fmt, ap);
189     }
190     else
191     {
192         tvsprintf (lb, sizeof(lb), fmt, ap);
193     }
194     
195
196     while (isspace (*lbp))
197     {
198         lbp++;
199     }
200
201     if (lbp && *lbp)
202     {
203         lineCurr = (lineCurr ?
204                     connectLine (lineCurr, newLineNode (lb)) :
205                     (lineHead = newLineNode (lb)));
206     }
207     
208     lineCurr->isInline = _G.inLine;
209     lineCurr->isDebug = _G.debugLine;
210     va_end (ap);
211 }
212
213 /*-----------------------------------------------------------------*/
214 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
215 /*-----------------------------------------------------------------*/
216 static regs *
217 getFreePtr (iCode * ic, asmop ** aopp, bool result)
218 {
219   bool r0iu, r1iu;
220   bool r0ou, r1ou;
221
222   /* the logic: if r0 & r1 used in the instruction
223      then we are in trouble otherwise */
224
225   /* first check if r0 & r1 are used by this
226      instruction, in which case we are in trouble */
227   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
228   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
229   if (r0iu && r1iu) {
230       goto endOfWorld;
231     }
232
233   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
234   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
235
236   /* if no usage of r0 then return it */
237   if (!r0iu && !r0ou)
238     {
239       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
240       (*aopp)->type = AOP_R0;
241
242       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
243     }
244
245   /* if no usage of r1 then return it */
246   if (!r1iu && !r1ou)
247     {
248       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
249       (*aopp)->type = AOP_R1;
250
251       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
252     }
253
254   /* now we know they both have usage */
255   /* if r0 not used in this instruction */
256   if (!r0iu)
257     {
258       /* push it if not already pushed */
259       if (!_G.r0Pushed)
260         {
261           emitcode ("push", "%s",
262                     ds390_regWithIdx (R0_IDX)->dname);
263           _G.r0Pushed++;
264         }
265
266       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
267       (*aopp)->type = AOP_R0;
268
269       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
270     }
271
272   /* if r1 not used then */
273
274   if (!r1iu)
275     {
276       /* push it if not already pushed */
277       if (!_G.r1Pushed)
278         {
279           emitcode ("push", "%s",
280                     ds390_regWithIdx (R1_IDX)->dname);
281           _G.r1Pushed++;
282         }
283
284       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
285       (*aopp)->type = AOP_R1;
286       return ds390_regWithIdx (R1_IDX);
287     }
288
289 endOfWorld:
290   /* I said end of world but not quite end of world yet */
291   /* if this is a result then we can push it on the stack */
292   if (result)
293     {
294       (*aopp)->type = AOP_STK;
295       return NULL;
296     }
297
298   /* other wise this is true end of the world */
299   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300           "getFreePtr should never reach here");
301   exit (1);
302     
303   return NULL; // notreached, but makes compiler happy.
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp                                  */
308 /*-----------------------------------------------------------------*/
309 static asmop *
310 newAsmop (short type)
311 {
312   asmop *aop;
313
314   aop = Safe_calloc (1, sizeof (asmop));
315   aop->type = type;
316   return aop;
317 }
318
319 static int _currentDPS;         /* Current processor DPS. */
320 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
321 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
322
323 /*-----------------------------------------------------------------*/
324 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
325 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
326 /* alternate DPTR (DPL1/DPH1/DPX1).          */
327 /*-----------------------------------------------------------------*/
328 static void
329 genSetDPTR (int n)
330 {
331
332   /* If we are doing lazy evaluation, simply note the desired
333    * change, but don't emit any code yet.
334    */
335   if (_lazyDPS)
336     {
337       _desiredDPS = n;
338       return;
339     }
340
341   if (!n)
342     {
343       emitcode ("mov", "dps,#0");
344     }
345   else
346     {
347       TR_DPTR("#1");
348       emitcode ("mov", "dps,#1");
349     }
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
354 /*                   */
355 /* Any code that operates on DPTR (NB: not on the individual     */
356 /* components, like DPH) *must* call _flushLazyDPS() before using  */
357 /* DPTR within a lazy DPS evaluation block.        */
358 /*                   */
359 /* Note that aopPut and aopGet already contain the proper calls to */
360 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
361 /* DPS evaluation block.             */
362 /*                   */
363 /* Also, _flushLazyDPS must be called before any flow control      */
364 /* operations that could potentially branch out of the block.    */
365 /*                         */
366 /* Lazy DPS evaluation is simply an optimization (though an      */
367 /* important one), so if in doubt, leave it out.       */
368 /*-----------------------------------------------------------------*/
369 static void
370 _startLazyDPSEvaluation (void)
371 {
372   _currentDPS = 0;
373   _desiredDPS = 0;
374 #ifdef BETTER_LITERAL_SHIFT  
375   _lazyDPS++;
376 #else
377   _lazyDPS = 1;
378 #endif  
379 }
380
381 /*-----------------------------------------------------------------*/
382 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
383 /* desired one. Call before using DPTR within a lazy DPS evaluation */
384 /* block.                */
385 /*-----------------------------------------------------------------*/
386 static void
387 _flushLazyDPS (void)
388 {
389   if (!_lazyDPS)
390     {
391       /* nothing to do. */
392       return;
393     }
394
395   if (_desiredDPS != _currentDPS)
396     {
397       if (_desiredDPS)
398         {
399           emitcode ("inc", "dps");
400         }
401       else
402         {
403           emitcode ("dec", "dps");
404         }
405       _currentDPS = _desiredDPS;
406     }
407 }
408
409 /*-----------------------------------------------------------------*/
410 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
411 /*                   */
412 /* Forces us back to the safe state (standard DPTR selected).    */
413 /*-----------------------------------------------------------------*/
414 static void
415 _endLazyDPSEvaluation (void)
416 {
417 #ifdef BETTER_LITERAL_SHIFT  
418   _lazyDPS--;
419 #else
420   _lazyDPS = 0;
421 #endif    
422   if (!_lazyDPS)
423   {
424     if (_currentDPS)
425     {
426       genSetDPTR (0);
427       _flushLazyDPS ();
428     }
429     _currentDPS = 0;
430     _desiredDPS = 0;
431   }
432 }
433
434
435
436 /*-----------------------------------------------------------------*/
437 /* pointerCode - returns the code for a pointer type               */
438 /*-----------------------------------------------------------------*/
439 static int
440 pointerCode (sym_link * etype)
441 {
442
443   return PTR_TYPE (SPEC_OCLS (etype));
444
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* aopForSym - for a true symbol                                   */
449 /*-----------------------------------------------------------------*/
450 static asmop *
451 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
452 {
453   asmop *aop;
454   memmap *space = SPEC_OCLS (sym->etype);
455
456   /* if already has one */
457   if (sym->aop)
458     return sym->aop;
459
460   /* assign depending on the storage class */
461   /* if it is on the stack or indirectly addressable */
462   /* space we need to assign either r0 or r1 to it   */
463   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
464     {
465       sym->aop = aop = newAsmop (0);
466       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
467       aop->size = getSize (sym->type);
468
469       /* now assign the address of the variable to
470          the pointer register */
471       if (aop->type != AOP_STK)
472         {
473
474           if (sym->onStack)
475             {
476               if (_G.accInUse)
477                 emitcode ("push", "acc");
478
479               if (_G.bInUse)
480                 emitcode ("push", "b");
481
482               emitcode ("mov", "a,_bp");
483               emitcode ("add", "a,#!constbyte",
484                         ((sym->stack < 0) ?
485                          ((char) (sym->stack - _G.nRegsSaved)) :
486                          ((char) sym->stack)) & 0xff);
487               emitcode ("mov", "%s,a",
488                         aop->aopu.aop_ptr->name);
489
490               if (_G.bInUse)
491                 emitcode ("pop", "b");
492
493               if (_G.accInUse)
494                 emitcode ("pop", "acc");
495             }
496           else
497             emitcode ("mov", "%s,#%s",
498                       aop->aopu.aop_ptr->name,
499                       sym->rname);
500           aop->paged = space->paged;
501         }
502       else
503         aop->aopu.aop_stk = sym->stack;
504       return aop;
505     }
506
507   if (sym->onStack && options.stack10bit)
508     {
509         short stack_val = -((sym->stack < 0) ?
510                             ((short) (sym->stack - _G.nRegsSaved)) :
511                             ((short) sym->stack)) ;
512         if (useDP2 && _G.dptr1InUse) {
513             emitcode ("push","dpl1");
514             emitcode ("push","dph1");
515             emitcode ("push","dpx1");
516         } else if (_G.dptrInUse ) {
517             emitcode ("push","dpl");
518             emitcode ("push","dph");
519             emitcode ("push","dpx");
520         }
521       /* It's on the 10 bit stack, which is located in
522        * far data space.
523        */           
524         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
525             if (useDP2) {
526                 if (options.model == MODEL_FLAT24)
527                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
528                 TR_DPTR("#2");
529                 emitcode ("mov", "dph1,_bpx+1");
530                 emitcode ("mov", "dpl1,_bpx");
531                 emitcode ("mov","dps,#1");
532             } else {
533                 if (options.model == MODEL_FLAT24)
534                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
535                 emitcode ("mov", "dph,_bpx+1");
536                 emitcode ("mov", "dpl,_bpx");
537             }
538             stack_val = -stack_val;
539             while (stack_val--) {
540                 emitcode ("inc","dptr");
541             }
542             if (useDP2) {
543                 emitcode("mov","dps,#0");
544             }
545         }  else {
546             if (_G.accInUse)
547                 emitcode ("push", "acc");
548             
549             if (_G.bInUse)
550                 emitcode ("push", "b");
551         
552             emitcode ("mov", "a,_bpx");
553             emitcode ("clr","c");
554             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555             emitcode ("mov","b,a");
556             emitcode ("mov","a,_bpx+1");
557             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
558             if (useDP2) {
559                 if (options.model == MODEL_FLAT24)
560                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
561                 TR_DPTR("#2");
562                 emitcode ("mov", "dph1,a");
563                 emitcode ("mov", "dpl1,b");
564             } else {
565                 if (options.model == MODEL_FLAT24)
566                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
567                 emitcode ("mov", "dph,a");
568                 emitcode ("mov", "dpl,b");
569             }
570             
571             if (_G.bInUse)
572                 emitcode ("pop", "b");
573             
574             if (_G.accInUse)
575                 emitcode ("pop", "acc");
576         }
577         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
578         aop->size = getSize (sym->type);
579         return aop;
580     }
581
582   /* if in bit space */
583   if (IN_BITSPACE (space))
584     {
585       sym->aop = aop = newAsmop (AOP_CRY);
586       aop->aopu.aop_dir = sym->rname;
587       aop->size = getSize (sym->type);
588       return aop;
589     }
590   /* if it is in direct space */
591   if (IN_DIRSPACE (space))
592     {
593       sym->aop = aop = newAsmop (AOP_DIR);
594       aop->aopu.aop_dir = sym->rname;
595       aop->size = getSize (sym->type);
596       return aop;
597     }
598
599   /* special case for a function */
600   if (IS_FUNC (sym->type))
601     {
602       sym->aop = aop = newAsmop (AOP_IMMD);
603       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
604       aop->size = FPTRSIZE;
605       return aop;
606     }
607   
608   /* only remaining is far space */
609   /* in which case DPTR gets the address */
610   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
611   if (useDP2)
612     {
613       genSetDPTR (1);
614       _flushLazyDPS ();
615       emitcode ("mov", "dptr,#%s", sym->rname);
616       genSetDPTR (0);
617     }
618   else
619     {
620       emitcode ("mov", "dptr,#%s", sym->rname);
621     }
622   aop->size = getSize (sym->type);
623
624   /* if it is in code space */
625   if (IN_CODESPACE (space))
626     aop->code = 1;
627
628   return aop;
629 }
630
631 /*-----------------------------------------------------------------*/
632 /* aopForRemat - rematerialzes an object                           */
633 /*-----------------------------------------------------------------*/
634 static asmop *
635 aopForRemat (symbol * sym)
636 {
637   iCode *ic = sym->rematiCode;
638   asmop *aop = newAsmop (AOP_IMMD);
639   int ptr_type =0;
640   int val = 0;
641
642   for (;;)
643     {
644       if (ic->op == '+')
645         val += (int) operandLitValue (IC_RIGHT (ic));
646       else if (ic->op == '-')
647         val -= (int) operandLitValue (IC_RIGHT (ic));
648       else if (IS_CAST_ICODE(ic)) {
649               sym_link *from_type = operandType(IC_RIGHT(ic));
650               aop->aopu.aop_immd.from_cast_remat = 1;
651               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
652               ptr_type = DCL_TYPE(from_type);
653               if (ptr_type == IPOINTER) {
654                 // bug #481053
655                 ptr_type = POINTER;
656               }
657               continue ;
658       } else break;
659       
660       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
661     }
662
663   if (val)
664   {
665       SNPRINTF (buffer, sizeof(buffer),
666                 "(%s %c 0x%04x)",
667                 OP_SYMBOL (IC_LEFT (ic))->rname,
668                 val >= 0 ? '+' : '-',
669                 abs (val) & 0xffff);
670   }
671   else 
672   {
673       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
674       {
675           SNPRINTF(buffer, sizeof(buffer), 
676                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
677       }
678       else
679       {
680           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
681       }
682   }
683
684   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
685   /* set immd2 field if required */
686   if (aop->aopu.aop_immd.from_cast_remat) 
687   {
688       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
689       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
690   }
691
692   return aop;
693 }
694
695 /*-----------------------------------------------------------------*/
696 /* aopHasRegs - returns true if aop has regs between from-to       */
697 /*-----------------------------------------------------------------*/
698 static int aopHasRegs(asmop *aop, int from, int to)
699 {
700     int size =0;
701
702     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
703
704     for (; size < aop->size ; size++) {
705         int reg;
706         for (reg = from ; reg <= to ; reg++)
707             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
708     }
709     return 0;
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* regsInCommon - two operands have some registers in common       */
714 /*-----------------------------------------------------------------*/
715 static bool
716 regsInCommon (operand * op1, operand * op2)
717 {
718   symbol *sym1, *sym2;
719   int i;
720
721   /* if they have registers in common */
722   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
723     return FALSE;
724
725   sym1 = OP_SYMBOL (op1);
726   sym2 = OP_SYMBOL (op2);
727
728   if (sym1->nRegs == 0 || sym2->nRegs == 0)
729     return FALSE;
730
731   for (i = 0; i < sym1->nRegs; i++)
732     {
733       int j;
734       if (!sym1->regs[i])
735         continue;
736
737       for (j = 0; j < sym2->nRegs; j++)
738         {
739           if (!sym2->regs[j])
740             continue;
741
742           if (sym2->regs[j] == sym1->regs[i])
743             return TRUE;
744         }
745     }
746
747   return FALSE;
748 }
749
750 /*-----------------------------------------------------------------*/
751 /* operandsEqu - equivalent                                        */
752 /*-----------------------------------------------------------------*/
753 static bool
754 operandsEqu (operand * op1, operand * op2)
755 {
756   symbol *sym1, *sym2;
757
758   /* if they not symbols */
759   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
760     return FALSE;
761
762   sym1 = OP_SYMBOL (op1);
763   sym2 = OP_SYMBOL (op2);
764
765   /* if both are itemps & one is spilt
766      and the other is not then false */
767   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
768       sym1->isspilt != sym2->isspilt)
769     return FALSE;
770
771   /* if they are the same */
772   if (sym1 == sym2)
773     return TRUE;
774
775   if (strcmp (sym1->rname, sym2->rname) == 0)
776     return TRUE;
777
778
779   /* if left is a tmp & right is not */
780   if (IS_ITEMP (op1) &&
781       !IS_ITEMP (op2) &&
782       sym1->isspilt &&
783       (sym1->usl.spillLoc == sym2))
784     return TRUE;
785
786   if (IS_ITEMP (op2) &&
787       !IS_ITEMP (op1) &&
788       sym2->isspilt &&
789       sym1->level > 0 &&
790       (sym2->usl.spillLoc == sym1))
791     return TRUE;
792
793   return FALSE;
794 }
795
796 /*-----------------------------------------------------------------*/
797 /* sameRegs - two asmops have the same registers                   */
798 /*-----------------------------------------------------------------*/
799 static bool
800 sameRegs (asmop * aop1, asmop * aop2)
801 {
802   int i;
803
804   if (aop1 == aop2)
805     {
806       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
807         {
808           return FALSE;
809         }
810       return TRUE;
811     }
812
813   if (aop1->type != AOP_REG ||
814       aop2->type != AOP_REG)
815     return FALSE;
816
817   if (aop1->size != aop2->size)
818     return FALSE;
819
820   for (i = 0; i < aop1->size; i++)
821     if (aop1->aopu.aop_reg[i] !=
822         aop2->aopu.aop_reg[i])
823       return FALSE;
824
825   return TRUE;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand  :                    */
830 /*-----------------------------------------------------------------*/
831 static void
832 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
833 {
834   asmop *aop;
835   symbol *sym;
836   int i;
837
838   if (!op)
839     return;
840
841   /* if this a literal */
842   if (IS_OP_LITERAL (op))
843     {
844       op->aop = aop = newAsmop (AOP_LIT);
845       aop->aopu.aop_lit = op->operand.valOperand;
846       aop->size = getSize (operandType (op));
847       return;
848     }
849
850   /* if already has a asmop then continue */
851   if (op->aop)
852     return;
853
854   /* if the underlying symbol has a aop */
855   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
856     {
857       op->aop = OP_SYMBOL (op)->aop;
858       return;
859     }
860
861   /* if this is a true symbol */
862   if (IS_TRUE_SYMOP (op))
863     {
864       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
865       return;
866     }
867
868   /* this is a temporary : this has
869      only four choices :
870      a) register
871      b) spillocation
872      c) rematerialize
873      d) conditional
874      e) can be a return use only */
875
876   sym = OP_SYMBOL (op);
877
878
879   /* if the type is a conditional */
880   if (sym->regType == REG_CND)
881     {
882       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
883       aop->size = 0;
884       return;
885     }
886
887   /* if it is spilt then two situations
888      a) is rematerialize
889      b) has a spill location */
890   if (sym->isspilt || sym->nRegs == 0)
891     {
892
893       /* rematerialize it NOW */
894       if (sym->remat)
895         {
896           sym->aop = op->aop = aop =
897             aopForRemat (sym);
898           aop->size = getSize (sym->type);
899           return;
900         }
901
902       if (sym->accuse)
903         {
904           int i;
905           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
906           aop->size = getSize (sym->type);
907           for (i = 0; i < 2; i++)
908             aop->aopu.aop_str[i] = accUse[i];
909           return;
910         }
911
912       if (sym->ruonly)
913         {
914           int i;
915
916           if (useDP2)
917             {
918               /* a AOP_STR uses DPTR, but DPTR is already in use;
919                * we're just hosed.
920                */
921                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
922             }
923
924           aop = op->aop = sym->aop = newAsmop (AOP_STR);
925           aop->size = getSize (sym->type);
926           for (i = 0; i < (int) fReturnSizeDS390; i++)
927             aop->aopu.aop_str[i] = fReturn[i];
928           return;
929         }
930       
931       if (sym->dptr) { /* has been allocated to a DPTRn */
932           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
933           aop->size = getSize (sym->type);
934           aop->aopu.dptr = sym->dptr;
935           return ;
936       }
937       /* else spill location  */
938       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
939           /* force a new aop if sizes differ */
940           sym->usl.spillLoc->aop = NULL;
941       }
942       sym->aop = op->aop = aop =
943         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
944       aop->size = getSize (sym->type);
945       return;
946     }
947
948   /* must be in a register */
949   sym->aop = op->aop = aop = newAsmop (AOP_REG);
950   aop->size = sym->nRegs;
951   for (i = 0; i < sym->nRegs; i++)
952     aop->aopu.aop_reg[i] = sym->regs[i];
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* freeAsmop - free up the asmop given to an operand               */
957 /*----------------------------------------------------------------*/
958 static void
959 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
960 {
961   asmop *aop;
962
963   if (!op)
964     aop = aaop;
965   else
966     aop = op->aop;
967
968   if (!aop)
969     return;
970
971   if (aop->freed)
972     goto dealloc;
973
974   aop->freed = 1;
975
976   /* depending on the asmop type only three cases need work AOP_RO
977      , AOP_R1 && AOP_STK */
978   switch (aop->type)
979     {
980     case AOP_R0:
981       if (_G.r0Pushed)
982         {
983           if (pop)
984             {
985               emitcode ("pop", "ar0");
986               _G.r0Pushed--;
987             }
988         }
989       bitVectUnSetBit (ic->rUsed, R0_IDX);
990       break;
991
992     case AOP_R1:
993       if (_G.r1Pushed)
994         {
995           if (pop)
996             {
997               emitcode ("pop", "ar1");
998               _G.r1Pushed--;
999             }
1000         }
1001       bitVectUnSetBit (ic->rUsed, R1_IDX);
1002       break;
1003
1004     case AOP_STK:
1005       {
1006         int sz = aop->size;
1007         int stk = aop->aopu.aop_stk + aop->size;
1008         bitVectUnSetBit (ic->rUsed, R0_IDX);
1009         bitVectUnSetBit (ic->rUsed, R1_IDX);
1010
1011         getFreePtr (ic, &aop, FALSE);
1012
1013         if (options.stack10bit)
1014           {
1015             /* I'm not sure what to do here yet... */
1016             /* #STUB */
1017             fprintf (stderr,
1018                      "*** Warning: probably generating bad code for "
1019                      "10 bit stack mode.\n");
1020           }
1021
1022         if (stk)
1023           {
1024             emitcode ("mov", "a,_bp");
1025             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1026             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1027           }
1028         else
1029           {
1030             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1031           }
1032
1033         while (sz--)
1034           {
1035             emitcode ("pop", "acc");
1036             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1037             if (!sz)
1038               break;
1039             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1040           }
1041         op->aop = aop;
1042         freeAsmop (op, NULL, ic, TRUE);
1043         if (_G.r0Pushed)
1044           {
1045             emitcode ("pop", "ar0");
1046             _G.r0Pushed--;
1047           }
1048
1049         if (_G.r1Pushed)
1050           {
1051             emitcode ("pop", "ar1");
1052             _G.r1Pushed--;
1053           }
1054       }
1055     case AOP_DPTR2:
1056         if (_G.dptr1InUse) {
1057             emitcode ("pop","dpx1");
1058             emitcode ("pop","dph1");
1059             emitcode ("pop","dpl1");
1060         }
1061         break;
1062     case AOP_DPTR:
1063         if (_G.dptrInUse) {
1064             emitcode ("pop","dpx");
1065             emitcode ("pop","dph");
1066             emitcode ("pop","dpl");
1067         }
1068         break;
1069     }
1070 dealloc:
1071   /* all other cases just dealloc */
1072   if (op)
1073     {
1074       op->aop = NULL;
1075       if (IS_SYMOP (op))
1076         {
1077           OP_SYMBOL (op)->aop = NULL;
1078           /* if the symbol has a spill */
1079           if (SPIL_LOC (op))
1080             SPIL_LOC (op)->aop = NULL;
1081         }
1082     }
1083 }
1084
1085 #define DEFAULT_ACC_WARNING 0
1086 static int saveAccWarn = DEFAULT_ACC_WARNING;
1087
1088 /*-------------------------------------------------------------------*/
1089 /* aopGet - for fetching value of the aop                            */
1090 /*                                                                   */
1091 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1092 /* in the accumulator. Set it to the name of a free register         */
1093 /* if acc must be preserved; the register will be used to preserve   */
1094 /* acc temporarily and to return the result byte.                    */
1095 /*-------------------------------------------------------------------*/
1096
1097 static char *
1098 aopGet (asmop *aop,
1099         int   offset,
1100         bool  bit16,
1101         bool  dname,
1102         char  *saveAcc)
1103 {
1104   /* offset is greater than
1105      size then zero */
1106   if (offset > (aop->size - 1) &&
1107       aop->type != AOP_LIT)
1108     return zero;
1109
1110   /* depending on type */
1111   switch (aop->type)
1112     {
1113
1114     case AOP_R0:
1115     case AOP_R1:
1116       /* if we need to increment it */
1117       while (offset > aop->coff)
1118         {
1119           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1120           aop->coff++;
1121         }
1122
1123       while (offset < aop->coff)
1124         {
1125           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126           aop->coff--;
1127         }
1128
1129       aop->coff = offset;
1130       if (aop->paged)
1131         {
1132           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1133           return (dname ? "acc" : "a");
1134         }
1135       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1136       return Safe_strdup(buffer);       
1137
1138     case AOP_DPTRn:
1139         assert(offset <= 3);
1140         return dptrn[aop->aopu.dptr][offset];
1141
1142     case AOP_DPTR:
1143     case AOP_DPTR2:
1144
1145       if (aop->type == AOP_DPTR2)
1146         {
1147           genSetDPTR (1);
1148         }
1149         
1150       if (saveAcc)
1151         {
1152             TR_AP("#1");
1153 //          if (aop->type != AOP_DPTR2)
1154 //          {
1155 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1156 //              emitcode(";", "spanky: saveAcc for DPTR");
1157 //          }
1158             
1159             emitcode ("xch", "a, %s", saveAcc);
1160         }
1161
1162       _flushLazyDPS ();
1163
1164       while (offset > aop->coff)
1165         {
1166           emitcode ("inc", "dptr");
1167           aop->coff++;
1168         }
1169
1170       while (offset < aop->coff)
1171         {
1172           emitcode ("lcall", "__decdptr");
1173           aop->coff--;
1174         }
1175
1176       aop->coff = offset;
1177       if (aop->code)
1178         {
1179           emitcode ("clr", "a");
1180           emitcode ("movc", "a,@a+dptr");
1181         }
1182       else
1183         {
1184           emitcode ("movx", "a,@dptr");
1185         }
1186
1187       if (aop->type == AOP_DPTR2)
1188         {
1189           genSetDPTR (0);
1190         }
1191         
1192         if (saveAcc)
1193         {
1194        TR_AP("#2");
1195               emitcode ("xch", "a, %s", saveAcc);
1196 //            if (strcmp(saveAcc, "_ap"))
1197 //            {
1198 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1199 //            }
1200                   
1201               return saveAcc;
1202         }
1203       return (dname ? "acc" : "a");
1204
1205     case AOP_IMMD:
1206       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1207       {
1208           SNPRINTF(buffer, sizeof(buffer), 
1209                    "%s",aop->aopu.aop_immd.aop_immd2);
1210       } 
1211       else if (bit16)
1212       {
1213          SNPRINTF(buffer, sizeof(buffer), 
1214                   "#%s", aop->aopu.aop_immd.aop_immd1);
1215       }
1216       else if (offset) 
1217       {
1218           switch (offset) {
1219           case 1:
1220               tsprintf(buffer, sizeof(buffer),
1221                        "#!his",aop->aopu.aop_immd.aop_immd1);
1222               break;
1223           case 2:
1224               tsprintf(buffer, sizeof(buffer), 
1225                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1226               break;
1227           case 3:
1228               tsprintf(buffer, sizeof(buffer),
1229                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1230               break;
1231           default: /* should not need this (just in case) */
1232               SNPRINTF (buffer, sizeof(buffer), 
1233                         "#(%s >> %d)",
1234                        aop->aopu.aop_immd.aop_immd1,
1235                        offset * 8);
1236           }
1237       }
1238       else
1239       {
1240         SNPRINTF (buffer, sizeof(buffer), 
1241                   "#%s", aop->aopu.aop_immd.aop_immd1);
1242       }
1243       return Safe_strdup(buffer);       
1244
1245     case AOP_DIR:
1246       if (offset)
1247       {
1248         SNPRINTF (buffer, sizeof(buffer),
1249                   "(%s + %d)",
1250                  aop->aopu.aop_dir,
1251                  offset);
1252       }
1253       else
1254       {
1255         SNPRINTF(buffer, sizeof(buffer), 
1256                  "%s", aop->aopu.aop_dir);
1257       }
1258
1259       return Safe_strdup(buffer);
1260
1261     case AOP_REG:
1262       if (dname)
1263         return aop->aopu.aop_reg[offset]->dname;
1264       else
1265         return aop->aopu.aop_reg[offset]->name;
1266
1267     case AOP_CRY:
1268       emitcode ("clr", "a");
1269       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1270       emitcode ("rlc", "a");
1271       return (dname ? "acc" : "a");
1272
1273     case AOP_ACC:
1274       if (!offset && dname)
1275         return "acc";
1276       return aop->aopu.aop_str[offset];
1277
1278     case AOP_LIT:
1279       return aopLiteral (aop->aopu.aop_lit, offset);
1280
1281     case AOP_STR:
1282       aop->coff = offset;
1283       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1284           dname)
1285         return "acc";
1286
1287       return aop->aopu.aop_str[offset];
1288
1289     }
1290
1291   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1292           "aopget got unsupported aop->type");
1293   exit (1);
1294     
1295   return NULL;  // not reached, but makes compiler happy.
1296 }
1297 /*-----------------------------------------------------------------*/
1298 /* aopPut - puts a string for a aop                                */
1299 /*-----------------------------------------------------------------*/
1300 static void
1301 aopPut (asmop * aop, char *s, int offset)
1302 {
1303   if (aop->size && offset > (aop->size - 1))
1304     {
1305       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306               "aopPut got offset > aop->size");
1307       exit (1);
1308     }
1309
1310   /* will assign value to value */
1311   /* depending on where it is ofcourse */
1312   switch (aop->type)
1313     {
1314     case AOP_DIR:
1315         if (offset)
1316         {
1317             SNPRINTF (buffer, sizeof(buffer),
1318                       "(%s + %d)",
1319                       aop->aopu.aop_dir, offset);
1320         }
1321         else
1322         {
1323             SNPRINTF (buffer, sizeof(buffer), 
1324                      "%s", aop->aopu.aop_dir);
1325         }
1326         
1327
1328         if (strcmp (buffer, s))
1329         {
1330             emitcode ("mov", "%s,%s", buffer, s);
1331         }
1332       break;
1333
1334     case AOP_REG:
1335       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1336           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1337         {
1338           if (*s == '@' ||
1339               strcmp (s, "r0") == 0 ||
1340               strcmp (s, "r1") == 0 ||
1341               strcmp (s, "r2") == 0 ||
1342               strcmp (s, "r3") == 0 ||
1343               strcmp (s, "r4") == 0 ||
1344               strcmp (s, "r5") == 0 ||
1345               strcmp (s, "r6") == 0 ||
1346               strcmp (s, "r7") == 0)
1347             {
1348                 emitcode ("mov", "%s,%s",
1349                           aop->aopu.aop_reg[offset]->dname, s);
1350             }
1351             else
1352             {
1353                 emitcode ("mov", "%s,%s",
1354                           aop->aopu.aop_reg[offset]->name, s);
1355             }
1356         }
1357       break;
1358
1359     case AOP_DPTRn:
1360         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1361         break;
1362
1363     case AOP_DPTR:
1364     case AOP_DPTR2:
1365
1366       if (aop->type == AOP_DPTR2)
1367         {
1368           genSetDPTR (1);
1369         }
1370       _flushLazyDPS ();
1371
1372       if (aop->code)
1373         {
1374           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375                   "aopPut writting to code space");
1376           exit (1);
1377         }
1378
1379       while (offset > aop->coff)
1380         {
1381           aop->coff++;
1382           emitcode ("inc", "dptr");
1383         }
1384
1385       while (offset < aop->coff)
1386         {
1387           aop->coff--;
1388           emitcode ("lcall", "__decdptr");
1389         }
1390
1391       aop->coff = offset;
1392
1393       /* if not in accumulater */
1394       MOVA (s);
1395
1396       emitcode ("movx", "@dptr,a");
1397
1398       if (aop->type == AOP_DPTR2)
1399         {
1400           genSetDPTR (0);
1401         }
1402       break;
1403
1404     case AOP_R0:
1405     case AOP_R1:
1406       while (offset > aop->coff)
1407         {
1408           aop->coff++;
1409           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1410         }
1411       while (offset < aop->coff)
1412         {
1413           aop->coff--;
1414           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1415         }
1416       aop->coff = offset;
1417
1418       if (aop->paged)
1419         {
1420           MOVA (s);
1421           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1422
1423         }
1424       else if (*s == '@')
1425         {
1426           MOVA (s);
1427           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1428         }
1429       else if (strcmp (s, "r0") == 0 ||
1430                strcmp (s, "r1") == 0 ||
1431                strcmp (s, "r2") == 0 ||
1432                strcmp (s, "r3") == 0 ||
1433                strcmp (s, "r4") == 0 ||
1434                strcmp (s, "r5") == 0 ||
1435                strcmp (s, "r6") == 0 ||
1436                strcmp (s, "r7") == 0)
1437         {
1438           char buff[10];
1439           SNPRINTF(buff, sizeof(buff), 
1440                    "a%s", s);
1441           emitcode ("mov", "@%s,%s",
1442                     aop->aopu.aop_ptr->name, buff);
1443         }
1444         else
1445         {
1446             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1447         }
1448       break;
1449
1450     case AOP_STK:
1451       if (strcmp (s, "a") == 0)
1452         emitcode ("push", "acc");
1453       else
1454         if (*s=='@') {
1455           MOVA(s);
1456           emitcode ("push", "acc");
1457         } else {
1458           emitcode ("push", s);
1459         }
1460
1461       break;
1462
1463     case AOP_CRY:
1464       /* if bit variable */
1465       if (!aop->aopu.aop_dir)
1466         {
1467           emitcode ("clr", "a");
1468           emitcode ("rlc", "a");
1469         }
1470       else
1471         {
1472           if (s == zero)
1473             emitcode ("clr", "%s", aop->aopu.aop_dir);
1474           else if (s == one)
1475             emitcode ("setb", "%s", aop->aopu.aop_dir);
1476           else if (!strcmp (s, "c"))
1477             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1478           else
1479             {
1480               if (strcmp (s, "a"))
1481                 {
1482                   MOVA (s);
1483                 }
1484               {
1485                 /* set C, if a >= 1 */
1486                 emitcode ("add", "a,#!constbyte",0xff);
1487                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1488               }
1489             }
1490         }
1491       break;
1492
1493     case AOP_STR:
1494       aop->coff = offset;
1495       if (strcmp (aop->aopu.aop_str[offset], s))
1496         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1497       break;
1498
1499     case AOP_ACC:
1500       aop->coff = offset;
1501       if (!offset && (strcmp (s, "acc") == 0))
1502         break;
1503
1504       if (strcmp (aop->aopu.aop_str[offset], s))
1505         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1506       break;
1507
1508     default:
1509       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1510               "aopPut got unsupported aop->type");
1511       exit (1);
1512     }
1513
1514 }
1515
1516
1517 /*--------------------------------------------------------------------*/
1518 /* reAdjustPreg - points a register back to where it should (coff==0) */
1519 /*--------------------------------------------------------------------*/
1520 static void
1521 reAdjustPreg (asmop * aop)
1522 {
1523   if ((aop->coff==0) || (aop->size <= 1)) {
1524     return;
1525   }
1526
1527   switch (aop->type)
1528     {
1529     case AOP_R0:
1530     case AOP_R1:
1531       while (aop->coff--)
1532         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1533       break;
1534     case AOP_DPTR:
1535     case AOP_DPTR2:
1536       if (aop->type == AOP_DPTR2)
1537         {
1538           genSetDPTR (1);
1539           _flushLazyDPS ();
1540         }
1541       while (aop->coff--)
1542         {
1543           emitcode ("lcall", "__decdptr");
1544         }
1545
1546       if (aop->type == AOP_DPTR2)
1547         {
1548           genSetDPTR (0);
1549         }
1550       break;
1551
1552     }
1553   aop->coff=0;
1554 }
1555
1556 #define AOP(op) op->aop
1557 #define AOP_TYPE(op) AOP(op)->type
1558 #define AOP_SIZE(op) AOP(op)->size
1559 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1560                        AOP_TYPE(x) == AOP_R0))
1561
1562 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1563                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1564                          AOP(x)->paged))
1565
1566 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1567                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1568                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1569 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1570 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1571 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1572
1573 // The following two macros can be used even if the aop has not yet been aopOp'd.
1574 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1575 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1576
1577 /* Workaround for DS80C390 bug: div ab may return bogus results
1578  * if A is accessed in instruction immediately before the div.
1579  *
1580  * Will be fixed in B4 rev of processor, Dallas claims.
1581  */
1582
1583 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1584     if (!AOP_NEEDSACC(RIGHT))         \
1585     {               \
1586       /* We can load A first, then B, since     \
1587        * B (the RIGHT operand) won't clobber A,   \
1588        * thus avoiding touching A right before the div. \
1589        */             \
1590       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1591       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1592       MOVA(L);            \
1593       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1594       MOVB(L); \
1595     }               \
1596     else              \
1597     {               \
1598       /* Just stuff in a nop after loading A. */    \
1599       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1600       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1601       MOVA(L);            \
1602       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1603     }
1604
1605 /*-----------------------------------------------------------------*/
1606 /* genNotFloat - generates not for float operations              */
1607 /*-----------------------------------------------------------------*/
1608 static void
1609 genNotFloat (operand * op, operand * res)
1610 {
1611   int size, offset;
1612   symbol *tlbl;
1613
1614   D (emitcode (";", "genNotFloat "););
1615
1616   /* we will put 127 in the first byte of
1617      the result */
1618   aopPut (AOP (res), "#127", 0);
1619   size = AOP_SIZE (op) - 1;
1620   offset = 1;
1621
1622   _startLazyDPSEvaluation ();
1623   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1624
1625   while (size--)
1626     {
1627       emitcode ("orl", "a,%s",
1628                 aopGet (op->aop,
1629                         offset++, FALSE, FALSE,
1630                         DP2_RESULT_REG));
1631     }
1632   _endLazyDPSEvaluation ();
1633
1634   tlbl = newiTempLabel (NULL);
1635   aopPut (res->aop, one, 1);
1636   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1637   aopPut (res->aop, zero, 1);
1638   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1639
1640   size = res->aop->size - 2;
1641   offset = 2;
1642   /* put zeros in the rest */
1643   while (size--)
1644     aopPut (res->aop, zero, offset++);
1645 }
1646
1647 /*-----------------------------------------------------------------*/
1648 /* opIsGptr: returns non-zero if the passed operand is       */
1649 /* a generic pointer type.             */
1650 /*-----------------------------------------------------------------*/
1651 static int
1652 opIsGptr (operand * op)
1653 {
1654   sym_link *type = operandType (op);
1655
1656   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1657     {
1658       return 1;
1659     }
1660   return 0;
1661 }
1662
1663 /*-----------------------------------------------------------------*/
1664 /* getDataSize - get the operand data size                         */
1665 /*-----------------------------------------------------------------*/
1666 static int
1667 getDataSize (operand * op)
1668 {
1669   int size;
1670   size = AOP_SIZE (op);
1671   if (size == GPTRSIZE)
1672     {
1673       sym_link *type = operandType (op);
1674       if (IS_GENPTR (type))
1675         {
1676           /* generic pointer; arithmetic operations
1677            * should ignore the high byte (pointer type).
1678            */
1679           size--;
1680         }
1681     }
1682   return size;
1683 }
1684
1685 /*-----------------------------------------------------------------*/
1686 /* outAcc - output Acc                                             */
1687 /*-----------------------------------------------------------------*/
1688 static void
1689 outAcc (operand * result)
1690 {
1691   int size, offset;
1692   size = getDataSize (result);
1693   if (size)
1694     {
1695       aopPut (AOP (result), "a", 0);
1696       size--;
1697       offset = 1;
1698       /* unsigned or positive */
1699       while (size--)
1700         {
1701           aopPut (AOP (result), zero, offset++);
1702         }
1703     }
1704 }
1705
1706 /*-----------------------------------------------------------------*/
1707 /* outBitC - output a bit C                                        */
1708 /*-----------------------------------------------------------------*/
1709 static void
1710 outBitC (operand * result)
1711 {
1712   /* if the result is bit */
1713   if (AOP_TYPE (result) == AOP_CRY)
1714     {
1715       aopPut (AOP (result), "c", 0);
1716     }
1717   else
1718     {
1719       emitcode ("clr", "a");
1720       emitcode ("rlc", "a");
1721       outAcc (result);
1722     }
1723 }
1724
1725 /*-----------------------------------------------------------------*/
1726 /* toBoolean - emit code for orl a,operator(sizeop)                */
1727 /*-----------------------------------------------------------------*/
1728 static void
1729 toBoolean (operand * oper)
1730 {
1731   int   size = AOP_SIZE (oper) - 1;
1732   int   offset = 1;
1733   bool usedB = FALSE;
1734
1735   /* The generic part of a generic pointer should
1736    * not participate in it's truth value.
1737    *
1738    * i.e. 0x10000000 is zero.
1739    */
1740   if (opIsGptr (oper))
1741     {
1742       D (emitcode (";", "toBoolean: generic ptr special case."););
1743       size--;
1744     }
1745
1746   _startLazyDPSEvaluation ();
1747   if (AOP_NEEDSACC (oper) && size)
1748     {
1749       usedB = TRUE;
1750       if (_G.bInUse)
1751       {
1752           emitcode ("push", "b");
1753       }
1754       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1755     }
1756   else
1757     {
1758       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1759     }
1760     
1761   while (size--)
1762     {
1763       if (usedB)
1764         {
1765           emitcode ("orl", "b,%s",
1766                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1767         }
1768       else
1769         {
1770           emitcode ("orl", "a,%s",
1771                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1772         }
1773     }
1774   _endLazyDPSEvaluation ();
1775
1776   if (usedB)
1777     {
1778       emitcode ("mov", "a,b");
1779       if (_G.bInUse)
1780       {
1781           emitcode ("pop", "b");
1782       }
1783         
1784     }
1785 }
1786
1787
1788 /*-----------------------------------------------------------------*/
1789 /* genNot - generate code for ! operation                          */
1790 /*-----------------------------------------------------------------*/
1791 static void
1792 genNot (iCode * ic)
1793 {
1794   symbol *tlbl;
1795   sym_link *optype = operandType (IC_LEFT (ic));
1796
1797   D (emitcode (";", "genNot "););
1798
1799   /* assign asmOps to operand & result */
1800   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1801   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1802
1803   /* if in bit space then a special case */
1804   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1805     {
1806       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1807       emitcode ("cpl", "c");
1808       outBitC (IC_RESULT (ic));
1809       goto release;
1810     }
1811
1812   /* if type float then do float */
1813   if (IS_FLOAT (optype))
1814     {
1815       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1816       goto release;
1817     }
1818
1819   toBoolean (IC_LEFT (ic));
1820
1821   tlbl = newiTempLabel (NULL);
1822   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1823   emitcode ("", "!tlabeldef", tlbl->key + 100);
1824   outBitC (IC_RESULT (ic));
1825
1826 release:
1827   /* release the aops */
1828   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1829   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1830 }
1831
1832
1833 /*-----------------------------------------------------------------*/
1834 /* genCpl - generate code for complement                           */
1835 /*-----------------------------------------------------------------*/
1836 static void
1837 genCpl (iCode * ic)
1838 {
1839   int offset = 0;
1840   int size;
1841   symbol *tlbl;
1842
1843   D (emitcode (";", "genCpl "););
1844
1845
1846   /* assign asmOps to operand & result */
1847   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1848   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1849
1850   /* special case if in bit space */
1851   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1852     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1853       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1854       emitcode ("cpl", "c");
1855       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1856       goto release;
1857     }
1858     tlbl=newiTempLabel(NULL);
1859     emitcode ("cjne", "%s,#0x01,%05d$", 
1860               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1861     emitcode ("", "%05d$:", tlbl->key+100);
1862     outBitC (IC_RESULT(ic));
1863     goto release;
1864   }
1865
1866   size = AOP_SIZE (IC_RESULT (ic));
1867   _startLazyDPSEvaluation ();
1868   while (size--)
1869     {
1870       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1871       emitcode ("cpl", "a");
1872       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1873     }
1874   _endLazyDPSEvaluation ();
1875
1876
1877 release:
1878   /* release the aops */
1879   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1880   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1881 }
1882
1883 /*-----------------------------------------------------------------*/
1884 /* genUminusFloat - unary minus for floating points                */
1885 /*-----------------------------------------------------------------*/
1886 static void
1887 genUminusFloat (operand * op, operand * result)
1888 {
1889   int size, offset = 0;
1890     
1891   D(emitcode (";", "genUminusFloat"););
1892   
1893   /* for this we just copy and then flip the bit */
1894     
1895   _startLazyDPSEvaluation ();
1896   size = AOP_SIZE (op) - 1;
1897
1898   while (size--)
1899   {
1900       aopPut (AOP (result),
1901               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1902               offset);
1903       offset++;
1904     }
1905   
1906   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1907
1908   emitcode ("cpl", "acc.7");
1909   aopPut (AOP (result), "a", offset);    
1910   _endLazyDPSEvaluation ();
1911 }
1912
1913 /*-----------------------------------------------------------------*/
1914 /* genUminus - unary minus code generation                         */
1915 /*-----------------------------------------------------------------*/
1916 static void
1917 genUminus (iCode * ic)
1918 {
1919   int offset, size;
1920   sym_link *optype;
1921
1922   D (emitcode (";", "genUminus "););
1923
1924   /* assign asmops */
1925   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1926   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1927
1928   /* if both in bit space then special
1929      case */
1930   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1931       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1932     {
1933
1934       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1935       emitcode ("cpl", "c");
1936       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1937       goto release;
1938     }
1939
1940   optype = operandType (IC_LEFT (ic));
1941
1942   /* if float then do float stuff */
1943   if (IS_FLOAT (optype))
1944     {
1945       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1946       goto release;
1947     }
1948
1949   /* otherwise subtract from zero */
1950   size = AOP_SIZE (IC_LEFT (ic));
1951   offset = 0;
1952   _startLazyDPSEvaluation ();
1953   while (size--)
1954     {
1955       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1956       if (!strcmp (l, "a"))
1957         {
1958           if (offset == 0)
1959             SETC;
1960           emitcode ("cpl", "a");
1961           emitcode ("addc", "a,#0");
1962         }
1963       else
1964         {
1965           if (offset == 0)
1966             CLRC;
1967           emitcode ("clr", "a");
1968           emitcode ("subb", "a,%s", l);
1969         }
1970       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1971     }
1972   _endLazyDPSEvaluation ();
1973
1974   /* if any remaining bytes in the result */
1975   /* we just need to propagate the sign   */
1976   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1977     {
1978       emitcode ("rlc", "a");
1979       emitcode ("subb", "a,acc");
1980       while (size--)
1981         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1982     }
1983
1984 release:
1985   /* release the aops */
1986   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1987   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1988 }
1989
1990 /*-----------------------------------------------------------------*/
1991 /* savermask - saves registers in the mask                         */
1992 /*-----------------------------------------------------------------*/
1993 static void savermask(bitVect *rs_mask)
1994 {
1995     int i;
1996     if (options.useXstack) {
1997         if (bitVectBitValue (rs_mask, R0_IDX))
1998             emitcode ("mov", "b,r0");
1999         emitcode ("mov", "r0,%s", spname);
2000         for (i = 0; i < ds390_nRegs; i++) {
2001             if (bitVectBitValue (rs_mask, i)) {
2002                 if (i == R0_IDX)
2003                     emitcode ("mov", "a,b");
2004                 else
2005                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2006                 emitcode ("movx", "@r0,a");
2007                 emitcode ("inc", "r0");
2008             }
2009         }
2010         emitcode ("mov", "%s,r0", spname);
2011         if (bitVectBitValue (rs_mask, R0_IDX))
2012             emitcode ("mov", "r0,b");
2013     } else {
2014         for (i = 0; i < ds390_nRegs; i++) {
2015             if (bitVectBitValue (rs_mask, i))
2016                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2017         }
2018     }
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* saveRegisters - will look for a call and save the registers     */
2023 /*-----------------------------------------------------------------*/
2024 static void
2025 saveRegisters (iCode * lic)
2026 {
2027   iCode *ic;
2028   bitVect *rsave;
2029
2030   /* look for call */
2031   for (ic = lic; ic; ic = ic->next)
2032     if (ic->op == CALL || ic->op == PCALL)
2033       break;
2034
2035   if (!ic)
2036     {
2037       fprintf (stderr, "found parameter push with no function call\n");
2038       return;
2039     }
2040
2041   /* if the registers have been saved already then
2042      do nothing */
2043   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2044
2045   /* special case if DPTR alive across a function call then must save it 
2046      even though callee saves */
2047   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2048       int i;
2049       rsave = newBitVect(ic->rMask->size);
2050       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2051           if (bitVectBitValue(ic->rMask,i))
2052               rsave = bitVectSetBit(rsave,i);
2053       }
2054       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2055   } else {
2056     /* safe the registers in use at this time but skip the
2057        ones for the result */
2058     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2059                            ds390_rUmaskForOp (IC_RESULT(ic)));
2060   }
2061   ic->regsSaved = 1;
2062   savermask(rsave);
2063 }
2064
2065 /*-----------------------------------------------------------------*/
2066 /* usavermask - restore registers with mask                        */
2067 /*-----------------------------------------------------------------*/
2068 static void unsavermask(bitVect *rs_mask)
2069 {
2070     int i;
2071     if (options.useXstack) {
2072         emitcode ("mov", "r0,%s", spname);
2073         for (i = ds390_nRegs; i >= 0; i--) {
2074             if (bitVectBitValue (rs_mask, i)) {
2075                 emitcode ("dec", "r0");
2076                 emitcode ("movx", "a,@r0");
2077                 if (i == R0_IDX)
2078                     emitcode ("mov", "b,a");
2079                 else
2080                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2081             }       
2082         }
2083         emitcode ("mov", "%s,r0", spname);
2084         if (bitVectBitValue (rs_mask, R0_IDX))
2085             emitcode ("mov", "r0,b");
2086     } else {
2087         for (i = ds390_nRegs; i >= 0; i--) {
2088             if (bitVectBitValue (rs_mask, i))
2089                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2090         }
2091     }
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* unsaveRegisters - pop the pushed registers                      */
2096 /*-----------------------------------------------------------------*/
2097 static void
2098 unsaveRegisters (iCode * ic)
2099 {
2100   bitVect *rsave;
2101
2102   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2103       int i;
2104       rsave = newBitVect(ic->rMask->size);
2105       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2106           if (bitVectBitValue(ic->rMask,i))
2107               rsave = bitVectSetBit(rsave,i);
2108       }
2109       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2110   } else {
2111     /* restore the registers in use at this time but skip the
2112        ones for the result */
2113     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2114                            ds390_rUmaskForOp (IC_RESULT(ic)));
2115   }
2116   unsavermask(rsave);
2117 }
2118
2119
2120 /*-----------------------------------------------------------------*/
2121 /* pushSide -                */
2122 /*-----------------------------------------------------------------*/
2123 static void
2124 pushSide (operand * oper, int size)
2125 {
2126   int offset = 0;
2127   _startLazyDPSEvaluation ();
2128   while (size--)
2129     {
2130       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2131       if (AOP_TYPE (oper) != AOP_REG &&
2132           AOP_TYPE (oper) != AOP_DIR &&
2133           strcmp (l, "a"))
2134         {
2135           emitcode ("mov", "a,%s", l);
2136           emitcode ("push", "acc");
2137         }
2138       else
2139         emitcode ("push", "%s", l);
2140     }
2141   _endLazyDPSEvaluation ();
2142 }
2143
2144 /*-----------------------------------------------------------------*/
2145 /* assignResultValue -               */
2146 /*-----------------------------------------------------------------*/
2147 static void
2148 assignResultValue (operand * oper)
2149 {
2150   int offset = 0;
2151   int size = AOP_SIZE (oper);
2152   bool pushedAcc = FALSE;
2153
2154   if (size == fReturnSizeDS390)
2155   {
2156       /* I don't think this case can ever happen... */
2157       /* ACC is the last part of this. If writing the result
2158        * uses AC, we must preserve it.
2159        */
2160       if (AOP_NEEDSACC(oper))
2161       {
2162           emitcode(";", "assignResultValue special case for ACC.");
2163           emitcode("push", "acc");
2164           pushedAcc = TRUE;
2165           size--;
2166       }
2167   }
2168     
2169     
2170   _startLazyDPSEvaluation ();
2171   while (size--)
2172     {
2173       aopPut (AOP (oper), fReturn[offset], offset);
2174       offset++;
2175     }
2176   _endLazyDPSEvaluation ();
2177     
2178   if (pushedAcc)
2179     {
2180         emitcode("pop", "acc");
2181         aopPut(AOP(oper), "a", offset);
2182     }
2183 }
2184
2185
2186 /*-----------------------------------------------------------------*/
2187 /* genXpush - pushes onto the external stack                       */
2188 /*-----------------------------------------------------------------*/
2189 static void
2190 genXpush (iCode * ic)
2191 {
2192   asmop *aop = newAsmop (0);
2193   regs *r;
2194   int size, offset = 0;
2195
2196   D (emitcode (";", "genXpush ");
2197     );
2198
2199   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2200   r = getFreePtr (ic, &aop, FALSE);
2201
2202
2203   emitcode ("mov", "%s,_spx", r->name);
2204
2205   size = AOP_SIZE (IC_LEFT (ic));
2206   _startLazyDPSEvaluation ();
2207   while (size--)
2208     {
2209
2210       MOVA (aopGet (AOP (IC_LEFT (ic)),
2211                         offset++, FALSE, FALSE, NULL));
2212       emitcode ("movx", "@%s,a", r->name);
2213       emitcode ("inc", "%s", r->name);
2214
2215     }
2216   _endLazyDPSEvaluation ();
2217
2218
2219   emitcode ("mov", "_spx,%s", r->name);
2220
2221   freeAsmop (NULL, aop, ic, TRUE);
2222   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2223 }
2224
2225 /*-----------------------------------------------------------------*/
2226 /* genIpush - generate code for pushing this gets a little complex  */
2227 /*-----------------------------------------------------------------*/
2228 static void
2229 genIpush (iCode * ic)
2230 {
2231   int size, offset = 0;
2232   char *l;
2233
2234   D (emitcode (";", "genIpush ");
2235     );
2236
2237   /* if this is not a parm push : ie. it is spill push
2238      and spill push is always done on the local stack */
2239   if (!ic->parmPush)
2240     {
2241
2242       /* and the item is spilt then do nothing */
2243       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2244         return;
2245
2246       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2247       size = AOP_SIZE (IC_LEFT (ic));
2248       /* push it on the stack */
2249       _startLazyDPSEvaluation ();
2250       while (size--)
2251         {
2252           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2253           if (*l == '#')
2254             {
2255               MOVA (l);
2256               l = "acc";
2257             }
2258           emitcode ("push", "%s", l);
2259         }
2260       _endLazyDPSEvaluation ();
2261       return;
2262     }
2263
2264   /* this is a paramter push: in this case we call
2265      the routine to find the call and save those
2266      registers that need to be saved */
2267   saveRegisters (ic);
2268
2269   /* if use external stack then call the external
2270      stack pushing routine */
2271   if (options.useXstack)
2272     {
2273       genXpush (ic);
2274       return;
2275     }
2276
2277   /* then do the push */
2278   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2279
2280   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2281   size = AOP_SIZE (IC_LEFT (ic));
2282
2283   _startLazyDPSEvaluation ();
2284   while (size--)
2285     {
2286       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2287       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2288           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2289           strcmp (l, "acc"))
2290         {
2291           emitcode ("mov", "a,%s", l);
2292           emitcode ("push", "acc");
2293         }
2294       else
2295         {
2296             emitcode ("push", "%s", l);
2297         }
2298     }
2299   _endLazyDPSEvaluation ();
2300
2301   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2302 }
2303
2304 /*-----------------------------------------------------------------*/
2305 /* genIpop - recover the registers: can happen only for spilling   */
2306 /*-----------------------------------------------------------------*/
2307 static void
2308 genIpop (iCode * ic)
2309 {
2310   int size, offset;
2311
2312   D (emitcode (";", "genIpop ");
2313     );
2314
2315
2316   /* if the temp was not pushed then */
2317   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2318     return;
2319
2320   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2321   size = AOP_SIZE (IC_LEFT (ic));
2322   offset = (size - 1);
2323   _startLazyDPSEvaluation ();
2324   while (size--)
2325     {
2326       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2327                                      FALSE, TRUE, NULL));
2328     }
2329   _endLazyDPSEvaluation ();
2330
2331   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2332 }
2333
2334 /*-----------------------------------------------------------------*/
2335 /* unsaveRBank - restores the resgister bank from stack            */
2336 /*-----------------------------------------------------------------*/
2337 static void
2338 unsaveRBank (int bank, iCode * ic, bool popPsw)
2339 {
2340   int i;
2341   asmop *aop = NULL;
2342   regs *r = NULL;
2343
2344   if (options.useXstack)
2345   {
2346       if (!ic)
2347       {
2348           /* Assume r0 is available for use. */
2349           r = ds390_regWithIdx (R0_IDX);;          
2350       } 
2351       else
2352       {
2353           aop = newAsmop (0);
2354           r = getFreePtr (ic, &aop, FALSE);
2355       }
2356       emitcode ("mov", "%s,_spx", r->name);      
2357   }
2358   
2359   if (popPsw)
2360     {
2361       if (options.useXstack)
2362       {
2363           emitcode ("movx", "a,@%s", r->name);
2364           emitcode ("mov", "psw,a");
2365           emitcode ("dec", "%s", r->name);
2366         }
2367       else
2368       {
2369         emitcode ("pop", "psw");
2370       }
2371     }
2372
2373   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2374     {
2375       if (options.useXstack)
2376         {
2377           emitcode ("movx", "a,@%s", r->name);
2378           emitcode ("mov", "(%s+%d),a",
2379                     regs390[i].base, 8 * bank + regs390[i].offset);
2380           emitcode ("dec", "%s", r->name);
2381
2382         }
2383       else
2384         emitcode ("pop", "(%s+%d)",
2385                   regs390[i].base, 8 * bank + regs390[i].offset);
2386     }
2387
2388   if (options.useXstack)
2389     {
2390       emitcode ("mov", "_spx,%s", r->name);
2391     }
2392     
2393   if (aop)
2394   {
2395       freeAsmop (NULL, aop, ic, TRUE);  
2396   }    
2397 }
2398
2399 /*-----------------------------------------------------------------*/
2400 /* saveRBank - saves an entire register bank on the stack          */
2401 /*-----------------------------------------------------------------*/
2402 static void
2403 saveRBank (int bank, iCode * ic, bool pushPsw)
2404 {
2405   int i;
2406   asmop *aop = NULL;
2407   regs *r = NULL;
2408
2409   if (options.useXstack)
2410     {
2411         if (!ic)
2412         {
2413           /* Assume r0 is available for use. */
2414                   r = ds390_regWithIdx (R0_IDX);;
2415         }
2416         else
2417         {
2418           aop = newAsmop (0);
2419           r = getFreePtr (ic, &aop, FALSE);
2420         }
2421         emitcode ("mov", "%s,_spx", r->name);    
2422     }
2423
2424   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2425     {
2426       if (options.useXstack)
2427         {
2428           emitcode ("inc", "%s", r->name);
2429           emitcode ("mov", "a,(%s+%d)",
2430                     regs390[i].base, 8 * bank + regs390[i].offset);
2431           emitcode ("movx", "@%s,a", r->name);
2432         }
2433       else
2434         emitcode ("push", "(%s+%d)",
2435                   regs390[i].base, 8 * bank + regs390[i].offset);
2436     }
2437
2438   if (pushPsw)
2439     {
2440       if (options.useXstack)
2441         {
2442           emitcode ("mov", "a,psw");
2443           emitcode ("movx", "@%s,a", r->name);
2444           emitcode ("inc", "%s", r->name);
2445           emitcode ("mov", "_spx,%s", r->name);
2446         }
2447       else
2448       {
2449         emitcode ("push", "psw");
2450       }
2451
2452       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2453     }
2454   
2455   if (aop)
2456   {
2457        freeAsmop (NULL, aop, ic, TRUE);
2458   }    
2459     
2460   if (ic)
2461   {  
2462       ic->bankSaved = 1;
2463   }
2464 }
2465
2466 /*-----------------------------------------------------------------*/
2467 /* genSend - gen code for SEND                                     */
2468 /*-----------------------------------------------------------------*/
2469 static void genSend(set *sendSet)
2470 {
2471     iCode *sic;
2472     int sendCount = 0 ;
2473     static int rb1_count = 0;
2474
2475     for (sic = setFirstItem (sendSet); sic;
2476          sic = setNextItem (sendSet)) {     
2477         int size, offset = 0;
2478         
2479         size=getSize(operandType(IC_LEFT(sic)));
2480         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2481         if (sendCount == 0) { /* first parameter */
2482             // we know that dpl(hxb) is the result, so
2483             rb1_count = 0 ;
2484             _startLazyDPSEvaluation ();
2485             if (size>1) {
2486                 aopOp (IC_LEFT (sic), sic, FALSE, 
2487                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2488             } else {
2489                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2490             }
2491             while (size--) {
2492                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2493                                   FALSE, FALSE, NULL);
2494                 if (strcmp (l, fReturn[offset])) {
2495                     emitcode ("mov", "%s,%s",
2496                               fReturn[offset],
2497                               l);
2498                 }
2499                 offset++;
2500             }
2501             _endLazyDPSEvaluation ();
2502             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2503             rb1_count =0;
2504         } else { /* if more parameter in registers */
2505             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2506             while (size--) {
2507                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2508                                                                 FALSE, FALSE, NULL));
2509             }
2510             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2511         }
2512         sendCount++;
2513     }
2514 }
2515
2516 /*-----------------------------------------------------------------*/
2517 /* genCall - generates a call statement                            */
2518 /*-----------------------------------------------------------------*/
2519 static void
2520 genCall (iCode * ic)
2521 {
2522   sym_link *dtype;
2523   bool restoreBank = FALSE;
2524   bool swapBanks = FALSE;
2525
2526   D (emitcode (";", "genCall "););
2527
2528   /* if we are calling a not _naked function that is not using
2529      the same register bank then we need to save the
2530      destination registers on the stack */
2531   dtype = operandType (IC_LEFT (ic));
2532   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2533       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2534       IFFUNC_ISISR (currFunc->type))
2535   {
2536       if (!ic->bankSaved) 
2537       {
2538            /* This is unexpected; the bank should have been saved in
2539             * genFunction.
2540             */
2541            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2542            restoreBank = TRUE;
2543       }
2544       swapBanks = TRUE;
2545   }
2546   
2547     /* if caller saves & we have not saved then */
2548     if (!ic->regsSaved)
2549       saveRegisters (ic);
2550   
2551   /* if send set is not empty the assign */
2552   /* We've saved all the registers we care about;
2553   * therefore, we may clobber any register not used
2554   * in the calling convention (i.e. anything not in
2555   * fReturn.
2556   */
2557   if (_G.sendSet)
2558     {
2559         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2560             genSend(reverseSet(_G.sendSet));
2561         } else {
2562             genSend(_G.sendSet);
2563         }
2564       _G.sendSet = NULL;
2565     }  
2566     
2567   if (swapBanks)
2568   {
2569         emitcode ("mov", "psw,#!constbyte", 
2570            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2571   }
2572
2573   /* make the call */
2574   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2575                             OP_SYMBOL (IC_LEFT (ic))->rname :
2576                             OP_SYMBOL (IC_LEFT (ic))->name));
2577
2578   if (swapBanks)
2579   {
2580        emitcode ("mov", "psw,#!constbyte", 
2581           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2582   }
2583
2584   /* if we need assign a result value */
2585   if ((IS_ITEMP (IC_RESULT (ic)) &&
2586        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2587         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2588         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2589       IS_TRUE_SYMOP (IC_RESULT (ic)))
2590     {
2591       if (isOperandInFarSpace (IC_RESULT (ic))
2592           && getSize (operandType (IC_RESULT (ic))) <= 2)
2593         {
2594           int size = getSize (operandType (IC_RESULT (ic)));
2595
2596           /* Special case for 1 or 2 byte return in far space. */
2597           MOVA (fReturn[0]);
2598           if (size > 1)
2599             {
2600               emitcode ("mov", "b,%s", fReturn[1]);
2601             }
2602
2603           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2604           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2605
2606           if (size > 1)
2607             {
2608               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2609             }
2610           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2611         }
2612       else
2613         {
2614           _G.accInUse++;
2615           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2616           _G.accInUse--;
2617
2618           assignResultValue (IC_RESULT (ic));
2619
2620           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2621         }
2622     }
2623
2624   /* adjust the stack for parameters if
2625      required */
2626   if (ic->parmBytes) {
2627       int i;
2628       if (options.stack10bit) {
2629           if (ic->parmBytes <= 10) {
2630               emitcode(";","stack adjustment for parms");
2631               for (i=0; i < ic->parmBytes ; i++) {
2632                   emitcode("pop","acc");
2633               }
2634           } else {            
2635               PROTECT_SP;
2636               emitcode ("clr","c");
2637               emitcode ("mov","a,sp");
2638               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2639               emitcode ("mov","sp,a");
2640               emitcode ("mov","a,esp");
2641               emitcode ("anl","a,#3");
2642               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2643               emitcode ("mov","esp,a");   
2644               UNPROTECT_SP;
2645           }
2646       } else {
2647           if (ic->parmBytes > 3) {
2648               emitcode ("mov", "a,%s", spname);
2649               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2650               emitcode ("mov", "%s,a", spname);
2651           } else
2652               for (i = 0; i < ic->parmBytes; i++)
2653                   emitcode ("dec", "%s", spname);
2654       }
2655   }
2656
2657   /* if we hade saved some registers then unsave them */
2658   if (ic->regsSaved)
2659     unsaveRegisters (ic);
2660
2661   /* if register bank was saved then pop them */
2662   if (restoreBank)
2663     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2664 }
2665
2666 /*-----------------------------------------------------------------*/
2667 /* genPcall - generates a call by pointer statement                */
2668 /*-----------------------------------------------------------------*/
2669 static void
2670 genPcall (iCode * ic)
2671 {
2672   sym_link *dtype;
2673   symbol *rlbl = newiTempLabel (NULL);
2674   bool restoreBank=FALSE;
2675
2676   D (emitcode (";", "genPcall ");
2677     );
2678
2679
2680   /* if caller saves & we have not saved then */
2681   if (!ic->regsSaved)
2682     saveRegisters (ic);
2683
2684   /* if we are calling a function that is not using
2685      the same register bank then we need to save the
2686      destination registers on the stack */
2687   dtype = operandType (IC_LEFT (ic));
2688   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2689       IFFUNC_ISISR (currFunc->type) &&
2690       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2691     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2692     restoreBank=TRUE;
2693   }
2694
2695   /* push the return address on to the stack */
2696   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2697   emitcode ("push", "acc");
2698   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2699   emitcode ("push", "acc");
2700
2701   if (options.model == MODEL_FLAT24)
2702     {
2703       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2704       emitcode ("push", "acc");
2705     }
2706
2707   /* now push the calling address */
2708   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2709
2710   pushSide (IC_LEFT (ic), FPTRSIZE);
2711
2712   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2713
2714   /* if send set is not empty the assign */
2715   if (_G.sendSet)
2716     {
2717         genSend(reverseSet(_G.sendSet));
2718         _G.sendSet = NULL;
2719     }
2720
2721   emitcode ("ret", "");
2722   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2723
2724
2725   /* if we need assign a result value */
2726   if ((IS_ITEMP (IC_RESULT (ic)) &&
2727        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2728         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2729       IS_TRUE_SYMOP (IC_RESULT (ic)))
2730     {
2731
2732       _G.accInUse++;
2733       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2734       _G.accInUse--;
2735
2736       assignResultValue (IC_RESULT (ic));
2737
2738       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2739     }
2740
2741   /* adjust the stack for parameters if
2742      required */
2743   if (ic->parmBytes)
2744     {
2745       int i;
2746       if (options.stack10bit) {
2747           if (ic->parmBytes <= 10) {
2748               emitcode(";","stack adjustment for parms");
2749               for (i=0; i < ic->parmBytes ; i++) {
2750                   emitcode("pop","acc");
2751               }
2752           } else {            
2753               PROTECT_SP;
2754               emitcode ("clr","c");
2755               emitcode ("mov","a,sp");
2756               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2757               emitcode ("mov","sp,a");
2758               emitcode ("mov","a,esp");
2759               emitcode ("anl","a,#3");
2760               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2761               emitcode ("mov","esp,a");   
2762               UNPROTECT_SP;
2763           }
2764       } else {
2765           if (ic->parmBytes > 3) {
2766               emitcode ("mov", "a,%s", spname);
2767               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2768               emitcode ("mov", "%s,a", spname);
2769           }
2770           else
2771               for (i = 0; i < ic->parmBytes; i++)
2772                   emitcode ("dec", "%s", spname);
2773           
2774       }
2775     }
2776   /* if register bank was saved then unsave them */
2777   if (restoreBank)
2778     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2779   
2780   /* if we hade saved some registers then
2781      unsave them */
2782   if (ic->regsSaved)
2783     unsaveRegisters (ic);
2784
2785 }
2786
2787 /*-----------------------------------------------------------------*/
2788 /* resultRemat - result  is rematerializable                       */
2789 /*-----------------------------------------------------------------*/
2790 static int
2791 resultRemat (iCode * ic)
2792 {
2793   if (SKIP_IC (ic) || ic->op == IFX)
2794     return 0;
2795
2796   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2797     {
2798       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2799       if (sym->remat && !POINTER_SET (ic))
2800         return 1;
2801     }
2802
2803   return 0;
2804 }
2805
2806 #if defined(__BORLANDC__) || defined(_MSC_VER)
2807 #define STRCASECMP stricmp
2808 #else
2809 #define STRCASECMP strcasecmp
2810 #endif
2811
2812 /*-----------------------------------------------------------------*/
2813 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2814 /*-----------------------------------------------------------------*/
2815 static bool
2816 inExcludeList (char *s)
2817 {
2818   int i = 0;
2819
2820   if (options.excludeRegs[i] &&
2821       STRCASECMP (options.excludeRegs[i], "none") == 0)
2822     return FALSE;
2823
2824   for (i = 0; options.excludeRegs[i]; i++)
2825     {
2826       if (options.excludeRegs[i] &&
2827           STRCASECMP (s, options.excludeRegs[i]) == 0)
2828         return TRUE;
2829     }
2830   return FALSE;
2831 }
2832
2833 /*-----------------------------------------------------------------*/
2834 /* genFunction - generated code for function entry                 */
2835 /*-----------------------------------------------------------------*/
2836 static void
2837 genFunction (iCode * ic)
2838 {
2839   symbol *sym;
2840   sym_link *ftype;
2841   bool   switchedPSW = FALSE;
2842
2843   D (emitcode (";", "genFunction "););
2844
2845   _G.nRegsSaved = 0;
2846   /* create the function header */
2847   emitcode (";", "-----------------------------------------");
2848   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2849   emitcode (";", "-----------------------------------------");
2850
2851   emitcode ("", "%s:", sym->rname);
2852   ftype = operandType (IC_LEFT (ic));
2853
2854   if (IFFUNC_ISNAKED(ftype))
2855   {
2856       emitcode(";", "naked function: no prologue.");
2857       return;
2858   }
2859   
2860   if (options.stack_probe) 
2861       emitcode ("lcall","__stack_probe");
2862   /* if critical function then turn interrupts off */
2863   if (IFFUNC_ISCRITICAL (ftype))
2864     emitcode ("clr", "ea");
2865
2866   /* here we need to generate the equates for the
2867      register bank if required */
2868   if (FUNC_REGBANK (ftype) != rbank)
2869     {
2870       int i;
2871
2872       rbank = FUNC_REGBANK (ftype);
2873       for (i = 0; i < ds390_nRegs; i++)
2874         {
2875           if (regs390[i].print) {
2876               if (strcmp (regs390[i].base, "0") == 0)
2877                   emitcode ("", "%s !equ !constbyte",
2878                             regs390[i].dname,
2879                             8 * rbank + regs390[i].offset);
2880               else
2881                   emitcode ("", "%s !equ %s + !constbyte",
2882                             regs390[i].dname,
2883                             regs390[i].base,
2884                             8 * rbank + regs390[i].offset);
2885           }
2886         }
2887     }
2888
2889   /* if this is an interrupt service routine then
2890      save acc, b, dpl, dph  */
2891   if (IFFUNC_ISISR (sym->type))
2892       { /* is ISR */
2893       if (!inExcludeList ("acc"))
2894         emitcode ("push", "acc");
2895       if (!inExcludeList ("b"))
2896         emitcode ("push", "b");
2897       if (!inExcludeList ("dpl"))
2898         emitcode ("push", "dpl");
2899       if (!inExcludeList ("dph"))
2900         emitcode ("push", "dph");
2901       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2902         {
2903           emitcode ("push", "dpx");
2904           /* Make sure we're using standard DPTR */
2905           emitcode ("push", "dps");
2906           emitcode ("mov", "dps,#0");
2907           if (options.stack10bit)
2908             {
2909               /* This ISR could conceivably use DPTR2. Better save it. */
2910               emitcode ("push", "dpl1");
2911               emitcode ("push", "dph1");
2912               emitcode ("push", "dpx1");
2913               emitcode ("push",  DP2_RESULT_REG);
2914             }
2915         }
2916       /* if this isr has no bank i.e. is going to
2917          run with bank 0 , then we need to save more
2918          registers :-) */
2919       if (!FUNC_REGBANK (sym->type))
2920         {
2921             int i;
2922
2923           /* if this function does not call any other
2924              function then we can be economical and
2925              save only those registers that are used */
2926           if (!IFFUNC_HASFCALL(sym->type))
2927             {
2928
2929               /* if any registers used */
2930               if (sym->regsUsed)
2931                 {
2932                   /* save the registers used */
2933                   for (i = 0; i < sym->regsUsed->size; i++)
2934                     {
2935                       if (bitVectBitValue (sym->regsUsed, i) ||
2936                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2937                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2938                     }
2939                 }
2940
2941             }
2942           else
2943             {
2944               /* this function has  a function call cannot
2945                  determines register usage so we will have to push the
2946                  entire bank */
2947               saveRBank (0, ic, FALSE);
2948               if (options.parms_in_bank1) {
2949                   for (i=0; i < 8 ; i++ ) {
2950                       emitcode ("push","%s",rb1regs[i]);
2951                   }
2952               }
2953             }
2954         }
2955         else
2956         {
2957             /* This ISR uses a non-zero bank.
2958              *
2959              * We assume that the bank is available for our
2960              * exclusive use.
2961              *
2962              * However, if this ISR calls a function which uses some
2963              * other bank, we must save that bank entirely.
2964              */
2965             unsigned long banksToSave = 0;
2966             
2967             if (IFFUNC_HASFCALL(sym->type))
2968             {
2969
2970 #define MAX_REGISTER_BANKS 4
2971
2972                 iCode *i;
2973                 int ix;
2974
2975                 for (i = ic; i; i = i->next)
2976                 {
2977                     if (i->op == ENDFUNCTION)
2978                     {
2979                         /* we got to the end OK. */
2980                         break;
2981                     }
2982                     
2983                     if (i->op == CALL)
2984                     {
2985                         sym_link *dtype;
2986                         
2987                         dtype = operandType (IC_LEFT(i));
2988                         if (dtype 
2989                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2990                         {
2991                              /* Mark this bank for saving. */
2992                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2993                              {
2994                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2995                              }
2996                              else
2997                              {
2998                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2999                              }
3000                              
3001                              /* And note that we don't need to do it in 
3002                               * genCall.
3003                               */
3004                              i->bankSaved = 1;
3005                         }
3006                     }
3007                     if (i->op == PCALL)
3008                     {
3009                         /* This is a mess; we have no idea what
3010                          * register bank the called function might
3011                          * use.
3012                          *
3013                          * The only thing I can think of to do is
3014                          * throw a warning and hope.
3015                          */
3016                         werror(W_FUNCPTR_IN_USING_ISR);   
3017                     }
3018                 }
3019
3020                 if (banksToSave && options.useXstack)
3021                 {
3022                     /* Since we aren't passing it an ic, 
3023                      * saveRBank will assume r0 is available to abuse.
3024                      *
3025                      * So switch to our (trashable) bank now, so
3026                      * the caller's R0 isn't trashed.
3027                      */
3028                     emitcode ("push", "psw");
3029                     emitcode ("mov", "psw,#!constbyte", 
3030                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3031                     switchedPSW = TRUE;
3032                 }
3033                 
3034                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3035                 {
3036                      if (banksToSave & (1 << ix))
3037                      {
3038                          saveRBank(ix, NULL, FALSE);
3039                      }
3040                 }
3041             }
3042             // jwk: this needs a closer look
3043             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3044         }
3045     }
3046   else
3047     {
3048       /* if callee-save to be used for this function
3049          then save the registers being used in this function */
3050       if (IFFUNC_CALLEESAVES(sym->type))
3051         {
3052           int i;
3053
3054           /* if any registers used */
3055           if (sym->regsUsed)
3056             {
3057               /* save the registers used */
3058               for (i = 0; i < sym->regsUsed->size; i++)
3059                 {
3060                   if (bitVectBitValue (sym->regsUsed, i) ||
3061                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3062                     {
3063                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3064                       _G.nRegsSaved++;
3065                     }
3066                 }
3067             }
3068         }
3069     }
3070
3071   /* set the register bank to the desired value */
3072   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3073    && !switchedPSW)
3074     {
3075       emitcode ("push", "psw");
3076       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3077     }
3078
3079   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3080        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3081       if (options.stack10bit) {
3082           emitcode ("push","_bpx");
3083           emitcode ("push","_bpx+1");
3084           emitcode ("mov","_bpx,%s",spname);
3085           emitcode ("mov","_bpx+1,esp");
3086           emitcode ("anl","_bpx+1,#3");
3087       } else {
3088           if (options.useXstack) {
3089               emitcode ("mov", "r0,%s", spname);
3090               emitcode ("mov", "a,_bp");
3091               emitcode ("movx", "@r0,a");
3092               emitcode ("inc", "%s", spname);
3093           } else {
3094               /* set up the stack */
3095               emitcode ("push", "_bp"); /* save the callers stack  */
3096           }
3097           emitcode ("mov", "_bp,%s", spname);
3098       }
3099   }
3100
3101   /* adjust the stack for the function */
3102   if (sym->stack) {
3103       int i = sym->stack;
3104       if (options.stack10bit) {
3105           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3106           assert (sym->recvSize <= 4);
3107           if (sym->stack <= 8) {
3108               while (i--) emitcode ("push","acc");
3109           } else {
3110               PROTECT_SP;
3111               emitcode ("mov","a,sp");
3112               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3113               emitcode ("mov","sp,a");
3114               emitcode ("mov","a,esp");
3115               emitcode ("anl","a,#3");
3116               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3117               emitcode ("mov","esp,a");
3118               UNPROTECT_SP;
3119           }
3120       } else {
3121           if (i > 256)
3122               werror (W_STACK_OVERFLOW, sym->name);
3123           
3124           if (i > 3 && sym->recvSize < 4) {
3125               
3126               emitcode ("mov", "a,sp");
3127               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3128               emitcode ("mov", "sp,a");
3129               
3130           } else
3131               while (i--)
3132                   emitcode ("inc", "sp");
3133       }
3134   }
3135
3136   if (sym->xstack)
3137     {
3138
3139       emitcode ("mov", "a,_spx");
3140       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3141       emitcode ("mov", "_spx,a");
3142     }
3143
3144 }
3145
3146 /*-----------------------------------------------------------------*/
3147 /* genEndFunction - generates epilogue for functions               */
3148 /*-----------------------------------------------------------------*/
3149 static void
3150 genEndFunction (iCode * ic)
3151 {
3152   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3153
3154   D (emitcode (";", "genEndFunction "););
3155
3156   if (IFFUNC_ISNAKED(sym->type))
3157   {
3158       emitcode(";", "naked function: no epilogue.");
3159       return;
3160   }
3161
3162   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3163        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3164
3165       if (options.stack10bit) {
3166           PROTECT_SP;     
3167           emitcode ("mov", "sp,_bpx", spname);
3168           emitcode ("mov", "esp,_bpx+1", spname);
3169           UNPROTECT_SP;
3170       } else {
3171           emitcode ("mov", "%s,_bp", spname);
3172       }
3173   }
3174
3175   /* if use external stack but some variables were
3176      added to the local stack then decrement the
3177      local stack */
3178   if (options.useXstack && sym->stack) {
3179       emitcode ("mov", "a,sp");
3180       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3181       emitcode ("mov", "sp,a");
3182   }
3183
3184
3185   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3186        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3187
3188       if (options.useXstack) {
3189           emitcode ("mov", "r0,%s", spname);
3190           emitcode ("movx", "a,@r0");
3191           emitcode ("mov", "_bp,a");
3192           emitcode ("dec", "%s", spname);
3193       } else {
3194           if (options.stack10bit) {
3195               emitcode ("pop", "_bpx+1");
3196               emitcode ("pop", "_bpx");
3197           } else {
3198               emitcode ("pop", "_bp");
3199           }
3200       }
3201   }
3202
3203   /* restore the register bank  */
3204   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3205   {
3206     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3207      || !options.useXstack)
3208     {
3209         /* Special case of ISR using non-zero bank with useXstack
3210          * is handled below.
3211          */
3212         emitcode ("pop", "psw");
3213     }
3214   } 
3215
3216   if (IFFUNC_ISISR (sym->type))
3217       { /* is ISR */  
3218
3219       /* now we need to restore the registers */
3220       /* if this isr has no bank i.e. is going to
3221          run with bank 0 , then we need to save more
3222          registers :-) */
3223       if (!FUNC_REGBANK (sym->type))
3224         {
3225             int i;
3226           /* if this function does not call any other
3227              function then we can be economical and
3228              save only those registers that are used */
3229           if (!IFFUNC_HASFCALL(sym->type))
3230             {
3231
3232               /* if any registers used */
3233               if (sym->regsUsed)
3234                 {
3235                   /* save the registers used */
3236                   for (i = sym->regsUsed->size; i >= 0; i--)
3237                     {
3238                       if (bitVectBitValue (sym->regsUsed, i) ||
3239                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3240                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3241                     }
3242                 }
3243
3244             }
3245           else
3246             {
3247               /* this function has  a function call cannot
3248                  determines register usage so we will have to pop the
3249                  entire bank */
3250               if (options.parms_in_bank1) {
3251                   for (i = 7 ; i >= 0 ; i-- ) {
3252                       emitcode ("pop","%s",rb1regs[i]);
3253                   }
3254               }
3255               unsaveRBank (0, ic, FALSE);
3256             }
3257         }
3258         else
3259         {
3260             /* This ISR uses a non-zero bank.
3261              *
3262              * Restore any register banks saved by genFunction
3263              * in reverse order.
3264              */
3265           // jwk: this needs a closer look
3266             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3267             int ix;
3268           
3269             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3270             {
3271                 if (savedBanks & (1 << ix))
3272                 {
3273                     unsaveRBank(ix, NULL, FALSE);
3274                 }
3275             }
3276             
3277             if (options.useXstack)
3278             {
3279                 /* Restore bank AFTER calling unsaveRBank,
3280                  * since it can trash r0.
3281                  */
3282                 emitcode ("pop", "psw");
3283             }
3284         }
3285
3286       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3287         {
3288           if (options.stack10bit)
3289             {
3290               emitcode ("pop", DP2_RESULT_REG);
3291               emitcode ("pop", "dpx1");
3292               emitcode ("pop", "dph1");
3293               emitcode ("pop", "dpl1");
3294             }
3295           emitcode ("pop", "dps");
3296           emitcode ("pop", "dpx");
3297         }
3298       if (!inExcludeList ("dph"))
3299         emitcode ("pop", "dph");
3300       if (!inExcludeList ("dpl"))
3301         emitcode ("pop", "dpl");
3302       if (!inExcludeList ("b"))
3303         emitcode ("pop", "b");
3304       if (!inExcludeList ("acc"))
3305         emitcode ("pop", "acc");
3306
3307       if (IFFUNC_ISCRITICAL (sym->type))
3308         emitcode ("setb", "ea");
3309
3310       /* if debug then send end of function */
3311       if (options.debug && currFunc) {
3312           _G.debugLine = 1;
3313           emitcode ("", "C$%s$%d$%d$%d ==.",
3314                     FileBaseName (ic->filename), currFunc->lastLine,
3315                     ic->level, ic->block);
3316           if (IS_STATIC (currFunc->etype))
3317             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3318           else
3319             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3320           _G.debugLine = 0;
3321         }
3322
3323       emitcode ("reti", "");
3324     }
3325   else
3326     {
3327       if (IFFUNC_ISCRITICAL (sym->type))
3328         emitcode ("setb", "ea");
3329
3330       if (IFFUNC_CALLEESAVES(sym->type))
3331         {
3332           int i;
3333
3334           /* if any registers used */
3335           if (sym->regsUsed)
3336             {
3337               /* save the registers used */
3338               for (i = sym->regsUsed->size; i >= 0; i--)
3339                 {
3340                   if (bitVectBitValue (sym->regsUsed, i) ||
3341                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3342                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3343                 }
3344             }
3345
3346         }
3347
3348       /* if debug then send end of function */
3349       if (options.debug && currFunc)
3350         {
3351           _G.debugLine = 1;
3352           emitcode ("", "C$%s$%d$%d$%d ==.",
3353                     FileBaseName (ic->filename), currFunc->lastLine,
3354                     ic->level, ic->block);
3355           if (IS_STATIC (currFunc->etype))
3356             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3357           else
3358             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3359           _G.debugLine = 0;
3360         }
3361
3362       emitcode ("ret", "");
3363     }
3364
3365 }
3366
3367 /*-----------------------------------------------------------------*/
3368 /* genJavaNativeRet - generate code for return JavaNative          */
3369 /*-----------------------------------------------------------------*/
3370 static void genJavaNativeRet(iCode *ic)
3371 {
3372     int i, size;
3373
3374     aopOp (IC_LEFT (ic), ic, FALSE, 
3375            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3376     size = AOP_SIZE (IC_LEFT (ic));
3377
3378     assert (size <= 4);
3379
3380     /* it is assigned to GPR0-R3 then push them */
3381     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3382         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3383         for (i = 0 ; i < size ; i++ ) {
3384             emitcode ("push","%s",
3385                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3386         }
3387         for (i = (size-1) ; i >= 0 ; i--) {
3388             emitcode ("pop","a%s",javaRet[i]);
3389         }
3390     } else {
3391         for (i = 0 ; i < size ; i++) 
3392             emitcode ("mov","%s,%s",javaRet[i],
3393                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3394     }
3395     for (i = size ; i < 4 ; i++ )
3396             emitcode ("mov","%s,#0",javaRet[i]);
3397     return;
3398 }
3399
3400 /*-----------------------------------------------------------------*/
3401 /* genRet - generate code for return statement                     */
3402 /*-----------------------------------------------------------------*/
3403 static void
3404 genRet (iCode * ic)
3405 {
3406   int size, offset = 0, pushed = 0;
3407
3408   D (emitcode (";", "genRet "););
3409
3410   /* if we have no return value then
3411      just generate the "ret" */
3412   if (!IC_LEFT (ic))
3413     goto jumpret;
3414
3415   /* if this is a JavaNative function then return 
3416      value in different register */
3417   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3418       genJavaNativeRet(ic);
3419       goto jumpret;
3420   }
3421   /* we have something to return then
3422      move the return value into place */
3423   aopOp (IC_LEFT (ic), ic, FALSE, 
3424          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3425   size = AOP_SIZE (IC_LEFT (ic));
3426
3427   _startLazyDPSEvaluation ();
3428   while (size--)
3429     {
3430       char *l;
3431       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3432         {
3433           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3434                       FALSE, TRUE, NULL);
3435           emitcode ("push", "%s", l);
3436           pushed++;
3437         }
3438       else
3439         {
3440           /* Since A is the last element of fReturn,
3441            * is is OK to clobber it in the aopGet.
3442            */
3443           l = aopGet (AOP (IC_LEFT (ic)), offset,
3444                       FALSE, FALSE, NULL);
3445           if (strcmp (fReturn[offset], l))
3446             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3447         }
3448     }
3449   _endLazyDPSEvaluation ();
3450
3451   if (pushed)
3452     {
3453       while (pushed)
3454         {
3455           pushed--;
3456           if (strcmp (fReturn[pushed], "a"))
3457             emitcode ("pop", fReturn[pushed]);
3458           else
3459             emitcode ("pop", "acc");
3460         }
3461     }
3462   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3463
3464 jumpret:
3465   /* generate a jump to the return label
3466      if the next is not the return statement */
3467   if (!(ic->next && ic->next->op == LABEL &&
3468         IC_LABEL (ic->next) == returnLabel))
3469
3470     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3471
3472 }
3473
3474 /*-----------------------------------------------------------------*/
3475 /* genLabel - generates a label                                    */
3476 /*-----------------------------------------------------------------*/
3477 static void
3478 genLabel (iCode * ic)
3479 {
3480   /* special case never generate */
3481   if (IC_LABEL (ic) == entryLabel)
3482     return;
3483
3484   D (emitcode (";", "genLabel ");
3485     );
3486
3487   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3488 }
3489
3490 /*-----------------------------------------------------------------*/
3491 /* genGoto - generates a ljmp                                      */
3492 /*-----------------------------------------------------------------*/
3493 static void
3494 genGoto (iCode * ic)
3495 {
3496   D (emitcode (";", "genGoto ");
3497     );
3498   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* findLabelBackwards: walks back through the iCode chain looking  */
3503 /* for the given label. Returns number of iCode instructions     */
3504 /* between that label and given ic.          */
3505 /* Returns zero if label not found.          */
3506 /*-----------------------------------------------------------------*/
3507 static int
3508 findLabelBackwards (iCode * ic, int key)
3509 {
3510   int count = 0;
3511
3512   while (ic->prev)
3513     {
3514       ic = ic->prev;
3515       count++;
3516
3517       /* If we have any pushes or pops, we cannot predict the distance.
3518          I don't like this at all, this should be dealt with in the 
3519          back-end */
3520       if (ic->op == IPUSH || ic->op == IPOP) {
3521         return 0;
3522       }
3523
3524       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3525         {
3526           /* printf("findLabelBackwards = %d\n", count); */
3527           return count;
3528         }
3529     }
3530
3531   return 0;
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genPlusIncr :- does addition with increment if possible         */
3536 /*-----------------------------------------------------------------*/
3537 static bool
3538 genPlusIncr (iCode * ic)
3539 {
3540   unsigned int icount;
3541   unsigned int size = getDataSize (IC_RESULT (ic));
3542
3543   /* will try to generate an increment */
3544   /* if the right side is not a literal
3545      we cannot */
3546   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3547     return FALSE;
3548
3549   /* if the literal value of the right hand side
3550      is greater than 4 then it is not worth it */
3551   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3552     return FALSE;
3553
3554   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3555       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3556       while (icount--) {
3557           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3558       }
3559       return TRUE;
3560   }
3561   /* if increment 16 bits in register */
3562   if (
3563        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3564        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3565        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3566        (size > 1) &&
3567        (icount == 1))
3568     {
3569       symbol  *tlbl;
3570       int     emitTlbl;
3571       int     labelRange;
3572       char    *l;
3573
3574       /* If the next instruction is a goto and the goto target
3575        * is <= 5 instructions previous to this, we can generate
3576        * jumps straight to that target.
3577        */
3578       if (ic->next && ic->next->op == GOTO
3579           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3580           && labelRange <= 5)
3581         {
3582           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3583           tlbl = IC_LABEL (ic->next);
3584           emitTlbl = 0;
3585         }
3586       else
3587         {
3588           tlbl = newiTempLabel (NULL);
3589           emitTlbl = 1;
3590         }
3591         
3592       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3593       emitcode ("inc", "%s", l);
3594       
3595       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3596           IS_AOP_PREG (IC_RESULT (ic)))
3597       {   
3598         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3599       }
3600       else
3601       {
3602           emitcode ("clr", "a");
3603           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3604       }
3605
3606       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3607       emitcode ("inc", "%s", l);
3608       if (size > 2)
3609         {
3610             if (!strcmp(l, "acc"))
3611             {
3612                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3613             }
3614             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615                      IS_AOP_PREG (IC_RESULT (ic)))
3616             {
3617                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3618             }
3619             else
3620             {
3621                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3622             }
3623
3624             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3625             emitcode ("inc", "%s", l);
3626         }
3627       if (size > 3)
3628         {
3629             if (!strcmp(l, "acc"))
3630             {
3631                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3632             }
3633             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634                      IS_AOP_PREG (IC_RESULT (ic)))
3635             {
3636                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3637             }
3638             else
3639             {
3640                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3641             }
3642
3643             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3644             emitcode ("inc", "%s", l);  }
3645
3646       if (emitTlbl)
3647         {
3648           emitcode ("", "!tlabeldef", tlbl->key + 100);
3649         }
3650       return TRUE;
3651     }
3652
3653   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3654       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3655       options.model == MODEL_FLAT24 ) {
3656
3657       switch (size) {
3658       case 3:
3659           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3660       case 2:
3661           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3662       case 1:
3663           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3664           break;
3665       }
3666       while (icount--) emitcode ("inc","dptr");      
3667       return TRUE;
3668   }
3669
3670   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3671       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3672       icount <= 5 ) {
3673       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3674       while (icount--) emitcode ("inc","dptr");
3675       emitcode ("mov","dps,#0");
3676       return TRUE;
3677   }
3678
3679   /* if the sizes are greater than 1 then we cannot */
3680   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3681       AOP_SIZE (IC_LEFT (ic)) > 1)
3682     return FALSE;
3683
3684   /* we can if the aops of the left & result match or
3685      if they are in registers and the registers are the
3686      same */
3687   if (
3688        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3689        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3690        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3691     {
3692
3693       if (icount > 3)
3694         {
3695           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3696           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3697           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3698         }
3699       else
3700         {
3701
3702           _startLazyDPSEvaluation ();
3703           while (icount--)
3704             {
3705               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3706             }
3707           _endLazyDPSEvaluation ();
3708         }
3709
3710       return TRUE;
3711     }
3712
3713   return FALSE;
3714 }
3715
3716 /*-----------------------------------------------------------------*/
3717 /* outBitAcc - output a bit in acc                                 */
3718 /*-----------------------------------------------------------------*/
3719 static void
3720 outBitAcc (operand * result)
3721 {
3722   symbol *tlbl = newiTempLabel (NULL);
3723   /* if the result is a bit */
3724   if (AOP_TYPE (result) == AOP_CRY)
3725     {
3726       aopPut (AOP (result), "a", 0);
3727     }
3728   else
3729     {
3730       emitcode ("jz", "!tlabel", tlbl->key + 100);
3731       emitcode ("mov", "a,%s", one);
3732       emitcode ("", "!tlabeldef", tlbl->key + 100);
3733       outAcc (result);
3734     }
3735 }
3736
3737 /*-----------------------------------------------------------------*/
3738 /* genPlusBits - generates code for addition of two bits           */
3739 /*-----------------------------------------------------------------*/
3740 static void
3741 genPlusBits (iCode * ic)
3742 {
3743   D (emitcode (";", "genPlusBits "););
3744     
3745   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3746     {
3747       symbol *lbl = newiTempLabel (NULL);
3748       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3749       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3750       emitcode ("cpl", "c");
3751       emitcode ("", "!tlabeldef", (lbl->key + 100));
3752       outBitC (IC_RESULT (ic));
3753     }
3754   else
3755     {
3756       emitcode ("clr", "a");
3757       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3758       emitcode ("rlc", "a");
3759       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3760       emitcode ("addc", "a,#0");
3761       outAcc (IC_RESULT (ic));
3762     }
3763 }
3764
3765 static void
3766 adjustArithmeticResult (iCode * ic)
3767 {
3768   if (opIsGptr (IC_RESULT (ic)) &&
3769       opIsGptr (IC_LEFT (ic)) &&
3770       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3771     {
3772       aopPut (AOP (IC_RESULT (ic)),
3773               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3774               GPTRSIZE - 1);
3775     }
3776
3777   if (opIsGptr (IC_RESULT (ic)) &&
3778       opIsGptr (IC_RIGHT (ic)) &&
3779       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3780     {
3781       aopPut (AOP (IC_RESULT (ic)),
3782             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3783               GPTRSIZE - 1);
3784     }
3785
3786   if (opIsGptr (IC_RESULT (ic)) &&
3787       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3788       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3789       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3790       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3791     {
3792       char buff[5];
3793       SNPRINTF (buff, sizeof(buff), 
3794                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3795       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3796     }
3797 }
3798
3799 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3800 // generates the result if possible. If result is generated, returns TRUE; otherwise
3801 // returns false and caller must deal with fact that result isn't aopOp'd.
3802 bool aopOp3(iCode * ic)
3803 {
3804     bool dp1InUse, dp2InUse;
3805     bool useDp2;
3806     
3807     // First, generate the right opcode. DPTR may be used if neither left nor result are
3808     // of type AOP_STR.
3809     
3810 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3811 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3812 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3813 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3814 //      );
3815 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3816 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3817 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3818 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3819 //      );      
3820
3821     
3822     // Right uses DPTR unless left or result is an AOP_STR.
3823     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3824     
3825     // if the right used DPTR, left MUST use DPTR2.
3826     // if the right used DPTR2, left MUST use DPTR.
3827     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3828     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3829     // enabling us to assign DPTR to result.
3830      
3831     if (AOP_USESDPTR(IC_RIGHT(ic)))
3832     {
3833         useDp2 = TRUE;
3834     }
3835     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3836     {
3837         useDp2 = FALSE;
3838     }
3839     else
3840     {
3841         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3842         {
3843             useDp2 = TRUE;
3844         }
3845         else
3846         {
3847             useDp2 = FALSE;
3848         }
3849     }
3850
3851     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3852     
3853     // We've op'd the left & right. So, if left or right are the same operand as result, 
3854     // we know aopOp will succeed, and we can just do it & bail.
3855     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3856         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3857     {
3858 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3859         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3860         return TRUE;
3861     }
3862     
3863     // Note which dptrs are currently in use.
3864     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3865     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3866     
3867     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3868     // generate it.
3869     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3870     {
3871         return FALSE;
3872     }
3873     
3874     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3875     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3876     {
3877         return FALSE;
3878     }
3879     
3880     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3881     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3882     {
3883         return FALSE;
3884     }
3885
3886     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3887
3888     // Some sanity checking...
3889     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3890     {
3891         fprintf(stderr,
3892                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3893                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3894         emitcode(";", ">>> unexpected DPTR here.");
3895     }
3896     
3897     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3898     {
3899         fprintf(stderr,
3900                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3901                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3902         emitcode(";", ">>> unexpected DPTR2 here.");
3903     }    
3904     
3905     return TRUE;
3906 }
3907
3908 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3909 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3910 // will be set TRUE. The caller must then handle the case specially, noting
3911 // that the IC_RESULT operand is not aopOp'd.
3912 // 
3913 #define AOP_OP_3_NOFATAL(ic, rc) \
3914             do { rc = !aopOp3(ic); } while (0)
3915
3916 // aopOp the left & right operands of an ic.
3917 #define AOP_OP_2(ic) \
3918     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3919     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3920
3921 // convienience macro.
3922 #define AOP_SET_LOCALS(ic) \
3923     left = IC_LEFT(ic); \
3924     right = IC_RIGHT(ic); \
3925     result = IC_RESULT(ic);
3926
3927
3928 // Given an integer value of pushedSize bytes on the stack,
3929 // adjust it to be resultSize bytes, either by discarding
3930 // the most significant bytes or by zero-padding.
3931 //
3932 // On exit from this macro, pushedSize will have been adjusted to
3933 // equal resultSize, and ACC may be trashed.
3934 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3935       /* If the pushed data is bigger than the result,          \
3936        * simply discard unused bytes. Icky, but works.          \
3937        */                                                       \
3938       while (pushedSize > resultSize)                           \
3939       {                                                         \
3940           D (emitcode (";", "discarding unused result byte."););\
3941           emitcode ("pop", "acc");                              \
3942           pushedSize--;                                         \
3943       }                                                         \
3944       if (pushedSize < resultSize)                              \
3945       {                                                         \
3946           emitcode ("clr", "a");                                \
3947           /* Conversly, we haven't pushed enough here.          \
3948            * just zero-pad, and all is well.                    \
3949            */                                                   \
3950           while (pushedSize < resultSize)                       \
3951           {                                                     \
3952               emitcode("push", "acc");                          \
3953               pushedSize++;                                     \
3954           }                                                     \
3955       }                                                         \
3956       assert(pushedSize == resultSize);
3957
3958 /*-----------------------------------------------------------------*/
3959 /* genPlus - generates code for addition                           */
3960 /*-----------------------------------------------------------------*/
3961 static void
3962 genPlus (iCode * ic)
3963 {
3964   int size, offset = 0;
3965   bool pushResult;
3966   int rSize;
3967
3968   D (emitcode (";", "genPlus "););
3969
3970   /* special cases :- */
3971   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3972       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3973       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3974       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3975       if (size <= 9) {
3976           while (size--) emitcode ("inc","dptr");
3977       } else {
3978           emitcode ("mov","a,dpl");
3979           emitcode ("add","a,#!constbyte",size & 0xff);
3980           emitcode ("mov","dpl,a");
3981           emitcode ("mov","a,dph");
3982           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3983           emitcode ("mov","dph,a");
3984           emitcode ("mov","a,dpx");
3985           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3986           emitcode ("mov","dpx,a");
3987       }
3988       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3989       return ;
3990   }
3991   if ( IS_SYMOP(IC_LEFT(ic)) && 
3992        OP_SYMBOL(IC_LEFT(ic))->remat &&
3993        isOperandInFarSpace(IC_RIGHT(ic))) {
3994       operand *op = IC_RIGHT(ic);
3995       IC_RIGHT(ic) = IC_LEFT(ic);
3996       IC_LEFT(ic) = op;
3997   }
3998                 
3999   AOP_OP_3_NOFATAL (ic, pushResult);
4000     
4001   if (pushResult)
4002     {
4003       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4004     }
4005
4006   if (!pushResult)
4007     {
4008       /* if literal, literal on the right or
4009          if left requires ACC or right is already
4010          in ACC */
4011       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4012        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4013           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4014         {
4015           operand *t = IC_RIGHT (ic);
4016           IC_RIGHT (ic) = IC_LEFT (ic);
4017           IC_LEFT (ic) = t;
4018           emitcode (";", "Swapped plus args.");
4019         }
4020
4021       /* if both left & right are in bit
4022          space */
4023       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4024           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4025         {
4026           genPlusBits (ic);
4027           goto release;
4028         }
4029
4030       /* if left in bit space & right literal */
4031       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4032           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4033         {
4034           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4035           /* if result in bit space */
4036           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4037             {
4038               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4039                 emitcode ("cpl", "c");
4040               outBitC (IC_RESULT (ic));
4041             }
4042           else
4043             {
4044               size = getDataSize (IC_RESULT (ic));
4045               _startLazyDPSEvaluation ();
4046               while (size--)
4047                 {
4048                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4049                   emitcode ("addc", "a,#0");
4050                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4051                 }
4052               _endLazyDPSEvaluation ();
4053             }
4054           goto release;
4055         }
4056
4057       /* if I can do an increment instead
4058          of add then GOOD for ME */
4059       if (genPlusIncr (ic) == TRUE)
4060         {
4061           emitcode (";", "did genPlusIncr");
4062           goto release;
4063         }
4064
4065     }
4066   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4067
4068   _startLazyDPSEvaluation ();
4069   while (size--)
4070     {
4071       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4072         {
4073           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4074           if (offset == 0)
4075             emitcode ("add", "a,%s",
4076                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4077           else
4078             emitcode ("addc", "a,%s",
4079                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4080         }
4081       else
4082         {
4083           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4084           {
4085               /* right is going to use ACC or we would have taken the
4086                * above branch.
4087                */
4088               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4089        TR_AP("#3");
4090               D(emitcode(";", "+ AOP_ACC special case."););
4091               emitcode("xch", "a, %s", DP2_RESULT_REG);
4092           }
4093           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4094           if (offset == 0)
4095           {
4096             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4097             {
4098          TR_AP("#4");
4099                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4100             }
4101             else
4102             {
4103                 emitcode ("add", "a,%s",
4104                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4105                                   DP2_RESULT_REG));
4106             }
4107           }
4108           else
4109           {
4110             emitcode ("addc", "a,%s",
4111                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4112                           DP2_RESULT_REG));
4113           }
4114         }
4115       if (!pushResult)
4116         {
4117           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4118         }
4119       else
4120         {
4121           emitcode ("push", "acc");
4122         }
4123       offset++;
4124     }
4125   _endLazyDPSEvaluation ();
4126
4127   if (pushResult)
4128     {
4129       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4130
4131       size = getDataSize (IC_LEFT (ic));
4132       rSize = getDataSize (IC_RESULT (ic));
4133
4134       ADJUST_PUSHED_RESULT(size, rSize);
4135
4136       _startLazyDPSEvaluation ();
4137       while (size--)
4138         {
4139           emitcode ("pop", "acc");
4140           aopPut (AOP (IC_RESULT (ic)), "a", size);
4141         }
4142       _endLazyDPSEvaluation ();
4143     }
4144
4145   adjustArithmeticResult (ic);
4146
4147 release:
4148   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4149   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4150   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genMinusDec :- does subtraction with deccrement if possible     */
4155 /*-----------------------------------------------------------------*/
4156 static bool
4157 genMinusDec (iCode * ic)
4158 {
4159   unsigned int icount;
4160   unsigned int size = getDataSize (IC_RESULT (ic));
4161
4162   /* will try to generate an increment */
4163   /* if the right side is not a literal
4164      we cannot */
4165   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4166     return FALSE;
4167
4168   /* if the literal value of the right hand side
4169      is greater than 4 then it is not worth it */
4170   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4171     return FALSE;
4172
4173   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4174       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4175       while (icount--) {
4176           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4177       }
4178       return TRUE;
4179   }
4180   /* if decrement 16 bits in register */
4181   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4182       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4183       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4184       (size > 1) &&
4185       (icount == 1))
4186     {
4187       symbol *tlbl;
4188       int    emitTlbl;
4189       int    labelRange;
4190       char   *l;
4191
4192       /* If the next instruction is a goto and the goto target
4193          * is <= 5 instructions previous to this, we can generate
4194          * jumps straight to that target.
4195        */
4196       if (ic->next && ic->next->op == GOTO
4197           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4198           && labelRange <= 5)
4199         {
4200           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4201           tlbl = IC_LABEL (ic->next);
4202           emitTlbl = 0;
4203         }
4204       else
4205         {
4206           tlbl = newiTempLabel (NULL);
4207           emitTlbl = 1;
4208         }
4209
4210       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4211       emitcode ("dec", "%s", l);
4212  
4213       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4214           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4215           IS_AOP_PREG (IC_RESULT (ic)))
4216       {     
4217           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4218       }
4219       else
4220       {
4221           emitcode ("mov", "a,#!constbyte",0xff);
4222           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4223       }
4224       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4225       emitcode ("dec", "%s", l);
4226       if (size > 2)
4227         {
4228             if (!strcmp(l, "acc"))
4229             {
4230                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4231             }
4232             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4233                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4234                      IS_AOP_PREG (IC_RESULT (ic)))
4235             {       
4236                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4237             }
4238             else
4239             {
4240                 emitcode ("mov", "a,#!constbyte",0xff);
4241                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4242             }
4243             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4244             emitcode ("dec", "%s", l);
4245         }
4246       if (size > 3)
4247         {
4248             if (!strcmp(l, "acc"))
4249             {
4250                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4251             }
4252             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4253                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4254                      IS_AOP_PREG (IC_RESULT (ic)))
4255             {       
4256                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4257             }
4258             else
4259             {
4260                 emitcode ("mov", "a,#!constbyte",0xff);
4261                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4262             }       
4263             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4264             emitcode ("dec", "%s", l);
4265         }
4266       if (emitTlbl)
4267         {
4268           emitcode ("", "!tlabeldef", tlbl->key + 100);
4269         }
4270       return TRUE;
4271     }
4272
4273   /* if the sizes are greater than 1 then we cannot */
4274   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4275       AOP_SIZE (IC_LEFT (ic)) > 1)
4276     return FALSE;
4277
4278   /* we can if the aops of the left & result match or
4279      if they are in registers and the registers are the
4280      same */
4281   if (
4282        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4283        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4284        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4285     {
4286
4287       _startLazyDPSEvaluation ();
4288       while (icount--)
4289         {
4290           emitcode ("dec", "%s",
4291                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4292         }
4293       _endLazyDPSEvaluation ();
4294
4295       return TRUE;
4296     }
4297
4298   return FALSE;
4299 }
4300
4301 /*-----------------------------------------------------------------*/
4302 /* addSign - complete with sign                                    */
4303 /*-----------------------------------------------------------------*/
4304 static void
4305 addSign (operand * result, int offset, int sign)
4306 {
4307   int size = (getDataSize (result) - offset);
4308   if (size > 0)
4309     {
4310       _startLazyDPSEvaluation();
4311       if (sign)
4312         {
4313           emitcode ("rlc", "a");
4314           emitcode ("subb", "a,acc");
4315           while (size--)
4316           {
4317             aopPut (AOP (result), "a", offset++);
4318           }
4319         }
4320       else
4321       {
4322         while (size--)
4323         {
4324           aopPut (AOP (result), zero, offset++);
4325         }
4326       }
4327       _endLazyDPSEvaluation();
4328     }
4329 }
4330
4331 /*-----------------------------------------------------------------*/
4332 /* genMinusBits - generates code for subtraction  of two bits      */
4333 /*-----------------------------------------------------------------*/
4334 static void
4335 genMinusBits (iCode * ic)
4336 {
4337   symbol *lbl = newiTempLabel (NULL);
4338
4339   D (emitcode (";", "genMinusBits "););
4340
4341   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4342     {
4343       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4344       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4345       emitcode ("cpl", "c");
4346       emitcode ("", "!tlabeldef", (lbl->key + 100));
4347       outBitC (IC_RESULT (ic));
4348     }
4349   else
4350     {
4351       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4352       emitcode ("subb", "a,acc");
4353       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4354       emitcode ("inc", "a");
4355       emitcode ("", "!tlabeldef", (lbl->key + 100));
4356       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4357       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4358     }
4359 }
4360
4361 /*-----------------------------------------------------------------*/
4362 /* genMinus - generates code for subtraction                       */
4363 /*-----------------------------------------------------------------*/
4364 static void
4365 genMinus (iCode * ic)
4366 {
4367     int size, offset = 0;
4368     int rSize;
4369     long lit = 0L;
4370     bool pushResult;
4371
4372     D (emitcode (";", "genMinus "););
4373
4374     AOP_OP_3_NOFATAL(ic, pushResult);   
4375
4376     if (!pushResult)
4377     {
4378       /* special cases :- */
4379       /* if both left & right are in bit space */
4380       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4381           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4382         {
4383           genMinusBits (ic);
4384           goto release;
4385         }
4386
4387       /* if I can do an decrement instead
4388          of subtract then GOOD for ME */
4389       if (genMinusDec (ic) == TRUE)
4390         goto release;
4391
4392     }
4393
4394   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4395
4396   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4397     {
4398       CLRC;
4399     }
4400   else
4401     {
4402       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4403       lit = -lit;
4404     }
4405
4406
4407   /* if literal, add a,#-lit, else normal subb */
4408   _startLazyDPSEvaluation ();
4409   while (size--) {
4410       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4411           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4412               emitcode ("mov","b,%s",
4413                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4414               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4415               emitcode ("subb","a,b");
4416           } else {
4417               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4418               emitcode ("subb", "a,%s",
4419                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4420                                 DP2_RESULT_REG));
4421           }
4422       } else {
4423           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4424           /* first add without previous c */
4425           if (!offset) {
4426               if (!size && lit==-1) {
4427                   emitcode ("dec", "a");
4428               } else {
4429                   emitcode ("add", "a,#!constbyte",
4430                             (unsigned int) (lit & 0x0FFL));
4431               }
4432           } else {
4433               emitcode ("addc", "a,#!constbyte",
4434                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4435           }
4436       }
4437       
4438       if (pushResult) {
4439           emitcode ("push", "acc");
4440       } else {
4441           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4442       }
4443       offset++;
4444   }
4445   _endLazyDPSEvaluation ();
4446   
4447   if (pushResult)
4448     {
4449       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4450
4451       size = getDataSize (IC_LEFT (ic));
4452       rSize = getDataSize (IC_RESULT (ic));
4453
4454       ADJUST_PUSHED_RESULT(size, rSize);
4455
4456       _startLazyDPSEvaluation ();
4457       while (size--)
4458         {
4459           emitcode ("pop", "acc");
4460           aopPut (AOP (IC_RESULT (ic)), "a", size);
4461         }
4462       _endLazyDPSEvaluation ();
4463     }
4464
4465   adjustArithmeticResult (ic);
4466
4467 release:
4468   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4469   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4470   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4471 }
4472
4473
4474 /*-----------------------------------------------------------------*/
4475 /* genMultbits :- multiplication of bits                           */
4476 /*-----------------------------------------------------------------*/
4477 static void
4478 genMultbits (operand * left,
4479              operand * right,
4480              operand * result,
4481              iCode   * ic)
4482 {
4483   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4484   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4485   aopOp(result, ic, TRUE, FALSE);
4486   outBitC (result);
4487 }
4488
4489
4490 /*-----------------------------------------------------------------*/
4491 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4492 /*-----------------------------------------------------------------*/
4493 static void
4494 genMultOneByte (operand * left,
4495                 operand * right,
4496                 operand * result,
4497                 iCode   * ic)
4498 {
4499   sym_link *opetype = operandType (result);
4500   symbol *lbl;
4501
4502
4503   /* (if two literals: the value is computed before) */
4504   /* if one literal, literal on the right */
4505   if (AOP_TYPE (left) == AOP_LIT)
4506     {
4507       operand *t = right;
4508       right = left;
4509       left = t;
4510       emitcode (";", "swapped left and right");
4511     }
4512
4513   if (SPEC_USIGN(opetype)
4514       // ignore the sign of left and right, what else can we do?
4515       || (SPEC_USIGN(operandType(left)) && 
4516           SPEC_USIGN(operandType(right)))) {
4517     // just an unsigned 8*8=8/16 multiply
4518     //emitcode (";","unsigned");
4519     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4520     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4521     emitcode ("mul", "ab");
4522    
4523     _G.accInUse++; _G.bInUse++;
4524     aopOp(result, ic, TRUE, FALSE);
4525       
4526       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4527       {
4528           // this should never happen
4529           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4530                    AOP_SIZE(result), __FILE__, lineno);
4531           exit (1);
4532       }      
4533       
4534     aopPut (AOP (result), "a", 0);
4535     _G.accInUse--; _G.bInUse--;
4536     if (AOP_SIZE(result)==2) 
4537     {
4538       aopPut (AOP (result), "b", 1);
4539     }
4540     return;
4541   }
4542
4543   // we have to do a signed multiply
4544
4545   emitcode (";", "signed");
4546   emitcode ("clr", "F0"); // reset sign flag
4547   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4548
4549   lbl=newiTempLabel(NULL);
4550   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4551   // left side is negative, 8-bit two's complement, this fails for -128
4552   emitcode ("setb", "F0"); // set sign flag
4553   emitcode ("cpl", "a");
4554   emitcode ("inc", "a");
4555
4556   emitcode ("", "!tlabeldef", lbl->key+100);
4557
4558   /* if literal */
4559   if (AOP_TYPE(right)==AOP_LIT) {
4560     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4561     /* AND literal negative */
4562     if ((int) val < 0) {
4563       emitcode ("cpl", "F0"); // complement sign flag
4564       emitcode ("mov", "b,#!constbyte", -val);
4565     } else {
4566       emitcode ("mov", "b,#!constbyte", val);
4567     }
4568   } else {
4569     lbl=newiTempLabel(NULL);
4570     emitcode ("mov", "b,a");
4571     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4572     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4573     // right side is negative, 8-bit two's complement
4574     emitcode ("cpl", "F0"); // complement sign flag
4575     emitcode ("cpl", "a");
4576     emitcode ("inc", "a");
4577     emitcode ("", "!tlabeldef", lbl->key+100);
4578   }
4579   emitcode ("mul", "ab");
4580     
4581   _G.accInUse++;_G.bInUse++;
4582   aopOp(result, ic, TRUE, FALSE);
4583     
4584   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4585   {
4586     // this should never happen
4587       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4588                AOP_SIZE(result), __FILE__, lineno);
4589       exit (1);
4590   }    
4591     
4592   lbl=newiTempLabel(NULL);
4593   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4594   // only ONE op was negative, we have to do a 8/16-bit two's complement
4595   emitcode ("cpl", "a"); // lsb
4596   if (AOP_SIZE(result)==1) {
4597     emitcode ("inc", "a");
4598   } else {
4599     emitcode ("add", "a,#1");
4600     emitcode ("xch", "a,b");
4601     emitcode ("cpl", "a"); // msb
4602     emitcode ("addc", "a,#0");
4603     emitcode ("xch", "a,b");
4604   }
4605
4606   emitcode ("", "!tlabeldef", lbl->key+100);
4607   aopPut (AOP (result), "a", 0);
4608   _G.accInUse--;_G.bInUse--;
4609   if (AOP_SIZE(result)==2) {
4610     aopPut (AOP (result), "b", 1);
4611   }
4612 }
4613
4614 /*-----------------------------------------------------------------*/
4615 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4616 /*-----------------------------------------------------------------*/
4617 static void genMultTwoByte (operand *left, operand *right, 
4618                             operand *result, iCode *ic)
4619 {
4620         sym_link *retype = getSpec(operandType(right));
4621         sym_link *letype = getSpec(operandType(left));
4622         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4623         symbol *lbl;
4624
4625         if (AOP_TYPE (left) == AOP_LIT) {
4626                 operand *t = right;
4627                 right = left;
4628                 left = t;
4629         }
4630         /* save EA bit in F1 */
4631         lbl = newiTempLabel(NULL);
4632         emitcode ("setb","F1");
4633         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4634         emitcode ("clr","F1");
4635         emitcode("","!tlabeldef",lbl->key+100);
4636
4637         /* load up MB with right */
4638         if (!umult) {
4639                 emitcode("clr","F0");
4640                 if (AOP_TYPE(right) == AOP_LIT) {
4641                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4642                         if (val < 0) {
4643                                 emitcode("setb","F0");
4644                                 val = -val;
4645                         }
4646                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4647                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4648                 } else {
4649                         lbl = newiTempLabel(NULL);
4650                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4651                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4652                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4653                         emitcode ("xch", "a,b");
4654                         emitcode ("cpl","a");
4655                         emitcode ("add", "a,#1");
4656                         emitcode ("xch", "a,b");
4657                         emitcode ("cpl", "a"); // msb
4658                         emitcode ("addc", "a,#0");
4659                         emitcode ("setb","F0");
4660                         emitcode ("","!tlabeldef",lbl->key+100);
4661                         emitcode ("mov","mb,b");
4662                         emitcode ("mov","mb,a");
4663                 }
4664         } else {
4665                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4666                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4667         }
4668         /* load up MA with left */
4669         if (!umult) {
4670                 lbl = newiTempLabel(NULL);
4671                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4672                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4673                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4674                 emitcode ("xch", "a,b");
4675                 emitcode ("cpl","a");
4676                 emitcode ("add", "a,#1");
4677                 emitcode ("xch", "a,b");
4678                 emitcode ("cpl", "a"); // msb
4679                 emitcode ("addc","a,#0");
4680                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4681                 emitcode ("setb","F0");
4682                 emitcode ("","!tlabeldef",lbl->key+100);
4683                 emitcode ("mov","ma,b");
4684                 emitcode ("mov","ma,a");
4685         } else {
4686                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4687                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4688         }
4689         /* wait for multiplication to finish */
4690         lbl = newiTempLabel(NULL);
4691         emitcode("","!tlabeldef", lbl->key+100);
4692         emitcode("mov","a,mcnt1");
4693         emitcode("anl","a,#!constbyte",0x80);
4694         emitcode("jnz","!tlabel",lbl->key+100);
4695         
4696         freeAsmop (left, NULL, ic, TRUE);
4697         freeAsmop (right, NULL, ic,TRUE);
4698         aopOp(result, ic, TRUE, FALSE);
4699
4700         /* if unsigned then simple */   
4701         if (umult) {
4702                 emitcode ("mov","a,ma");
4703                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4704                 emitcode ("mov","a,ma");
4705                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4706                 aopPut(AOP(result),"ma",1);
4707                 aopPut(AOP(result),"ma",0);
4708         } else {
4709                 emitcode("push","ma");
4710                 emitcode("push","ma");
4711                 emitcode("push","ma");
4712                 MOVA("ma");
4713                 /* negate result if needed */
4714                 lbl = newiTempLabel(NULL);      
4715                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716                 emitcode("cpl","a");
4717                 emitcode("add","a,#1");
4718                 emitcode("","!tlabeldef", lbl->key+100);
4719                 if (AOP_TYPE(result) == AOP_ACC)
4720                 {
4721                     D(emitcode(";", "ACC special case."););
4722                     /* We know result is the only live aop, and 
4723                      * it's obviously not a DPTR2, so AP is available.
4724                      */
4725                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4726                 }
4727                 else
4728                 {
4729                     aopPut(AOP(result),"a",0);
4730                 }
4731             
4732                 emitcode("pop","acc");
4733                 lbl = newiTempLabel(NULL);      
4734                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4735                 emitcode("cpl","a");
4736                 emitcode("addc","a,#0");
4737                 emitcode("","!tlabeldef", lbl->key+100);
4738                 aopPut(AOP(result),"a",1);
4739                 emitcode("pop","acc");
4740                 if (AOP_SIZE(result) >= 3) {
4741                         lbl = newiTempLabel(NULL);      
4742                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4743                         emitcode("cpl","a");
4744                         emitcode("addc","a,#0");                        
4745                         emitcode("","!tlabeldef", lbl->key+100);
4746                         aopPut(AOP(result),"a",2);
4747                 }
4748                 emitcode("pop","acc");
4749                 if (AOP_SIZE(result) >= 4) {
4750                         lbl = newiTempLabel(NULL);      
4751                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4752                         emitcode("cpl","a");
4753                         emitcode("addc","a,#0");                        
4754                         emitcode("","!tlabeldef", lbl->key+100);
4755                         aopPut(AOP(result),"a",3);
4756                 }
4757                 if (AOP_TYPE(result) == AOP_ACC)
4758                 {
4759                     /* We stashed the result away above. */
4760                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4761                 }           
4762                 
4763         }
4764         freeAsmop (result, NULL, ic, TRUE);
4765
4766         /* restore EA bit in F1 */
4767         lbl = newiTempLabel(NULL);
4768         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4769         emitcode ("setb","EA");
4770         emitcode("","!tlabeldef",lbl->key+100);
4771         return ;
4772 }
4773
4774 /*-----------------------------------------------------------------*/
4775 /* genMult - generates code for multiplication                     */
4776 /*-----------------------------------------------------------------*/
4777 static void
4778 genMult (iCode * ic)
4779 {
4780   operand *left = IC_LEFT (ic);
4781   operand *right = IC_RIGHT (ic);
4782   operand *result = IC_RESULT (ic);
4783
4784   D (emitcode (";", "genMult "););
4785
4786   /* assign the amsops */
4787   AOP_OP_2 (ic);
4788
4789   /* special cases first */
4790   /* both are bits */
4791   if (AOP_TYPE (left) == AOP_CRY &&
4792       AOP_TYPE (right) == AOP_CRY)
4793     {
4794       genMultbits (left, right, result, ic);
4795       goto release;
4796     }
4797
4798   /* if both are of size == 1 */
4799   if (AOP_SIZE (left) == 1 &&
4800       AOP_SIZE (right) == 1)
4801     {
4802       genMultOneByte (left, right, result, ic);
4803       goto release;
4804     }
4805
4806   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4807           /* use the ds390 ARITHMETIC accel UNIT */
4808           genMultTwoByte (left, right, result, ic);
4809           return ;
4810   }
4811   /* should have been converted to function call */
4812   assert (0);
4813
4814 release:
4815   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817   freeAsmop (result, NULL, ic, TRUE);
4818 }
4819
4820 /*-----------------------------------------------------------------*/
4821 /* genDivbits :- division of bits                                  */
4822 /*-----------------------------------------------------------------*/
4823 static void
4824 genDivbits (operand * left,
4825             operand * right,
4826             operand * result,
4827             iCode   * ic)
4828 {
4829
4830   char *l;
4831
4832   /* the result must be bit */
4833   LOAD_AB_FOR_DIV (left, right, l);
4834   emitcode ("div", "ab");
4835   emitcode ("rrc", "a");
4836   aopOp(result, ic, TRUE, FALSE);
4837     
4838   aopPut (AOP (result), "c", 0);
4839 }
4840
4841 /*-----------------------------------------------------------------*/
4842 /* genDivOneByte : 8 bit division                                  */
4843 /*-----------------------------------------------------------------*/
4844 static void
4845 genDivOneByte (operand * left,
4846                operand * right,
4847                operand * result,
4848                iCode   * ic)
4849 {
4850   sym_link *opetype = operandType (result);
4851   char *l;
4852   symbol *lbl;
4853   int size, offset;
4854
4855   offset = 1;
4856   /* signed or unsigned */
4857   if (SPEC_USIGN (opetype))
4858     {
4859         /* unsigned is easy */
4860         LOAD_AB_FOR_DIV (left, right, l);
4861         emitcode ("div", "ab");
4862
4863         _G.accInUse++;
4864         aopOp(result, ic, TRUE, FALSE);
4865         aopPut (AOP (result), "a", 0);
4866         _G.accInUse--;
4867
4868         size = AOP_SIZE (result) - 1;
4869         
4870         while (size--)
4871         {
4872             aopPut (AOP (result), zero, offset++);
4873         }
4874       return;
4875     }
4876
4877   /* signed is a little bit more difficult */
4878
4879   /* save the signs of the operands */
4880   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4881   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4882   emitcode ("push", "acc");     /* save it on the stack */
4883
4884   /* now sign adjust for both left & right */
4885   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4886   lbl = newiTempLabel (NULL);
4887   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4888   emitcode ("cpl", "a");
4889   emitcode ("inc", "a");
4890   emitcode ("", "!tlabeldef", (lbl->key + 100));
4891   emitcode ("mov", "b,a");
4892
4893   /* sign adjust left side */
4894   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4895
4896   lbl = newiTempLabel (NULL);
4897   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4898   emitcode ("cpl", "a");
4899   emitcode ("inc", "a");
4900   emitcode ("", "!tlabeldef", (lbl->key + 100));
4901
4902   /* now the division */
4903   emitcode ("nop", "; workaround for DS80C390 div bug.");
4904   emitcode ("div", "ab");
4905   /* we are interested in the lower order
4906      only */
4907   emitcode ("mov", "b,a");
4908   lbl = newiTempLabel (NULL);
4909   emitcode ("pop", "acc");
4910   /* if there was an over flow we don't
4911      adjust the sign of the result */
4912   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4913   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4914   CLRC;
4915   emitcode ("clr", "a");
4916   emitcode ("subb", "a,b");
4917   emitcode ("mov", "b,a");
4918   emitcode ("", "!tlabeldef", (lbl->key + 100));
4919
4920   /* now we are done */
4921   _G.accInUse++;     _G.bInUse++;
4922     aopOp(result, ic, TRUE, FALSE);
4923     
4924     aopPut (AOP (result), "b", 0);
4925     
4926     size = AOP_SIZE (result) - 1;
4927     
4928     if (size > 0)
4929     {
4930       emitcode ("mov", "c,b.7");
4931       emitcode ("subb", "a,acc");
4932     }
4933     while (size--)
4934     {
4935         aopPut (AOP (result), "a", offset++);
4936     }
4937     _G.accInUse--;     _G.bInUse--;
4938
4939 }
4940
4941 /*-----------------------------------------------------------------*/
4942 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4943 /*-----------------------------------------------------------------*/
4944 static void genDivTwoByte (operand *left, operand *right, 
4945                             operand *result, iCode *ic)
4946 {
4947         sym_link *retype = getSpec(operandType(right));
4948         sym_link *letype = getSpec(operandType(left));
4949         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4950         symbol *lbl;
4951
4952         /* save EA bit in F1 */
4953         lbl = newiTempLabel(NULL);
4954         emitcode ("setb","F1");
4955         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4956         emitcode ("clr","F1");
4957         emitcode("","!tlabeldef",lbl->key+100);
4958
4959         /* load up MA with left */
4960         if (!umult) {
4961                 emitcode("clr","F0");
4962                 lbl = newiTempLabel(NULL);
4963                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4964                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4965                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4966                 emitcode ("xch", "a,b");
4967                 emitcode ("cpl","a");
4968                 emitcode ("add", "a,#1");
4969                 emitcode ("xch", "a,b");
4970                 emitcode ("cpl", "a"); // msb
4971                 emitcode ("addc","a,#0");
4972                 emitcode ("setb","F0");
4973                 emitcode ("","!tlabeldef",lbl->key+100);
4974                 emitcode ("mov","ma,b");
4975                 emitcode ("mov","ma,a");
4976         } else {
4977                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4978                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4979         }
4980
4981         /* load up MB with right */
4982         if (!umult) {
4983                 if (AOP_TYPE(right) == AOP_LIT) {
4984                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4985                         if (val < 0) {
4986                                 lbl = newiTempLabel(NULL);
4987                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4988                                 emitcode("setb","F0");
4989                                 emitcode ("","!tlabeldef",lbl->key+100);
4990                                 val = -val;
4991                         } 
4992                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4993                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4994                 } else {
4995                         lbl = newiTempLabel(NULL);
4996                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4997                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4998                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4999                         emitcode ("xch", "a,b");
5000                         emitcode ("cpl","a");
5001                         emitcode ("add", "a,#1");
5002                         emitcode ("xch", "a,b");
5003                         emitcode ("cpl", "a"); // msb
5004                         emitcode ("addc", "a,#0");
5005                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5006                         emitcode ("setb","F0");
5007                         emitcode ("","!tlabeldef",lbl->key+100);
5008                         emitcode ("mov","mb,b");
5009                         emitcode ("mov","mb,a");
5010                 }
5011         } else {
5012                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5013                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5014         }
5015
5016         /* wait for multiplication to finish */
5017         lbl = newiTempLabel(NULL);
5018         emitcode("","!tlabeldef", lbl->key+100);
5019         emitcode("mov","a,mcnt1");
5020         emitcode("anl","a,#!constbyte",0x80);
5021         emitcode("jnz","!tlabel",lbl->key+100);
5022         
5023         freeAsmop (left, NULL, ic, TRUE);
5024         freeAsmop (right, NULL, ic,TRUE);
5025         aopOp(result, ic, TRUE, FALSE);
5026
5027         /* if unsigned then simple */   
5028         if (umult) {
5029                 aopPut(AOP(result),"ma",1);
5030                 aopPut(AOP(result),"ma",0);
5031         } else {
5032                 emitcode("push","ma");
5033                 MOVA("ma");
5034                 /* negate result if needed */
5035                 lbl = newiTempLabel(NULL);      
5036                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5037                 emitcode("cpl","a");
5038                 emitcode("add","a,#1");
5039                 emitcode("","!tlabeldef", lbl->key+100);
5040                 aopPut(AOP(result),"a",0);
5041                 emitcode("pop","acc");
5042                 lbl = newiTempLabel(NULL);      
5043                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5044                 emitcode("cpl","a");
5045                 emitcode("addc","a,#0");
5046                 emitcode("","!tlabeldef", lbl->key+100);
5047                 aopPut(AOP(result),"a",1);
5048         }
5049         freeAsmop (result, NULL, ic, TRUE);
5050         /* restore EA bit in F1 */
5051         lbl = newiTempLabel(NULL);
5052         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5053         emitcode ("setb","EA");
5054         emitcode("","!tlabeldef",lbl->key+100);
5055         return ;
5056 }
5057
5058 /*-----------------------------------------------------------------*/
5059 /* genDiv - generates code for division                            */
5060 /*-----------------------------------------------------------------*/
5061 static void
5062 genDiv (iCode * ic)
5063 {
5064   operand *left = IC_LEFT (ic);
5065   operand *right = IC_RIGHT (ic);
5066   operand *result = IC_RESULT (ic);
5067
5068   D (emitcode (";", "genDiv "););
5069
5070   /* assign the amsops */
5071   AOP_OP_2 (ic);
5072
5073   /* special cases first */
5074   /* both are bits */
5075   if (AOP_TYPE (left) == AOP_CRY &&
5076       AOP_TYPE (right) == AOP_CRY)
5077     {
5078       genDivbits (left, right, result, ic);
5079       goto release;
5080     }
5081
5082   /* if both are of size == 1 */
5083   if (AOP_SIZE (left) == 1 &&
5084       AOP_SIZE (right) == 1)
5085     {
5086       genDivOneByte (left, right, result, ic);
5087       goto release;
5088     }
5089
5090   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5091           /* use the ds390 ARITHMETIC accel UNIT */
5092           genDivTwoByte (left, right, result, ic);
5093           return ;
5094   }
5095   /* should have been converted to function call */
5096   assert (0);
5097 release:
5098   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5099   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5100   freeAsmop (result, NULL, ic, TRUE);
5101 }
5102
5103 /*-----------------------------------------------------------------*/
5104 /* genModbits :- modulus of bits                                   */
5105 /*-----------------------------------------------------------------*/
5106 static void
5107 genModbits (operand * left,
5108             operand * right,
5109             operand * result,
5110             iCode   * ic)
5111 {
5112
5113   char *l;
5114
5115   /* the result must be bit */
5116   LOAD_AB_FOR_DIV (left, right, l);
5117   emitcode ("div", "ab");
5118   emitcode ("mov", "a,b");
5119   emitcode ("rrc", "a");
5120   aopOp(result, ic, TRUE, FALSE);
5121   aopPut (AOP (result), "c", 0);
5122 }
5123
5124 /*-----------------------------------------------------------------*/
5125 /* genModOneByte : 8 bit modulus                                   */
5126 /*-----------------------------------------------------------------*/
5127 static void
5128 genModOneByte (operand * left,
5129                operand * right,
5130                operand * result,
5131                iCode   * ic)
5132 {
5133   sym_link *opetype = operandType (result);
5134   char *l;
5135   symbol *lbl;
5136
5137   /* signed or unsigned */
5138   if (SPEC_USIGN (opetype))
5139     {
5140       /* unsigned is easy */
5141       LOAD_AB_FOR_DIV (left, right, l);
5142       emitcode ("div", "ab");
5143       aopOp(result, ic, TRUE, FALSE);   
5144       aopPut (AOP (result), "b", 0);
5145       return;
5146     }
5147
5148   /* signed is a little bit more difficult */
5149
5150   /* save the signs of the operands */
5151   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5152
5153   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5154   emitcode ("push", "acc");     /* save it on the stack */
5155
5156   /* now sign adjust for both left & right */
5157   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5158
5159   lbl = newiTempLabel (NULL);
5160   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5161   emitcode ("cpl", "a");
5162   emitcode ("inc", "a");
5163   emitcode ("", "!tlabeldef", (lbl->key + 100));
5164   emitcode ("mov", "b,a");
5165
5166   /* sign adjust left side */
5167   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5168
5169   lbl = newiTempLabel (NULL);
5170   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5171   emitcode ("cpl", "a");
5172   emitcode ("inc", "a");
5173   emitcode ("", "!tlabeldef", (lbl->key + 100));
5174
5175   /* now the multiplication */
5176   emitcode ("nop", "; workaround for DS80C390 div bug.");
5177   emitcode ("div", "ab");
5178   /* we are interested in the lower order
5179      only */
5180   lbl = newiTempLabel (NULL);
5181   emitcode ("pop", "acc");
5182   /* if there was an over flow we don't
5183      adjust the sign of the result */
5184   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5185   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5186   CLRC;
5187   emitcode ("clr", "a");
5188   emitcode ("subb", "a,b");
5189   emitcode ("mov", "b,a");
5190   emitcode ("", "!tlabeldef", (lbl->key + 100));
5191   
5192   _G.bInUse++;
5193   /* now we are done */
5194   aopOp(result, ic, TRUE, FALSE);    
5195   aopPut (AOP (result), "b", 0);
5196   _G.bInUse--;
5197
5198 }
5199
5200 /*-----------------------------------------------------------------*/
5201 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5202 /*-----------------------------------------------------------------*/
5203 static void genModTwoByte (operand *left, operand *right, 
5204                             operand *result, iCode *ic)
5205 {
5206         sym_link *retype = getSpec(operandType(right));
5207         sym_link *letype = getSpec(operandType(left));
5208         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5209         symbol *lbl;
5210
5211         /* load up MA with left */
5212         /* save EA bit in F1 */
5213         lbl = newiTempLabel(NULL);
5214         emitcode ("setb","F1");
5215         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5216         emitcode ("clr","F1");
5217         emitcode("","!tlabeldef",lbl->key+100);
5218
5219         if (!umult) {
5220                 lbl = newiTempLabel(NULL);
5221                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5222                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5223                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5224                 emitcode ("xch", "a,b");
5225                 emitcode ("cpl","a");
5226                 emitcode ("add", "a,#1");
5227                 emitcode ("xch", "a,b");
5228                 emitcode ("cpl", "a"); // msb
5229                 emitcode ("addc","a,#0");
5230                 emitcode ("","!tlabeldef",lbl->key+100);
5231                 emitcode ("mov","ma,b");
5232                 emitcode ("mov","ma,a");
5233         } else {
5234                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5235                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5236         }
5237
5238         /* load up MB with right */
5239         if (!umult) {
5240                 if (AOP_TYPE(right) == AOP_LIT) {
5241                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5242                         if (val < 0) {
5243                                 val = -val;
5244                         } 
5245                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5246                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5247                 } else {
5248                         lbl = newiTempLabel(NULL);
5249                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5250                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5251                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5252                         emitcode ("xch", "a,b");
5253                         emitcode ("cpl","a");
5254                         emitcode ("add", "a,#1");
5255                         emitcode ("xch", "a,b");
5256                         emitcode ("cpl", "a"); // msb
5257                         emitcode ("addc", "a,#0");
5258                         emitcode ("","!tlabeldef",lbl->key+100);
5259                         emitcode ("mov","mb,b");
5260                         emitcode ("mov","mb,a");
5261                 }
5262         } else {
5263                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5264                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5265         }
5266
5267         /* wait for multiplication to finish */
5268         lbl = newiTempLabel(NULL);
5269         emitcode("","!tlabeldef", lbl->key+100);
5270         emitcode("mov","a,mcnt1");
5271         emitcode("anl","a,#!constbyte",0x80);
5272         emitcode("jnz","!tlabel",lbl->key+100);
5273         
5274         freeAsmop (left, NULL, ic, TRUE);
5275         freeAsmop (right, NULL, ic,TRUE);
5276         aopOp(result, ic, TRUE, FALSE);
5277
5278         aopPut(AOP(result),"mb",1);
5279         aopPut(AOP(result),"mb",0);
5280         freeAsmop (result, NULL, ic, TRUE);
5281
5282         /* restore EA bit in F1 */
5283         lbl = newiTempLabel(NULL);
5284         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5285         emitcode ("setb","EA");
5286         emitcode("","!tlabeldef",lbl->key+100);
5287         return ;
5288 }
5289
5290 /*-----------------------------------------------------------------*/
5291 /* genMod - generates code for division                            */
5292 /*-----------------------------------------------------------------*/
5293 static void
5294 genMod (iCode * ic)
5295 {
5296   operand *left = IC_LEFT (ic);
5297   operand *right = IC_RIGHT (ic);
5298   operand *result = IC_RESULT (ic);
5299
5300   D (emitcode (";", "genMod "); );
5301
5302   /* assign the amsops */
5303   AOP_OP_2 (ic);
5304
5305   /* special cases first */
5306   /* both are bits */
5307   if (AOP_TYPE (left) == AOP_CRY &&
5308       AOP_TYPE (right) == AOP_CRY)
5309     {
5310       genModbits (left, right, result, ic);
5311       goto release;
5312     }
5313
5314   /* if both are of size == 1 */
5315   if (AOP_SIZE (left) == 1 &&
5316       AOP_SIZE (right) == 1)
5317     {
5318       genModOneByte (left, right, result, ic);
5319       goto release;
5320     }
5321
5322   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5323           /* use the ds390 ARITHMETIC accel UNIT */
5324           genModTwoByte (left, right, result, ic);
5325           return ;
5326   }
5327
5328   /* should have been converted to function call */
5329   assert (0);
5330
5331 release:
5332   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5333   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5334   freeAsmop (result, NULL, ic, TRUE);
5335 }
5336
5337 /*-----------------------------------------------------------------*/
5338 /* genIfxJump :- will create a jump depending on the ifx           */
5339 /*-----------------------------------------------------------------*/
5340 static void
5341 genIfxJump (iCode * ic, char *jval)
5342 {
5343   symbol *jlbl;
5344   symbol *tlbl = newiTempLabel (NULL);
5345   char *inst;
5346
5347   D (emitcode (";", "genIfxJump"););
5348
5349   /* if true label then we jump if condition
5350      supplied is true */
5351   if (IC_TRUE (ic))
5352     {
5353       jlbl = IC_TRUE (ic);
5354       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5355                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5356     }
5357   else
5358     {
5359       /* false label is present */
5360       jlbl = IC_FALSE (ic);
5361       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5362                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5363     }
5364   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5365     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5366   else
5367     emitcode (inst, "!tlabel", tlbl->key + 100);
5368   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5369   emitcode ("", "!tlabeldef", tlbl->key + 100);
5370
5371   /* mark the icode as generated */
5372   ic->generated = 1;
5373 }
5374
5375 /*-----------------------------------------------------------------*/
5376 /* genCmp :- greater or less than comparison                       */
5377 /*-----------------------------------------------------------------*/
5378 static void
5379 genCmp (operand * left, operand * right,
5380         iCode * ic, iCode * ifx, int sign)
5381 {
5382   int size, offset = 0;
5383   unsigned long lit = 0L;
5384   operand *result;
5385
5386   D (emitcode (";", "genCmp"););
5387
5388   result = IC_RESULT (ic);
5389
5390   /* if left & right are bit variables */
5391   if (AOP_TYPE (left) == AOP_CRY &&
5392       AOP_TYPE (right) == AOP_CRY)
5393     {
5394       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5395       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5396     }
5397   else
5398     {
5399       /* subtract right from left if at the
5400          end the carry flag is set then we know that
5401          left is greater than right */
5402       size = max (AOP_SIZE (left), AOP_SIZE (right));
5403
5404       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5405       if ((size == 1) && !sign 
5406           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5407         {
5408           symbol *lbl = newiTempLabel (NULL);
5409           emitcode ("cjne", "%s,%s,!tlabel",
5410                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5411                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5412                     lbl->key + 100);
5413           emitcode ("", "!tlabeldef", lbl->key + 100);
5414         }
5415       else
5416         {
5417           if (AOP_TYPE (right) == AOP_LIT)
5418             {
5419               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5420               /* optimize if(x < 0) or if(x >= 0) */
5421               if (lit == 0L)
5422                 {
5423                   if (!sign)
5424                     {
5425                       CLRC;
5426                     }
5427                   else
5428                     {
5429                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5430
5431                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5432                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5433
5434                       aopOp (result, ic, FALSE, FALSE);
5435
5436                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5437                         {
5438                           freeAsmop (result, NULL, ic, TRUE);
5439                           genIfxJump (ifx, "acc.7");
5440                           return;
5441                         }
5442                       else
5443                         {
5444                           emitcode ("rlc", "a");
5445                         }
5446                       goto release_freedLR;
5447                     }
5448                   goto release;
5449                 }
5450             }
5451           CLRC;
5452           while (size--)
5453             {
5454               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5455               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5456               // emitcode (";", "genCmp #2");
5457               if (sign && (size == 0))
5458                 {
5459                   // emitcode (";", "genCmp #3");
5460                   emitcode ("xrl", "a,#!constbyte",0x80);
5461                   if (AOP_TYPE (right) == AOP_LIT)
5462                     {
5463                       unsigned long lit = (unsigned long)
5464                       floatFromVal (AOP (right)->aopu.aop_lit);
5465                       // emitcode (";", "genCmp #3.1");
5466                       emitcode ("subb", "a,#!constbyte",
5467                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5468                     }
5469                   else
5470                     {
5471                       // emitcode (";", "genCmp #3.2");
5472                       saveAccWarn = 0;  
5473                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5474                       saveAccWarn = DEFAULT_ACC_WARNING;
5475                       emitcode ("xrl", "b,#!constbyte",0x80);
5476                       emitcode ("subb", "a,b");
5477                     }
5478                 }
5479               else
5480                 {
5481                   const char *s;
5482
5483                   // emitcode (";", "genCmp #4");
5484                   saveAccWarn = 0;
5485                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5486                   saveAccWarn = DEFAULT_ACC_WARNING;
5487
5488                   emitcode ("subb", "a,%s", s);
5489                 }
5490             }
5491         }
5492     }
5493
5494 release:
5495 /* Don't need the left & right operands any more; do need the result. */
5496   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5497   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5498
5499   aopOp (result, ic, FALSE, FALSE);
5500
5501 release_freedLR:
5502
5503   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5504     {
5505       outBitC (result);
5506     }
5507   else
5508     {
5509       /* if the result is used in the next
5510          ifx conditional branch then generate
5511          code a little differently */
5512       if (ifx)
5513         {
5514           genIfxJump (ifx, "c");
5515         }
5516       else
5517         {
5518           outBitC (result);
5519         }
5520       /* leave the result in acc */
5521     }
5522   freeAsmop (result, NULL, ic, TRUE);
5523 }
5524
5525 /*-----------------------------------------------------------------*/
5526 /* genCmpGt :- greater than comparison                             */
5527 /*-----------------------------------------------------------------*/
5528 static void
5529 genCmpGt (iCode * ic, iCode * ifx)
5530 {
5531   operand *left, *right;
5532   sym_link *letype, *retype;
5533   int sign;
5534
5535   D (emitcode (";", "genCmpGt ");
5536     );
5537
5538   left = IC_LEFT (ic);
5539   right = IC_RIGHT (ic);
5540
5541   letype = getSpec (operandType (left));
5542   retype = getSpec (operandType (right));
5543   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5544
5545   /* assign the left & right amsops */
5546   AOP_OP_2 (ic);
5547
5548   genCmp (right, left, ic, ifx, sign);
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* genCmpLt - less than comparisons                                */
5553 /*-----------------------------------------------------------------*/
5554 static void
5555 genCmpLt (iCode * ic, iCode * ifx)
5556 {
5557   operand *left, *right;
5558   sym_link *letype, *retype;
5559   int sign;
5560
5561   D (emitcode (";", "genCmpLt "););
5562
5563   left = IC_LEFT (ic);
5564   right = IC_RIGHT (ic);
5565
5566   letype = getSpec (operandType (left));
5567   retype = getSpec (operandType (right));
5568   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5569
5570   /* assign the left & right amsops */
5571   AOP_OP_2 (ic);
5572
5573   genCmp (left, right, ic, ifx, sign);
5574 }
5575
5576 /*-----------------------------------------------------------------*/
5577 /* gencjneshort - compare and jump if not equal                    */
5578 /*-----------------------------------------------------------------*/
5579 static void
5580 gencjneshort (operand * left, operand * right, symbol * lbl)
5581 {
5582   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5583   int offset = 0;
5584   unsigned long lit = 0L;
5585
5586   D (emitcode (";", "gencjneshort");
5587     );
5588
5589   /* if the left side is a literal or
5590      if the right is in a pointer register and left
5591      is not */
5592   if ((AOP_TYPE (left) == AOP_LIT) ||
5593       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5594     {
5595       operand *t = right;
5596       right = left;
5597       left = t;
5598     }
5599
5600   if (AOP_TYPE (right) == AOP_LIT)
5601     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5602
5603   if (opIsGptr (left) || opIsGptr (right))
5604     {
5605       /* We are comparing a generic pointer to something.
5606        * Exclude the generic type byte from the comparison.
5607        */
5608       size--;
5609       D (emitcode (";", "cjneshort: generic ptr special case."););
5610     }
5611
5612
5613   /* if the right side is a literal then anything goes */
5614   if (AOP_TYPE (right) == AOP_LIT &&
5615       AOP_TYPE (left) != AOP_DIR)
5616     {
5617       while (size--)
5618         {
5619           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5620           emitcode ("cjne", "a,%s,!tlabel",
5621                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5622                     lbl->key + 100);
5623           offset++;
5624         }
5625     }
5626
5627   /* if the right side is in a register or in direct space or
5628      if the left is a pointer register & right is not */
5629   else if (AOP_TYPE (right) == AOP_REG ||
5630            AOP_TYPE (right) == AOP_DIR ||
5631            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5632            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5633     {
5634       while (size--)
5635         {
5636           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5637           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5638               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5639             emitcode ("jnz", "!tlabel", lbl->key + 100);
5640           else
5641             emitcode ("cjne", "a,%s,!tlabel",
5642                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5643                       lbl->key + 100);
5644           offset++;
5645         }
5646     }
5647   else
5648     {
5649       /* right is a pointer reg need both a & b */
5650       while (size--)
5651         {
5652           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5653           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5654           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5655           offset++;
5656         }
5657     }
5658 }
5659
5660 /*-----------------------------------------------------------------*/
5661 /* gencjne - compare and jump if not equal                         */
5662 /*-----------------------------------------------------------------*/
5663 static void
5664 gencjne (operand * left, operand * right, symbol * lbl)
5665 {
5666   symbol *tlbl = newiTempLabel (NULL);
5667
5668   D (emitcode (";", "gencjne");
5669     );
5670
5671   gencjneshort (left, right, lbl);
5672
5673   emitcode ("mov", "a,%s", one);
5674   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5675   emitcode ("", "!tlabeldef", lbl->key + 100);
5676   emitcode ("clr", "a");
5677   emitcode ("", "!tlabeldef", tlbl->key + 100);
5678 }
5679
5680 /*-----------------------------------------------------------------*/
5681 /* genCmpEq - generates code for equal to                          */
5682 /*-----------------------------------------------------------------*/
5683 static void
5684 genCmpEq (iCode * ic, iCode * ifx)
5685 {
5686   operand *left, *right, *result;
5687
5688   D (emitcode (";", "genCmpEq ");
5689     );
5690
5691   AOP_OP_2 (ic);
5692   AOP_SET_LOCALS (ic);
5693
5694   /* if literal, literal on the right or
5695      if the right is in a pointer register and left
5696      is not */
5697   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5698       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5699     {
5700       operand *t = IC_RIGHT (ic);
5701       IC_RIGHT (ic) = IC_LEFT (ic);
5702       IC_LEFT (ic) = t;
5703     }
5704
5705   if (ifx &&                    /* !AOP_SIZE(result) */
5706       OP_SYMBOL (result) &&
5707       OP_SYMBOL (result)->regType == REG_CND)
5708     {
5709       symbol *tlbl;
5710       /* if they are both bit variables */
5711       if (AOP_TYPE (left) == AOP_CRY &&
5712           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5713         {
5714           if (AOP_TYPE (right) == AOP_LIT)
5715             {
5716               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5717               if (lit == 0L)
5718                 {
5719                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5720                   emitcode ("cpl", "c");
5721                 }
5722               else if (lit == 1L)
5723                 {
5724                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5725                 }
5726               else
5727                 {
5728                   emitcode ("clr", "c");
5729                 }
5730               /* AOP_TYPE(right) == AOP_CRY */
5731             }
5732           else
5733             {
5734               symbol *lbl = newiTempLabel (NULL);
5735               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5736               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5737               emitcode ("cpl", "c");
5738               emitcode ("", "!tlabeldef", (lbl->key + 100));
5739             }
5740           /* if true label then we jump if condition
5741              supplied is true */
5742           tlbl = newiTempLabel (NULL);
5743           if (IC_TRUE (ifx))
5744             {
5745               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5746               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5747             }
5748           else
5749             {
5750               emitcode ("jc", "!tlabel", tlbl->key + 100);
5751               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5752             }
5753           emitcode ("", "!tlabeldef", tlbl->key + 100);
5754         }
5755       else
5756         {
5757           tlbl = newiTempLabel (NULL);
5758           gencjneshort (left, right, tlbl);
5759           if (IC_TRUE (ifx))
5760             {
5761               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5762               emitcode ("", "!tlabeldef", tlbl->key + 100);
5763             }
5764           else
5765             {
5766               symbol *lbl = newiTempLabel (NULL);
5767               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5768               emitcode ("", "!tlabeldef", tlbl->key + 100);
5769               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5770               emitcode ("", "!tlabeldef", lbl->key + 100);
5771             }
5772         }
5773       /* mark the icode as generated */
5774       ifx->generated = 1;
5775
5776       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5777       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5778       return;
5779     }
5780
5781   /* if they are both bit variables */
5782   if (AOP_TYPE (left) == AOP_CRY &&
5783       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5784     {
5785       if (AOP_TYPE (right) == AOP_LIT)
5786         {
5787           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5788           if (lit == 0L)
5789             {
5790               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5791               emitcode ("cpl", "c");
5792             }
5793           else if (lit == 1L)
5794             {
5795               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796             }
5797           else
5798             {
5799               emitcode ("clr", "c");
5800             }
5801           /* AOP_TYPE(right) == AOP_CRY */
5802         }
5803       else
5804         {
5805           symbol *lbl = newiTempLabel (NULL);
5806           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5807           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5808           emitcode ("cpl", "c");
5809           emitcode ("", "!tlabeldef", (lbl->key + 100));
5810         }
5811
5812       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5813       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5814
5815       aopOp (result, ic, TRUE, FALSE);
5816
5817       /* c = 1 if egal */
5818       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5819         {
5820           outBitC (result);
5821           goto release;
5822         }
5823       if (ifx)
5824         {
5825           genIfxJump (ifx, "c");
5826           goto release;
5827         }
5828       /* if the result is used in an arithmetic operation
5829          then put the result in place */
5830       outBitC (result);
5831     }
5832   else
5833     {
5834       gencjne (left, right, newiTempLabel (NULL));
5835
5836       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5838
5839       aopOp (result, ic, TRUE, FALSE);
5840
5841       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5842         {
5843           aopPut (AOP (result), "a", 0);
5844           goto release;
5845         }
5846       if (ifx)
5847         {
5848           genIfxJump (ifx, "a");
5849           goto release;
5850         }
5851       /* if the result is used in an arithmetic operation
5852          then put the result in place */
5853       if (AOP_TYPE (result) != AOP_CRY)
5854         outAcc (result);
5855       /* leave the result in acc */
5856     }
5857
5858 release:
5859   freeAsmop (result, NULL, ic, TRUE);
5860 }
5861
5862 /*-----------------------------------------------------------------*/
5863 /* ifxForOp - returns the icode containing the ifx for operand     */
5864 /*-----------------------------------------------------------------*/
5865 static iCode *
5866 ifxForOp (operand * op, iCode * ic)
5867 {
5868   /* if true symbol then needs to be assigned */
5869   if (IS_TRUE_SYMOP (op))
5870     return NULL;
5871
5872   /* if this has register type condition and
5873      the next instruction is ifx with the same operand
5874      and live to of the operand is upto the ifx only then */
5875   if (ic->next &&
5876       ic->next->op == IFX &&
5877       IC_COND (ic->next)->key == op->key &&
5878       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5879     return ic->next;
5880
5881   return NULL;
5882 }
5883 /*-----------------------------------------------------------------*/
5884 /* hasInc - operand is incremented before any other use            */
5885 /*-----------------------------------------------------------------*/
5886 static iCode *
5887 hasInc (operand *op, iCode *ic, int osize)
5888 {
5889   sym_link *type = operandType(op);
5890   sym_link *retype = getSpec (type);
5891   iCode *lic = ic->next;
5892   int isize ;
5893   
5894   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5895   if (!IS_SYMOP(op)) return NULL;
5896
5897   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5898   if (IS_AGGREGATE(type->next)) return NULL;
5899   if (osize != (isize = getSize(type->next))) return NULL;
5900
5901   while (lic) {
5902       /* if operand of the form op = op + <sizeof *op> */
5903       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5904           isOperandEqual(IC_RESULT(lic),op) && 
5905           isOperandLiteral(IC_RIGHT(lic)) &&
5906           operandLitValue(IC_RIGHT(lic)) == isize) {
5907           return lic;
5908       }
5909       /* if the operand used or deffed */
5910       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5911           return NULL;
5912       }
5913       /* if GOTO or IFX */
5914       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5915       lic = lic->next;
5916   }
5917   return NULL;
5918 }
5919
5920 /*-----------------------------------------------------------------*/
5921 /* genAndOp - for && operation                                     */
5922 /*-----------------------------------------------------------------*/
5923 static void
5924 genAndOp (iCode * ic)
5925 {
5926   operand *left, *right, *result;
5927   symbol *tlbl;
5928
5929   D (emitcode (";", "genAndOp "););
5930
5931   /* note here that && operations that are in an
5932      if statement are taken away by backPatchLabels
5933      only those used in arthmetic operations remain */
5934   AOP_OP_2 (ic);
5935   AOP_SET_LOCALS (ic);
5936
5937   /* if both are bit variables */
5938   if (AOP_TYPE (left) == AOP_CRY &&
5939       AOP_TYPE (right) == AOP_CRY)
5940     {
5941       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5942       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5943       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5944       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5945   
5946       aopOp (result,ic,FALSE, FALSE);
5947       outBitC (result);
5948     }
5949   else
5950     {
5951       tlbl = newiTempLabel (NULL);
5952       toBoolean (left);
5953       emitcode ("jz", "!tlabel", tlbl->key + 100);
5954       toBoolean (right);
5955       emitcode ("", "!tlabeldef", tlbl->key + 100);
5956       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5957       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5958   
5959       aopOp (result,ic,FALSE, FALSE);
5960       outBitAcc (result);
5961     }
5962     freeAsmop (result, NULL, ic, TRUE);
5963 }
5964
5965
5966 /*-----------------------------------------------------------------*/
5967 /* genOrOp - for || operation                                      */
5968 /*-----------------------------------------------------------------*/
5969 static void
5970 genOrOp (iCode * ic)
5971 {
5972   operand *left, *right, *result;
5973   symbol *tlbl;
5974
5975   D (emitcode (";", "genOrOp "););
5976
5977   /* note here that || operations that are in an
5978      if statement are taken away by backPatchLabels
5979      only those used in arthmetic operations remain */
5980   AOP_OP_2 (ic);
5981   AOP_SET_LOCALS (ic);
5982
5983   /* if both are bit variables */
5984   if (AOP_TYPE (left) == AOP_CRY &&
5985       AOP_TYPE (right) == AOP_CRY)
5986     {
5987       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5988       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5989       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5990       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5991   
5992       aopOp (result,ic,FALSE, FALSE);
5993       
5994       outBitC (result);
5995     }
5996   else
5997     {
5998       tlbl = newiTempLabel (NULL);
5999       toBoolean (left);
6000       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6001       toBoolean (right);
6002       emitcode ("", "!tlabeldef", tlbl->key + 100);
6003       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005   
6006       aopOp (result,ic,FALSE, FALSE);
6007       
6008       outBitAcc (result);
6009     }
6010
6011   freeAsmop (result, NULL, ic, TRUE);
6012 }
6013
6014 /*-----------------------------------------------------------------*/
6015 /* isLiteralBit - test if lit == 2^n                               */
6016 /*-----------------------------------------------------------------*/
6017 static int
6018 isLiteralBit (unsigned long lit)
6019 {
6020   unsigned long pw[32] =
6021   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6022    0x100L, 0x200L, 0x400L, 0x800L,
6023    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6024    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6025    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6026    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6027    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6028   int idx;
6029
6030   for (idx = 0; idx < 32; idx++)
6031     if (lit == pw[idx])
6032       return idx + 1;
6033   return 0;
6034 }
6035
6036 /*-----------------------------------------------------------------*/
6037 /* continueIfTrue -                                                */
6038 /*-----------------------------------------------------------------*/
6039 static void
6040 continueIfTrue (iCode * ic)
6041 {
6042   if (IC_TRUE (ic))
6043     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6044   ic->generated = 1;
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* jmpIfTrue -                                                     */
6049 /*-----------------------------------------------------------------*/
6050 static void
6051 jumpIfTrue (iCode * ic)
6052 {
6053   if (!IC_TRUE (ic))
6054     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6055   ic->generated = 1;
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* jmpTrueOrFalse -                                                */
6060 /*-----------------------------------------------------------------*/
6061 static void
6062 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6063 {
6064   // ugly but optimized by peephole
6065   if (IC_TRUE (ic))
6066     {
6067       symbol *nlbl = newiTempLabel (NULL);
6068       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6069       emitcode ("", "!tlabeldef", tlbl->key + 100);
6070       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6071       emitcode ("", "!tlabeldef", nlbl->key + 100);
6072     }
6073   else
6074     {
6075       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6076       emitcode ("", "!tlabeldef", tlbl->key + 100);
6077     }
6078   ic->generated = 1;
6079 }
6080
6081 // Generate code to perform a bit-wise logic operation
6082 // on two operands in far space (assumed to already have been 
6083 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6084 // in far space. This requires pushing the result on the stack
6085 // then popping it into the result.
6086 static void
6087 genFarFarLogicOp(iCode *ic, char *logicOp)
6088 {
6089       int size, resultSize, compSize;
6090       int offset = 0;
6091       
6092       TR_AP("#5");
6093       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6094       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6095                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6096       
6097       _startLazyDPSEvaluation();
6098       for (size = compSize; (size--); offset++)
6099       {
6100           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6101           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6102           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6103           
6104           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6105           emitcode ("push", "acc");
6106       }
6107       _endLazyDPSEvaluation();
6108      
6109       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6110       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6111       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6112      
6113       resultSize = AOP_SIZE(IC_RESULT(ic));
6114
6115       ADJUST_PUSHED_RESULT(compSize, resultSize);
6116
6117       _startLazyDPSEvaluation();
6118       while (compSize--)
6119       {
6120           emitcode ("pop", "acc");
6121           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6122       }
6123       _endLazyDPSEvaluation();
6124       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6125 }
6126
6127
6128 /*-----------------------------------------------------------------*/
6129 /* genAnd  - code for and                                          */
6130 /*-----------------------------------------------------------------*/
6131 static void
6132 genAnd (iCode * ic, iCode * ifx)
6133 {
6134   operand *left, *right, *result;
6135   int size, offset = 0;
6136   unsigned long lit = 0L;
6137   int bytelit;
6138   char buff[10];
6139   bool pushResult;
6140
6141   D (emitcode (";", "genAnd "););
6142
6143   AOP_OP_3_NOFATAL (ic, pushResult);
6144   AOP_SET_LOCALS (ic);
6145
6146   if (pushResult)
6147   {
6148       genFarFarLogicOp(ic, "anl");
6149       return;
6150   }  
6151
6152 #ifdef DEBUG_TYPE
6153   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6154             AOP_TYPE (result),
6155             AOP_TYPE (left), AOP_TYPE (right));
6156   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6157             AOP_SIZE (result),
6158             AOP_SIZE (left), AOP_SIZE (right));
6159 #endif
6160
6161   /* if left is a literal & right is not then exchange them */
6162   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6163 #ifdef LOGIC_OPS_BROKEN      
6164     ||  AOP_NEEDSACC (left)
6165 #endif
6166     )
6167     {
6168       operand *tmp = right;
6169       right = left;
6170       left = tmp;
6171     }
6172
6173   /* if result = right then exchange them */
6174   if (sameRegs (AOP (result), AOP (right)))
6175     {
6176       operand *tmp = right;
6177       right = left;
6178       left = tmp;
6179     }
6180
6181   /* if right is bit then exchange them */
6182   if (AOP_TYPE (right) == AOP_CRY &&
6183       AOP_TYPE (left) != AOP_CRY)
6184     {
6185       operand *tmp = right;
6186       right = left;
6187       left = tmp;
6188     }
6189   if (AOP_TYPE (right) == AOP_LIT)
6190     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6191
6192   size = AOP_SIZE (result);
6193
6194   // if(bit & yy)
6195   // result = bit & yy;
6196   if (AOP_TYPE (left) == AOP_CRY)
6197     {
6198       // c = bit & literal;
6199       if (AOP_TYPE (right) == AOP_LIT)
6200         {
6201           if (lit & 1)
6202             {
6203               if (size && sameRegs (AOP (result), AOP (left)))
6204                 // no change
6205                 goto release;
6206               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207             }
6208           else
6209             {
6210               // bit(result) = 0;
6211               if (size && (AOP_TYPE (result) == AOP_CRY))
6212                 {
6213                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6214                   goto release;
6215                 }
6216               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6217                 {
6218                   jumpIfTrue (ifx);
6219                   goto release;
6220                 }
6221               emitcode ("clr", "c");
6222             }
6223         }
6224       else
6225         {
6226           if (AOP_TYPE (right) == AOP_CRY)
6227             {
6228               // c = bit & bit;
6229               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6230               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6231             }
6232           else
6233             {
6234               // c = bit & val;
6235               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6236               // c = lsb
6237               emitcode ("rrc", "a");
6238               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6239             }
6240         }
6241       // bit = c
6242       // val = c
6243       if (size)
6244         outBitC (result);
6245       // if(bit & ...)
6246       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6247         genIfxJump (ifx, "c");
6248       goto release;
6249     }
6250
6251   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6252   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6253   if ((AOP_TYPE (right) == AOP_LIT) &&
6254       (AOP_TYPE (result) == AOP_CRY) &&
6255       (AOP_TYPE (left) != AOP_CRY))
6256     {
6257       int posbit = isLiteralBit (lit);
6258       /* left &  2^n */
6259       if (posbit)
6260         {
6261           posbit--;
6262           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6263           // bit = left & 2^n
6264           if (size)
6265             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6266           // if(left &  2^n)
6267           else
6268             {
6269               if (ifx)
6270                 {
6271                   SNPRINTF (buff, sizeof(buff), 
6272                             "acc.%d", posbit & 0x07);
6273                   genIfxJump (ifx, buff);
6274                 }
6275               else 
6276                   {
6277                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6278                   }
6279               goto release;
6280             }
6281         }
6282       else
6283         {
6284           symbol *tlbl = newiTempLabel (NULL);
6285           int sizel = AOP_SIZE (left);
6286           if (size)
6287             emitcode ("setb", "c");
6288           while (sizel--)
6289             {
6290               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6291                 {
6292                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6293                   // byte ==  2^n ?
6294                   if ((posbit = isLiteralBit (bytelit)) != 0)
6295                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6296                   else
6297                     {
6298                       if (bytelit != 0x0FFL)
6299                         emitcode ("anl", "a,%s",
6300                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6301                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6302                     }
6303                 }
6304               offset++;
6305             }
6306           // bit = left & literal
6307           if (size)
6308             {
6309               emitcode ("clr", "c");
6310               emitcode ("", "!tlabeldef", tlbl->key + 100);
6311             }
6312           // if(left & literal)
6313           else
6314             {
6315               if (ifx)
6316                 jmpTrueOrFalse (ifx, tlbl);
6317               goto release;
6318             }
6319         }
6320       outBitC (result);
6321       goto release;
6322     }
6323
6324   /* if left is same as result */
6325   if (sameRegs (AOP (result), AOP (left)))
6326     {
6327       for (; size--; offset++)
6328         {
6329           if (AOP_TYPE (right) == AOP_LIT)
6330             {
6331               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6332                 continue;
6333               else if (bytelit == 0)
6334                 aopPut (AOP (result), zero, offset);
6335               else if (IS_AOP_PREG (result))
6336                 {
6337                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6338                   emitcode ("anl", "a,%s",
6339                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6340                   aopPut (AOP (result), "a", offset);
6341                 }
6342               else
6343                 emitcode ("anl", "%s,%s",
6344                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6345                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6346             }
6347           else
6348             {
6349               if (AOP_TYPE (left) == AOP_ACC)
6350                 emitcode ("anl", "a,%s",
6351                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6352               else
6353                 {
6354                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6355                   if (IS_AOP_PREG (result))
6356                     {
6357                       emitcode ("anl", "a,%s",
6358                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6359                       aopPut (AOP (result), "a", offset);
6360                     }
6361                   else
6362                     emitcode ("anl", "%s,a",
6363                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6364                 }
6365             }
6366         }
6367     }
6368   else
6369     {
6370       // left & result in different registers
6371       if (AOP_TYPE (result) == AOP_CRY)
6372         {
6373           // result = bit
6374           // if(size), result in bit
6375           // if(!size && ifx), conditional oper: if(left & right)
6376           symbol *tlbl = newiTempLabel (NULL);
6377           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6378           if (size)
6379             emitcode ("setb", "c");
6380           while (sizer--)
6381             {
6382               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6383                 emitcode ("anl", "a,%s",
6384                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6385               } else {
6386                 if (AOP_TYPE(left)==AOP_ACC) {
6387                   emitcode("mov", "b,a");
6388                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6389                   emitcode("anl", "a,b");
6390                 }else {
6391                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6392                   emitcode ("anl", "a,%s",
6393                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6394                 }
6395               }
6396               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6397               offset++;
6398             }
6399           if (size)
6400             {
6401               CLRC;
6402               emitcode ("", "!tlabeldef", tlbl->key + 100);
6403               outBitC (result);
6404             }
6405           else if (ifx)
6406             jmpTrueOrFalse (ifx, tlbl);
6407         }
6408       else
6409         {
6410           for (; (size--); offset++)
6411             {
6412               // normal case
6413               // result = left & right
6414               if (AOP_TYPE (right) == AOP_LIT)
6415                 {
6416                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6417                     {
6418                       aopPut (AOP (result),
6419                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6420                               offset);
6421                       continue;
6422                     }
6423                   else if (bytelit == 0)
6424                     {
6425                       aopPut (AOP (result), zero, offset);
6426                       continue;
6427                     }
6428                   D (emitcode (";", "better literal AND."););
6429                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6430                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6431                                                     FALSE, FALSE, DP2_RESULT_REG));
6432
6433                 }
6434               else
6435                 {
6436                   // faster than result <- left, anl result,right
6437                   // and better if result is SFR
6438                   if (AOP_TYPE (left) == AOP_ACC)
6439                     {
6440                       emitcode ("anl", "a,%s", 
6441                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6442                     }
6443                   else
6444                     {
6445                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6446                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6447                       {
6448                           emitcode("mov", "b,a");
6449                           rOp = "b";
6450                       }
6451                         
6452                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6453                       emitcode ("anl", "a,%s", rOp);
6454                     }                   
6455                 }
6456               aopPut (AOP (result), "a", offset);
6457             }
6458         }
6459     }
6460
6461 release:
6462   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464   freeAsmop (result, NULL, ic, TRUE);
6465 }
6466
6467
6468 /*-----------------------------------------------------------------*/
6469 /* genOr  - code for or                                            */
6470 /*-----------------------------------------------------------------*/
6471 static void
6472 genOr (iCode * ic, iCode * ifx)
6473 {
6474   operand *left, *right, *result;
6475   int size, offset = 0;
6476   unsigned long lit = 0L;
6477   bool     pushResult;
6478
6479   D (emitcode (";", "genOr "););
6480
6481   AOP_OP_3_NOFATAL (ic, pushResult);
6482   AOP_SET_LOCALS (ic);
6483
6484   if (pushResult)
6485   {
6486       genFarFarLogicOp(ic, "orl");
6487       return;
6488   }
6489
6490
6491 #ifdef DEBUG_TYPE
6492   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6493             AOP_TYPE (result),
6494             AOP_TYPE (left), AOP_TYPE (right));
6495   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6496             AOP_SIZE (result),
6497             AOP_SIZE (left), AOP_SIZE (right));
6498 #endif
6499
6500   /* if left is a literal & right is not then exchange them */
6501   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6502 #ifdef LOGIC_OPS_BROKEN
6503    || AOP_NEEDSACC (left) // I think this is a net loss now.
6504 #endif      
6505       )
6506     {
6507       operand *tmp = right;
6508       right = left;
6509       left = tmp;
6510     }
6511
6512   /* if result = right then exchange them */
6513   if (sameRegs (AOP (result), AOP (right)))
6514     {
6515       operand *tmp = right;
6516       right = left;
6517       left = tmp;
6518     }
6519
6520   /* if right is bit then exchange them */
6521   if (AOP_TYPE (right) == AOP_CRY &&
6522       AOP_TYPE (left) != AOP_CRY)
6523     {
6524       operand *tmp = right;
6525       right = left;
6526       left = tmp;
6527     }
6528   if (AOP_TYPE (right) == AOP_LIT)
6529     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6530
6531   size = AOP_SIZE (result);
6532
6533   // if(bit | yy)
6534   // xx = bit | yy;
6535   if (AOP_TYPE (left) == AOP_CRY)
6536     {
6537       if (AOP_TYPE (right) == AOP_LIT)
6538         {
6539           // c = bit & literal;
6540           if (lit)
6541             {
6542               // lit != 0 => result = 1
6543               if (AOP_TYPE (result) == AOP_CRY)
6544                 {
6545                   if (size)
6546                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6547                   else if (ifx)
6548                     continueIfTrue (ifx);
6549                   goto release;
6550                 }
6551               emitcode ("setb", "c");
6552             }
6553           else
6554             {
6555               // lit == 0 => result = left
6556               if (size && sameRegs (AOP (result), AOP (left)))
6557                 goto release;
6558               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6559             }
6560         }
6561       else
6562         {
6563           if (AOP_TYPE (right) == AOP_CRY)
6564             {
6565               // c = bit | bit;
6566               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6567               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6568             }
6569           else
6570             {
6571               // c = bit | val;
6572               symbol *tlbl = newiTempLabel (NULL);
6573               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6574                 emitcode ("setb", "c");
6575               emitcode ("jb", "%s,!tlabel",
6576                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6577               toBoolean (right);
6578               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6579               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6580                 {
6581                   jmpTrueOrFalse (ifx, tlbl);
6582                   goto release;
6583                 }
6584               else
6585                 {
6586                   CLRC;
6587                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6588                 }
6589             }
6590         }
6591       // bit = c
6592       // val = c
6593       if (size)
6594         outBitC (result);
6595       // if(bit | ...)
6596       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6597            genIfxJump (ifx, "c");
6598       goto release;
6599     }
6600
6601   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6602   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6603   if ((AOP_TYPE (right) == AOP_LIT) &&
6604       (AOP_TYPE (result) == AOP_CRY) &&
6605       (AOP_TYPE (left) != AOP_CRY))
6606     {
6607       if (lit)
6608         {
6609           // result = 1
6610           if (size)
6611             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6612           else
6613             continueIfTrue (ifx);
6614           goto release;
6615         }
6616       else
6617         {
6618           // lit = 0, result = boolean(left)
6619           if (size)
6620             emitcode ("setb", "c");
6621           toBoolean (right);
6622           if (size)
6623             {
6624               symbol *tlbl = newiTempLabel (NULL);
6625               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6626               CLRC;
6627               emitcode ("", "!tlabeldef", tlbl->key + 100);
6628             }
6629           else
6630             {
6631               genIfxJump (ifx, "a");
6632               goto release;
6633             }
6634         }
6635       outBitC (result);
6636       goto release;
6637     }
6638
6639   /* if left is same as result */
6640   if (sameRegs (AOP (result), AOP (left)))
6641     {
6642       for (; size--; offset++)
6643         {
6644           if (AOP_TYPE (right) == AOP_LIT)
6645             {
6646               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6647                 {
6648                   continue;
6649                 }
6650               else
6651                 {
6652                   if (IS_AOP_PREG (left))
6653                     {
6654                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6655                       emitcode ("orl", "a,%s",
6656                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6657                       aopPut (AOP (result), "a", offset);
6658                     }
6659                   else
6660                     {
6661                       emitcode ("orl", "%s,%s",
6662                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6663                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6664                     }
6665                 }
6666             }
6667           else
6668             {
6669               if (AOP_TYPE (left) == AOP_ACC)
6670                 {
6671                   emitcode ("orl", "a,%s",
6672                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6673                 }
6674               else
6675                 {
6676                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6677                   if (IS_AOP_PREG (left))
6678                     {
6679                       emitcode ("orl", "a,%s", 
6680                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6681                       aopPut (AOP (result), "a", offset);
6682                     }
6683                   else
6684                     {
6685                       emitcode ("orl", "%s,a",
6686                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6687                     }
6688                 }
6689             }
6690         }
6691     }
6692   else
6693     {
6694       // left & result in different registers
6695       if (AOP_TYPE (result) == AOP_CRY)
6696         {
6697           // result = bit
6698           // if(size), result in bit
6699           // if(!size && ifx), conditional oper: if(left | right)
6700           symbol *tlbl = newiTempLabel (NULL);
6701           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6702           if (size)
6703             emitcode ("setb", "c");
6704           while (sizer--)
6705             {
6706               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6707                 emitcode ("orl", "a,%s",
6708                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6709               } else {
6710                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6711                 emitcode ("orl", "a,%s",
6712                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6713               }
6714               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6715               offset++;
6716             }
6717           if (size)
6718             {
6719               CLRC;
6720               emitcode ("", "!tlabeldef", tlbl->key + 100);
6721               outBitC (result);
6722             }
6723           else if (ifx)
6724             jmpTrueOrFalse (ifx, tlbl);
6725         }
6726       else
6727         {
6728             _startLazyDPSEvaluation();
6729           for (; (size--); offset++)
6730             {
6731               // normal case
6732               // result = left & right
6733               if (AOP_TYPE (right) == AOP_LIT)
6734                 {
6735                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6736                     {
6737                       aopPut (AOP (result),
6738                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6739                               offset);
6740                       continue;
6741                     }
6742                   D (emitcode (";", "better literal OR."););
6743                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6744                   emitcode ("orl", "a, %s",
6745                             aopGet (AOP (right), offset,
6746                                     FALSE, FALSE, DP2_RESULT_REG));
6747
6748                 }
6749               else
6750                 {
6751                   // faster than result <- left, anl result,right
6752                   // and better if result is SFR
6753                   if (AOP_TYPE (left) == AOP_ACC)
6754                     {
6755                       emitcode ("orl", "a,%s",
6756                                 aopGet (AOP (right), offset,
6757                                         FALSE, FALSE, DP2_RESULT_REG));
6758                     }
6759                   else
6760                     {
6761                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6762                         
6763                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6764                       {
6765                           emitcode("mov", "b,a");
6766                           rOp = "b";
6767                       }
6768                         
6769                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6770                       emitcode ("orl", "a,%s", rOp);
6771                     }
6772                 }
6773               aopPut (AOP (result), "a", offset);
6774             }
6775             _endLazyDPSEvaluation();
6776         }
6777     }
6778
6779 release:
6780   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782   freeAsmop (result, NULL, ic, TRUE);
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* genXor - code for xclusive or                                   */
6787 /*-----------------------------------------------------------------*/
6788 static void
6789 genXor (iCode * ic, iCode * ifx)
6790 {
6791   operand *left, *right, *result;
6792   int size, offset = 0;
6793   unsigned long lit = 0L;
6794   bool pushResult;
6795
6796   D (emitcode (";", "genXor "););
6797
6798   AOP_OP_3_NOFATAL (ic, pushResult);
6799   AOP_SET_LOCALS (ic);
6800
6801   if (pushResult)
6802   {
6803       genFarFarLogicOp(ic, "xrl");
6804       return;
6805   }  
6806
6807 #ifdef DEBUG_TYPE
6808   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6809             AOP_TYPE (result),
6810             AOP_TYPE (left), AOP_TYPE (right));
6811   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6812             AOP_SIZE (result),
6813             AOP_SIZE (left), AOP_SIZE (right));
6814 #endif
6815
6816   /* if left is a literal & right is not ||
6817      if left needs acc & right does not */
6818   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6819 #ifdef LOGIC_OPS_BROKEN      
6820       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6821 #endif
6822      )
6823     {
6824       operand *tmp = right;
6825       right = left;
6826       left = tmp;
6827     }
6828
6829   /* if result = right then exchange them */
6830   if (sameRegs (AOP (result), AOP (right)))
6831     {
6832       operand *tmp = right;
6833       right = left;
6834       left = tmp;
6835     }
6836
6837   /* if right is bit then exchange them */
6838   if (AOP_TYPE (right) == AOP_CRY &&
6839       AOP_TYPE (left) != AOP_CRY)
6840     {
6841       operand *tmp = right;
6842       right = left;
6843       left = tmp;
6844     }
6845   if (AOP_TYPE (right) == AOP_LIT)
6846     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6847
6848   size = AOP_SIZE (result);
6849
6850   // if(bit ^ yy)
6851   // xx = bit ^ yy;
6852   if (AOP_TYPE (left) == AOP_CRY)
6853     {
6854       if (AOP_TYPE (right) == AOP_LIT)
6855         {
6856           // c = bit & literal;
6857           if (lit >> 1)
6858             {
6859               // lit>>1  != 0 => result = 1
6860               if (AOP_TYPE (result) == AOP_CRY)
6861                 {
6862                   if (size)
6863                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6864                   else if (ifx)
6865                     continueIfTrue (ifx);
6866                   goto release;
6867                 }
6868               emitcode ("setb", "c");
6869             }
6870           else
6871             {
6872               // lit == (0 or 1)
6873               if (lit == 0)
6874                 {
6875                   // lit == 0, result = left
6876                   if (size && sameRegs (AOP (result), AOP (left)))
6877                     goto release;
6878                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6879                 }
6880               else
6881                 {
6882                   // lit == 1, result = not(left)
6883                   if (size && sameRegs (AOP (result), AOP (left)))
6884                     {
6885                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6886                       goto release;
6887                     }
6888                   else
6889                     {
6890                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6891                       emitcode ("cpl", "c");
6892                     }
6893                 }
6894             }
6895
6896         }
6897       else
6898         {
6899           // right != literal
6900           symbol *tlbl = newiTempLabel (NULL);
6901           if (AOP_TYPE (right) == AOP_CRY)
6902             {
6903               // c = bit ^ bit;
6904               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6905             }
6906           else
6907             {
6908               int sizer = AOP_SIZE (right);
6909               // c = bit ^ val
6910               // if val>>1 != 0, result = 1
6911               emitcode ("setb", "c");
6912               while (sizer)
6913                 {
6914                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6915                   if (sizer == 1)
6916                     // test the msb of the lsb
6917                     emitcode ("anl", "a,#!constbyte",0xfe);
6918                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6919                   sizer--;
6920                 }
6921               // val = (0,1)
6922               emitcode ("rrc", "a");
6923             }
6924           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6925           emitcode ("cpl", "c");
6926           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6927         }
6928       // bit = c
6929       // val = c
6930       if (size)
6931         outBitC (result);
6932       // if(bit | ...)
6933       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6934         genIfxJump (ifx, "c");
6935       goto release;
6936     }
6937
6938   if (sameRegs (AOP (result), AOP (left)))
6939     {
6940       /* if left is same as result */
6941       for (; size--; offset++)
6942         {
6943           if (AOP_TYPE (right) == AOP_LIT)
6944             {
6945               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6946                 continue;
6947               else if (IS_AOP_PREG (left))
6948                 {
6949                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6950                   emitcode ("xrl", "a,%s",
6951                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6952                   aopPut (AOP (result), "a", offset);
6953                 }
6954               else
6955                 emitcode ("xrl", "%s,%s",
6956                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6957                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6958             }
6959           else
6960             {
6961               if (AOP_TYPE (left) == AOP_ACC)
6962                 emitcode ("xrl", "a,%s",
6963                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6964               else
6965                 {
6966                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6967                   if (IS_AOP_PREG (left))
6968                     {
6969                       emitcode ("xrl", "a,%s",
6970                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6971                       aopPut (AOP (result), "a", offset);
6972                     }
6973                   else
6974                     emitcode ("xrl", "%s,a",
6975                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6976                 }
6977             }
6978         }
6979     }
6980   else
6981     {
6982       // left & result in different registers
6983       if (AOP_TYPE (result) == AOP_CRY)
6984         {
6985           // result = bit
6986           // if(size), result in bit
6987           // if(!size && ifx), conditional oper: if(left ^ right)
6988           symbol *tlbl = newiTempLabel (NULL);
6989           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6990                   
6991           if (size)
6992             emitcode ("setb", "c");
6993           while (sizer--)
6994             {
6995               if ((AOP_TYPE (right) == AOP_LIT) &&
6996                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6997                 {
6998                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6999                 }
7000               else
7001                 {
7002                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7003                     emitcode ("xrl", "a,%s",
7004                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7005                   } else {
7006                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7007                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7008                       {
7009                           emitcode("mov", "b,a");
7010                           rOp = "b";
7011                       }
7012                         
7013                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7014                       emitcode ("xrl", "a,%s", rOp);                  
7015                   }
7016                 }
7017               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7018               offset++;
7019             }
7020           if (size)
7021             {
7022               CLRC;
7023               emitcode ("", "!tlabeldef", tlbl->key + 100);
7024               outBitC (result);
7025             }
7026           else if (ifx)
7027             jmpTrueOrFalse (ifx, tlbl);
7028         }
7029       else
7030         {
7031         for (; (size--); offset++)
7032           {
7033             // normal case
7034             // result = left & right
7035             if (AOP_TYPE (right) == AOP_LIT)
7036               {
7037                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7038                   {
7039                     aopPut (AOP (result),
7040                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7041                             offset);
7042                     continue;
7043                   }
7044                 D (emitcode (";", "better literal XOR."););
7045                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7046                 emitcode ("xrl", "a, %s",
7047                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7048               }
7049             else
7050               {
7051                 // faster than result <- left, anl result,right
7052                 // and better if result is SFR
7053                 if (AOP_TYPE (left) == AOP_ACC)
7054                   {
7055                     emitcode ("xrl", "a,%s",
7056                               aopGet (AOP (right), offset,
7057                                       FALSE, FALSE, DP2_RESULT_REG));
7058                   }
7059                 else
7060                   {
7061                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7062                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7063                       {
7064                           emitcode("mov", "b,a");
7065                           rOp = "b";
7066                       }
7067                         
7068                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7069                       emitcode ("xrl", "a,%s", rOp);
7070                   }
7071               }
7072             aopPut (AOP (result), "a", offset);
7073           }
7074         }
7075         
7076     }
7077
7078 release:
7079   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7080   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7081   freeAsmop (result, NULL, ic, TRUE);
7082 }
7083
7084 /*-----------------------------------------------------------------*/
7085 /* genInline - write the inline code out                           */
7086 /*-----------------------------------------------------------------*/
7087 static void
7088 genInline (iCode * ic)
7089 {
7090   char *buffer, *bp, *bp1;
7091
7092   D (emitcode (";", "genInline "); );
7093
7094   _G.inLine += (!options.asmpeep);
7095
7096   buffer = Safe_strdup(IC_INLINE(ic));
7097   bp = buffer;
7098   bp1 = buffer;
7099
7100   /* emit each line as a code */
7101   while (*bp)
7102     {
7103       if (*bp == '\n')
7104         {
7105           *bp++ = '\0';
7106           emitcode (bp1, "");
7107           bp1 = bp;
7108         }
7109       else
7110         {
7111           if (*bp == ':')
7112             {
7113               bp++;
7114               *bp = '\0';
7115               bp++;
7116               emitcode (bp1, "");
7117               bp1 = bp;
7118             }
7119           else
7120             bp++;
7121         }
7122     }
7123   if (bp1 != bp)
7124     emitcode (bp1, "");
7125   /*     emitcode("",buffer); */
7126   _G.inLine -= (!options.asmpeep);
7127 }
7128
7129 /*-----------------------------------------------------------------*/
7130 /* genRRC - rotate right with carry                                */
7131 /*-----------------------------------------------------------------*/
7132 static void
7133 genRRC (iCode * ic)
7134 {
7135   operand *left, *result;
7136   int     size, offset;
7137
7138   D (emitcode (";", "genRRC "););
7139
7140   /* rotate right with carry */
7141   left = IC_LEFT (ic);
7142   result = IC_RESULT (ic);
7143   aopOp (left, ic, FALSE, FALSE);
7144   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7145
7146   /* move it to the result */
7147   size = AOP_SIZE (result);
7148   offset = size - 1;
7149   CLRC;
7150
7151   _startLazyDPSEvaluation ();
7152   while (size--)
7153     {
7154       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7155       emitcode ("rrc", "a");
7156       if (AOP_SIZE (result) > 1)
7157         aopPut (AOP (result), "a", offset--);
7158     }
7159   _endLazyDPSEvaluation ();
7160
7161   /* now we need to put the carry into the
7162      highest order byte of the result */
7163   if (AOP_SIZE (result) > 1)
7164     {
7165       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7166     }
7167   emitcode ("mov", "acc.7,c");
7168   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7169   freeAsmop (left, NULL, ic, TRUE);
7170   freeAsmop (result, NULL, ic, TRUE);
7171 }
7172
7173 /*-----------------------------------------------------------------*/
7174 /* genRLC - generate code for rotate left with carry               */
7175 /*-----------------------------------------------------------------*/
7176 static void
7177 genRLC (iCode * ic)
7178 {
7179   operand *left, *result;
7180   int size, offset;
7181   char *l;
7182
7183   D (emitcode (";", "genRLC "););
7184
7185   /* rotate right with carry */
7186   left = IC_LEFT (ic);
7187   result = IC_RESULT (ic);
7188   aopOp (left, ic, FALSE, FALSE);
7189   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7190
7191   /* move it to the result */
7192   size = AOP_SIZE (result);
7193   offset = 0;
7194   if (size--)
7195     {
7196       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7197       MOVA (l);
7198       emitcode ("add", "a,acc");
7199       if (AOP_SIZE (result) > 1)
7200         {
7201           aopPut (AOP (result), "a", offset++);
7202         }
7203
7204       _startLazyDPSEvaluation ();
7205       while (size--)
7206         {
7207           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7208           MOVA (l);
7209           emitcode ("rlc", "a");
7210           if (AOP_SIZE (result) > 1)
7211             aopPut (AOP (result), "a", offset++);
7212         }
7213       _endLazyDPSEvaluation ();
7214     }
7215   /* now we need to put the carry into the
7216      highest order byte of the result */
7217   if (AOP_SIZE (result) > 1)
7218     {
7219       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7220       MOVA (l);
7221     }
7222   emitcode ("mov", "acc.0,c");
7223   aopPut (AOP (result), "a", 0);
7224   freeAsmop (left, NULL, ic, TRUE);
7225   freeAsmop (result, NULL, ic, TRUE);
7226 }
7227
7228 /*-----------------------------------------------------------------*/
7229 /* genGetHbit - generates code get highest order bit               */
7230 /*-----------------------------------------------------------------*/
7231 static void
7232 genGetHbit (iCode * ic)
7233 {
7234   operand *left, *result;
7235   left = IC_LEFT (ic);
7236   result = IC_RESULT (ic);
7237   aopOp (left, ic, FALSE, FALSE);
7238   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7239
7240   D (emitcode (";", "genGetHbit "););
7241
7242   /* get the highest order byte into a */
7243   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7244   if (AOP_TYPE (result) == AOP_CRY)
7245     {
7246       emitcode ("rlc", "a");
7247       outBitC (result);
7248     }
7249   else
7250     {
7251       emitcode ("rl", "a");
7252       emitcode ("anl", "a,#1");
7253       outAcc (result);
7254     }
7255
7256
7257   freeAsmop (left, NULL, ic, TRUE);
7258   freeAsmop (result, NULL, ic, TRUE);
7259 }
7260
7261 /*-----------------------------------------------------------------*/
7262 /* AccRol - rotate left accumulator by known count                 */
7263 /*-----------------------------------------------------------------*/
7264 static void
7265 AccRol (int shCount)
7266 {
7267   shCount &= 0x0007;            // shCount : 0..7
7268
7269   switch (shCount)
7270     {
7271     case 0:
7272       break;
7273     case 1:
7274       emitcode ("rl", "a");
7275       break;
7276     case 2:
7277       emitcode ("rl", "a");
7278       emitcode ("rl", "a");
7279       break;
7280     case 3:
7281       emitcode ("swap", "a");
7282       emitcode ("rr", "a");
7283       break;
7284     case 4:
7285       emitcode ("swap", "a");
7286       break;
7287     case 5:
7288       emitcode ("swap", "a");
7289       emitcode ("rl", "a");
7290       break;
7291     case 6:
7292       emitcode ("rr", "a");
7293       emitcode ("rr", "a");
7294       break;
7295     case 7:
7296       emitcode ("rr", "a");
7297       break;
7298     }
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* AccLsh - left shift accumulator by known count                  */
7303 /*-----------------------------------------------------------------*/
7304 static void
7305 AccLsh (int shCount)
7306 {
7307   if (shCount != 0)
7308     {
7309       if (shCount == 1)
7310         emitcode ("add", "a,acc");
7311       else if (shCount == 2)
7312         {
7313           emitcode ("add", "a,acc");
7314           emitcode ("add", "a,acc");
7315         }
7316       else
7317         {
7318           /* rotate left accumulator */
7319           AccRol (shCount);
7320           /* and kill the lower order bits */
7321           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7322         }
7323     }
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* AccRsh - right shift accumulator by known count                 */
7328 /*-----------------------------------------------------------------*/
7329 static void
7330 AccRsh (int shCount)
7331 {
7332   if (shCount != 0)
7333     {
7334       if (shCount == 1)
7335         {
7336           CLRC;
7337           emitcode ("rrc", "a");
7338         }
7339       else
7340         {
7341           /* rotate right accumulator */
7342           AccRol (8 - shCount);
7343           /* and kill the higher order bits */
7344           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7345         }
7346     }
7347 }
7348
7349 #ifdef BETTER_LITERAL_SHIFT
7350 /*-----------------------------------------------------------------*/
7351 /* AccSRsh - signed right shift accumulator by known count                 */
7352 /*-----------------------------------------------------------------*/
7353 static void
7354 AccSRsh (int shCount)
7355 {
7356   symbol *tlbl;
7357   if (shCount != 0)
7358     {
7359       if (shCount == 1)
7360         {
7361           emitcode ("mov", "c,acc.7");
7362           emitcode ("rrc", "a");
7363         }
7364       else if (shCount == 2)
7365         {
7366           emitcode ("mov", "c,acc.7");
7367           emitcode ("rrc", "a");
7368           emitcode ("mov", "c,acc.7");
7369           emitcode ("rrc", "a");
7370         }
7371       else
7372         {
7373           tlbl = newiTempLabel (NULL);
7374           /* rotate right accumulator */
7375           AccRol (8 - shCount);
7376           /* and kill the higher order bits */
7377           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7378           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7379           emitcode ("orl", "a,#!constbyte",
7380                     (unsigned char) ~SRMask[shCount]);
7381           emitcode ("", "!tlabeldef", tlbl->key + 100);
7382         }
7383     }
7384 }
7385 #endif
7386
7387 #ifdef BETTER_LITERAL_SHIFT
7388 /*-----------------------------------------------------------------*/
7389 /* shiftR1Left2Result - shift right one byte from left to result   */
7390 /*-----------------------------------------------------------------*/
7391 static void
7392 shiftR1Left2Result (operand * left, int offl,
7393                     operand * result, int offr,
7394                     int shCount, int sign)
7395 {
7396   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7397   /* shift right accumulator */
7398   if (sign)
7399     AccSRsh (shCount);
7400   else
7401     AccRsh (shCount);
7402   aopPut (AOP (result), "a", offr);
7403 }
7404 #endif
7405
7406 #ifdef BETTER_LITERAL_SHIFT
7407 /*-----------------------------------------------------------------*/
7408 /* shiftL1Left2Result - shift left one byte from left to result    */
7409 /*-----------------------------------------------------------------*/
7410 static void
7411 shiftL1Left2Result (operand * left, int offl,
7412                     operand * result, int offr, int shCount)
7413 {
7414   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7415   /* shift left accumulator */
7416   AccLsh (shCount);
7417   aopPut (AOP (result), "a", offr);
7418 }
7419 #endif
7420
7421 #ifdef BETTER_LITERAL_SHIFT
7422 /*-----------------------------------------------------------------*/
7423 /* movLeft2Result - move byte from left to result                  */
7424 /*-----------------------------------------------------------------*/
7425 static void
7426 movLeft2Result (operand * left, int offl,
7427                 operand * result, int offr, int sign)
7428 {
7429   char *l;
7430   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7431   {
7432       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7433
7434       if (*l == '@' && (IS_AOP_PREG (result)))
7435       {
7436           emitcode ("mov", "a,%s", l);
7437           aopPut (AOP (result), "a", offr);
7438       }
7439       else
7440       {
7441           if (!sign)
7442           {
7443             aopPut (AOP (result), l, offr);
7444           }
7445           else
7446             {
7447               /* MSB sign in acc.7 ! */
7448               if (getDataSize (left) == offl + 1)
7449                 {
7450                   emitcode ("mov", "a,%s", l);
7451                   aopPut (AOP (result), "a", offr);
7452                 }
7453             }
7454       }
7455   }
7456 }
7457 #endif
7458
7459 #ifdef BETTER_LITERAL_SHIFT
7460 /*-----------------------------------------------------------------*/
7461 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7462 /*-----------------------------------------------------------------*/
7463 static void
7464 AccAXRrl1 (char *x)
7465 {
7466   emitcode ("rrc", "a");
7467   emitcode ("xch", "a,%s", x);
7468   emitcode ("rrc", "a");
7469   emitcode ("xch", "a,%s", x);
7470 }
7471 #endif
7472
7473 #ifdef BETTER_LITERAL_SHIFT
7474 //REMOVE ME!!!
7475 /*-----------------------------------------------------------------*/
7476 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7477 /*-----------------------------------------------------------------*/
7478 static void
7479 AccAXLrl1 (char *x)
7480 {
7481   emitcode ("xch", "a,%s", x);
7482   emitcode ("rlc", "a");
7483   emitcode ("xch", "a,%s", x);
7484   emitcode ("rlc", "a");
7485 }
7486 #endif
7487
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 AccAXLsh1 (char *x)
7494 {
7495   emitcode ("xch", "a,%s", x);
7496   emitcode ("add", "a,acc");
7497   emitcode ("xch", "a,%s", x);
7498   emitcode ("rlc", "a");
7499 }
7500 #endif
7501
7502 #ifdef BETTER_LITERAL_SHIFT
7503 /*-----------------------------------------------------------------*/
7504 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7505 /*-----------------------------------------------------------------*/
7506 static void
7507 AccAXLsh (char *x, int shCount)
7508 {
7509   switch (shCount)
7510     {
7511     case 0:
7512       break;
7513     case 1:
7514       AccAXLsh1 (x);
7515       break;
7516     case 2:
7517       AccAXLsh1 (x);
7518       AccAXLsh1 (x);
7519       break;
7520     case 3:
7521     case 4:
7522     case 5:                     // AAAAABBB:CCCCCDDD
7523
7524       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7525
7526       emitcode ("anl", "a,#!constbyte",
7527                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7528
7529       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7530
7531       AccRol (shCount);         // DDDCCCCC:BBB00000
7532
7533       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7534
7535       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7536
7537       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7538
7539       emitcode ("anl", "a,#!constbyte",
7540                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7541
7542       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7543
7544       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7545
7546       break;
7547     case 6:                     // AAAAAABB:CCCCCCDD
7548       emitcode ("anl", "a,#!constbyte",
7549                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7550       emitcode ("mov", "c,acc.0");      // c = B
7551       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7552 #if 0
7553       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7554       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7555 #else
7556       emitcode("rrc","a"); 
7557       emitcode("xch","a,%s", x); 
7558       emitcode("rrc","a"); 
7559       emitcode("mov","c,acc.0"); //<< get correct bit 
7560       emitcode("xch","a,%s", x); 
7561
7562       emitcode("rrc","a"); 
7563       emitcode("xch","a,%s", x); 
7564       emitcode("rrc","a"); 
7565       emitcode("xch","a,%s", x); 
7566 #endif
7567       break;
7568     case 7:                     // a:x <<= 7
7569
7570       emitcode ("anl", "a,#!constbyte",
7571                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7572
7573       emitcode ("mov", "c,acc.0");      // c = B
7574
7575       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7576
7577       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7578
7579       break;
7580     default:
7581       break;
7582     }
7583 }
7584 #endif
7585
7586 #ifdef BETTER_LITERAL_SHIFT
7587 //REMOVE ME!!!
7588 /*-----------------------------------------------------------------*/
7589 /* AccAXRsh - right shift a:x known count (0..7)                   */
7590 /*-----------------------------------------------------------------*/
7591 static void
7592 AccAXRsh (char *x, int shCount)
7593 {
7594   switch (shCount)
7595     {
7596     case 0:
7597       break;
7598     case 1:
7599       CLRC;
7600       AccAXRrl1 (x);            // 0->a:x
7601
7602       break;
7603     case 2:
7604       CLRC;
7605       AccAXRrl1 (x);            // 0->a:x
7606
7607       CLRC;
7608       AccAXRrl1 (x);            // 0->a:x
7609
7610       break;
7611     case 3:
7612     case 4:
7613     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7614
7615       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7616
7617       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7618
7619       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7620
7621       emitcode ("anl", "a,#!constbyte",
7622                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7623
7624       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7625
7626       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7627
7628       emitcode ("anl", "a,#!constbyte",
7629                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7630
7631       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7632
7633       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7634
7635       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7636
7637       break;
7638     case 6:                     // AABBBBBB:CCDDDDDD
7639
7640       emitcode ("mov", "c,acc.7");
7641       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7642
7643       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7644
7645       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7646
7647       emitcode ("anl", "a,#!constbyte",
7648                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7649
7650       break;
7651     case 7:                     // ABBBBBBB:CDDDDDDD
7652
7653       emitcode ("mov", "c,acc.7");      // c = A
7654
7655       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7656
7657       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7658
7659       emitcode ("anl", "a,#!constbyte",
7660                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7661
7662       break;
7663     default:
7664       break;
7665     }
7666 }
7667 #endif
7668
7669 #ifdef BETTER_LITERAL_SHIFT
7670 /*-----------------------------------------------------------------*/
7671 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7672 /*-----------------------------------------------------------------*/
7673 static void
7674 AccAXRshS (char *x, int shCount)
7675 {
7676   symbol *tlbl;
7677   switch (shCount)
7678     {
7679     case 0:
7680       break;
7681     case 1:
7682       emitcode ("mov", "c,acc.7");
7683       AccAXRrl1 (x);            // s->a:x
7684
7685       break;
7686     case 2:
7687       emitcode ("mov", "c,acc.7");
7688       AccAXRrl1 (x);            // s->a:x
7689
7690       emitcode ("mov", "c,acc.7");
7691       AccAXRrl1 (x);            // s->a:x
7692
7693       break;
7694     case 3:
7695     case 4:
7696     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7697
7698       tlbl = newiTempLabel (NULL);
7699       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7700
7701       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7702
7703       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7704
7705       emitcode ("anl", "a,#!constbyte",
7706                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7707
7708       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7709
7710       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7711
7712       emitcode ("anl", "a,#!constbyte",
7713                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7714
7715       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7716
7717       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7718
7719       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7720
7721       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7722       emitcode ("orl", "a,#!constbyte",
7723                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7724
7725       emitcode ("", "!tlabeldef", tlbl->key + 100);
7726       break;                    // SSSSAAAA:BBBCCCCC
7727
7728     case 6:                     // AABBBBBB:CCDDDDDD
7729
7730       tlbl = newiTempLabel (NULL);
7731       emitcode ("mov", "c,acc.7");
7732       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7733
7734       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7735
7736       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7737
7738       emitcode ("anl", "a,#!constbyte",
7739                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7740
7741       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7742       emitcode ("orl", "a,#!constbyte",
7743                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7744
7745       emitcode ("", "!tlabeldef", tlbl->key + 100);
7746       break;
7747     case 7:                     // ABBBBBBB:CDDDDDDD
7748
7749       tlbl = newiTempLabel (NULL);
7750       emitcode ("mov", "c,acc.7");      // c = A
7751
7752       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7753
7754       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7755
7756       emitcode ("anl", "a,#!constbyte",
7757                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7758
7759       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7760       emitcode ("orl", "a,#!constbyte",
7761                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7762
7763       emitcode ("", "!tlabeldef", tlbl->key + 100);
7764       break;
7765     default:
7766       break;
7767     }
7768 }
7769 #endif
7770
7771 #ifdef BETTER_LITERAL_SHIFT
7772 static void
7773 _loadLeftIntoAx(char    **lsb, 
7774                 operand *left, 
7775                 operand *result,
7776                 int     offl,
7777                 int     offr)
7778 {
7779   // Get the initial value from left into a pair of registers.
7780   // MSB must be in A, LSB can be any register.
7781   //
7782   // If the result is held in registers, it is an optimization
7783   // if the LSB can be held in the register which will hold the,
7784   // result LSB since this saves us from having to copy it into
7785   // the result following AccAXLsh.
7786   //
7787   // If the result is addressed indirectly, this is not a gain.
7788   if (AOP_NEEDSACC(result))
7789   {
7790        char *leftByte;
7791        
7792        _startLazyDPSEvaluation();
7793       if (AOP_TYPE(left) == AOP_DPTR2)
7794        {
7795            // Get MSB in A.
7796            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7797            // get LSB in DP2_RESULT_REG.
7798            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7799            assert(!strcmp(leftByte, DP2_RESULT_REG));
7800        }
7801        else
7802        {
7803            // get LSB into DP2_RESULT_REG
7804            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7805            if (strcmp(leftByte, DP2_RESULT_REG))
7806            {
7807                TR_AP("#7");
7808                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7809            }
7810            // And MSB in A.
7811            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7812            assert(strcmp(leftByte, DP2_RESULT_REG));
7813            MOVA(leftByte);
7814        }
7815        _endLazyDPSEvaluation();
7816        *lsb = DP2_RESULT_REG;
7817   }
7818   else
7819   {
7820       if (sameRegs (AOP (result), AOP (left)) &&
7821         ((offl + MSB16) == offr))
7822       {
7823           /* don't crash result[offr] */
7824           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7825           emitcode ("xch", "a,%s", 
7826                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7827       }
7828       else
7829       {
7830           movLeft2Result (left, offl, result, offr, 0);
7831           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7832       }
7833       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7834       assert(strcmp(*lsb,"a"));      
7835   }
7836 }
7837
7838 static void
7839 _storeAxResults(char    *lsb,
7840                 operand *result,
7841                 int     offr)
7842 {
7843   _startLazyDPSEvaluation();
7844   if (AOP_NEEDSACC(result))
7845   {
7846       /* We have to explicitly update the result LSB.
7847        */
7848       emitcode("xch","a,%s", lsb);
7849       aopPut(AOP(result), "a", offr);
7850       emitcode("mov","a,%s", lsb);
7851   }
7852   if (getDataSize (result) > 1)
7853   {
7854       aopPut (AOP (result), "a", offr + MSB16);
7855   }
7856   _endLazyDPSEvaluation();
7857 }
7858
7859 /*-----------------------------------------------------------------*/
7860 /* shiftL2Left2Result - shift left two bytes from left to result   */
7861 /*-----------------------------------------------------------------*/
7862 static void
7863 shiftL2Left2Result (operand * left, int offl,
7864                     operand * result, int offr, int shCount)
7865 {
7866   char *lsb;
7867
7868   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7869   
7870   AccAXLsh (lsb, shCount);
7871   
7872   _storeAxResults(lsb, result, offr);
7873 }
7874 #endif
7875
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* shiftR2Left2Result - shift right two bytes from left to result  */
7879 /*-----------------------------------------------------------------*/
7880 static void
7881 shiftR2Left2Result (operand * left, int offl,
7882                     operand * result, int offr,
7883                     int shCount, int sign)
7884 {
7885   char *lsb;
7886   
7887   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7888   
7889   /* a:x >> shCount (x = lsb(result)) */
7890   if (sign)
7891   {
7892      AccAXRshS(lsb, shCount);
7893   }
7894   else
7895   {
7896     AccAXRsh(lsb, shCount);
7897   }
7898   
7899   _storeAxResults(lsb, result, offr);
7900 }
7901 #endif
7902
7903 #if 0
7904 //REMOVE ME!!!
7905 /*-----------------------------------------------------------------*/
7906 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7907 /*-----------------------------------------------------------------*/
7908 static void
7909 shiftLLeftOrResult (operand * left, int offl,
7910                     operand * result, int offr, int shCount)
7911 {
7912   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7913   /* shift left accumulator */
7914   AccLsh (shCount);
7915   /* or with result */
7916   emitcode ("orl", "a,%s",
7917             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7918   /* back to result */
7919   aopPut (AOP (result), "a", offr);
7920 }
7921 #endif
7922
7923 #if 0
7924 //REMOVE ME!!!
7925 /*-----------------------------------------------------------------*/
7926 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7927 /*-----------------------------------------------------------------*/
7928 static void
7929 shiftRLeftOrResult (operand * left, int offl,
7930                     operand * result, int offr, int shCount)
7931 {
7932   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7933   /* shift right accumulator */
7934   AccRsh (shCount);
7935   /* or with result */
7936   emitcode ("orl", "a,%s",
7937             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7938   /* back to result */
7939   aopPut (AOP (result), "a", offr);
7940 }
7941 #endif
7942
7943 #ifdef BETTER_LITERAL_SHIFT
7944 /*-----------------------------------------------------------------*/
7945 /* genlshOne - left shift a one byte quantity by known count       */
7946 /*-----------------------------------------------------------------*/
7947 static void
7948 genlshOne (operand * result, operand * left, int shCount)
7949 {
7950   D (emitcode (";", "genlshOne "););
7951   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7952 }
7953 #endif
7954
7955 #ifdef BETTER_LITERAL_SHIFT
7956 /*-----------------------------------------------------------------*/
7957 /* genlshTwo - left shift two bytes by known amount != 0           */
7958 /*-----------------------------------------------------------------*/
7959 static void
7960 genlshTwo (operand * result, operand * left, int shCount)
7961 {
7962   int size;
7963
7964   D (emitcode (";", "genlshTwo "););
7965
7966   size = getDataSize (result);
7967
7968   /* if shCount >= 8 */
7969   if (shCount >= 8)
7970   {
7971       shCount -= 8;
7972
7973       _startLazyDPSEvaluation();
7974
7975       if (size > 1)
7976         {
7977           if (shCount)
7978           {
7979             _endLazyDPSEvaluation();
7980             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7981             aopPut (AOP (result), zero, LSB);       
7982           }
7983           else
7984           {
7985             movLeft2Result (left, LSB, result, MSB16, 0);
7986             aopPut (AOP (result), zero, LSB);
7987             _endLazyDPSEvaluation();
7988           }
7989         }
7990         else
7991         {
7992           aopPut (AOP (result), zero, LSB);
7993           _endLazyDPSEvaluation();
7994         }
7995   }
7996
7997   /*  1 <= shCount <= 7 */
7998   else
7999     {
8000       if (size == 1)
8001       {
8002         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8003       }
8004       else
8005       {
8006         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8007       }
8008     }
8009 }
8010 #endif
8011
8012 #if 0
8013 //REMOVE ME!!!
8014 /*-----------------------------------------------------------------*/
8015 /* shiftLLong - shift left one long from left to result            */
8016 /* offl = LSB or MSB16                                             */
8017 /*-----------------------------------------------------------------*/
8018 static void
8019 shiftLLong (operand * left, operand * result, int offr)
8020 {
8021   char *l;
8022   int size = AOP_SIZE (result);
8023
8024   if (size >= LSB + offr)
8025     {
8026       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8027       MOVA (l);
8028       emitcode ("add", "a,acc");
8029       if (sameRegs (AOP (left), AOP (result)) &&
8030           size >= MSB16 + offr && offr != LSB)
8031         emitcode ("xch", "a,%s",
8032                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8033       else
8034         aopPut (AOP (result), "a", LSB + offr);
8035     }
8036
8037   if (size >= MSB16 + offr)
8038     {
8039       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8040         {
8041           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8042         }
8043       emitcode ("rlc", "a");
8044       if (sameRegs (AOP (left), AOP (result)) &&
8045           size >= MSB24 + offr && offr != LSB)
8046         emitcode ("xch", "a,%s",
8047                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8048       else
8049         aopPut (AOP (result), "a", MSB16 + offr);
8050     }
8051
8052   if (size >= MSB24 + offr)
8053     {
8054       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8055         {
8056           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8057         }
8058       emitcode ("rlc", "a");
8059       if (sameRegs (AOP (left), AOP (result)) &&
8060           size >= MSB32 + offr && offr != LSB)
8061         emitcode ("xch", "a,%s",
8062                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8063       else
8064         aopPut (AOP (result), "a", MSB24 + offr);
8065     }
8066
8067   if (size > MSB32 + offr)
8068     {
8069       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8070         {
8071           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8072         }
8073       emitcode ("rlc", "a");
8074       aopPut (AOP (result), "a", MSB32 + offr);
8075     }
8076   if (offr != LSB)
8077     aopPut (AOP (result), zero, LSB);
8078 }
8079 #endif
8080
8081 #if 0
8082 //REMOVE ME!!!
8083 /*-----------------------------------------------------------------*/
8084 /* genlshFour - shift four byte by a known amount != 0             */
8085 /*-----------------------------------------------------------------*/
8086 static void
8087 genlshFour (operand * result, operand * left, int shCount)
8088 {
8089   int size;
8090
8091   D (emitcode (";", "genlshFour ");
8092     );
8093
8094   size = AOP_SIZE (result);
8095
8096   /* if shifting more that 3 bytes */
8097   if (shCount >= 24)
8098     {
8099       shCount -= 24;
8100       if (shCount)
8101         /* lowest order of left goes to the highest
8102            order of the destination */
8103         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8104       else
8105         movLeft2Result (left, LSB, result, MSB32, 0);
8106       aopPut (AOP (result), zero, LSB);
8107       aopPut (AOP (result), zero, MSB16);
8108       aopPut (AOP (result), zero, MSB24);
8109       return;
8110     }
8111
8112   /* more than two bytes */
8113   else if (shCount >= 16)
8114     {
8115       /* lower order two bytes goes to higher order two bytes */
8116       shCount -= 16;
8117       /* if some more remaining */
8118       if (shCount)
8119         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8120       else
8121         {
8122           movLeft2Result (left, MSB16, result, MSB32, 0);
8123           movLeft2Result (left, LSB, result, MSB24, 0);
8124         }
8125       aopPut (AOP (result), zero, MSB16);
8126       aopPut (AOP (result), zero, LSB);
8127       return;
8128     }
8129
8130   /* if more than 1 byte */
8131   else if (shCount >= 8)
8132     {
8133       /* lower order three bytes goes to higher order  three bytes */
8134       shCount -= 8;
8135       if (size == 2)
8136         {
8137           if (shCount)
8138             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8139           else
8140             movLeft2Result (left, LSB, result, MSB16, 0);
8141         }
8142       else
8143         {                       /* size = 4 */
8144           if (shCount == 0)
8145             {
8146               movLeft2Result (left, MSB24, result, MSB32, 0);
8147               movLeft2Result (left, MSB16, result, MSB24, 0);
8148               movLeft2Result (left, LSB, result, MSB16, 0);
8149               aopPut (AOP (result), zero, LSB);
8150             }
8151           else if (shCount == 1)
8152             shiftLLong (left, result, MSB16);
8153           else
8154             {
8155               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8156               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8157               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8158               aopPut (AOP (result), zero, LSB);
8159             }
8160         }
8161     }
8162
8163   /* 1 <= shCount <= 7 */
8164   else if (shCount <= 2)
8165     {
8166       shiftLLong (left, result, LSB);
8167       if (shCount == 2)
8168         shiftLLong (result, result, LSB);
8169     }
8170   /* 3 <= shCount <= 7, optimize */
8171   else
8172     {
8173       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8174       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8175       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8176     }
8177 }
8178 #endif
8179
8180 #ifdef BETTER_LITERAL_SHIFT
8181 /*-----------------------------------------------------------------*/
8182 /* genLeftShiftLiteral - left shifting by known count              */
8183 /*-----------------------------------------------------------------*/
8184 static bool
8185 genLeftShiftLiteral (operand * left,
8186                      operand * right,
8187                      operand * result,
8188                      iCode * ic)
8189 {
8190   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8191   int size;
8192
8193   size = getSize (operandType (result));
8194
8195   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8196
8197   /* We only handle certain easy cases so far. */
8198   if ((shCount != 0)
8199    && (shCount < (size * 8))
8200    && (size != 1)
8201    && (size != 2))
8202   {
8203       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8204       return FALSE;
8205   }
8206
8207   freeAsmop (right, NULL, ic, TRUE);
8208
8209   aopOp(left, ic, FALSE, FALSE);
8210   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8211
8212 #if 0 // debug spew
8213   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8214   {
8215         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8216         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8217         {
8218            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8219         }
8220   }
8221   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8222   {
8223         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8224         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8225         {
8226            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8227         }       
8228   }  
8229 #endif
8230   
8231 #if VIEW_SIZE
8232   emitcode ("; shift left ", "result %d, left %d", size,
8233             AOP_SIZE (left));
8234 #endif
8235
8236   /* I suppose that the left size >= result size */
8237   if (shCount == 0)
8238   {
8239         _startLazyDPSEvaluation();
8240         while (size--)
8241         {
8242           movLeft2Result (left, size, result, size, 0);
8243         }
8244         _endLazyDPSEvaluation();
8245   }
8246   else if (shCount >= (size * 8))
8247   {
8248     _startLazyDPSEvaluation();
8249     while (size--)
8250     {
8251       aopPut (AOP (result), zero, size);
8252     }
8253     _endLazyDPSEvaluation();
8254   }
8255   else
8256   {
8257       switch (size)
8258         {
8259         case 1:
8260           genlshOne (result, left, shCount);
8261           break;
8262
8263         case 2:
8264           genlshTwo (result, left, shCount);
8265           break;
8266 #if 0
8267         case 4:
8268           genlshFour (result, left, shCount);
8269           break;
8270 #endif
8271         default:
8272           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8273           break;
8274         }
8275     }
8276   freeAsmop (left, NULL, ic, TRUE);
8277   freeAsmop (result, NULL, ic, TRUE);
8278   return TRUE;
8279 }
8280 #endif
8281
8282 /*-----------------------------------------------------------------*/
8283 /* genLeftShift - generates code for left shifting                 */
8284 /*-----------------------------------------------------------------*/
8285 static void
8286 genLeftShift (iCode * ic)
8287 {
8288   operand *left, *right, *result;
8289   int size, offset;
8290   char *l;
8291   symbol *tlbl, *tlbl1;
8292
8293   D (emitcode (";", "genLeftShift "););
8294
8295   right = IC_RIGHT (ic);
8296   left = IC_LEFT (ic);
8297   result = IC_RESULT (ic);
8298
8299   aopOp (right, ic, FALSE, FALSE);
8300
8301
8302 #ifdef BETTER_LITERAL_SHIFT
8303   /* if the shift count is known then do it
8304      as efficiently as possible */
8305   if (AOP_TYPE (right) == AOP_LIT)
8306     {
8307       if (genLeftShiftLiteral (left, right, result, ic))
8308       {
8309         return;
8310       }
8311     }
8312 #endif
8313
8314   /* shift count is unknown then we have to form
8315      a loop get the loop count in B : Note: we take
8316      only the lower order byte since shifting
8317      more that 32 bits make no sense anyway, ( the
8318      largest size of an object can be only 32 bits ) */
8319
8320   if (AOP_TYPE (right) == AOP_LIT)
8321   {
8322       /* Really should be handled by genLeftShiftLiteral,
8323        * but since I'm too lazy to fix that today, at least we can make
8324        * some small improvement.
8325        */
8326        emitcode("mov", "b,#!constbyte",
8327                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8328   }
8329   else
8330   {
8331       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8332       emitcode ("inc", "b");
8333   }
8334   freeAsmop (right, NULL, ic, TRUE);
8335   aopOp (left, ic, FALSE, FALSE);
8336   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8337
8338   /* now move the left to the result if they are not the
8339      same */
8340   if (!sameRegs (AOP (left), AOP (result)) &&
8341       AOP_SIZE (result) > 1)
8342     {
8343
8344       size = AOP_SIZE (result);
8345       offset = 0;
8346       _startLazyDPSEvaluation ();
8347       while (size--)
8348         {
8349           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8350           if (*l == '@' && (IS_AOP_PREG (result)))
8351             {
8352
8353               emitcode ("mov", "a,%s", l);
8354               aopPut (AOP (result), "a", offset);
8355             }
8356           else
8357             aopPut (AOP (result), l, offset);
8358           offset++;
8359         }
8360       _endLazyDPSEvaluation ();
8361     }
8362
8363   tlbl = newiTempLabel (NULL);
8364   size = AOP_SIZE (result);
8365   offset = 0;
8366   tlbl1 = newiTempLabel (NULL);
8367
8368   /* if it is only one byte then */
8369   if (size == 1)
8370     {
8371       symbol *tlbl1 = newiTempLabel (NULL);
8372
8373       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8374       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8375       emitcode ("", "!tlabeldef", tlbl->key + 100);
8376       emitcode ("add", "a,acc");
8377       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8378       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8379       aopPut (AOP (result), "a", 0);
8380       goto release;
8381     }
8382
8383   reAdjustPreg (AOP (result));
8384
8385   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8386   emitcode ("", "!tlabeldef", tlbl->key + 100);
8387   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8388   emitcode ("add", "a,acc");
8389   aopPut (AOP (result), "a", offset++);
8390   _startLazyDPSEvaluation ();
8391   while (--size)
8392     {
8393       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8394       emitcode ("rlc", "a");
8395       aopPut (AOP (result), "a", offset++);
8396     }
8397   _endLazyDPSEvaluation ();
8398   reAdjustPreg (AOP (result));
8399
8400   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8401   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8402 release:
8403   freeAsmop (left, NULL, ic, TRUE);
8404   freeAsmop (result, NULL, ic, TRUE);
8405 }
8406
8407 #ifdef BETTER_LITERAL_SHIFT
8408 /*-----------------------------------------------------------------*/
8409 /* genrshOne - right shift a one byte quantity by known count      */
8410 /*-----------------------------------------------------------------*/
8411 static void
8412 genrshOne (operand * result, operand * left,
8413            int shCount, int sign)
8414 {
8415   D (emitcode (";", "genrshOne"););
8416   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8417 }
8418 #endif
8419
8420 #ifdef BETTER_LITERAL_SHIFT
8421 /*-----------------------------------------------------------------*/
8422 /* genrshTwo - right shift two bytes by known amount != 0          */
8423 /*-----------------------------------------------------------------*/
8424 static void
8425 genrshTwo (operand * result, operand * left,
8426            int shCount, int sign)
8427 {
8428   D (emitcode (";", "genrshTwo"););
8429
8430   /* if shCount >= 8 */
8431   if (shCount >= 8)
8432     {
8433       shCount -= 8;
8434       _startLazyDPSEvaluation();
8435       if (shCount)
8436       {
8437         shiftR1Left2Result (left, MSB16, result, LSB,
8438                             shCount, sign);
8439       }                     
8440       else
8441       {
8442         movLeft2Result (left, MSB16, result, LSB, sign);
8443       }
8444       addSign (result, MSB16, sign);
8445       _endLazyDPSEvaluation();
8446     }
8447
8448   /*  1 <= shCount <= 7 */
8449   else
8450   {
8451     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8452   }
8453 }
8454 #endif
8455
8456 #if 0
8457 //REMOVE ME!!!
8458 /*-----------------------------------------------------------------*/
8459 /* shiftRLong - shift right one long from left to result           */
8460 /* offl = LSB or MSB16                                             */
8461 /*-----------------------------------------------------------------*/
8462 static void
8463 shiftRLong (operand * left, int offl,
8464             operand * result, int sign)
8465 {
8466   int isSameRegs=sameRegs(AOP(left),AOP(result));
8467
8468   if (isSameRegs && offl>1) {
8469     // we are in big trouble, but this shouldn't happen
8470     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8471   }
8472
8473   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8474   
8475   if (offl==MSB16) {
8476     // shift is > 8
8477     if (sign) {
8478       emitcode ("rlc", "a");
8479       emitcode ("subb", "a,acc");
8480       emitcode ("xch", "a,%s",
8481                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8482     } else {
8483       aopPut (AOP(result), zero, MSB32);
8484     }
8485   }
8486
8487   if (!sign) {
8488     emitcode ("clr", "c");
8489   } else {
8490     emitcode ("mov", "c,acc.7");
8491   }
8492
8493   emitcode ("rrc", "a");
8494
8495   if (isSameRegs && offl==MSB16) {
8496     emitcode ("xch",
8497               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8498   } else {
8499     aopPut (AOP (result), "a", MSB32);
8500     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8501   }
8502
8503   emitcode ("rrc", "a");
8504   if (isSameRegs && offl==1) {
8505     emitcode ("xch", "a,%s",
8506               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8507   } else {
8508     aopPut (AOP (result), "a", MSB24);
8509     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8510   }
8511   emitcode ("rrc", "a");
8512   aopPut (AOP (result), "a", MSB16 - offl);
8513
8514   if (offl == LSB)
8515     {
8516       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8517       emitcode ("rrc", "a");
8518       aopPut (AOP (result), "a", LSB);
8519     }
8520 }
8521 #endif
8522
8523 #if 0
8524 //REMOVE ME!!!
8525 /*-----------------------------------------------------------------*/
8526 /* genrshFour - shift four byte by a known amount != 0             */
8527 /*-----------------------------------------------------------------*/
8528 static void
8529 genrshFour (operand * result, operand * left,
8530             int shCount, int sign)
8531 {
8532   D (emitcode (";", "genrshFour");
8533     );
8534
8535   /* if shifting more that 3 bytes */
8536   if (shCount >= 24)
8537     {
8538       shCount -= 24;
8539       if (shCount)
8540         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8541       else
8542         movLeft2Result (left, MSB32, result, LSB, sign);
8543       addSign (result, MSB16, sign);
8544     }
8545   else if (shCount >= 16)
8546     {
8547       shCount -= 16;
8548       if (shCount)
8549         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8550       else
8551         {
8552           movLeft2Result (left, MSB24, result, LSB, 0);
8553           movLeft2Result (left, MSB32, result, MSB16, sign);
8554         }
8555       addSign (result, MSB24, sign);
8556     }
8557   else if (shCount >= 8)
8558     {
8559       shCount -= 8;
8560       if (shCount == 1)
8561         shiftRLong (left, MSB16, result, sign);
8562       else if (shCount == 0)
8563         {
8564           movLeft2Result (left, MSB16, result, LSB, 0);
8565           movLeft2Result (left, MSB24, result, MSB16, 0);
8566           movLeft2Result (left, MSB32, result, MSB24, sign);
8567           addSign (result, MSB32, sign);
8568         }
8569       else
8570         {
8571           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8572           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8573           /* the last shift is signed */
8574           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8575           addSign (result, MSB32, sign);
8576         }
8577     }
8578   else
8579     {                           /* 1 <= shCount <= 7 */
8580       if (shCount <= 2)
8581         {
8582           shiftRLong (left, LSB, result, sign);
8583           if (shCount == 2)
8584             shiftRLong (result, LSB, result, sign);
8585         }
8586       else
8587         {
8588           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8589           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8590           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8591         }
8592     }
8593 }
8594 #endif
8595
8596 #ifdef BETTER_LITERAL_SHIFT
8597 /*-----------------------------------------------------------------*/
8598 /* genRightShiftLiteral - right shifting by known count            */
8599 /*-----------------------------------------------------------------*/
8600 static bool
8601 genRightShiftLiteral (operand * left,
8602                       operand * right,
8603                       operand * result,
8604                       iCode * ic,
8605                       int sign)
8606 {
8607   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8608   int size;
8609
8610   size = getSize (operandType (result));
8611
8612   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8613
8614   /* We only handle certain easy cases so far. */
8615   if ((shCount != 0)
8616    && (shCount < (size * 8))
8617    && (size != 1)
8618    && (size != 2))
8619   {
8620       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8621       return FALSE;
8622   }
8623
8624   freeAsmop (right, NULL, ic, TRUE);
8625
8626   aopOp (left, ic, FALSE, FALSE);
8627   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8628
8629 #if VIEW_SIZE
8630   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8631             AOP_SIZE (left));
8632 #endif
8633
8634   /* test the LEFT size !!! */
8635
8636   /* I suppose that the left size >= result size */
8637   if (shCount == 0)
8638   {
8639       size = getDataSize (result);
8640       _startLazyDPSEvaluation();
8641       while (size--)
8642       {
8643         movLeft2Result (left, size, result, size, 0);
8644       }
8645       _endLazyDPSEvaluation();
8646   }
8647   else if (shCount >= (size * 8))
8648     {
8649       if (sign)
8650       {
8651         /* get sign in acc.7 */
8652         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8653       }
8654       addSign (result, LSB, sign);
8655     }
8656   else
8657     {
8658       switch (size)
8659         {
8660         case 1:
8661           genrshOne (result, left, shCount, sign);
8662           break;
8663
8664         case 2:
8665           genrshTwo (result, left, shCount, sign);
8666           break;
8667 #if 0
8668         case 4:
8669           genrshFour (result, left, shCount, sign);
8670           break;
8671 #endif    
8672         default:
8673           break;
8674         }
8675     }
8676   freeAsmop (left, NULL, ic, TRUE);
8677   freeAsmop (result, NULL, ic, TRUE);
8678   
8679   return TRUE;
8680 }
8681 #endif
8682
8683 /*-----------------------------------------------------------------*/
8684 /* genSignedRightShift - right shift of signed number              */
8685 /*-----------------------------------------------------------------*/
8686 static void
8687 genSignedRightShift (iCode * ic)
8688 {
8689   operand *right, *left, *result;
8690   int size, offset;
8691   char *l;
8692   symbol *tlbl, *tlbl1;
8693
8694   D (emitcode (";", "genSignedRightShift "););
8695
8696   /* we do it the hard way put the shift count in b
8697      and loop thru preserving the sign */
8698
8699   right = IC_RIGHT (ic);
8700   left = IC_LEFT (ic);
8701   result = IC_RESULT (ic);
8702
8703   aopOp (right, ic, FALSE, FALSE);
8704
8705 #ifdef BETTER_LITERAL_SHIFT
8706   if (AOP_TYPE (right) == AOP_LIT)
8707     {
8708       if (genRightShiftLiteral (left, right, result, ic, 1))
8709       {
8710         return;
8711       }
8712     }
8713 #endif
8714   /* shift count is unknown then we have to form
8715      a loop get the loop count in B : Note: we take
8716      only the lower order byte since shifting
8717      more that 32 bits make no sense anyway, ( the
8718      largest size of an object can be only 32 bits ) */
8719
8720   if (AOP_TYPE (right) == AOP_LIT)
8721   {
8722       /* Really should be handled by genRightShiftLiteral,
8723        * but since I'm too lazy to fix that today, at least we can make
8724        * some small improvement.
8725        */
8726        emitcode("mov", "b,#!constbyte",
8727                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8728   }
8729   else
8730   {
8731         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8732         emitcode ("inc", "b");
8733   }
8734   freeAsmop (right, NULL, ic, TRUE);
8735   aopOp (left, ic, FALSE, FALSE);
8736   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8737
8738   /* now move the left to the result if they are not the
8739      same */
8740   if (!sameRegs (AOP (left), AOP (result)) &&
8741       AOP_SIZE (result) > 1)
8742     {
8743
8744       size = AOP_SIZE (result);
8745       offset = 0;
8746       _startLazyDPSEvaluation ();
8747       while (size--)
8748         {
8749           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8750           if (*l == '@' && IS_AOP_PREG (result))
8751             {
8752
8753               emitcode ("mov", "a,%s", l);
8754               aopPut (AOP (result), "a", offset);
8755             }
8756           else
8757             aopPut (AOP (result), l, offset);
8758           offset++;
8759         }
8760       _endLazyDPSEvaluation ();
8761     }
8762
8763   /* mov the highest order bit to OVR */
8764   tlbl = newiTempLabel (NULL);
8765   tlbl1 = newiTempLabel (NULL);
8766
8767   size = AOP_SIZE (result);
8768   offset = size - 1;
8769   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8770   emitcode ("rlc", "a");
8771   emitcode ("mov", "ov,c");
8772   /* if it is only one byte then */
8773   if (size == 1)
8774     {
8775       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8776       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8777       emitcode ("", "!tlabeldef", tlbl->key + 100);
8778       emitcode ("mov", "c,ov");
8779       emitcode ("rrc", "a");
8780       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8781       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8782       aopPut (AOP (result), "a", 0);
8783       goto release;
8784     }
8785
8786   reAdjustPreg (AOP (result));
8787   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8788   emitcode ("", "!tlabeldef", tlbl->key + 100);
8789   emitcode ("mov", "c,ov");
8790   _startLazyDPSEvaluation ();
8791   while (size--)
8792     {
8793       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8794       emitcode ("rrc", "a");
8795       aopPut (AOP (result), "a", offset--);
8796     }
8797   _endLazyDPSEvaluation ();
8798   reAdjustPreg (AOP (result));
8799   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8800   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8801
8802 release:
8803   freeAsmop (left, NULL, ic, TRUE);
8804   freeAsmop (result, NULL, ic, TRUE);
8805 }
8806
8807 /*-----------------------------------------------------------------*/
8808 /* genRightShift - generate code for right shifting                */
8809 /*-----------------------------------------------------------------*/
8810 static void
8811 genRightShift (iCode * ic)
8812 {
8813   operand *right, *left, *result;
8814   sym_link *retype;
8815   int size, offset;
8816   char *l;
8817   symbol *tlbl, *tlbl1;
8818
8819   D (emitcode (";", "genRightShift "););
8820
8821   /* if signed then we do it the hard way preserve the
8822      sign bit moving it inwards */
8823   retype = getSpec (operandType (IC_RESULT (ic)));
8824
8825   if (!SPEC_USIGN (retype))
8826     {
8827       genSignedRightShift (ic);
8828       return;
8829     }
8830
8831   /* signed & unsigned types are treated the same : i.e. the
8832      signed is NOT propagated inwards : quoting from the
8833      ANSI - standard : "for E1 >> E2, is equivalent to division
8834      by 2**E2 if unsigned or if it has a non-negative value,
8835      otherwise the result is implementation defined ", MY definition
8836      is that the sign does not get propagated */
8837
8838   right = IC_RIGHT (ic);
8839   left = IC_LEFT (ic);
8840   result = IC_RESULT (ic);
8841
8842   aopOp (right, ic, FALSE, FALSE);
8843
8844 #ifdef BETTER_LITERAL_SHIFT
8845   /* if the shift count is known then do it
8846      as efficiently as possible */
8847   if (AOP_TYPE (right) == AOP_LIT)
8848     {
8849       if (genRightShiftLiteral (left, right, result, ic, 0))
8850       {
8851         return;
8852       }
8853     }
8854 #endif
8855
8856   /* shift count is unknown then we have to form
8857      a loop get the loop count in B : Note: we take
8858      only the lower order byte since shifting
8859      more that 32 bits make no sense anyway, ( the
8860      largest size of an object can be only 32 bits ) */
8861   
8862   if (AOP_TYPE (right) == AOP_LIT)
8863   {
8864       /* Really should be handled by genRightShiftLiteral,
8865        * but since I'm too lazy to fix that today, at least we can make
8866        * some small improvement.
8867        */
8868        emitcode("mov", "b,#!constbyte",
8869                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8870   }
8871   else
8872   {
8873       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8874       emitcode ("inc", "b");
8875   }
8876   freeAsmop (right, NULL, ic, TRUE);
8877   aopOp (left, ic, FALSE, FALSE);
8878   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8879
8880   /* now move the left to the result if they are not the
8881      same */
8882   if (!sameRegs (AOP (left), AOP (result)) &&
8883       AOP_SIZE (result) > 1)
8884     {
8885
8886       size = AOP_SIZE (result);
8887       offset = 0;
8888       _startLazyDPSEvaluation ();
8889       while (size--)
8890         {
8891           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8892           if (*l == '@' && IS_AOP_PREG (result))
8893             {
8894
8895               emitcode ("mov", "a,%s", l);
8896               aopPut (AOP (result), "a", offset);
8897             }
8898           else
8899             aopPut (AOP (result), l, offset);
8900           offset++;
8901         }
8902       _endLazyDPSEvaluation ();
8903     }
8904
8905   tlbl = newiTempLabel (NULL);
8906   tlbl1 = newiTempLabel (NULL);
8907   size = AOP_SIZE (result);
8908   offset = size - 1;
8909
8910   /* if it is only one byte then */
8911   if (size == 1)
8912     {
8913       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8914       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8915       emitcode ("", "!tlabeldef", tlbl->key + 100);
8916       CLRC;
8917       emitcode ("rrc", "a");
8918       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8920       aopPut (AOP (result), "a", 0);
8921       goto release;
8922     }
8923
8924   reAdjustPreg (AOP (result));
8925   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926   emitcode ("", "!tlabeldef", tlbl->key + 100);
8927   CLRC;
8928   _startLazyDPSEvaluation ();
8929   while (size--)
8930     {
8931       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8932       emitcode ("rrc", "a");
8933       aopPut (AOP (result), "a", offset--);
8934     }
8935   _endLazyDPSEvaluation ();
8936   reAdjustPreg (AOP (result));
8937
8938   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8939   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8940
8941 release:
8942   freeAsmop (left, NULL, ic, TRUE);
8943   freeAsmop (result, NULL, ic, TRUE);
8944 }
8945
8946 /*-----------------------------------------------------------------*/
8947 /* genUnpackBits - generates code for unpacking bits               */
8948 /*-----------------------------------------------------------------*/
8949 static void
8950 genUnpackBits (operand * result, char *rname, int ptype)
8951 {
8952   int shCnt;
8953   int rlen;
8954   sym_link *etype;
8955   int offset = 0;
8956
8957   D (emitcode (";", "genUnpackBits "););
8958
8959   etype = getSpec (operandType (result));
8960
8961   /* read the first byte  */
8962   switch (ptype)
8963     {
8964
8965     case POINTER:
8966     case IPOINTER:
8967       emitcode ("mov", "a,@%s", rname);
8968       break;
8969
8970     case PPOINTER:
8971       emitcode ("movx", "a,@%s", rname);
8972       break;
8973
8974     case FPOINTER:
8975       emitcode ("movx", "a,@dptr");
8976       break;
8977
8978     case CPOINTER:
8979       emitcode ("clr", "a");
8980       emitcode ("movc", "a,@a+dptr");
8981       break;
8982
8983     case GPOINTER:
8984       emitcode ("lcall", "__gptrget");
8985       break;
8986     }
8987
8988   /* if we have bitdisplacement then it fits   */
8989   /* into this byte completely or if length is */
8990   /* less than a byte                          */
8991   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8992     {
8993
8994       /* shift right acc */
8995       AccRsh (shCnt);
8996
8997       emitcode ("anl", "a,#!constbyte",
8998                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8999       aopPut (AOP (result), "a", offset);
9000       return;
9001     }
9002
9003   /* bit field did not fit in a byte  */
9004   rlen = SPEC_BLEN (etype) - 8;
9005   aopPut (AOP (result), "a", offset++);
9006
9007   while (1)
9008     {
9009
9010       switch (ptype)
9011         {
9012         case POINTER:
9013         case IPOINTER:
9014           emitcode ("inc", "%s", rname);
9015           emitcode ("mov", "a,@%s", rname);
9016           break;
9017
9018         case PPOINTER:
9019           emitcode ("inc", "%s", rname);
9020           emitcode ("movx", "a,@%s", rname);
9021           break;
9022
9023         case FPOINTER:
9024           emitcode ("inc", "dptr");
9025           emitcode ("movx", "a,@dptr");
9026           break;
9027
9028         case CPOINTER:
9029           emitcode ("clr", "a");
9030           emitcode ("inc", "dptr");
9031           emitcode ("movc", "a,@a+dptr");
9032           break;
9033
9034         case GPOINTER:
9035           emitcode ("inc", "dptr");
9036           emitcode ("lcall", "__gptrget");
9037           break;
9038         }
9039
9040       rlen -= 8;
9041       /* if we are done */
9042       if (rlen < 8)
9043         break;
9044
9045       aopPut (AOP (result), "a", offset++);
9046
9047     }
9048
9049   if (rlen)
9050     {
9051       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9052       aopPut (AOP (result), "a", offset);
9053     }
9054
9055   return;
9056 }
9057
9058
9059 /*-----------------------------------------------------------------*/
9060 /* genDataPointerGet - generates code when ptr offset is known     */
9061 /*-----------------------------------------------------------------*/
9062 static void
9063 genDataPointerGet (operand * left,
9064                    operand * result,
9065                    iCode * ic)
9066 {
9067   char *l;
9068   char buff[256];
9069   int size, offset = 0;
9070   aopOp (result, ic, TRUE, FALSE);
9071
9072   /* get the string representation of the name */
9073   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9074   size = AOP_SIZE (result);
9075   _startLazyDPSEvaluation ();
9076   while (size--)
9077     {
9078         if (offset)
9079         {
9080             SNPRINTF (buff, sizeof(buff), 
9081                       "(%s + %d)", l + 1, offset);
9082         }
9083         else
9084         {
9085             SNPRINTF (buff, sizeof(buff), 
9086                       "%s", l + 1);
9087         }
9088       aopPut (AOP (result), buff, offset++);
9089     }
9090   _endLazyDPSEvaluation ();
9091
9092   freeAsmop (left, NULL, ic, TRUE);
9093   freeAsmop (result, NULL, ic, TRUE);
9094 }
9095
9096 /*-----------------------------------------------------------------*/
9097 /* genNearPointerGet - emitcode for near pointer fetch             */
9098 /*-----------------------------------------------------------------*/
9099 static void
9100 genNearPointerGet (operand * left,
9101                    operand * result,
9102                    iCode * ic,
9103                    iCode *pi)
9104 {
9105   asmop *aop = NULL;
9106   regs *preg;
9107   char *rname;
9108   sym_link *rtype, *retype, *letype;
9109   sym_link *ltype = operandType (left);
9110   char buff[80];
9111
9112   rtype = operandType (result);
9113   retype = getSpec (rtype);
9114   letype = getSpec (ltype);
9115
9116   aopOp (left, ic, FALSE, FALSE);
9117
9118   /* if left is rematerialisable and
9119      result is not bit variable type and
9120      the left is pointer to data space i.e
9121      lower 128 bytes of space */
9122   if (AOP_TYPE (left) == AOP_IMMD &&
9123       !IS_BITVAR (retype) &&
9124       !IS_BITVAR (letype) &&
9125       DCL_TYPE (ltype) == POINTER)
9126     {
9127       genDataPointerGet (left, result, ic);
9128       return;
9129     }
9130
9131   /* if the value is already in a pointer register
9132      then don't need anything more */
9133   if (!AOP_INPREG (AOP (left)))
9134     {
9135       /* otherwise get a free pointer register */
9136       aop = newAsmop (0);
9137       preg = getFreePtr (ic, &aop, FALSE);
9138       emitcode ("mov", "%s,%s",
9139                 preg->name,
9140                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9141       rname = preg->name;
9142     }
9143   else
9144     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9145
9146   freeAsmop (left, NULL, ic, TRUE);
9147   aopOp (result, ic, FALSE, FALSE);
9148
9149   /* if bitfield then unpack the bits */
9150   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9151     genUnpackBits (result, rname, POINTER);
9152   else
9153     {
9154       /* we have can just get the values */
9155       int size = AOP_SIZE (result);
9156       int offset = 0;
9157
9158       while (size--)
9159         {
9160           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9161             {
9162
9163               emitcode ("mov", "a,@%s", rname);
9164               aopPut (AOP (result), "a", offset);
9165             }
9166           else
9167             {
9168               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9169               aopPut (AOP (result), buff, offset);
9170             }
9171           offset++;
9172           if (size || pi)
9173             {
9174                 emitcode ("inc", "%s", rname);
9175             }
9176         }
9177     }
9178
9179   /* now some housekeeping stuff */
9180   if (aop)
9181     {
9182       /* we had to allocate for this iCode */
9183       if (pi) { /* post increment present */
9184         aopPut(AOP ( left ),rname,0);
9185       }
9186       freeAsmop (NULL, aop, ic, TRUE);
9187     }
9188   else
9189     {
9190       /* we did not allocate which means left
9191          already in a pointer register, then
9192          if size > 0 && this could be used again
9193          we have to point it back to where it
9194          belongs */
9195       if (AOP_SIZE (result) > 1 &&
9196           !OP_SYMBOL (left)->remat &&
9197           (OP_SYMBOL (left)->liveTo > ic->seq ||
9198            ic->depth) &&
9199           !pi)
9200         {
9201           int size = AOP_SIZE (result) - 1;
9202           while (size--)
9203             emitcode ("dec", "%s", rname);
9204         }
9205     }
9206
9207   /* done */
9208   freeAsmop (result, NULL, ic, TRUE);
9209   if (pi) pi->generated = 1;
9210 }
9211
9212 /*-----------------------------------------------------------------*/
9213 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9214 /*-----------------------------------------------------------------*/
9215 static void
9216 genPagedPointerGet (operand * left,
9217                     operand * result,
9218                     iCode * ic,
9219                     iCode * pi)
9220 {
9221   asmop *aop = NULL;
9222   regs *preg;
9223   char *rname;
9224   sym_link *rtype, *retype, *letype;
9225
9226   rtype = operandType (result);
9227   retype = getSpec (rtype);
9228   letype = getSpec (operandType (left));
9229   aopOp (left, ic, FALSE, FALSE);
9230
9231   /* if the value is already in a pointer register
9232      then don't need anything more */
9233   if (!AOP_INPREG (AOP (left)))
9234     {
9235       /* otherwise get a free pointer register */
9236       aop = newAsmop (0);
9237       preg = getFreePtr (ic, &aop, FALSE);
9238       emitcode ("mov", "%s,%s",
9239                 preg->name,
9240                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9241       rname = preg->name;
9242     }
9243   else
9244     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9245
9246   freeAsmop (left, NULL, ic, TRUE);
9247   aopOp (result, ic, FALSE, FALSE);
9248
9249   /* if bitfield then unpack the bits */
9250   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9251     genUnpackBits (result, rname, PPOINTER);
9252   else
9253     {
9254       /* we have can just get the values */
9255       int size = AOP_SIZE (result);
9256       int offset = 0;
9257
9258       while (size--)
9259         {
9260
9261           emitcode ("movx", "a,@%s", rname);
9262           aopPut (AOP (result), "a", offset);
9263
9264           offset++;
9265
9266           if (size || pi)
9267             emitcode ("inc", "%s", rname);
9268         }
9269     }
9270
9271   /* now some housekeeping stuff */
9272   if (aop)
9273     {
9274       /* we had to allocate for this iCode */
9275       if (pi) aopPut ( AOP (left), rname, 0);
9276       freeAsmop (NULL, aop, ic, TRUE);
9277     }
9278   else
9279     {
9280       /* we did not allocate which means left
9281          already in a pointer register, then
9282          if size > 0 && this could be used again
9283          we have to point it back to where it
9284          belongs */
9285       if (AOP_SIZE (result) > 1 &&
9286           !OP_SYMBOL (left)->remat &&
9287           (OP_SYMBOL (left)->liveTo > ic->seq ||
9288            ic->depth) &&
9289           !pi)
9290         {
9291           int size = AOP_SIZE (result) - 1;
9292           while (size--)
9293             emitcode ("dec", "%s", rname);
9294         }
9295     }
9296
9297   /* done */
9298   freeAsmop (result, NULL, ic, TRUE);
9299   if (pi) pi->generated = 1;
9300 }
9301
9302 /*-----------------------------------------------------------------*/
9303 /* genFarPointerGet - gget value from far space                    */
9304 /*-----------------------------------------------------------------*/
9305 static void
9306 genFarPointerGet (operand * left,
9307                   operand * result, iCode * ic, iCode *pi)
9308 {
9309     int size, offset, dopi=1;
9310   sym_link *retype = getSpec (operandType (result));
9311   sym_link *letype = getSpec (operandType (left));
9312   D (emitcode (";", "genFarPointerGet"););
9313
9314   aopOp (left, ic, FALSE, FALSE);
9315
9316   /* if the operand is already in dptr
9317      then we do nothing else we move the value to dptr */
9318   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9319     {
9320       /* if this is remateriazable */
9321       if (AOP_TYPE (left) == AOP_IMMD)
9322         {
9323           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9324         }
9325       else
9326         {
9327           /* we need to get it byte by byte */
9328           _startLazyDPSEvaluation ();
9329           if (AOP_TYPE (left) != AOP_DPTR)
9330             {
9331               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9332               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9333               if (options.model == MODEL_FLAT24)
9334                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9335             }
9336           else
9337             {
9338               /* We need to generate a load to DPTR indirect through DPTR. */
9339               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9340               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9341               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9342               if (options.model == MODEL_FLAT24)
9343                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9344               emitcode ("pop", "dph");
9345               emitcode ("pop", "dpl");
9346               dopi =0;
9347             }
9348           _endLazyDPSEvaluation ();
9349         }
9350     }
9351   /* so dptr know contains the address */
9352   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9353
9354   /* if bit then unpack */
9355   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9356       if (AOP_INDPTRn(left)) {
9357           genSetDPTR(AOP(left)->aopu.dptr);
9358       }
9359       genUnpackBits (result, "dptr", FPOINTER);
9360       if (AOP_INDPTRn(left)) {
9361           genSetDPTR(0);
9362       }
9363   } else
9364     {
9365       size = AOP_SIZE (result);
9366       offset = 0;
9367
9368       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9369           while (size--) {
9370               genSetDPTR(AOP(left)->aopu.dptr);
9371               emitcode ("movx", "a,@dptr");
9372               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9373                   emitcode ("inc", "dptr");
9374               genSetDPTR (0);
9375               aopPut (AOP (result), "a", offset++);
9376           }
9377       } else {
9378           _startLazyDPSEvaluation ();
9379           while (size--) {
9380               if (AOP_INDPTRn(left)) {
9381                   genSetDPTR(AOP(left)->aopu.dptr);
9382               } else {
9383                   genSetDPTR (0);
9384               }
9385               _flushLazyDPS ();
9386               
9387               emitcode ("movx", "a,@dptr");
9388               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9389                   emitcode ("inc", "dptr");
9390               
9391               aopPut (AOP (result), "a", offset++);
9392           }
9393           _endLazyDPSEvaluation ();
9394       }
9395     }
9396   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9397       if (!AOP_INDPTRn(left)) {
9398           _startLazyDPSEvaluation ();
9399           aopPut ( AOP (left), "dpl", 0);
9400           aopPut ( AOP (left), "dph", 1);
9401           if (options.model == MODEL_FLAT24)
9402               aopPut ( AOP (left), "dpx", 2);
9403           _endLazyDPSEvaluation ();
9404       }
9405     pi->generated = 1;
9406   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9407              AOP_SIZE(result) > 1 &&
9408              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9409       
9410       size = AOP_SIZE (result) - 1;
9411       if (AOP_INDPTRn(left)) {
9412           genSetDPTR(AOP(left)->aopu.dptr);
9413       }
9414       while (size--) emitcode ("lcall","__decdptr");
9415       if (AOP_INDPTRn(left)) {
9416           genSetDPTR(0);
9417       }
9418   }
9419
9420   freeAsmop (left, NULL, ic, TRUE);
9421   freeAsmop (result, NULL, ic, TRUE);
9422 }
9423
9424 /*-----------------------------------------------------------------*/
9425 /* genCodePointerGet - get value from code space                  */
9426 /*-----------------------------------------------------------------*/
9427 static void
9428 genCodePointerGet (operand * left,
9429                     operand * result, iCode * ic, iCode *pi)
9430 {
9431   int size, offset, dopi=1;
9432   sym_link *retype = getSpec (operandType (result));
9433
9434   aopOp (left, ic, FALSE, FALSE);
9435
9436   /* if the operand is already in dptr
9437      then we do nothing else we move the value to dptr */
9438   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9439     {
9440       /* if this is remateriazable */
9441       if (AOP_TYPE (left) == AOP_IMMD)
9442         {
9443           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9444         }
9445       else
9446         {                       /* we need to get it byte by byte */
9447           _startLazyDPSEvaluation ();
9448           if (AOP_TYPE (left) != AOP_DPTR)
9449             {
9450               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9451               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9452               if (options.model == MODEL_FLAT24)
9453                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9454             }
9455           else
9456             {
9457               /* We need to generate a load to DPTR indirect through DPTR. */
9458               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9459               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9460               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9461               if (options.model == MODEL_FLAT24)
9462                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9463               emitcode ("pop", "dph");
9464               emitcode ("pop", "dpl");
9465               dopi=0;
9466             }
9467           _endLazyDPSEvaluation ();
9468         }
9469     }
9470   /* so dptr know contains the address */
9471   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9472
9473   /* if bit then unpack */
9474   if (IS_BITVAR (retype)) {
9475       if (AOP_INDPTRn(left)) {
9476           genSetDPTR(AOP(left)->aopu.dptr);
9477       }
9478       genUnpackBits (result, "dptr", CPOINTER);
9479       if (AOP_INDPTRn(left)) {
9480           genSetDPTR(0);
9481       }
9482   } else
9483     {
9484       size = AOP_SIZE (result);
9485       offset = 0;
9486       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9487           while (size--) {
9488               genSetDPTR(AOP(left)->aopu.dptr);
9489               emitcode ("clr", "a");
9490               emitcode ("movc", "a,@a+dptr");
9491               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9492                   emitcode ("inc", "dptr");
9493               genSetDPTR (0);
9494               aopPut (AOP (result), "a", offset++);
9495           }
9496       } else {
9497           _startLazyDPSEvaluation ();
9498           while (size--)
9499               {
9500                   if (AOP_INDPTRn(left)) {
9501                       genSetDPTR(AOP(left)->aopu.dptr);
9502                   } else {
9503                       genSetDPTR (0);
9504                   }
9505                   _flushLazyDPS ();
9506                   
9507                   emitcode ("clr", "a");
9508                   emitcode ("movc", "a,@a+dptr");
9509                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9510                       emitcode ("inc", "dptr");
9511                   aopPut (AOP (result), "a", offset++);
9512               }
9513           _endLazyDPSEvaluation ();
9514       }
9515     }
9516   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9517       if (!AOP_INDPTRn(left)) {
9518           _startLazyDPSEvaluation ();
9519           
9520           aopPut ( AOP (left), "dpl", 0);
9521           aopPut ( AOP (left), "dph", 1);
9522           if (options.model == MODEL_FLAT24)
9523               aopPut ( AOP (left), "dpx", 2);
9524
9525           _endLazyDPSEvaluation ();
9526       }
9527       pi->generated = 1;
9528   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9529              AOP_SIZE(result) > 1 &&
9530              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9531       
9532       size = AOP_SIZE (result) - 1;
9533       if (AOP_INDPTRn(left)) {
9534           genSetDPTR(AOP(left)->aopu.dptr);
9535       }
9536       while (size--) emitcode ("lcall","__decdptr");
9537       if (AOP_INDPTRn(left)) {
9538           genSetDPTR(0);
9539       }
9540   }
9541   
9542   freeAsmop (left, NULL, ic, TRUE);
9543   freeAsmop (result, NULL, ic, TRUE);
9544 }
9545
9546 /*-----------------------------------------------------------------*/
9547 /* genGenPointerGet - gget value from generic pointer space        */
9548 /*-----------------------------------------------------------------*/
9549 static void
9550 genGenPointerGet (operand * left,
9551                   operand * result, iCode * ic, iCode * pi)
9552 {
9553   int size, offset;
9554   sym_link *retype = getSpec (operandType (result));
9555   sym_link *letype = getSpec (operandType (left));
9556
9557   D (emitcode (";", "genGenPointerGet "); );
9558
9559   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9560
9561   /* if the operand is already in dptr
9562      then we do nothing else we move the value to dptr */
9563   if (AOP_TYPE (left) != AOP_STR)
9564     {
9565       /* if this is remateriazable */
9566       if (AOP_TYPE (left) == AOP_IMMD)
9567         {
9568           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9569           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9570             {
9571                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9572             }
9573             else
9574             {
9575                 emitcode ("mov", "b,#%d", pointerCode (retype));
9576             }
9577         }
9578       else
9579         {                       /* we need to get it byte by byte */
9580             _startLazyDPSEvaluation ();
9581             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9582             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9583             if (options.model == MODEL_FLAT24) {
9584                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9585                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9586             } else {
9587                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9588             }
9589             _endLazyDPSEvaluation ();
9590         }
9591     }
9592
9593   /* so dptr-b now contains the address */
9594   _G.bInUse++;
9595   aopOp (result, ic, FALSE, TRUE);
9596   _G.bInUse--;
9597
9598   /* if bit then unpack */
9599   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9600   {
9601     genUnpackBits (result, "dptr", GPOINTER);
9602   }
9603   else
9604     {
9605         size = AOP_SIZE (result);
9606         offset = 0;
9607
9608         while (size--)
9609         {
9610             if (size)
9611             {
9612                 // Get two bytes at a time, results in _AP & A.
9613                 // dptr will be incremented ONCE by __gptrgetWord.
9614                 //
9615                 // Note: any change here must be coordinated
9616                 // with the implementation of __gptrgetWord
9617                 // in device/lib/_gptrget.c
9618                 emitcode ("lcall", "__gptrgetWord");
9619                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9620                 aopPut (AOP (result), "a", offset++);
9621                 size--;
9622             }
9623             else
9624             {
9625                 // Only one byte to get.
9626                 emitcode ("lcall", "__gptrget");
9627                 aopPut (AOP (result), "a", offset++);
9628             }
9629             
9630             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9631             {
9632                 emitcode ("inc", "dptr");
9633             }
9634         }
9635     }
9636
9637   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9638     _startLazyDPSEvaluation ();
9639       
9640     aopPut ( AOP (left), "dpl", 0);
9641     aopPut ( AOP (left), "dph", 1);
9642     if (options.model == MODEL_FLAT24) {
9643         aopPut ( AOP (left), "dpx", 2);
9644         aopPut ( AOP (left), "b", 3);   
9645     } else  aopPut ( AOP (left), "b", 2);       
9646     
9647     _endLazyDPSEvaluation ();
9648       
9649     pi->generated = 1;
9650   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9651              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9652       
9653       size = AOP_SIZE (result) - 1;
9654       while (size--) emitcode ("lcall","__decdptr");
9655   }
9656
9657   freeAsmop (left, NULL, ic, TRUE);
9658   freeAsmop (result, NULL, ic, TRUE);
9659 }
9660
9661 /*-----------------------------------------------------------------*/
9662 /* genPointerGet - generate code for pointer get                   */
9663 /*-----------------------------------------------------------------*/
9664 static void
9665 genPointerGet (iCode * ic, iCode *pi)
9666 {
9667   operand *left, *result;
9668   sym_link *type, *etype;
9669   int p_type;
9670
9671   D (emitcode (";", "genPointerGet ");
9672     );
9673
9674   left = IC_LEFT (ic);
9675   result = IC_RESULT (ic);
9676
9677   /* depending on the type of pointer we need to
9678      move it to the correct pointer register */
9679   type = operandType (left);
9680   etype = getSpec (type);
9681   /* if left is of type of pointer then it is simple */
9682   if (IS_PTR (type) && !IS_FUNC (type->next))
9683     p_type = DCL_TYPE (type);
9684   else
9685     {
9686       /* we have to go by the storage class */
9687       p_type = PTR_TYPE (SPEC_OCLS (etype));
9688     }
9689   /* special case when cast remat */
9690   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9691       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9692           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9693           type = operandType (left);
9694           p_type = DCL_TYPE (type);
9695   }
9696   /* now that we have the pointer type we assign
9697      the pointer values */
9698   switch (p_type)
9699     {
9700
9701     case POINTER:
9702     case IPOINTER:
9703       genNearPointerGet (left, result, ic, pi);
9704       break;
9705
9706     case PPOINTER:
9707       genPagedPointerGet (left, result, ic, pi);
9708       break;
9709
9710     case FPOINTER:
9711       genFarPointerGet (left, result, ic, pi);
9712       break;
9713
9714     case CPOINTER:
9715       genCodePointerGet (left, result, ic, pi);
9716       break;
9717
9718     case GPOINTER:
9719       genGenPointerGet (left, result, ic, pi);
9720       break;
9721     }
9722
9723 }
9724
9725 /*-----------------------------------------------------------------*/
9726 /* genPackBits - generates code for packed bit storage             */
9727 /*-----------------------------------------------------------------*/
9728 static void
9729 genPackBits (sym_link * etype,
9730              operand * right,
9731              char *rname, int p_type)
9732 {
9733   int offset = 0;
9734   int rLen;
9735   int blen, bstr;
9736   char *l;
9737
9738   blen = SPEC_BLEN (etype);
9739   bstr = SPEC_BSTR (etype);
9740
9741   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9742
9743   /* if the bit lenth is less than or    */
9744   /* it exactly fits a byte then         */
9745   if (SPEC_BLEN (etype) <= 8)
9746     {
9747       /* shift left acc */
9748       AccLsh (SPEC_BSTR (etype));
9749
9750       if (SPEC_BLEN (etype) < 8)
9751         {                       /* if smaller than a byte */
9752
9753
9754           switch (p_type)
9755             {
9756             case POINTER:
9757               emitcode ("mov", "b,a");
9758               emitcode ("mov", "a,@%s", rname);
9759               break;
9760
9761             case FPOINTER:
9762               emitcode ("mov", "b,a");
9763               emitcode ("movx", "a,@dptr");
9764               break;
9765
9766             case GPOINTER:
9767               emitcode ("push", "b");
9768               emitcode ("push", "acc");
9769               emitcode ("lcall", "__gptrget");
9770               emitcode ("pop", "b");
9771               break;
9772             }
9773
9774           emitcode ("anl", "a,#!constbyte", (unsigned char)
9775                     ((unsigned char) (0xFF << (blen + bstr)) |
9776                      (unsigned char) (0xFF >> (8 - bstr))));
9777           emitcode ("orl", "a,b");
9778           if (p_type == GPOINTER)
9779             emitcode ("pop", "b");
9780         }
9781     }
9782
9783   switch (p_type)
9784     {
9785     case POINTER:
9786       emitcode ("mov", "@%s,a", rname);
9787       break;
9788
9789     case FPOINTER:
9790       emitcode ("movx", "@dptr,a");
9791       break;
9792
9793     case GPOINTER:
9794       emitcode ("lcall", "__gptrput");
9795       break;
9796     }
9797
9798   /* if we r done */
9799   if (SPEC_BLEN (etype) <= 8)
9800     return;
9801
9802   emitcode ("inc", "%s", rname);
9803   rLen = SPEC_BLEN (etype);
9804
9805   /* now generate for lengths greater than one byte */
9806   while (1)
9807     {
9808
9809       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9810
9811       rLen -= 8;
9812       if (rLen < 8)
9813         break;
9814
9815       switch (p_type)
9816         {
9817         case POINTER:
9818           if (*l == '@')
9819             {
9820               MOVA (l);
9821               emitcode ("mov", "@%s,a", rname);
9822             }
9823           else
9824             emitcode ("mov", "@%s,%s", rname, l);
9825           break;
9826
9827         case FPOINTER:
9828           MOVA (l);
9829           emitcode ("movx", "@dptr,a");
9830           break;
9831
9832         case GPOINTER:
9833           MOVA (l);
9834           emitcode ("lcall", "__gptrput");
9835           break;
9836         }
9837       emitcode ("inc", "%s", rname);
9838     }
9839
9840   MOVA (l);
9841
9842   /* last last was not complete */
9843   if (rLen)
9844     {
9845       /* save the byte & read byte */
9846       switch (p_type)
9847         {
9848         case POINTER:
9849           emitcode ("mov", "b,a");
9850           emitcode ("mov", "a,@%s", rname);
9851           break;
9852
9853         case FPOINTER:
9854           emitcode ("mov", "b,a");
9855           emitcode ("movx", "a,@dptr");
9856           break;
9857
9858         case GPOINTER:
9859           emitcode ("push", "b");
9860           emitcode ("push", "acc");
9861           emitcode ("lcall", "__gptrget");
9862           emitcode ("pop", "b");
9863           break;
9864         }
9865
9866       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9867       emitcode ("orl", "a,b");
9868     }
9869
9870   if (p_type == GPOINTER)
9871     emitcode ("pop", "b");
9872
9873   switch (p_type)
9874     {
9875
9876     case POINTER:
9877       emitcode ("mov", "@%s,a", rname);
9878       break;
9879
9880     case FPOINTER:
9881       emitcode ("movx", "@dptr,a");
9882       break;
9883
9884     case GPOINTER:
9885       emitcode ("lcall", "__gptrput");
9886       break;
9887     }
9888 }
9889 /*-----------------------------------------------------------------*/
9890 /* genDataPointerSet - remat pointer to data space                 */
9891 /*-----------------------------------------------------------------*/
9892 static void
9893 genDataPointerSet (operand * right,
9894                    operand * result,
9895                    iCode * ic)
9896 {
9897   int size, offset = 0;
9898   char *l, buff[256];
9899
9900   aopOp (right, ic, FALSE, FALSE);
9901
9902   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9903   size = AOP_SIZE (right);
9904   while (size--)
9905     {
9906       if (offset)
9907         {
9908             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9909         }
9910       else
9911         {
9912             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9913         }
9914         
9915       emitcode ("mov", "%s,%s", buff,
9916                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9917     }
9918
9919   freeAsmop (right, NULL, ic, TRUE);
9920   freeAsmop (result, NULL, ic, TRUE);
9921 }
9922
9923 /*-----------------------------------------------------------------*/
9924 /* genNearPointerSet - emitcode for near pointer put                */
9925 /*-----------------------------------------------------------------*/
9926 static void
9927 genNearPointerSet (operand * right,
9928                    operand * result,
9929                    iCode * ic,
9930                    iCode * pi)
9931 {
9932   asmop *aop = NULL;
9933   char *rname, *l;
9934   sym_link *retype, *letype;
9935   sym_link *ptype = operandType (result);
9936
9937   retype = getSpec (operandType (right));
9938   letype = getSpec (ptype);
9939
9940   aopOp (result, ic, FALSE, FALSE);
9941
9942   /* if the result is rematerializable &
9943      in data space & not a bit variable */
9944   if (AOP_TYPE (result) == AOP_IMMD &&
9945       DCL_TYPE (ptype) == POINTER &&
9946       !IS_BITVAR (retype) &&
9947       !IS_BITVAR (letype))
9948     {
9949       genDataPointerSet (right, result, ic);
9950       return;
9951     }
9952
9953   /* if the value is already in a pointer register
9954      then don't need anything more */
9955   if (!AOP_INPREG (AOP (result)))
9956     {
9957       /* otherwise get a free pointer register */
9958       regs *preg;
9959         
9960       aop = newAsmop (0);
9961       preg = getFreePtr (ic, &aop, FALSE);
9962       emitcode ("mov", "%s,%s",
9963                 preg->name,
9964                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9965       rname = preg->name;
9966     }
9967   else
9968     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9969
9970   aopOp (right, ic, FALSE, FALSE);
9971
9972   /* if bitfield then unpack the bits */
9973   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9974     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9975   else
9976     {
9977       /* we have can just get the values */
9978       int size = AOP_SIZE (right);
9979       int offset = 0;
9980
9981       while (size--)
9982         {
9983           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9984           if (*l == '@')
9985             {
9986               MOVA (l);
9987               emitcode ("mov", "@%s,a", rname);
9988             }
9989           else
9990             emitcode ("mov", "@%s,%s", rname, l);
9991           if (size || pi)
9992             emitcode ("inc", "%s", rname);
9993           offset++;
9994         }
9995     }
9996
9997   /* now some housekeeping stuff */
9998   if (aop)
9999     {
10000       /* we had to allocate for this iCode */
10001       if (pi) aopPut (AOP (result),rname,0);
10002       freeAsmop (NULL, aop, ic, TRUE);
10003     }
10004   else
10005     {
10006       /* we did not allocate which means left
10007          already in a pointer register, then
10008          if size > 0 && this could be used again
10009          we have to point it back to where it
10010          belongs */
10011       if (AOP_SIZE (right) > 1 &&
10012           !OP_SYMBOL (result)->remat &&
10013           (OP_SYMBOL (result)->liveTo > ic->seq ||
10014            ic->depth) &&
10015           !pi)
10016         {
10017           int size = AOP_SIZE (right) - 1;
10018           while (size--)
10019             emitcode ("dec", "%s", rname);
10020         }
10021     }
10022
10023   /* done */
10024   if (pi) pi->generated = 1;
10025   freeAsmop (result, NULL, ic, TRUE);
10026   freeAsmop (right, NULL, ic, TRUE);
10027
10028
10029 }
10030
10031 /*-----------------------------------------------------------------*/
10032 /* genPagedPointerSet - emitcode for Paged pointer put             */
10033 /*-----------------------------------------------------------------*/
10034 static void
10035 genPagedPointerSet (operand * right,
10036                     operand * result,
10037                     iCode * ic,
10038                     iCode *pi)
10039 {
10040   asmop *aop = NULL;
10041   char *rname;
10042   sym_link *retype, *letype;
10043
10044   retype = getSpec (operandType (right));
10045   letype = getSpec (operandType (result));
10046
10047   aopOp (result, ic, FALSE, FALSE);
10048
10049   /* if the value is already in a pointer register
10050      then don't need anything more */
10051   if (!AOP_INPREG (AOP (result)))
10052     {
10053       /* otherwise get a free pointer register */
10054       regs *preg;
10055         
10056       aop = newAsmop (0);
10057       preg = getFreePtr (ic, &aop, FALSE);
10058       emitcode ("mov", "%s,%s",
10059                 preg->name,
10060                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10061       rname = preg->name;
10062     }
10063   else
10064     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10065
10066   aopOp (right, ic, FALSE, FALSE);
10067
10068   /* if bitfield then unpack the bits */
10069   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10070     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10071   else
10072     {
10073       /* we have can just get the values */
10074       int size = AOP_SIZE (right);
10075       int offset = 0;
10076
10077       while (size--)
10078         {
10079           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10080
10081           emitcode ("movx", "@%s,a", rname);
10082
10083           if (size || pi)
10084             emitcode ("inc", "%s", rname);
10085
10086           offset++;
10087         }
10088     }
10089
10090   /* now some housekeeping stuff */
10091   if (aop)
10092     {
10093       if (pi) aopPut (AOP (result),rname,0);
10094       /* we had to allocate for this iCode */
10095       freeAsmop (NULL, aop, ic, TRUE);
10096     }
10097   else
10098     {
10099       /* we did not allocate which means left
10100          already in a pointer register, then
10101          if size > 0 && this could be used again
10102          we have to point it back to where it
10103          belongs */
10104       if (AOP_SIZE (right) > 1 &&
10105           !OP_SYMBOL (result)->remat &&
10106           (OP_SYMBOL (result)->liveTo > ic->seq ||
10107            ic->depth) &&
10108           !pi)
10109         {
10110           int size = AOP_SIZE (right) - 1;
10111           while (size--)
10112             emitcode ("dec", "%s", rname);
10113         }
10114     }
10115
10116   /* done */
10117   if (pi) pi->generated = 1;
10118   freeAsmop (result, NULL, ic, TRUE);
10119   freeAsmop (right, NULL, ic, TRUE);
10120
10121
10122 }
10123
10124 /*-----------------------------------------------------------------*/
10125 /* genFarPointerSet - set value from far space                     */
10126 /*-----------------------------------------------------------------*/
10127 static void
10128 genFarPointerSet (operand * right,
10129                   operand * result, iCode * ic, iCode *pi)
10130 {
10131   int size, offset, dopi=1;
10132   sym_link *retype = getSpec (operandType (right));
10133   sym_link *letype = getSpec (operandType (result));
10134
10135   aopOp (result, ic, FALSE, FALSE);
10136
10137   /* if the operand is already in dptr
10138      then we do nothing else we move the value to dptr */
10139   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10140     {
10141       /* if this is remateriazable */
10142       if (AOP_TYPE (result) == AOP_IMMD)
10143         emitcode ("mov", "dptr,%s", 
10144                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10145       else
10146         {
10147           /* we need to get it byte by byte */
10148           _startLazyDPSEvaluation ();
10149           if (AOP_TYPE (result) != AOP_DPTR)
10150             {
10151               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10152               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10153               if (options.model == MODEL_FLAT24)
10154                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10155             }
10156           else
10157             {
10158               /* We need to generate a load to DPTR indirect through DPTR. */
10159               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10160                 
10161               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10162               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10163               if (options.model == MODEL_FLAT24)
10164                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10165               emitcode ("pop", "dph");
10166               emitcode ("pop", "dpl");
10167               dopi=0;
10168             }
10169           _endLazyDPSEvaluation ();
10170         }
10171     }
10172   /* so dptr know contains the address */
10173   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10174
10175   /* if bit then unpack */
10176   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10177       if (AOP_INDPTRn(result)) {
10178           genSetDPTR(AOP(result)->aopu.dptr);
10179       }
10180       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10181       if (AOP_INDPTRn(result)) {
10182           genSetDPTR(0);
10183       }
10184   } else {
10185       size = AOP_SIZE (right);
10186       offset = 0;
10187       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10188           while (size--) {
10189               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10190               
10191               genSetDPTR(AOP(result)->aopu.dptr);
10192               emitcode ("movx", "@dptr,a");
10193               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10194                   emitcode ("inc", "dptr");
10195               genSetDPTR (0);
10196           }
10197       } else {
10198           _startLazyDPSEvaluation ();
10199           while (size--) {
10200               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10201               
10202               if (AOP_INDPTRn(result)) {
10203                   genSetDPTR(AOP(result)->aopu.dptr);
10204               } else {
10205                   genSetDPTR (0);
10206               }
10207               _flushLazyDPS ();
10208               
10209               emitcode ("movx", "@dptr,a");
10210               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10211                   emitcode ("inc", "dptr");
10212           }
10213           _endLazyDPSEvaluation ();
10214       }
10215   }
10216   
10217   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10218       if (!AOP_INDPTRn(result)) {
10219           _startLazyDPSEvaluation ();
10220           
10221           aopPut (AOP(result),"dpl",0);
10222           aopPut (AOP(result),"dph",1);
10223           if (options.model == MODEL_FLAT24)
10224               aopPut (AOP(result),"dpx",2);
10225
10226           _endLazyDPSEvaluation ();
10227       }
10228       pi->generated=1;
10229   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10230              AOP_SIZE(right) > 1 &&
10231              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10232       
10233       size = AOP_SIZE (right) - 1;
10234       if (AOP_INDPTRn(result)) {
10235           genSetDPTR(AOP(result)->aopu.dptr);
10236       } 
10237       while (size--) emitcode ("lcall","__decdptr");
10238       if (AOP_INDPTRn(result)) {
10239           genSetDPTR(0);
10240       }
10241   }
10242   freeAsmop (result, NULL, ic, TRUE);
10243   freeAsmop (right, NULL, ic, TRUE);
10244 }
10245
10246 /*-----------------------------------------------------------------*/
10247 /* genGenPointerSet - set value from generic pointer space         */
10248 /*-----------------------------------------------------------------*/
10249 static void
10250 genGenPointerSet (operand * right,
10251                   operand * result, iCode * ic, iCode *pi)
10252 {
10253   int size, offset;
10254   sym_link *retype = getSpec (operandType (right));
10255   sym_link *letype = getSpec (operandType (result));
10256
10257   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10258
10259   /* if the operand is already in dptr
10260      then we do nothing else we move the value to dptr */
10261   if (AOP_TYPE (result) != AOP_STR)
10262     {
10263       _startLazyDPSEvaluation ();
10264       /* if this is remateriazable */
10265       if (AOP_TYPE (result) == AOP_IMMD)
10266         {
10267           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10268           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10269           {
10270               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10271           }
10272           else
10273           {
10274               emitcode ("mov", 
10275                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10276           }
10277         }
10278       else
10279         {                       /* we need to get it byte by byte */
10280           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10281           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10282           if (options.model == MODEL_FLAT24) {
10283             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10284             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10285           } else {
10286             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10287           }
10288         }
10289       _endLazyDPSEvaluation ();
10290     }
10291   /* so dptr + b now contains the address */
10292   _G.bInUse++;
10293   aopOp (right, ic, FALSE, TRUE);
10294   _G.bInUse--;
10295     
10296
10297   /* if bit then unpack */
10298   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10299     {
10300         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10301     }
10302   else
10303     {
10304         size = AOP_SIZE (right);
10305         offset = 0;
10306
10307         _startLazyDPSEvaluation ();
10308         while (size--)
10309         {
10310             if (size)
10311             {
10312                 // Set two bytes at a time, passed in _AP & A.
10313                 // dptr will be incremented ONCE by __gptrputWord.
10314                 //
10315                 // Note: any change here must be coordinated
10316                 // with the implementation of __gptrputWord
10317                 // in device/lib/_gptrput.c
10318                 emitcode("mov", "_ap, %s", 
10319                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10320                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10321                 
10322                 genSetDPTR (0);
10323                 _flushLazyDPS ();
10324                 emitcode ("lcall", "__gptrputWord");
10325                 size--;
10326             }
10327             else
10328             {
10329                 // Only one byte to put.
10330                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10331
10332                 genSetDPTR (0);
10333                 _flushLazyDPS ();               
10334                 emitcode ("lcall", "__gptrput");
10335             }
10336             
10337             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10338             {
10339                 emitcode ("inc", "dptr");
10340             }
10341         }
10342         _endLazyDPSEvaluation ();
10343     }
10344
10345   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10346       _startLazyDPSEvaluation ();
10347       
10348       aopPut (AOP(result),"dpl",0);
10349       aopPut (AOP(result),"dph",1);
10350       if (options.model == MODEL_FLAT24) {
10351           aopPut (AOP(result),"dpx",2);
10352           aopPut (AOP(result),"b",3);
10353       } else {
10354           aopPut (AOP(result),"b",2);
10355       }
10356       _endLazyDPSEvaluation ();
10357       
10358       pi->generated=1;
10359   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10360              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10361       
10362       size = AOP_SIZE (right) - 1;
10363       while (size--) emitcode ("lcall","__decdptr");
10364   }
10365   freeAsmop (result, NULL, ic, TRUE);
10366   freeAsmop (right, NULL, ic, TRUE);
10367 }
10368
10369 /*-----------------------------------------------------------------*/
10370 /* genPointerSet - stores the value into a pointer location        */
10371 /*-----------------------------------------------------------------*/
10372 static void
10373 genPointerSet (iCode * ic, iCode *pi)
10374 {
10375   operand *right, *result;
10376   sym_link *type, *etype;
10377   int p_type;
10378
10379   D (emitcode (";", "genPointerSet "););
10380
10381   right = IC_RIGHT (ic);
10382   result = IC_RESULT (ic);
10383
10384   /* depending on the type of pointer we need to
10385      move it to the correct pointer register */
10386   type = operandType (result);
10387   etype = getSpec (type);
10388   /* if left is of type of pointer then it is simple */
10389   if (IS_PTR (type) && !IS_FUNC (type->next))
10390     {
10391       p_type = DCL_TYPE (type);
10392     }
10393   else
10394     {
10395       /* we have to go by the storage class */
10396       p_type = PTR_TYPE (SPEC_OCLS (etype));
10397     }
10398   /* special case when cast remat */
10399   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10400       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10401           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10402           type = operandType (result);
10403           p_type = DCL_TYPE (type);
10404   }
10405
10406   /* now that we have the pointer type we assign
10407      the pointer values */
10408   switch (p_type)
10409     {
10410
10411     case POINTER:
10412     case IPOINTER:
10413       genNearPointerSet (right, result, ic, pi);
10414       break;
10415
10416     case PPOINTER:
10417       genPagedPointerSet (right, result, ic, pi);
10418       break;
10419
10420     case FPOINTER:
10421       genFarPointerSet (right, result, ic, pi);
10422       break;
10423
10424     case GPOINTER:
10425       genGenPointerSet (right, result, ic, pi);
10426       break;
10427
10428     default:
10429       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10430               "genPointerSet: illegal pointer type");
10431     }
10432
10433 }
10434
10435 /*-----------------------------------------------------------------*/
10436 /* genIfx - generate code for Ifx statement                        */
10437 /*-----------------------------------------------------------------*/
10438 static void
10439 genIfx (iCode * ic, iCode * popIc)
10440 {
10441   operand *cond = IC_COND (ic);
10442   int isbit = 0;
10443
10444   D (emitcode (";", "genIfx "););
10445
10446   aopOp (cond, ic, FALSE, FALSE);
10447
10448   /* get the value into acc */
10449   if (AOP_TYPE (cond) != AOP_CRY)
10450     {
10451         toBoolean (cond);
10452     }
10453   else
10454     {
10455         isbit = 1;
10456     }
10457     
10458   /* the result is now in the accumulator */
10459   freeAsmop (cond, NULL, ic, TRUE);
10460
10461   /* if there was something to be popped then do it */
10462   if (popIc)
10463     genIpop (popIc);
10464
10465   /* if the condition is  a bit variable */
10466   if (isbit && IS_ITEMP (cond) &&
10467       SPIL_LOC (cond))
10468     {
10469         genIfxJump (ic, SPIL_LOC (cond)->rname);
10470     }
10471   else if (isbit && !IS_ITEMP (cond))
10472     {
10473         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10474     }
10475   else
10476     {
10477         genIfxJump (ic, "a");
10478     }
10479
10480   ic->generated = 1;
10481 }
10482
10483 /*-----------------------------------------------------------------*/
10484 /* genAddrOf - generates code for address of                       */
10485 /*-----------------------------------------------------------------*/
10486 static void
10487 genAddrOf (iCode * ic)
10488 {
10489   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10490   int size, offset;
10491
10492   D (emitcode (";", "genAddrOf ");
10493     );
10494
10495   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10496
10497   /* if the operand is on the stack then we
10498      need to get the stack offset of this
10499      variable */
10500   if (sym->onStack) {
10501       
10502       /* if 10 bit stack */
10503       if (options.stack10bit) {
10504           char buff[10];
10505           tsprintf(buff, sizeof(buff), 
10506                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10507           /* if it has an offset then we need to compute it */
10508 /*        emitcode ("subb", "a,#!constbyte", */
10509 /*                  -((sym->stack < 0) ? */
10510 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10511 /*                    ((short) sym->stack)) & 0xff); */
10512 /*        emitcode ("mov","b,a"); */
10513 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10514 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10515 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10516           if (sym->stack) {
10517               emitcode ("mov", "a,_bpx");
10518               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10519                                              ((char) (sym->stack - _G.nRegsSaved)) :
10520                                              ((char) sym->stack )) & 0xff);
10521               emitcode ("mov", "b,a");
10522               emitcode ("mov", "a,_bpx+1");
10523               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10524                                               ((short) (sym->stack - _G.nRegsSaved)) :
10525                                               ((short) sym->stack )) >> 8) & 0xff);
10526               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10527               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10528               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10529           } else {
10530               /* we can just move _bp */
10531               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10532               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10533               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10534           }       
10535       } else {
10536           /* if it has an offset then we need to compute it */
10537           if (sym->stack) {
10538               emitcode ("mov", "a,_bp");
10539               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10540               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10541           } else {
10542               /* we can just move _bp */
10543               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10544           }
10545           /* fill the result with zero */
10546           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10547           
10548           
10549           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10550               fprintf (stderr,
10551                        "*** warning: pointer to stack var truncated.\n");
10552           }
10553
10554           offset = 1;
10555           while (size--) {
10556               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10557           }      
10558       }
10559       goto release;
10560   }
10561
10562   /* object not on stack then we need the name */
10563   size = AOP_SIZE (IC_RESULT (ic));
10564   offset = 0;
10565
10566   while (size--)
10567     {
10568       char s[SDCC_NAME_MAX];
10569       if (offset) {
10570           switch (offset) {
10571           case 1:
10572               tsprintf(s, sizeof(s), "!his",sym->rname);
10573               break;
10574           case 2:
10575               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10576               break;
10577           case 3:
10578               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10579               break;
10580           default: /* should not need this (just in case) */
10581               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10582                        sym->rname,
10583                        offset * 8);
10584           }
10585       } 
10586       else
10587       {
10588           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10589       }
10590         
10591       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10592     }
10593
10594 release:
10595   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10596
10597 }
10598
10599 /*-----------------------------------------------------------------*/
10600 /* genArrayInit - generates code for address of                       */
10601 /*-----------------------------------------------------------------*/
10602 static void
10603 genArrayInit (iCode * ic)
10604 {
10605     literalList *iLoop;
10606     int         ix, count;
10607     int         elementSize = 0, eIndex;
10608     unsigned    val, lastVal;
10609     sym_link    *type;
10610     operand     *left=IC_LEFT(ic);
10611     
10612     D (emitcode (";", "genArrayInit "););
10613
10614     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10615     
10616     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10617     {
10618         // Load immediate value into DPTR.
10619         emitcode("mov", "dptr, %s",
10620              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10621     }
10622     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10623     {
10624 #if 0
10625       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10626               "Unexpected operand to genArrayInit.\n");
10627       exit(1);
10628 #else
10629       // a regression because of SDCCcse.c:1.52
10630       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10631       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10632       if (options.model == MODEL_FLAT24)
10633         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10634 #endif
10635     }
10636     
10637     type = operandType(IC_LEFT(ic));
10638     
10639     if (type && type->next)
10640     {
10641         elementSize = getSize(type->next);
10642     }
10643     else
10644     {
10645         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10646                                 "can't determine element size in genArrayInit.\n");
10647         exit(1);
10648     }
10649     
10650     iLoop = IC_ARRAYILIST(ic);
10651     lastVal = 0xffff;
10652     
10653     while (iLoop)
10654     {
10655         bool firstpass = TRUE;
10656         
10657         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10658                  iLoop->count, (int)iLoop->literalValue, elementSize);
10659         
10660         ix = iLoop->count;
10661         
10662         while (ix)
10663         {
10664             symbol *tlbl = NULL;
10665             
10666             count = ix > 256 ? 256 : ix;
10667             
10668             if (count > 1)
10669             {
10670                 tlbl = newiTempLabel (NULL);
10671                 if (firstpass || (count & 0xff))
10672                 {
10673                     emitcode("mov", "b, #!constbyte", count & 0xff);
10674                 }
10675                 
10676                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10677             }
10678             
10679             firstpass = FALSE;
10680                 
10681             for (eIndex = 0; eIndex < elementSize; eIndex++)
10682             {
10683                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10684                 if (val != lastVal)
10685                 {
10686                     emitcode("mov", "a, #!constbyte", val);
10687                     lastVal = val;
10688                 }
10689                 
10690                 emitcode("movx", "@dptr, a");
10691                 emitcode("inc", "dptr");
10692             }
10693             
10694             if (count > 1)
10695             {
10696                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10697             }
10698             
10699             ix -= count;
10700         }
10701         
10702         iLoop = iLoop->next;
10703     }
10704     
10705     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10706 }
10707
10708 /*-----------------------------------------------------------------*/
10709 /* genFarFarAssign - assignment when both are in far space         */
10710 /*-----------------------------------------------------------------*/
10711 static void
10712 genFarFarAssign (operand * result, operand * right, iCode * ic)
10713 {
10714   int size = AOP_SIZE (right);
10715   int offset = 0;
10716   symbol *rSym = NULL;
10717
10718   if (size == 1)
10719   {
10720       /* quick & easy case. */
10721       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10722       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10723       freeAsmop (right, NULL, ic, FALSE);
10724       /* now assign DPTR to result */
10725       _G.accInUse++;
10726       aopOp(result, ic, FALSE, FALSE);
10727       _G.accInUse--;
10728       aopPut(AOP(result), "a", 0);
10729       freeAsmop(result, NULL, ic, FALSE);
10730       return;
10731   }
10732   
10733   /* See if we've got an underlying symbol to abuse. */
10734   if (IS_SYMOP(result) && OP_SYMBOL(result))
10735   {
10736       if (IS_TRUE_SYMOP(result))
10737       {
10738           rSym = OP_SYMBOL(result);
10739       }
10740       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10741       {
10742           rSym = OP_SYMBOL(result)->usl.spillLoc;
10743       }
10744   }
10745              
10746   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10747   {
10748       /* We can use the '390 auto-toggle feature to good effect here. */
10749       
10750       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10751       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10752       emitcode ("mov", "dptr,#%s", rSym->rname); 
10753       /* DP2 = result, DP1 = right, DP1 is current. */
10754       while (size)
10755       {
10756           emitcode("movx", "a,@dptr");
10757           emitcode("movx", "@dptr,a");
10758           if (--size)
10759           {
10760                emitcode("inc", "dptr");
10761                emitcode("inc", "dptr");
10762           }
10763       }
10764       emitcode("mov", "dps,#0");
10765       freeAsmop (right, NULL, ic, FALSE);
10766 #if 0
10767 some alternative code for processors without auto-toggle
10768 no time to test now, so later well put in...kpb
10769         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10770         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10771         emitcode ("mov", "dptr,#%s", rSym->rname); 
10772         /* DP2 = result, DP1 = right, DP1 is current. */
10773         while (size)
10774         {
10775           --size;
10776           emitcode("movx", "a,@dptr");
10777           if (size)
10778             emitcode("inc", "dptr");
10779           emitcode("inc", "dps");
10780           emitcode("movx", "@dptr,a");
10781           if (size)
10782             emitcode("inc", "dptr");
10783           emitcode("inc", "dps");
10784         }
10785         emitcode("mov", "dps,#0");
10786         freeAsmop (right, NULL, ic, FALSE);
10787 #endif
10788   }
10789   else
10790   {
10791       D (emitcode (";", "genFarFarAssign"););
10792       aopOp (result, ic, TRUE, TRUE);
10793
10794       _startLazyDPSEvaluation ();
10795       
10796       while (size--)
10797         {
10798           aopPut (AOP (result),
10799                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10800           offset++;
10801         }
10802       _endLazyDPSEvaluation ();
10803       freeAsmop (result, NULL, ic, FALSE);
10804       freeAsmop (right, NULL, ic, FALSE);
10805   }
10806 }
10807
10808 /*-----------------------------------------------------------------*/
10809 /* genAssign - generate code for assignment                        */
10810 /*-----------------------------------------------------------------*/
10811 static void
10812 genAssign (iCode * ic)
10813 {
10814   operand *result, *right;
10815   int size, offset;
10816   unsigned long lit = 0L;
10817
10818   D (emitcode (";", "genAssign ");
10819     );
10820
10821   result = IC_RESULT (ic);
10822   right = IC_RIGHT (ic);
10823
10824   /* if they are the same */
10825   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10826     return;
10827
10828   aopOp (right, ic, FALSE, FALSE);
10829
10830   emitcode (";", "genAssign: resultIsFar = %s",
10831             isOperandInFarSpace (result) ?
10832             "TRUE" : "FALSE");
10833
10834   /* special case both in far space */
10835   if ((AOP_TYPE (right) == AOP_DPTR ||
10836        AOP_TYPE (right) == AOP_DPTR2) &&
10837   /* IS_TRUE_SYMOP(result)       && */
10838       isOperandInFarSpace (result))
10839     {
10840       genFarFarAssign (result, right, ic);
10841       return;
10842     }
10843
10844   aopOp (result, ic, TRUE, FALSE);
10845
10846   /* if they are the same registers */
10847   if (sameRegs (AOP (right), AOP (result)))
10848     goto release;
10849
10850   /* if the result is a bit */
10851   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10852     {
10853       /* if the right size is a literal then
10854          we know what the value is */
10855       if (AOP_TYPE (right) == AOP_LIT)
10856         {
10857           if (((int) operandLitValue (right)))
10858             aopPut (AOP (result), one, 0);
10859           else
10860             aopPut (AOP (result), zero, 0);
10861           goto release;
10862         }
10863
10864       /* the right is also a bit variable */
10865       if (AOP_TYPE (right) == AOP_CRY)
10866         {
10867           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10868           aopPut (AOP (result), "c", 0);
10869           goto release;
10870         }
10871
10872       /* we need to or */
10873       toBoolean (right);
10874       aopPut (AOP (result), "a", 0);
10875       goto release;
10876     }
10877
10878   /* bit variables done */
10879   /* general case */
10880   size = AOP_SIZE (result);
10881   offset = 0;
10882   if (AOP_TYPE (right) == AOP_LIT)
10883     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10884
10885   if ((size > 1) &&
10886       (AOP_TYPE (result) != AOP_REG) &&
10887       (AOP_TYPE (right) == AOP_LIT) &&
10888       !IS_FLOAT (operandType (right)))
10889     {
10890       _startLazyDPSEvaluation ();
10891       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10892         {
10893           aopPut (AOP (result),
10894                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10895                   offset);
10896           offset++;
10897           size--;
10898         }
10899       /* And now fill the rest with zeros. */
10900       if (size)
10901         {
10902           emitcode ("clr", "a");
10903         }
10904       while (size--)
10905         {
10906           aopPut (AOP (result), "a", offset++);
10907         }
10908       _endLazyDPSEvaluation ();
10909     }
10910   else
10911     {
10912       _startLazyDPSEvaluation ();
10913       while (size--)
10914         {
10915           aopPut (AOP (result),
10916                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10917                   offset);
10918           offset++;
10919         }
10920       _endLazyDPSEvaluation ();
10921     }
10922
10923 release:
10924   freeAsmop (right, NULL, ic, FALSE);
10925   freeAsmop (result, NULL, ic, TRUE);
10926 }
10927
10928 /*-----------------------------------------------------------------*/
10929 /* genJumpTab - generates code for jump table                      */
10930 /*-----------------------------------------------------------------*/
10931 static void
10932 genJumpTab (iCode * ic)
10933 {
10934   symbol *jtab;
10935   char *l;
10936
10937   D (emitcode (";", "genJumpTab ");
10938     );
10939
10940   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10941   /* get the condition into accumulator */
10942   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10943   MOVA (l);
10944   /* multiply by four! */
10945   emitcode ("add", "a,acc");
10946   emitcode ("add", "a,acc");
10947   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10948
10949   jtab = newiTempLabel (NULL);
10950   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10951   emitcode ("jmp", "@a+dptr");
10952   emitcode ("", "!tlabeldef", jtab->key + 100);
10953   /* now generate the jump labels */
10954   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10955        jtab = setNextItem (IC_JTLABELS (ic)))
10956     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10957
10958 }
10959
10960 /*-----------------------------------------------------------------*/
10961 /* genCast - gen code for casting                                  */
10962 /*-----------------------------------------------------------------*/
10963 static void
10964 genCast (iCode * ic)
10965 {
10966   operand *result = IC_RESULT (ic);
10967   sym_link *ctype = operandType (IC_LEFT (ic));
10968   sym_link *rtype = operandType (IC_RIGHT (ic));
10969   operand *right = IC_RIGHT (ic);
10970   int size, offset;
10971
10972   D (emitcode (";", "genCast "););
10973
10974   /* if they are equivalent then do nothing */
10975   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10976     return;
10977
10978   aopOp (right, ic, FALSE, FALSE);
10979   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10980
10981   /* if the result is a bit */
10982   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10983   if (IS_BITVAR(OP_SYMBOL(result)->type))
10984     {
10985       /* if the right size is a literal then
10986          we know what the value is */
10987       if (AOP_TYPE (right) == AOP_LIT)
10988         {
10989           if (((int) operandLitValue (right)))
10990             aopPut (AOP (result), one, 0);
10991           else
10992             aopPut (AOP (result), zero, 0);
10993
10994           goto release;
10995         }
10996
10997       /* the right is also a bit variable */
10998       if (AOP_TYPE (right) == AOP_CRY)
10999         {
11000           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11001           aopPut (AOP (result), "c", 0);
11002           goto release;
11003         }
11004
11005       /* we need to or */
11006       toBoolean (right);
11007       aopPut (AOP (result), "a", 0);
11008       goto release;
11009     }
11010
11011   /* if they are the same size : or less */
11012   if (AOP_SIZE (result) <= AOP_SIZE (right))
11013     {
11014
11015       /* if they are in the same place */
11016       if (sameRegs (AOP (right), AOP (result)))
11017         goto release;
11018
11019       /* if they in different places then copy */
11020       size = AOP_SIZE (result);
11021       offset = 0;
11022       _startLazyDPSEvaluation ();
11023       while (size--)
11024         {
11025           aopPut (AOP (result),
11026                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11027                   offset);
11028           offset++;
11029         }
11030       _endLazyDPSEvaluation ();
11031       goto release;
11032     }
11033
11034
11035   /* if the result is of type pointer */
11036   if (IS_PTR (ctype))
11037     {
11038
11039       int p_type;
11040       sym_link *type = operandType (right);
11041
11042       /* pointer to generic pointer */
11043       if (IS_GENPTR (ctype))
11044         {
11045           if (IS_PTR (type))
11046             {
11047               p_type = DCL_TYPE (type);
11048             }
11049           else
11050             {
11051 #if OLD_CAST_BEHAVIOR
11052               /* KV: we are converting a non-pointer type to
11053                * a generic pointer. This (ifdef'd out) code
11054                * says that the resulting generic pointer
11055                * should have the same class as the storage
11056                * location of the non-pointer variable.
11057                *
11058                * For example, converting an int (which happens
11059                * to be stored in DATA space) to a pointer results
11060                * in a DATA generic pointer; if the original int
11061                * in XDATA space, so will be the resulting pointer.
11062                *
11063                * I don't like that behavior, and thus this change:
11064                * all such conversions will be forced to XDATA and
11065                * throw a warning. If you want some non-XDATA
11066                * type, or you want to suppress the warning, you
11067                * must go through an intermediate cast, like so:
11068                *
11069                * char _generic *gp = (char _xdata *)(intVar);
11070                */
11071               sym_link *etype = getSpec (type);
11072
11073               /* we have to go by the storage class */
11074               if (SPEC_OCLS (etype) != generic)
11075                 {
11076                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11077                 }
11078               else
11079 #endif
11080                 {
11081                   /* Converting unknown class (i.e. register variable)
11082                    * to generic pointer. This is not good, but
11083                    * we'll make a guess (and throw a warning).
11084                    */
11085                   p_type = FPOINTER;
11086                   werror (W_INT_TO_GEN_PTR_CAST);
11087                 }
11088             }
11089
11090           /* the first two bytes are known */
11091           size = GPTRSIZE - 1;
11092           offset = 0;
11093           _startLazyDPSEvaluation ();
11094           while (size--)
11095             {
11096               aopPut (AOP (result),
11097                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11098                       offset);
11099               offset++;
11100             }
11101           _endLazyDPSEvaluation ();
11102
11103           /* the last byte depending on type */
11104             {
11105                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11106                 char gpValStr[10];
11107             
11108                 if (gpVal == -1)
11109                 {
11110                     // pointerTypeToGPByte will have bitched.
11111                     exit(1);
11112                 }
11113             
11114                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11115                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11116             }
11117           goto release;
11118         }
11119
11120       /* just copy the pointers */
11121       size = AOP_SIZE (result);
11122       offset = 0;
11123       _startLazyDPSEvaluation ();
11124       while (size--)
11125         {
11126           aopPut (AOP (result),
11127                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11128                   offset);
11129           offset++;
11130         }
11131       _endLazyDPSEvaluation ();
11132       goto release;
11133     }
11134
11135   /* so we now know that the size of destination is greater
11136      than the size of the source */
11137   /* we move to result for the size of source */
11138   size = AOP_SIZE (right);
11139   offset = 0;
11140   _startLazyDPSEvaluation ();
11141   while (size--)
11142     {
11143       aopPut (AOP (result),
11144               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11145               offset);
11146       offset++;
11147     }
11148   _endLazyDPSEvaluation ();
11149
11150   /* now depending on the sign of the source && destination */
11151   size = AOP_SIZE (result) - AOP_SIZE (right);
11152   /* if unsigned or not an integral type */
11153   /* also, if the source is a bit, we don't need to sign extend, because
11154    * it can't possibly have set the sign bit.
11155    */
11156   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11157     {
11158       while (size--)
11159         {
11160           aopPut (AOP (result), zero, offset++);
11161         }
11162     }
11163   else
11164     {
11165       /* we need to extend the sign :{ */
11166       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11167                         FALSE, FALSE, NULL));
11168       emitcode ("rlc", "a");
11169       emitcode ("subb", "a,acc");
11170       while (size--)
11171         aopPut (AOP (result), "a", offset++);
11172     }
11173
11174   /* we are done hurray !!!! */
11175
11176 release:
11177   freeAsmop (right, NULL, ic, TRUE);
11178   freeAsmop (result, NULL, ic, TRUE);
11179
11180 }
11181
11182 /*-----------------------------------------------------------------*/
11183 /* genDjnz - generate decrement & jump if not zero instrucion      */
11184 /*-----------------------------------------------------------------*/
11185 static int
11186 genDjnz (iCode * ic, iCode * ifx)
11187 {
11188   symbol *lbl, *lbl1;
11189   if (!ifx)
11190     return 0;
11191
11192   /* if the if condition has a false label
11193      then we cannot save */
11194   if (IC_FALSE (ifx))
11195     return 0;
11196
11197   /* if the minus is not of the form
11198      a = a - 1 */
11199   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11200       !IS_OP_LITERAL (IC_RIGHT (ic)))
11201     return 0;
11202
11203   if (operandLitValue (IC_RIGHT (ic)) != 1)
11204     return 0;
11205
11206   /* if the size of this greater than one then no
11207      saving */
11208   if (getSize (operandType (IC_RESULT (ic))) > 1)
11209     return 0;
11210
11211   /* otherwise we can save BIG */
11212   D(emitcode(";", "genDjnz"););
11213
11214   lbl = newiTempLabel (NULL);
11215   lbl1 = newiTempLabel (NULL);
11216
11217   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11218
11219   if (AOP_NEEDSACC(IC_RESULT(ic)))
11220   {
11221       /* If the result is accessed indirectly via
11222        * the accumulator, we must explicitly write
11223        * it back after the decrement.
11224        */
11225       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11226       
11227       if (strcmp(rByte, "a"))
11228       {
11229            /* Something is hopelessly wrong */
11230            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11231                    __FILE__, __LINE__);
11232            /* We can just give up; the generated code will be inefficient,
11233             * but what the hey.
11234             */
11235            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11236            return 0;
11237       }
11238       emitcode ("dec", "%s", rByte);
11239       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11240       emitcode ("jnz", "!tlabel", lbl->key + 100);
11241   }
11242   else if (IS_AOP_PREG (IC_RESULT (ic)))
11243     {
11244       emitcode ("dec", "%s",
11245                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11246       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11247       emitcode ("jnz", "!tlabel", lbl->key + 100);
11248     }
11249   else
11250     {
11251       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11252                 lbl->key + 100);
11253     }
11254   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11255   emitcode ("", "!tlabeldef", lbl->key + 100);
11256   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11257   emitcode ("", "!tlabeldef", lbl1->key + 100);
11258
11259   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11260   ifx->generated = 1;
11261   return 1;
11262 }
11263
11264 /*-----------------------------------------------------------------*/
11265 /* genReceive - generate code for a receive iCode                  */
11266 /*-----------------------------------------------------------------*/
11267 static void
11268 genReceive (iCode * ic)
11269 {
11270     int size = getSize (operandType (IC_RESULT (ic)));
11271     int offset = 0;
11272     int rb1off ;
11273     
11274     D (emitcode (";", "genReceive "););
11275
11276     if (ic->argreg == 1) 
11277     {
11278         /* first parameter */
11279         if (AOP_IS_STR(IC_RESULT(ic)))
11280         {
11281             /* Nothing to do: it's already in the proper place. */
11282             return;
11283         }
11284         else
11285         {
11286             bool useDp2;
11287             
11288             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11289                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11290                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11291             
11292             _G.accInUse++;
11293             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11294             _G.accInUse--; 
11295             
11296             /* Sanity checking... */
11297             if (AOP_USESDPTR(IC_RESULT(ic)))
11298             {
11299                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11300                         "genReceive got unexpected DPTR.");
11301             }
11302             assignResultValue (IC_RESULT (ic));
11303         }
11304     } 
11305     else 
11306     { 
11307         /* second receive onwards */
11308         /* this gets a little tricky since unused recevies will be
11309          eliminated, we have saved the reg in the type field . and
11310          we use that to figure out which register to use */
11311         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11312         rb1off = ic->argreg;
11313         while (size--) 
11314         {
11315             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11316         }
11317     }
11318     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11319 }
11320
11321 /*-----------------------------------------------------------------*/
11322 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11323 /*-----------------------------------------------------------------*/
11324 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11325 {
11326     operand *from , *to , *count;
11327     symbol *lbl;
11328     bitVect *rsave;
11329     int i;
11330
11331     /* we know it has to be 3 parameters */
11332     assert (nparms == 3);
11333     
11334     rsave = newBitVect(16);
11335     /* save DPTR if it needs to be saved */
11336     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11337             if (bitVectBitValue(ic->rMask,i))
11338                     rsave = bitVectSetBit(rsave,i);
11339     }
11340     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11341                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11342     savermask(rsave);
11343     
11344     to = parms[0];
11345     from = parms[1];
11346     count = parms[2];
11347
11348     aopOp (from, ic->next, FALSE, FALSE);
11349
11350     /* get from into DPTR1 */
11351     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11352     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11353     if (options.model == MODEL_FLAT24) {
11354         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11355     }
11356
11357     freeAsmop (from, NULL, ic, FALSE);
11358     aopOp (to, ic, FALSE, FALSE);
11359     /* get "to" into DPTR */
11360     /* if the operand is already in dptr
11361        then we do nothing else we move the value to dptr */
11362     if (AOP_TYPE (to) != AOP_STR) {
11363         /* if already in DPTR then we need to push */
11364         if (AOP_TYPE(to) == AOP_DPTR) {
11365             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11366             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11367             if (options.model == MODEL_FLAT24)
11368                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11369             emitcode ("pop", "dph");
11370             emitcode ("pop", "dpl");        
11371         } else {
11372             _startLazyDPSEvaluation ();
11373             /* if this is remateriazable */
11374             if (AOP_TYPE (to) == AOP_IMMD) {
11375                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11376             } else {                    /* we need to get it byte by byte */
11377                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11378                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11379                 if (options.model == MODEL_FLAT24) {
11380                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11381                 }
11382             }
11383             _endLazyDPSEvaluation ();
11384         }
11385     }
11386     freeAsmop (to, NULL, ic, FALSE);
11387     _G.dptrInUse = _G.dptr1InUse = 1;
11388     aopOp (count, ic->next->next, FALSE,FALSE);
11389     lbl =newiTempLabel(NULL);
11390
11391     /* now for the actual copy */
11392     if (AOP_TYPE(count) == AOP_LIT && 
11393         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11394         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11395         if (fromc) {
11396             emitcode ("lcall","__bi_memcpyc2x_s");
11397         } else {
11398             emitcode ("lcall","__bi_memcpyx2x_s");
11399         }
11400         freeAsmop (count, NULL, ic, FALSE);
11401     } else {
11402         symbol *lbl1 = newiTempLabel(NULL);
11403         
11404         emitcode (";"," Auto increment but no djnz");
11405         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11406         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11407         freeAsmop (count, NULL, ic, FALSE);
11408         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11409         emitcode ("","!tlabeldef",lbl->key+100);
11410         if (fromc) {
11411             emitcode ("clr","a");
11412             emitcode ("movc", "a,@a+dptr");
11413         } else 
11414             emitcode ("movx", "a,@dptr");
11415         emitcode ("movx", "@dptr,a");
11416         emitcode ("inc", "dptr");
11417         emitcode ("inc", "dptr");
11418         emitcode ("mov","a,b");
11419         emitcode ("orl","a,_ap");
11420         emitcode ("jz","!tlabel",lbl1->key+100);
11421         emitcode ("mov","a,_ap");
11422         emitcode ("add","a,#!constbyte",0xFF);
11423         emitcode ("mov","_ap,a");
11424         emitcode ("mov","a,b");
11425         emitcode ("addc","a,#!constbyte",0xFF);
11426         emitcode ("mov","b,a");
11427         emitcode ("sjmp","!tlabel",lbl->key+100);
11428         emitcode ("","!tlabeldef",lbl1->key+100);
11429     }
11430     emitcode ("mov", "dps,#0"); 
11431     _G.dptrInUse = _G.dptr1InUse = 0;
11432     unsavermask(rsave);
11433
11434 }
11435
11436 /*-----------------------------------------------------------------*/
11437 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11438 /*-----------------------------------------------------------------*/
11439 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11440 {
11441     operand *from , *to , *count;
11442     symbol *lbl,*lbl2;
11443     bitVect *rsave;
11444     int i;
11445
11446     /* we know it has to be 3 parameters */
11447     assert (nparms == 3);
11448     
11449     rsave = newBitVect(16);
11450     /* save DPTR if it needs to be saved */
11451     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11452             if (bitVectBitValue(ic->rMask,i))
11453                     rsave = bitVectSetBit(rsave,i);
11454     }
11455     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11456                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11457     savermask(rsave);
11458     
11459     to = parms[0];
11460     from = parms[1];
11461     count = parms[2];
11462
11463     aopOp (from, ic->next, FALSE, FALSE);
11464
11465     /* get from into DPTR1 */
11466     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11467     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11468     if (options.model == MODEL_FLAT24) {
11469         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11470     }
11471
11472     freeAsmop (from, NULL, ic, FALSE);
11473     aopOp (to, ic, FALSE, FALSE);
11474     /* get "to" into DPTR */
11475     /* if the operand is already in dptr
11476        then we do nothing else we move the value to dptr */
11477     if (AOP_TYPE (to) != AOP_STR) {
11478         /* if already in DPTR then we need to push */
11479         if (AOP_TYPE(to) == AOP_DPTR) {
11480             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11481             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11482             if (options.model == MODEL_FLAT24)
11483                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11484             emitcode ("pop", "dph");
11485             emitcode ("pop", "dpl");        
11486         } else {
11487             _startLazyDPSEvaluation ();
11488             /* if this is remateriazable */
11489             if (AOP_TYPE (to) == AOP_IMMD) {
11490                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11491             } else {                    /* we need to get it byte by byte */
11492                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11493                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11494                 if (options.model == MODEL_FLAT24) {
11495                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11496                 }
11497             }
11498             _endLazyDPSEvaluation ();
11499         }
11500     }
11501     freeAsmop (to, NULL, ic, FALSE);
11502     _G.dptrInUse = _G.dptr1InUse = 1;
11503     aopOp (count, ic->next->next, FALSE,FALSE);
11504     lbl =newiTempLabel(NULL);
11505     lbl2 =newiTempLabel(NULL);
11506
11507     /* now for the actual compare */
11508     if (AOP_TYPE(count) == AOP_LIT && 
11509         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11510         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11511         if (fromc)
11512             emitcode("lcall","__bi_memcmpc2x_s");
11513         else
11514             emitcode("lcall","__bi_memcmpx2x_s");
11515         freeAsmop (count, NULL, ic, FALSE);
11516         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11517         aopPut(AOP(IC_RESULT(ic)),"a",0);
11518         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11519     } else {
11520         symbol *lbl1 = newiTempLabel(NULL);
11521
11522         emitcode("push","ar0");         
11523         emitcode (";"," Auto increment but no djnz");
11524         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11525         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11526         freeAsmop (count, NULL, ic, FALSE);
11527         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11528         emitcode ("","!tlabeldef",lbl->key+100);
11529         if (fromc) {
11530             emitcode ("clr","a");
11531             emitcode ("movc", "a,@a+dptr");
11532         } else 
11533             emitcode ("movx", "a,@dptr");
11534         emitcode ("mov","r0,a");
11535         emitcode ("movx", "a,@dptr");
11536         emitcode ("clr","c");
11537         emitcode ("subb","a,r0");
11538         emitcode ("jnz","!tlabel",lbl2->key+100);
11539         emitcode ("inc", "dptr");
11540         emitcode ("inc", "dptr");
11541         emitcode ("mov","a,b");
11542         emitcode ("orl","a,_ap");
11543         emitcode ("jz","!tlabel",lbl1->key+100);
11544         emitcode ("mov","a,_ap");
11545         emitcode ("add","a,#!constbyte",0xFF);
11546         emitcode ("mov","_ap,a");
11547         emitcode ("mov","a,b");
11548         emitcode ("addc","a,#!constbyte",0xFF);
11549         emitcode ("mov","b,a");
11550         emitcode ("sjmp","!tlabel",lbl->key+100);
11551         emitcode ("","!tlabeldef",lbl1->key+100);
11552         emitcode ("clr","a");
11553         emitcode ("","!tlabeldef",lbl2->key+100);
11554         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11555         aopPut(AOP(IC_RESULT(ic)),"a",0);
11556         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11557         emitcode("pop","ar0");
11558         emitcode ("mov", "dps,#0");      
11559     }
11560     _G.dptrInUse = _G.dptr1InUse = 0;
11561     unsavermask(rsave);
11562
11563 }
11564
11565 /*-----------------------------------------------------------------*/
11566 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11567 /* port, first parameter output area second parameter pointer to   */
11568 /* port third parameter count                                      */
11569 /*-----------------------------------------------------------------*/
11570 static void genInp( iCode *ic, int nparms, operand **parms)
11571 {
11572     operand *from , *to , *count;
11573     symbol *lbl;
11574     bitVect *rsave;
11575     int i;
11576
11577     /* we know it has to be 3 parameters */
11578     assert (nparms == 3);
11579     
11580     rsave = newBitVect(16);
11581     /* save DPTR if it needs to be saved */
11582     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11583             if (bitVectBitValue(ic->rMask,i))
11584                     rsave = bitVectSetBit(rsave,i);
11585     }
11586     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11587                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11588     savermask(rsave);
11589     
11590     to = parms[0];
11591     from = parms[1];
11592     count = parms[2];
11593
11594     aopOp (from, ic->next, FALSE, FALSE);
11595
11596     /* get from into DPTR1 */
11597     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11598     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11599     if (options.model == MODEL_FLAT24) {
11600         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11601     }
11602
11603     freeAsmop (from, NULL, ic, FALSE);
11604     aopOp (to, ic, FALSE, FALSE);
11605     /* get "to" into DPTR */
11606     /* if the operand is already in dptr
11607        then we do nothing else we move the value to dptr */
11608     if (AOP_TYPE (to) != AOP_STR) {
11609         /* if already in DPTR then we need to push */
11610         if (AOP_TYPE(to) == AOP_DPTR) {
11611             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11612             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11613             if (options.model == MODEL_FLAT24)
11614                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11615             emitcode ("pop", "dph");
11616             emitcode ("pop", "dpl");        
11617         } else {
11618             _startLazyDPSEvaluation ();
11619             /* if this is remateriazable */
11620             if (AOP_TYPE (to) == AOP_IMMD) {
11621                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11622             } else {                    /* we need to get it byte by byte */
11623                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11624                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11625                 if (options.model == MODEL_FLAT24) {
11626                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11627                 }
11628             }
11629             _endLazyDPSEvaluation ();
11630         }
11631     }
11632     freeAsmop (to, NULL, ic, FALSE);
11633
11634     _G.dptrInUse = _G.dptr1InUse = 1;
11635     aopOp (count, ic->next->next, FALSE,FALSE);
11636     lbl =newiTempLabel(NULL);
11637
11638     /* now for the actual copy */
11639     if (AOP_TYPE(count) == AOP_LIT && 
11640         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11641         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11642         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11643         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11644         freeAsmop (count, NULL, ic, FALSE);
11645         emitcode ("","!tlabeldef",lbl->key+100);
11646         emitcode ("movx", "a,@dptr");   /* read data from port */
11647         emitcode ("dec","dps");         /* switch to DPTR */
11648         emitcode ("movx", "@dptr,a");   /* save into location */
11649         emitcode ("inc", "dptr");       /* point to next area */
11650         emitcode ("inc","dps");         /* switch to DPTR2 */
11651         emitcode ("djnz","b,!tlabel",lbl->key+100);
11652     } else {
11653         symbol *lbl1 = newiTempLabel(NULL);
11654         
11655         emitcode (";"," Auto increment but no djnz");
11656         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11657         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11658         freeAsmop (count, NULL, ic, FALSE);
11659         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11660         emitcode ("","!tlabeldef",lbl->key+100);
11661         emitcode ("movx", "a,@dptr");
11662         emitcode ("dec","dps");         /* switch to DPTR */
11663         emitcode ("movx", "@dptr,a");
11664         emitcode ("inc", "dptr");
11665         emitcode ("inc","dps");         /* switch to DPTR2 */
11666 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11667 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11668         emitcode ("mov","a,b");
11669         emitcode ("orl","a,_ap");
11670         emitcode ("jz","!tlabel",lbl1->key+100);
11671         emitcode ("mov","a,_ap");
11672         emitcode ("add","a,#!constbyte",0xFF);
11673         emitcode ("mov","_ap,a");
11674         emitcode ("mov","a,b");
11675         emitcode ("addc","a,#!constbyte",0xFF);
11676         emitcode ("mov","b,a");
11677         emitcode ("sjmp","!tlabel",lbl->key+100);
11678         emitcode ("","!tlabeldef",lbl1->key+100);
11679     }
11680     emitcode ("mov", "dps,#0"); 
11681     _G.dptrInUse = _G.dptr1InUse = 0;
11682     unsavermask(rsave);
11683
11684 }
11685
11686 /*-----------------------------------------------------------------*/
11687 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11688 /* port, first parameter output area second parameter pointer to   */
11689 /* port third parameter count                                      */
11690 /*-----------------------------------------------------------------*/
11691 static void genOutp( iCode *ic, int nparms, operand **parms)
11692 {
11693     operand *from , *to , *count;
11694     symbol *lbl;
11695     bitVect *rsave;
11696     int i;
11697
11698     /* we know it has to be 3 parameters */
11699     assert (nparms == 3);
11700     
11701     rsave = newBitVect(16);
11702     /* save DPTR if it needs to be saved */
11703     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11704             if (bitVectBitValue(ic->rMask,i))
11705                     rsave = bitVectSetBit(rsave,i);
11706     }
11707     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11708                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11709     savermask(rsave);
11710     
11711     to = parms[0];
11712     from = parms[1];
11713     count = parms[2];
11714
11715     aopOp (from, ic->next, FALSE, FALSE);
11716
11717     /* get from into DPTR1 */
11718     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11719     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11720     if (options.model == MODEL_FLAT24) {
11721         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11722     }
11723
11724     freeAsmop (from, NULL, ic, FALSE);
11725     aopOp (to, ic, FALSE, FALSE);
11726     /* get "to" into DPTR */
11727     /* if the operand is already in dptr
11728        then we do nothing else we move the value to dptr */
11729     if (AOP_TYPE (to) != AOP_STR) {
11730         /* if already in DPTR then we need to push */
11731         if (AOP_TYPE(to) == AOP_DPTR) {
11732             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11733             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11734             if (options.model == MODEL_FLAT24)
11735                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11736             emitcode ("pop", "dph");
11737             emitcode ("pop", "dpl");        
11738         } else {
11739             _startLazyDPSEvaluation ();
11740             /* if this is remateriazable */
11741             if (AOP_TYPE (to) == AOP_IMMD) {
11742                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11743             } else {                    /* we need to get it byte by byte */
11744                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11745                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11746                 if (options.model == MODEL_FLAT24) {
11747                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11748                 }
11749             }
11750             _endLazyDPSEvaluation ();
11751         }
11752     }
11753     freeAsmop (to, NULL, ic, FALSE);
11754
11755     _G.dptrInUse = _G.dptr1InUse = 1;
11756     aopOp (count, ic->next->next, FALSE,FALSE);
11757     lbl =newiTempLabel(NULL);
11758
11759     /* now for the actual copy */
11760     if (AOP_TYPE(count) == AOP_LIT && 
11761         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11762         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11763         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11764         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11765         emitcode ("","!tlabeldef",lbl->key+100);
11766         emitcode ("movx", "a,@dptr");   /* read data from port */
11767         emitcode ("inc","dps");         /* switch to DPTR2 */
11768         emitcode ("movx", "@dptr,a");   /* save into location */
11769         emitcode ("inc", "dptr");       /* point to next area */
11770         emitcode ("dec","dps");         /* switch to DPTR */
11771         emitcode ("djnz","b,!tlabel",lbl->key+100);
11772         freeAsmop (count, NULL, ic, FALSE);
11773     } else {
11774         symbol *lbl1 = newiTempLabel(NULL);
11775         
11776         emitcode (";"," Auto increment but no djnz");
11777         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11778         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11779         freeAsmop (count, NULL, ic, FALSE);
11780         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11781         emitcode ("","!tlabeldef",lbl->key+100);
11782         emitcode ("movx", "a,@dptr");
11783         emitcode ("inc", "dptr");
11784         emitcode ("inc","dps");         /* switch to DPTR2 */
11785         emitcode ("movx", "@dptr,a");
11786         emitcode ("dec","dps");         /* switch to DPTR */
11787         emitcode ("mov","a,b");
11788         emitcode ("orl","a,_ap");
11789         emitcode ("jz","!tlabel",lbl1->key+100);
11790         emitcode ("mov","a,_ap");
11791         emitcode ("add","a,#!constbyte",0xFF);
11792         emitcode ("mov","_ap,a");
11793         emitcode ("mov","a,b");
11794         emitcode ("addc","a,#!constbyte",0xFF);
11795         emitcode ("mov","b,a");
11796         emitcode ("sjmp","!tlabel",lbl->key+100);
11797         emitcode ("","!tlabeldef",lbl1->key+100);
11798     }
11799     emitcode ("mov", "dps,#0"); 
11800     _G.dptrInUse = _G.dptr1InUse = 0;
11801     unsavermask(rsave);
11802
11803 }
11804
11805 /*-----------------------------------------------------------------*/
11806 /* genSwapW - swap lower & high order bytes                        */
11807 /*-----------------------------------------------------------------*/
11808 static void genSwapW(iCode *ic, int nparms, operand **parms)
11809 {
11810     operand *dest;
11811     operand *src;
11812     assert (nparms==1);
11813
11814     src = parms[0];
11815     dest=IC_RESULT(ic);
11816
11817     assert(getSize(operandType(src))==2);
11818
11819     aopOp (src, ic, FALSE, FALSE);
11820     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11821     _G.accInUse++;
11822     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11823     _G.accInUse--;
11824     freeAsmop (src, NULL, ic, FALSE);
11825     
11826     aopOp (dest,ic, FALSE, FALSE);
11827     aopPut(AOP(dest),"b",0);
11828     aopPut(AOP(dest),"a",1);
11829     freeAsmop (dest, NULL, ic, FALSE);    
11830 }
11831
11832 /*-----------------------------------------------------------------*/
11833 /* genMemsetX - gencode for memSetX data                           */
11834 /*-----------------------------------------------------------------*/
11835 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11836 {
11837     operand *to , *val , *count;
11838     symbol *lbl;
11839     char *l;
11840     int i;
11841     bitVect *rsave;
11842
11843     /* we know it has to be 3 parameters */
11844     assert (nparms == 3);
11845     
11846     to = parms[0];
11847     val = parms[1];
11848     count = parms[2];
11849         
11850     /* save DPTR if it needs to be saved */
11851     rsave = newBitVect(16);
11852     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11853             if (bitVectBitValue(ic->rMask,i))
11854                     rsave = bitVectSetBit(rsave,i);
11855     }
11856     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11857                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11858     savermask(rsave);
11859
11860     aopOp (to, ic, FALSE, FALSE);
11861     /* get "to" into DPTR */
11862     /* if the operand is already in dptr
11863        then we do nothing else we move the value to dptr */
11864     if (AOP_TYPE (to) != AOP_STR) {
11865         /* if already in DPTR then we need to push */
11866         if (AOP_TYPE(to) == AOP_DPTR) {
11867             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11868             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11869             if (options.model == MODEL_FLAT24)
11870                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11871             emitcode ("pop", "dph");
11872             emitcode ("pop", "dpl");        
11873         } else {
11874             _startLazyDPSEvaluation ();
11875             /* if this is remateriazable */
11876             if (AOP_TYPE (to) == AOP_IMMD) {
11877                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11878             } else {                    /* we need to get it byte by byte */
11879                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11880                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11881                 if (options.model == MODEL_FLAT24) {
11882                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11883                 }
11884             }
11885             _endLazyDPSEvaluation ();
11886         }
11887     }
11888     freeAsmop (to, NULL, ic, FALSE);
11889
11890     aopOp (val, ic->next->next, FALSE,FALSE);
11891     aopOp (count, ic->next->next, FALSE,FALSE);    
11892     lbl =newiTempLabel(NULL);
11893     /* now for the actual copy */
11894     if (AOP_TYPE(count) == AOP_LIT && 
11895         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11896         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11897         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11898         MOVA(l);
11899         emitcode ("","!tlabeldef",lbl->key+100);
11900         emitcode ("movx", "@dptr,a");
11901         emitcode ("inc", "dptr");
11902         emitcode ("djnz","b,!tlabel",lbl->key+100);
11903     } else {
11904         symbol *lbl1 = newiTempLabel(NULL);
11905         
11906         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11907         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11908         emitcode ("","!tlabeldef",lbl->key+100);
11909         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11910         emitcode ("movx", "@dptr,a");
11911         emitcode ("inc", "dptr");
11912         emitcode ("mov","a,b");
11913         emitcode ("orl","a,_ap");
11914         emitcode ("jz","!tlabel",lbl1->key+100);
11915         emitcode ("mov","a,_ap");
11916         emitcode ("add","a,#!constbyte",0xFF);
11917         emitcode ("mov","_ap,a");
11918         emitcode ("mov","a,b");
11919         emitcode ("addc","a,#!constbyte",0xFF);
11920         emitcode ("mov","b,a");
11921         emitcode ("sjmp","!tlabel",lbl->key+100);
11922         emitcode ("","!tlabeldef",lbl1->key+100);
11923     }
11924     freeAsmop (count, NULL, ic, FALSE);
11925     unsavermask(rsave);
11926 }
11927
11928 /*-----------------------------------------------------------------*/
11929 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11930 /*-----------------------------------------------------------------*/
11931 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11932 {
11933         bitVect *rsave ;
11934         operand *pnum, *result;
11935         int i;
11936     
11937         assert (nparms==1);
11938         /* save registers that need to be saved */
11939         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11940                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11941     
11942         pnum = parms[0]; 
11943         aopOp (pnum, ic, FALSE, FALSE);
11944         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11945         freeAsmop (pnum, NULL, ic, FALSE);
11946         emitcode ("lcall","NatLib_LoadPrimitive");
11947         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11948         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11949             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11950                 for (i = (size-1) ; i >= 0 ; i-- ) {
11951                         emitcode ("push","a%s",javaRet[i]);
11952                 }
11953                 for (i=0; i < size ; i++ ) {
11954                         emitcode ("pop","a%s",
11955                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11956                 }
11957         } else {
11958                 for (i = 0 ; i < size ; i++ ) {
11959                         aopPut(AOP(result),javaRet[i],i);
11960                 }
11961         }    
11962         freeAsmop (result, NULL, ic, FALSE);
11963         unsavermask(rsave);
11964 }
11965
11966 /*-----------------------------------------------------------------*/
11967 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11968 /*-----------------------------------------------------------------*/
11969 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11970 {
11971         bitVect *rsave ;
11972         operand *pnum, *result;
11973         int size = 3;
11974         int i;
11975     
11976         assert (nparms==1);
11977         /* save registers that need to be saved */
11978         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11979                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11980     
11981         pnum = parms[0]; 
11982         aopOp (pnum, ic, FALSE, FALSE);
11983         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11984         freeAsmop (pnum, NULL, ic, FALSE);
11985         emitcode ("lcall","NatLib_LoadPointer");
11986         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11987         if (AOP_TYPE(result)!=AOP_STR) {
11988                 for (i = 0 ; i < size ; i++ ) {
11989                         aopPut(AOP(result),fReturn[i],i);
11990                 }
11991         }    
11992         freeAsmop (result, NULL, ic, FALSE);
11993         unsavermask(rsave);
11994 }
11995
11996 /*-----------------------------------------------------------------*/
11997 /* genNatLibInstallStateBlock -                                    */
11998 /*-----------------------------------------------------------------*/
11999 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12000                                        operand **parms, const char *name)
12001 {
12002         bitVect *rsave ;
12003         operand *psb, *handle;
12004         assert (nparms==2);
12005
12006         /* save registers that need to be saved */
12007         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12008                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12009         psb = parms[0];
12010         handle = parms[1];
12011
12012         /* put pointer to state block into DPTR1 */
12013         aopOp (psb, ic, FALSE, FALSE);
12014         if (AOP_TYPE (psb) == AOP_IMMD) {
12015                 emitcode ("mov","dps,#1");
12016                 emitcode ("mov", "dptr,%s",
12017                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12018                 emitcode ("mov","dps,#0");
12019         } else {
12020                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12021                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12022                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12023         }
12024         freeAsmop (psb, NULL, ic, FALSE);
12025
12026         /* put libraryID into DPTR */
12027         emitcode ("mov","dptr,#LibraryID");
12028
12029         /* put handle into r3:r2 */
12030         aopOp (handle, ic, FALSE, FALSE);
12031         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12032                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12033                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12034                 emitcode ("pop","ar3");
12035                 emitcode ("pop","ar2");
12036         } else {        
12037                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12038                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12039         }
12040         freeAsmop (psb, NULL, ic, FALSE);
12041
12042         /* make the call */
12043         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12044
12045         /* put return value into place*/
12046         _G.accInUse++;
12047         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12048         _G.accInUse--;
12049         aopPut(AOP(IC_RESULT(ic)),"a",0);
12050         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12051         unsavermask(rsave);
12052 }
12053
12054 /*-----------------------------------------------------------------*/
12055 /* genNatLibRemoveStateBlock -                                     */
12056 /*-----------------------------------------------------------------*/
12057 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12058 {
12059         bitVect *rsave ;
12060
12061         assert(nparms==0);
12062
12063         /* save registers that need to be saved */
12064         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12065                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12066
12067         /* put libraryID into DPTR */
12068         emitcode ("mov","dptr,#LibraryID");
12069         /* make the call */
12070         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12071         unsavermask(rsave);
12072 }
12073
12074 /*-----------------------------------------------------------------*/
12075 /* genNatLibGetStateBlock -                                        */
12076 /*-----------------------------------------------------------------*/
12077 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12078                                    operand **parms,const char *name)
12079 {
12080         bitVect *rsave ;
12081         symbol *lbl = newiTempLabel(NULL);
12082         
12083         assert(nparms==0);
12084         /* save registers that need to be saved */
12085         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12086                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12087
12088         /* put libraryID into DPTR */
12089         emitcode ("mov","dptr,#LibraryID");
12090         /* make the call */
12091         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12092         emitcode ("jnz","!tlabel",lbl->key+100);
12093
12094         /* put return value into place */
12095         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12096         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12097                 emitcode ("push","ar3");
12098                 emitcode ("push","ar2");
12099                 emitcode ("pop","%s",
12100                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12101                 emitcode ("pop","%s",
12102                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12103         } else {
12104                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12105                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12106         }
12107         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12108         emitcode ("","!tlabeldef",lbl->key+100);
12109         unsavermask(rsave);
12110 }
12111
12112 /*-----------------------------------------------------------------*/
12113 /* genMMMalloc -                                                   */
12114 /*-----------------------------------------------------------------*/
12115 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12116                          int size, const char *name)
12117 {
12118         bitVect *rsave ;
12119         operand *bsize;
12120         symbol *rsym;
12121         symbol *lbl = newiTempLabel(NULL);
12122
12123         assert (nparms == 1);
12124         /* save registers that need to be saved */
12125         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12126                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12127         
12128         bsize=parms[0];
12129         aopOp (bsize,ic,FALSE,FALSE);
12130
12131         /* put the size in R4-R2 */
12132         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12133                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12134                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12135                 if (size==3) {
12136                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12137                         emitcode("pop","ar4");
12138                 }
12139                 emitcode("pop","ar3");
12140                 emitcode("pop","ar2");          
12141         } else {
12142                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12143                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12144                 if (size==3) {
12145                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12146                 }
12147         }
12148         freeAsmop (bsize, NULL, ic, FALSE);
12149
12150         /* make the call */
12151         emitcode ("lcall","MM_%s",name);
12152         emitcode ("jz","!tlabel",lbl->key+100);
12153         emitcode ("mov","r2,#!constbyte",0xff);
12154         emitcode ("mov","r3,#!constbyte",0xff);
12155         emitcode ("","!tlabeldef",lbl->key+100);
12156         /* we don't care about the pointer : we just save the handle */
12157         rsym = OP_SYMBOL(IC_RESULT(ic));
12158         if (rsym->liveFrom != rsym->liveTo) {
12159                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12160                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12161                         emitcode ("push","ar3");
12162                         emitcode ("push","ar2");
12163                         emitcode ("pop","%s",
12164                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12165                         emitcode ("pop","%s",
12166                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12167                 } else {
12168                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12169                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12170                 }
12171                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12172         }
12173         unsavermask(rsave);
12174 }
12175
12176 /*-----------------------------------------------------------------*/
12177 /* genMMDeref -                                                    */
12178 /*-----------------------------------------------------------------*/
12179 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12180 {
12181         bitVect *rsave ;
12182         operand *handle;
12183
12184         assert (nparms == 1);
12185         /* save registers that need to be saved */
12186         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12188         
12189         handle=parms[0];
12190         aopOp (handle,ic,FALSE,FALSE);
12191
12192         /* put the size in R4-R2 */
12193         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12194                 emitcode("push","%s",
12195                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12196                 emitcode("push","%s",
12197                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12198                 emitcode("pop","ar3");
12199                 emitcode("pop","ar2");          
12200         } else {
12201                 emitcode ("mov","r2,%s",
12202                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12203                 emitcode ("mov","r3,%s",
12204                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12205         }
12206         freeAsmop (handle, NULL, ic, FALSE);
12207
12208         /* make the call */
12209         emitcode ("lcall","MM_Deref");
12210         
12211         {
12212                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12213                 if (rsym->liveFrom != rsym->liveTo) {                   
12214                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12215                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12216                             _startLazyDPSEvaluation ();
12217                             
12218                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12219                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12220                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12221
12222                             _endLazyDPSEvaluation ();
12223                             
12224                         }
12225                 }
12226         }
12227         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12228         unsavermask(rsave);
12229 }
12230
12231 /*-----------------------------------------------------------------*/
12232 /* genMMUnrestrictedPersist -                                      */
12233 /*-----------------------------------------------------------------*/
12234 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12235 {
12236         bitVect *rsave ;
12237         operand *handle;
12238
12239         assert (nparms == 1);
12240         /* save registers that need to be saved */
12241         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12242                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12243         
12244         handle=parms[0];
12245         aopOp (handle,ic,FALSE,FALSE);
12246
12247         /* put the size in R3-R2 */
12248         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12249                 emitcode("push","%s",
12250                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12251                 emitcode("push","%s",
12252                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12253                 emitcode("pop","ar3");
12254                 emitcode("pop","ar2");          
12255         } else {
12256                 emitcode ("mov","r2,%s",
12257                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12258                 emitcode ("mov","r3,%s",
12259                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12260         }
12261         freeAsmop (handle, NULL, ic, FALSE);
12262
12263         /* make the call */
12264         emitcode ("lcall","MM_UnrestrictedPersist");
12265
12266         {
12267                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12268                 if (rsym->liveFrom != rsym->liveTo) {   
12269                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12270                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12271                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12272                 }
12273         }
12274         unsavermask(rsave);
12275 }
12276
12277 /*-----------------------------------------------------------------*/
12278 /* genSystemExecJavaProcess -                                      */
12279 /*-----------------------------------------------------------------*/
12280 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12281 {
12282         bitVect *rsave ;
12283         operand *handle, *pp;
12284
12285         assert (nparms==2);
12286         /* save registers that need to be saved */
12287         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12288                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12289         
12290         pp = parms[0];
12291         handle = parms[1];
12292         
12293         /* put the handle in R3-R2 */
12294         aopOp (handle,ic,FALSE,FALSE);
12295         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12296                 emitcode("push","%s",
12297                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12298                 emitcode("push","%s",
12299                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12300                 emitcode("pop","ar3");
12301                 emitcode("pop","ar2");          
12302         } else {
12303                 emitcode ("mov","r2,%s",
12304                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12305                 emitcode ("mov","r3,%s",
12306                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12307         }
12308         freeAsmop (handle, NULL, ic, FALSE);
12309         
12310         /* put pointer in DPTR */
12311         aopOp (pp,ic,FALSE,FALSE);
12312         if (AOP_TYPE(pp) == AOP_IMMD) {
12313                 emitcode ("mov", "dptr,%s",
12314                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12315         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12316                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12317                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12318                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12319         }
12320         freeAsmop (handle, NULL, ic, FALSE);
12321
12322         /* make the call */
12323         emitcode ("lcall","System_ExecJavaProcess");
12324         
12325         /* put result in place */
12326         {
12327                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12328                 if (rsym->liveFrom != rsym->liveTo) {   
12329                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12330                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12331                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12332                 }
12333         }
12334         
12335         unsavermask(rsave);
12336 }
12337
12338 /*-----------------------------------------------------------------*/
12339 /* genSystemRTCRegisters -                                         */
12340 /*-----------------------------------------------------------------*/
12341 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12342                                   char *name)
12343 {
12344         bitVect *rsave ;
12345         operand *pp;
12346
12347         assert (nparms==1);
12348         /* save registers that need to be saved */
12349         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12350                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12351         
12352         pp=parms[0];
12353         /* put pointer in DPTR */
12354         aopOp (pp,ic,FALSE,FALSE);
12355         if (AOP_TYPE (pp) == AOP_IMMD) {
12356                 emitcode ("mov","dps,#1");
12357                 emitcode ("mov", "dptr,%s", 
12358                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12359                 emitcode ("mov","dps,#0");
12360         } else {
12361                 emitcode ("mov","dpl1,%s",
12362                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12363                 emitcode ("mov","dph1,%s",
12364                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12365                 emitcode ("mov","dpx1,%s",
12366                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12367         }
12368         freeAsmop (pp, NULL, ic, FALSE);
12369
12370         /* make the call */
12371         emitcode ("lcall","System_%sRTCRegisters",name);
12372
12373         unsavermask(rsave);
12374 }
12375
12376 /*-----------------------------------------------------------------*/
12377 /* genSystemThreadSleep -                                          */
12378 /*-----------------------------------------------------------------*/
12379 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12380 {
12381         bitVect *rsave ;
12382         operand *to, *s;
12383
12384         assert (nparms==1);
12385         /* save registers that need to be saved */
12386         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12387                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12388
12389         to = parms[0];
12390         aopOp(to,ic,FALSE,FALSE);
12391         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12392             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12393                 emitcode ("push","%s",
12394                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12395                 emitcode ("push","%s",
12396                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12397                 emitcode ("push","%s",
12398                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12399                 emitcode ("push","%s",
12400                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12401                 emitcode ("pop","ar3");
12402                 emitcode ("pop","ar2");
12403                 emitcode ("pop","ar1");
12404                 emitcode ("pop","ar0");
12405         } else {
12406                 emitcode ("mov","r0,%s",
12407                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12408                 emitcode ("mov","r1,%s",
12409                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12410                 emitcode ("mov","r2,%s",
12411                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12412                 emitcode ("mov","r3,%s",
12413                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12414         }
12415         freeAsmop (to, NULL, ic, FALSE);
12416
12417         /* suspend in acc */
12418         s = parms[1];
12419         aopOp(s,ic,FALSE,FALSE);
12420         emitcode ("mov","a,%s",
12421                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12422         freeAsmop (s, NULL, ic, FALSE);
12423
12424         /* make the call */
12425         emitcode ("lcall","System_%s",name);
12426
12427         unsavermask(rsave);
12428 }
12429
12430 /*-----------------------------------------------------------------*/
12431 /* genSystemThreadResume -                                         */
12432 /*-----------------------------------------------------------------*/
12433 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12434 {
12435         bitVect *rsave ;
12436         operand *tid,*pid;
12437
12438         assert (nparms==2);
12439         /* save registers that need to be saved */
12440         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12441                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12442         
12443         tid = parms[0];
12444         pid = parms[1];
12445         
12446         /* PID in R0 */
12447         aopOp(pid,ic,FALSE,FALSE);
12448         emitcode ("mov","r0,%s",
12449                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12450         freeAsmop (pid, NULL, ic, FALSE);
12451         
12452         /* tid into ACC */
12453         aopOp(tid,ic,FALSE,FALSE);
12454         emitcode ("mov","a,%s",
12455                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12456         freeAsmop (tid, NULL, ic, FALSE);
12457         
12458         emitcode ("lcall","System_ThreadResume");
12459
12460         /* put result into place */
12461         {
12462                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12463                 if (rsym->liveFrom != rsym->liveTo) {   
12464                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12465                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12466                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12467                 }
12468         }
12469         unsavermask(rsave);
12470 }
12471
12472 /*-----------------------------------------------------------------*/
12473 /* genSystemProcessResume -                                        */
12474 /*-----------------------------------------------------------------*/
12475 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12476 {
12477         bitVect *rsave ;
12478         operand *pid;
12479
12480         assert (nparms==1);
12481         /* save registers that need to be saved */
12482         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12483                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12484         
12485         pid = parms[0];
12486         
12487         /* pid into ACC */
12488         aopOp(pid,ic,FALSE,FALSE);
12489         emitcode ("mov","a,%s",
12490                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12491         freeAsmop (pid, NULL, ic, FALSE);
12492         
12493         emitcode ("lcall","System_ProcessResume");
12494
12495         unsavermask(rsave);
12496 }
12497
12498 /*-----------------------------------------------------------------*/
12499 /* genSystem -                                                     */
12500 /*-----------------------------------------------------------------*/
12501 static void genSystem (iCode *ic,int nparms,char *name)
12502 {
12503         assert(nparms == 0);
12504
12505         emitcode ("lcall","System_%s",name);
12506 }
12507
12508 /*-----------------------------------------------------------------*/
12509 /* genSystemPoll -                                                  */
12510 /*-----------------------------------------------------------------*/
12511 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12512 {
12513         bitVect *rsave ;
12514         operand *fp;
12515
12516         assert (nparms==1);
12517         /* save registers that need to be saved */
12518         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12519                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12520
12521         fp = parms[0];
12522         aopOp (fp,ic,FALSE,FALSE);
12523         if (AOP_TYPE (fp) == AOP_IMMD) {
12524                 emitcode ("mov", "dptr,%s", 
12525                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12526         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12527                 emitcode ("mov","dpl,%s",
12528                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12529                 emitcode ("mov","dph,%s",
12530                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12531                 emitcode ("mov","dpx,%s",
12532                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12533         }
12534         freeAsmop (fp, NULL, ic, FALSE);
12535
12536         emitcode ("lcall","System_%sPoll",name);
12537
12538         /* put result into place */
12539         {
12540                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12541                 if (rsym->liveFrom != rsym->liveTo) {   
12542                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12543                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12544                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12545                 }
12546         }
12547         unsavermask(rsave);
12548 }
12549
12550 /*-----------------------------------------------------------------*/
12551 /* genSystemGetCurrentID -                                         */
12552 /*-----------------------------------------------------------------*/
12553 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12554 {
12555         assert (nparms==0);
12556
12557         emitcode ("lcall","System_GetCurrent%sId",name);
12558         /* put result into place */
12559         {
12560                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12561                 if (rsym->liveFrom != rsym->liveTo) {   
12562                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12563                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12564                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12565                 }
12566         }
12567 }
12568
12569 /*-----------------------------------------------------------------*/
12570 /* genBuiltIn - calls the appropriate function to  generating code */
12571 /* for a built in function                                         */
12572 /*-----------------------------------------------------------------*/
12573 static void genBuiltIn (iCode *ic)
12574 {
12575         operand *bi_parms[MAX_BUILTIN_ARGS];
12576         int nbi_parms;
12577         iCode *bi_iCode;
12578         symbol *bif;
12579
12580         /* get all the arguments for a built in function */
12581         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12582
12583         /* which function is it */
12584         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12585         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12586                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12587         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12588                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12589         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12590                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12591         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12592                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12593         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12594                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12595         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12596                 genInp(bi_iCode,nbi_parms,bi_parms);
12597         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12598                 genOutp(bi_iCode,nbi_parms,bi_parms);
12599         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12600                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12601                 /* JavaNative builtIns */               
12602         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12603                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12604         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12605                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12606         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12607                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12608         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12609                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12610         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12611                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12612         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12613                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12614         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12615                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12616         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12617                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12618         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12619                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12620         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12621                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12622         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12623                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12624         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12625                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12626         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12627                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12628         } else if (strcmp(bif->name,"MM_Free")==0) {
12629                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12630         } else if (strcmp(bif->name,"MM_Deref")==0) {
12631                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12632         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12633                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12634         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12635                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12636         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12637                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12638         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12639                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12640         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12641                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12642         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12643                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12644         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12645                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12646         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12647                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12648         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12649                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12650         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12651                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12652         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12653                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12654         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12655                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12656         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12657                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12658         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12659                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12660         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12661                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12662         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12663                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12664         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12665                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12666         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12667                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12668         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12669                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12670         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12671                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12672         } else {
12673                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12674                 return ;
12675         }
12676         return ;    
12677 }
12678
12679 /*-----------------------------------------------------------------*/
12680 /* gen390Code - generate code for Dallas 390 based controllers     */
12681 /*-----------------------------------------------------------------*/
12682 void
12683 gen390Code (iCode * lic)
12684 {
12685   iCode *ic;
12686   int cln = 0;
12687
12688   lineHead = lineCurr = NULL;
12689   dptrn[1][0] = "dpl1";
12690   dptrn[1][1] = "dph1";
12691   dptrn[1][2] = "dpx1";
12692   
12693   if (options.model == MODEL_FLAT24) {
12694     fReturnSizeDS390 = 5;
12695     fReturn = fReturn24;
12696   } else {
12697     fReturnSizeDS390 = 4;
12698     fReturn = fReturn16;
12699     options.stack10bit=0;
12700   }
12701 #if 1
12702   /* print the allocation information */
12703   if (allocInfo)
12704     printAllocInfo (currFunc, codeOutFile);
12705 #endif
12706   /* if debug information required */
12707   if (options.debug && currFunc)
12708     {
12709       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12710       _G.debugLine = 1;
12711       if (IS_STATIC (currFunc->etype))
12712         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12713       else
12714         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12715       _G.debugLine = 0;
12716     }
12717   /* stack pointer name */
12718   if (options.useXstack)
12719     spname = "_spx";
12720   else
12721     spname = "sp";
12722
12723
12724   for (ic = lic; ic; ic = ic->next)
12725     {
12726
12727       if (ic->lineno && cln != ic->lineno)
12728         {
12729           if (options.debug)
12730             {
12731               _G.debugLine = 1;
12732               emitcode ("", "C$%s$%d$%d$%d ==.",
12733                         FileBaseName (ic->filename), ic->lineno,
12734                         ic->level, ic->block);
12735               _G.debugLine = 0;
12736             }
12737           if (!options.noCcodeInAsm) {
12738             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12739                       printCLine(ic->filename, ic->lineno));
12740           }
12741           cln = ic->lineno;
12742         }
12743       if (options.iCodeInAsm) {
12744         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12745       }
12746       /* if the result is marked as
12747          spilt and rematerializable or code for
12748          this has already been generated then
12749          do nothing */
12750       if (resultRemat (ic) || ic->generated)
12751         continue;
12752
12753       /* depending on the operation */
12754       switch (ic->op)
12755         {
12756         case '!':
12757           genNot (ic);
12758           break;
12759
12760         case '~':
12761           genCpl (ic);
12762           break;
12763
12764         case UNARYMINUS:
12765           genUminus (ic);
12766           break;
12767
12768         case IPUSH:
12769           genIpush (ic);
12770           break;
12771
12772         case IPOP:
12773           /* IPOP happens only when trying to restore a
12774              spilt live range, if there is an ifx statement
12775              following this pop then the if statement might
12776              be using some of the registers being popped which
12777              would destory the contents of the register so
12778              we need to check for this condition and handle it */
12779           if (ic->next &&
12780               ic->next->op == IFX &&
12781               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12782             genIfx (ic->next, ic);
12783           else
12784             genIpop (ic);
12785           break;
12786
12787         case CALL:
12788           genCall (ic);
12789           break;
12790
12791         case PCALL:
12792           genPcall (ic);
12793           break;
12794
12795         case FUNCTION:
12796           genFunction (ic);
12797           break;
12798
12799         case ENDFUNCTION:
12800           genEndFunction (ic);
12801           break;
12802
12803         case RETURN:
12804           genRet (ic);
12805           break;
12806
12807         case LABEL:
12808           genLabel (ic);
12809           break;
12810
12811         case GOTO:
12812           genGoto (ic);
12813           break;
12814
12815         case '+':
12816           genPlus (ic);
12817           break;
12818
12819         case '-':
12820           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12821             genMinus (ic);
12822           break;
12823
12824         case '*':
12825           genMult (ic);
12826           break;
12827
12828         case '/':
12829           genDiv (ic);
12830           break;
12831
12832         case '%':
12833           genMod (ic);
12834           break;
12835
12836         case '>':
12837           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12838           break;
12839
12840         case '<':
12841           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12842           break;
12843
12844         case LE_OP:
12845         case GE_OP:
12846         case NE_OP:
12847
12848           /* note these two are xlated by algebraic equivalence
12849              during parsing SDCC.y */
12850           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12851                   "got '>=' or '<=' shouldn't have come here");
12852           break;
12853
12854         case EQ_OP:
12855           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12856           break;
12857
12858         case AND_OP:
12859           genAndOp (ic);
12860           break;
12861
12862         case OR_OP:
12863           genOrOp (ic);
12864           break;
12865
12866         case '^':
12867           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12868           break;
12869
12870         case '|':
12871           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12872           break;
12873
12874         case BITWISEAND:
12875           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12876           break;
12877
12878         case INLINEASM:
12879           genInline (ic);
12880           break;
12881
12882         case RRC:
12883           genRRC (ic);
12884           break;
12885
12886         case RLC:
12887           genRLC (ic);
12888           break;
12889
12890         case GETHBIT:
12891           genGetHbit (ic);
12892           break;
12893
12894         case LEFT_OP:
12895           genLeftShift (ic);
12896           break;
12897
12898         case RIGHT_OP:
12899           genRightShift (ic);
12900           break;
12901
12902         case GET_VALUE_AT_ADDRESS:
12903           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12904           break;
12905
12906         case '=':
12907           if (POINTER_SET (ic))
12908             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12909           else
12910             genAssign (ic);
12911           break;
12912
12913         case IFX:
12914           genIfx (ic, NULL);
12915           break;
12916
12917         case ADDRESS_OF:
12918           genAddrOf (ic);
12919           break;
12920
12921         case JUMPTABLE:
12922           genJumpTab (ic);
12923           break;
12924
12925         case CAST:
12926           genCast (ic);
12927           break;
12928
12929         case RECEIVE:
12930           genReceive (ic);
12931           break;
12932
12933         case SEND:
12934           if (ic->builtinSEND) genBuiltIn(ic);
12935           else addSet (&_G.sendSet, ic);
12936           break;
12937
12938         case ARRAYINIT:
12939             genArrayInit(ic);
12940             break;
12941             
12942         default:
12943           ic = ic;
12944         }
12945     }
12946
12947
12948   /* now we are ready to call the
12949      peep hole optimizer */
12950   if (!options.nopeep)
12951     peepHole (&lineHead);
12952
12953   /* now do the actual printing */
12954   printLine (lineHead, codeOutFile);
12955   return;
12956 }