2805631307ac1363bb0e3447ee1e567bc0f28d3d
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59 extern int allocInfo;
60
61 /* this is the down and dirty file with all kinds of
62    kludgy & hacky stuff. This is what it is all about
63    CODE GENERATION for a specific MCU . some of the
64    routines may be reusable, will have to see */
65
66 static char *zero = "#0";
67 static char *one = "#1";
68 static char *spname;
69
70 #define D(x) x
71
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74
75 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
82 {"a", "b"};
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
86
87 static struct
88   {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short bInUse;
93     short inLine;
94     short debugLine;
95     short nRegsSaved;
96     short dptrInUse;
97     short dptr1InUse;
98     set *sendSet;
99   }
100 _G;
101
102 static char *rb1regs[] = {
103     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
104 };
105
106 static void saveRBank (int, iCode *, bool);
107
108 #define RESULTONSTACK(x) \
109                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
110                          IC_RESULT(x)->aop->type == AOP_STK )
111
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
115                  { \
116                     emitcode("mov","a,%s",_mova_tmp); \
117                  } \
118                  free(_mova_tmp); \
119                 }
120 #define MOVB(x) { char *_movb_tmp = strdup(x); \
121                  if (strcmp(_movb_tmp,"b")) \
122                  { \
123                     emitcode("mov","b,%s",_movb_tmp); \
124                  } \
125                  free(_movb_tmp); \
126                 }
127 #define CLRC    emitcode("clr","c")
128 #define SETC    emitcode("setb","c")
129
130 // A scratch register which will be used to hold
131 // result bytes from operands in far space via DPTR2.
132 #define DP2_RESULT_REG  "_ap"
133
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
136
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139  0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142  0x07, 0x03, 0x01, 0x00};
143
144 #define LSB     0
145 #define MSB16   1
146 #define MSB24   2
147 #define MSB32   3
148 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
149                                 symbol *lbl = newiTempLabel(NULL);              \
150                                 emitcode ("setb","F1");                         \
151                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
152                                 emitcode ("clr","F1");                          \
153                                 emitcode ("","!tlabeldef",lbl->key+100);        \
154                         }}
155 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
156                                 symbol *lbl = newiTempLabel(NULL);              \
157                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
158                                 emitcode ("setb","EA");                         \
159                                 emitcode ("","!tlabeldef",lbl->key+100);        \
160                         }}
161
162
163 /*-----------------------------------------------------------------*/
164 /* emitcode - writes the code into a file : for now it is simple    */
165 /*-----------------------------------------------------------------*/
166 static void
167 emitcode (char *inst, char *fmt,...)
168 {
169     va_list ap;
170     char lb[INITIAL_INLINEASM];
171     char *lbp = lb;
172     
173     va_start (ap, fmt);
174     
175     if (inst && *inst)
176     {
177         if (fmt && *fmt)
178         {
179             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
180         }
181         else
182         {
183             SNPRINTF (lb, sizeof(lb), "%s", inst);
184         }
185         
186         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
187                    fmt, ap);
188     }
189     else
190     {
191         tvsprintf (lb, sizeof(lb), fmt, ap);
192     }
193     
194
195     while (isspace (*lbp))
196     {
197         lbp++;
198     }
199
200     if (lbp && *lbp)
201     {
202         lineCurr = (lineCurr ?
203                     connectLine (lineCurr, newLineNode (lb)) :
204                     (lineHead = newLineNode (lb)));
205     }
206     
207     lineCurr->isInline = _G.inLine;
208     lineCurr->isDebug = _G.debugLine;
209     va_end (ap);
210 }
211
212 /*-----------------------------------------------------------------*/
213 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
214 /*-----------------------------------------------------------------*/
215 static regs *
216 getFreePtr (iCode * ic, asmop ** aopp, bool result)
217 {
218   bool r0iu, r1iu;
219   bool r0ou, r1ou;
220
221   /* the logic: if r0 & r1 used in the instruction
222      then we are in trouble otherwise */
223
224   /* first check if r0 & r1 are used by this
225      instruction, in which case we are in trouble */
226   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
227   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
228   if (r0iu && r1iu) {
229       goto endOfWorld;
230     }
231
232   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
233   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
234
235   /* if no usage of r0 then return it */
236   if (!r0iu && !r0ou)
237     {
238       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
239       (*aopp)->type = AOP_R0;
240
241       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
242     }
243
244   /* if no usage of r1 then return it */
245   if (!r1iu && !r1ou)
246     {
247       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
248       (*aopp)->type = AOP_R1;
249
250       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
251     }
252
253   /* now we know they both have usage */
254   /* if r0 not used in this instruction */
255   if (!r0iu)
256     {
257       /* push it if not already pushed */
258       if (!_G.r0Pushed)
259         {
260           emitcode ("push", "%s",
261                     ds390_regWithIdx (R0_IDX)->dname);
262           _G.r0Pushed++;
263         }
264
265       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
266       (*aopp)->type = AOP_R0;
267
268       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
269     }
270
271   /* if r1 not used then */
272
273   if (!r1iu)
274     {
275       /* push it if not already pushed */
276       if (!_G.r1Pushed)
277         {
278           emitcode ("push", "%s",
279                     ds390_regWithIdx (R1_IDX)->dname);
280           _G.r1Pushed++;
281         }
282
283       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
284       (*aopp)->type = AOP_R1;
285       return ds390_regWithIdx (R1_IDX);
286     }
287
288 endOfWorld:
289   /* I said end of world but not quite end of world yet */
290   /* if this is a result then we can push it on the stack */
291   if (result)
292     {
293       (*aopp)->type = AOP_STK;
294       return NULL;
295     }
296
297   /* other wise this is true end of the world */
298   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
299           "getFreePtr should never reach here");
300   exit (1);
301     
302   return NULL; // notreached, but makes compiler happy.
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* newAsmop - creates a new asmOp                                  */
307 /*-----------------------------------------------------------------*/
308 static asmop *
309 newAsmop (short type)
310 {
311   asmop *aop;
312
313   aop = Safe_calloc (1, sizeof (asmop));
314   aop->type = type;
315   return aop;
316 }
317
318 static int _currentDPS;         /* Current processor DPS. */
319 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
320 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
321
322 /*-----------------------------------------------------------------*/
323 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
324 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
325 /* alternate DPTR (DPL1/DPH1/DPX1).          */
326 /*-----------------------------------------------------------------*/
327 static void
328 genSetDPTR (int n)
329 {
330
331   /* If we are doing lazy evaluation, simply note the desired
332    * change, but don't emit any code yet.
333    */
334   if (_lazyDPS)
335     {
336       _desiredDPS = n;
337       return;
338     }
339
340   if (!n)
341     {
342       emitcode ("mov", "dps,#0");
343     }
344   else
345     {
346       TR_DPTR("#1");
347       emitcode ("mov", "dps,#1");
348     }
349 }
350
351 /*-----------------------------------------------------------------*/
352 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
353 /*                   */
354 /* Any code that operates on DPTR (NB: not on the individual     */
355 /* components, like DPH) *must* call _flushLazyDPS() before using  */
356 /* DPTR within a lazy DPS evaluation block.        */
357 /*                   */
358 /* Note that aopPut and aopGet already contain the proper calls to */
359 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
360 /* DPS evaluation block.             */
361 /*                   */
362 /* Also, _flushLazyDPS must be called before any flow control      */
363 /* operations that could potentially branch out of the block.    */
364 /*                         */
365 /* Lazy DPS evaluation is simply an optimization (though an      */
366 /* important one), so if in doubt, leave it out.       */
367 /*-----------------------------------------------------------------*/
368 static void
369 _startLazyDPSEvaluation (void)
370 {
371   _currentDPS = 0;
372   _desiredDPS = 0;
373 #ifdef BETTER_LITERAL_SHIFT  
374   _lazyDPS++;
375 #else
376   _lazyDPS = 1;
377 #endif  
378 }
379
380 /*-----------------------------------------------------------------*/
381 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
382 /* desired one. Call before using DPTR within a lazy DPS evaluation */
383 /* block.                */
384 /*-----------------------------------------------------------------*/
385 static void
386 _flushLazyDPS (void)
387 {
388   if (!_lazyDPS)
389     {
390       /* nothing to do. */
391       return;
392     }
393
394   if (_desiredDPS != _currentDPS)
395     {
396       if (_desiredDPS)
397         {
398           emitcode ("inc", "dps");
399         }
400       else
401         {
402           emitcode ("dec", "dps");
403         }
404       _currentDPS = _desiredDPS;
405     }
406 }
407
408 /*-----------------------------------------------------------------*/
409 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
410 /*                   */
411 /* Forces us back to the safe state (standard DPTR selected).    */
412 /*-----------------------------------------------------------------*/
413 static void
414 _endLazyDPSEvaluation (void)
415 {
416 #ifdef BETTER_LITERAL_SHIFT  
417   _lazyDPS--;
418 #else
419   _lazyDPS = 0;
420 #endif    
421   if (!_lazyDPS)
422   {
423     if (_currentDPS)
424     {
425       genSetDPTR (0);
426       _flushLazyDPS ();
427     }
428     _currentDPS = 0;
429     _desiredDPS = 0;
430   }
431 }
432
433
434
435 /*-----------------------------------------------------------------*/
436 /* pointerCode - returns the code for a pointer type               */
437 /*-----------------------------------------------------------------*/
438 static int
439 pointerCode (sym_link * etype)
440 {
441
442   return PTR_TYPE (SPEC_OCLS (etype));
443
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* aopForSym - for a true symbol                                   */
448 /*-----------------------------------------------------------------*/
449 static asmop *
450 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
451 {
452   asmop *aop;
453   memmap *space = SPEC_OCLS (sym->etype);
454
455   /* if already has one */
456   if (sym->aop)
457     return sym->aop;
458
459   /* assign depending on the storage class */
460   /* if it is on the stack or indirectly addressable */
461   /* space we need to assign either r0 or r1 to it   */
462   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
463     {
464       sym->aop = aop = newAsmop (0);
465       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
466       aop->size = getSize (sym->type);
467
468       /* now assign the address of the variable to
469          the pointer register */
470       if (aop->type != AOP_STK)
471         {
472
473           if (sym->onStack)
474             {
475               if (_G.accInUse)
476                 emitcode ("push", "acc");
477
478               if (_G.bInUse)
479                 emitcode ("push", "b");
480
481               emitcode ("mov", "a,_bp");
482               emitcode ("add", "a,#!constbyte",
483                         ((sym->stack < 0) ?
484                          ((char) (sym->stack - _G.nRegsSaved)) :
485                          ((char) sym->stack)) & 0xff);
486               emitcode ("mov", "%s,a",
487                         aop->aopu.aop_ptr->name);
488
489               if (_G.bInUse)
490                 emitcode ("pop", "b");
491
492               if (_G.accInUse)
493                 emitcode ("pop", "acc");
494             }
495           else
496             emitcode ("mov", "%s,#%s",
497                       aop->aopu.aop_ptr->name,
498                       sym->rname);
499           aop->paged = space->paged;
500         }
501       else
502         aop->aopu.aop_stk = sym->stack;
503       return aop;
504     }
505
506   if (sym->onStack && options.stack10bit)
507     {
508         short stack_val = -((sym->stack < 0) ?
509                             ((short) (sym->stack - _G.nRegsSaved)) :
510                             ((short) sym->stack)) ;
511         if (useDP2 && _G.dptr1InUse) {
512             emitcode ("push","dpl1");
513             emitcode ("push","dph1");
514             emitcode ("push","dpx1");
515         } else if (_G.dptrInUse ) {
516             emitcode ("push","dpl");
517             emitcode ("push","dph");
518             emitcode ("push","dpx");
519         }
520       /* It's on the 10 bit stack, which is located in
521        * far data space.
522        */           
523         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
524             if (useDP2) {
525                 if (options.model == MODEL_FLAT24)
526                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
527                 TR_DPTR("#2");
528                 emitcode ("mov", "dph1,_bpx+1");
529                 emitcode ("mov", "dpl1,_bpx");
530                 emitcode ("mov","dps,#1");
531             } else {
532                 if (options.model == MODEL_FLAT24)
533                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
534                 emitcode ("mov", "dph,_bpx+1");
535                 emitcode ("mov", "dpl,_bpx");
536             }
537             stack_val = -stack_val;
538             while (stack_val--) {
539                 emitcode ("inc","dptr");
540             }
541             if (useDP2) {
542                 emitcode("mov","dps,#0");
543             }
544         }  else {
545             if (_G.accInUse)
546                 emitcode ("push", "acc");
547             
548             if (_G.bInUse)
549                 emitcode ("push", "b");
550         
551             emitcode ("mov", "a,_bpx");
552             emitcode ("clr","c");
553             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
554             emitcode ("mov","b,a");
555             emitcode ("mov","a,_bpx+1");
556             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
557             if (useDP2) {
558                 if (options.model == MODEL_FLAT24)
559                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
560                 TR_DPTR("#2");
561                 emitcode ("mov", "dph1,a");
562                 emitcode ("mov", "dpl1,b");
563             } else {
564                 if (options.model == MODEL_FLAT24)
565                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
566                 emitcode ("mov", "dph,a");
567                 emitcode ("mov", "dpl,b");
568             }
569             
570             if (_G.bInUse)
571                 emitcode ("pop", "b");
572             
573             if (_G.accInUse)
574                 emitcode ("pop", "acc");
575         }
576         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
577         aop->size = getSize (sym->type);
578         return aop;
579     }
580
581   /* if in bit space */
582   if (IN_BITSPACE (space))
583     {
584       sym->aop = aop = newAsmop (AOP_CRY);
585       aop->aopu.aop_dir = sym->rname;
586       aop->size = getSize (sym->type);
587       return aop;
588     }
589   /* if it is in direct space */
590   if (IN_DIRSPACE (space))
591     {
592       sym->aop = aop = newAsmop (AOP_DIR);
593       aop->aopu.aop_dir = sym->rname;
594       aop->size = getSize (sym->type);
595       return aop;
596     }
597
598   /* special case for a function */
599   if (IS_FUNC (sym->type))
600     {
601       sym->aop = aop = newAsmop (AOP_IMMD);
602       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
603       aop->size = FPTRSIZE;
604       return aop;
605     }
606   
607   /* only remaining is far space */
608   /* in which case DPTR gets the address */
609   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
610   if (useDP2)
611     {
612       genSetDPTR (1);
613       _flushLazyDPS ();
614       emitcode ("mov", "dptr,#%s", sym->rname);
615       genSetDPTR (0);
616     }
617   else
618     {
619       emitcode ("mov", "dptr,#%s", sym->rname);
620     }
621   aop->size = getSize (sym->type);
622
623   /* if it is in code space */
624   if (IN_CODESPACE (space))
625     aop->code = 1;
626
627   return aop;
628 }
629
630 /*-----------------------------------------------------------------*/
631 /* aopForRemat - rematerialzes an object                           */
632 /*-----------------------------------------------------------------*/
633 static asmop *
634 aopForRemat (symbol * sym)
635 {
636   iCode *ic = sym->rematiCode;
637   asmop *aop = newAsmop (AOP_IMMD);
638   int ptr_type =0;
639   int val = 0;
640
641   for (;;)
642     {
643       if (ic->op == '+')
644         val += (int) operandLitValue (IC_RIGHT (ic));
645       else if (ic->op == '-')
646         val -= (int) operandLitValue (IC_RIGHT (ic));
647       else if (IS_CAST_ICODE(ic)) {
648               sym_link *from_type = operandType(IC_RIGHT(ic));
649               aop->aopu.aop_immd.from_cast_remat = 1;
650               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
651               ptr_type = DCL_TYPE(from_type);
652               if (ptr_type == IPOINTER) {
653                 // bug #481053
654                 ptr_type = POINTER;
655               }
656               continue ;
657       } else break;
658       
659       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
660     }
661
662   if (val)
663   {
664       SNPRINTF (buffer, sizeof(buffer),
665                 "(%s %c 0x%04x)",
666                 OP_SYMBOL (IC_LEFT (ic))->rname,
667                 val >= 0 ? '+' : '-',
668                 abs (val) & 0xffff);
669   }
670   else 
671   {
672       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
673       {
674           SNPRINTF(buffer, sizeof(buffer), 
675                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
676       }
677       else
678       {
679           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
680       }
681   }
682
683   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
684   /* set immd2 field if required */
685   if (aop->aopu.aop_immd.from_cast_remat) 
686   {
687       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
688       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
689   }
690
691   return aop;
692 }
693
694 /*-----------------------------------------------------------------*/
695 /* aopHasRegs - returns true if aop has regs between from-to       */
696 /*-----------------------------------------------------------------*/
697 static int aopHasRegs(asmop *aop, int from, int to)
698 {
699     int size =0;
700
701     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
702
703     for (; size < aop->size ; size++) {
704         int reg;
705         for (reg = from ; reg <= to ; reg++)
706             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
707     }
708     return 0;
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* regsInCommon - two operands have some registers in common       */
713 /*-----------------------------------------------------------------*/
714 static bool
715 regsInCommon (operand * op1, operand * op2)
716 {
717   symbol *sym1, *sym2;
718   int i;
719
720   /* if they have registers in common */
721   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
722     return FALSE;
723
724   sym1 = OP_SYMBOL (op1);
725   sym2 = OP_SYMBOL (op2);
726
727   if (sym1->nRegs == 0 || sym2->nRegs == 0)
728     return FALSE;
729
730   for (i = 0; i < sym1->nRegs; i++)
731     {
732       int j;
733       if (!sym1->regs[i])
734         continue;
735
736       for (j = 0; j < sym2->nRegs; j++)
737         {
738           if (!sym2->regs[j])
739             continue;
740
741           if (sym2->regs[j] == sym1->regs[i])
742             return TRUE;
743         }
744     }
745
746   return FALSE;
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* operandsEqu - equivalent                                        */
751 /*-----------------------------------------------------------------*/
752 static bool
753 operandsEqu (operand * op1, operand * op2)
754 {
755   symbol *sym1, *sym2;
756
757   /* if they not symbols */
758   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
759     return FALSE;
760
761   sym1 = OP_SYMBOL (op1);
762   sym2 = OP_SYMBOL (op2);
763
764   /* if both are itemps & one is spilt
765      and the other is not then false */
766   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
767       sym1->isspilt != sym2->isspilt)
768     return FALSE;
769
770   /* if they are the same */
771   if (sym1 == sym2)
772     return TRUE;
773
774   if (strcmp (sym1->rname, sym2->rname) == 0)
775     return TRUE;
776
777
778   /* if left is a tmp & right is not */
779   if (IS_ITEMP (op1) &&
780       !IS_ITEMP (op2) &&
781       sym1->isspilt &&
782       (sym1->usl.spillLoc == sym2))
783     return TRUE;
784
785   if (IS_ITEMP (op2) &&
786       !IS_ITEMP (op1) &&
787       sym2->isspilt &&
788       sym1->level > 0 &&
789       (sym2->usl.spillLoc == sym1))
790     return TRUE;
791
792   return FALSE;
793 }
794
795 /*-----------------------------------------------------------------*/
796 /* sameRegs - two asmops have the same registers                   */
797 /*-----------------------------------------------------------------*/
798 static bool
799 sameRegs (asmop * aop1, asmop * aop2)
800 {
801   int i;
802
803   if (aop1 == aop2)
804     {
805       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
806         {
807           return FALSE;
808         }
809       return TRUE;
810     }
811
812   if (aop1->type != AOP_REG ||
813       aop2->type != AOP_REG)
814     return FALSE;
815
816   if (aop1->size != aop2->size)
817     return FALSE;
818
819   for (i = 0; i < aop1->size; i++)
820     if (aop1->aopu.aop_reg[i] !=
821         aop2->aopu.aop_reg[i])
822       return FALSE;
823
824   return TRUE;
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* aopOp - allocates an asmop for an operand  :                    */
829 /*-----------------------------------------------------------------*/
830 static void
831 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
832 {
833   asmop *aop;
834   symbol *sym;
835   int i;
836
837   if (!op)
838     return;
839
840   /* if this a literal */
841   if (IS_OP_LITERAL (op))
842     {
843       op->aop = aop = newAsmop (AOP_LIT);
844       aop->aopu.aop_lit = op->operand.valOperand;
845       aop->size = getSize (operandType (op));
846       return;
847     }
848
849   /* if already has a asmop then continue */
850   if (op->aop)
851     return;
852
853   /* if the underlying symbol has a aop */
854   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
855     {
856       op->aop = OP_SYMBOL (op)->aop;
857       return;
858     }
859
860   /* if this is a true symbol */
861   if (IS_TRUE_SYMOP (op))
862     {
863       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
864       return;
865     }
866
867   /* this is a temporary : this has
868      only four choices :
869      a) register
870      b) spillocation
871      c) rematerialize
872      d) conditional
873      e) can be a return use only */
874
875   sym = OP_SYMBOL (op);
876
877
878   /* if the type is a conditional */
879   if (sym->regType == REG_CND)
880     {
881       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
882       aop->size = 0;
883       return;
884     }
885
886   /* if it is spilt then two situations
887      a) is rematerialize
888      b) has a spill location */
889   if (sym->isspilt || sym->nRegs == 0)
890     {
891
892       /* rematerialize it NOW */
893       if (sym->remat)
894         {
895           sym->aop = op->aop = aop =
896             aopForRemat (sym);
897           aop->size = getSize (sym->type);
898           return;
899         }
900
901       if (sym->accuse)
902         {
903           int i;
904           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
905           aop->size = getSize (sym->type);
906           for (i = 0; i < 2; i++)
907             aop->aopu.aop_str[i] = accUse[i];
908           return;
909         }
910
911       if (sym->ruonly)
912         {
913           int i;
914
915           if (useDP2)
916             {
917               /* a AOP_STR uses DPTR, but DPTR is already in use;
918                * we're just hosed.
919                */
920                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
921             }
922
923           aop = op->aop = sym->aop = newAsmop (AOP_STR);
924           aop->size = getSize (sym->type);
925           for (i = 0; i < (int) fReturnSizeDS390; i++)
926             aop->aopu.aop_str[i] = fReturn[i];
927           return;
928         }
929       
930       if (sym->dptr) { /* has been allocated to a DPTRn */
931           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
932           aop->size = getSize (sym->type);
933           aop->aopu.dptr = sym->dptr;
934           return ;
935       }
936       /* else spill location  */
937       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
938           /* force a new aop if sizes differ */
939           sym->usl.spillLoc->aop = NULL;
940       }
941       sym->aop = op->aop = aop =
942         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
943       aop->size = getSize (sym->type);
944       return;
945     }
946
947   /* must be in a register */
948   sym->aop = op->aop = aop = newAsmop (AOP_REG);
949   aop->size = sym->nRegs;
950   for (i = 0; i < sym->nRegs; i++)
951     aop->aopu.aop_reg[i] = sym->regs[i];
952 }
953
954 /*-----------------------------------------------------------------*/
955 /* freeAsmop - free up the asmop given to an operand               */
956 /*----------------------------------------------------------------*/
957 static void
958 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
959 {
960   asmop *aop;
961
962   if (!op)
963     aop = aaop;
964   else
965     aop = op->aop;
966
967   if (!aop)
968     return;
969
970   if (aop->freed)
971     goto dealloc;
972
973   aop->freed = 1;
974
975   /* depending on the asmop type only three cases need work AOP_RO
976      , AOP_R1 && AOP_STK */
977   switch (aop->type)
978     {
979     case AOP_R0:
980       if (_G.r0Pushed)
981         {
982           if (pop)
983             {
984               emitcode ("pop", "ar0");
985               _G.r0Pushed--;
986             }
987         }
988       bitVectUnSetBit (ic->rUsed, R0_IDX);
989       break;
990
991     case AOP_R1:
992       if (_G.r1Pushed)
993         {
994           if (pop)
995             {
996               emitcode ("pop", "ar1");
997               _G.r1Pushed--;
998             }
999         }
1000       bitVectUnSetBit (ic->rUsed, R1_IDX);
1001       break;
1002
1003     case AOP_STK:
1004       {
1005         int sz = aop->size;
1006         int stk = aop->aopu.aop_stk + aop->size;
1007         bitVectUnSetBit (ic->rUsed, R0_IDX);
1008         bitVectUnSetBit (ic->rUsed, R1_IDX);
1009
1010         getFreePtr (ic, &aop, FALSE);
1011
1012         if (options.stack10bit)
1013           {
1014             /* I'm not sure what to do here yet... */
1015             /* #STUB */
1016             fprintf (stderr,
1017                      "*** Warning: probably generating bad code for "
1018                      "10 bit stack mode.\n");
1019           }
1020
1021         if (stk)
1022           {
1023             emitcode ("mov", "a,_bp");
1024             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1025             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1026           }
1027         else
1028           {
1029             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1030           }
1031
1032         while (sz--)
1033           {
1034             emitcode ("pop", "acc");
1035             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1036             if (!sz)
1037               break;
1038             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1039           }
1040         op->aop = aop;
1041         freeAsmop (op, NULL, ic, TRUE);
1042         if (_G.r0Pushed)
1043           {
1044             emitcode ("pop", "ar0");
1045             _G.r0Pushed--;
1046           }
1047
1048         if (_G.r1Pushed)
1049           {
1050             emitcode ("pop", "ar1");
1051             _G.r1Pushed--;
1052           }
1053       }
1054     case AOP_DPTR2:
1055         if (_G.dptr1InUse) {
1056             emitcode ("pop","dpx1");
1057             emitcode ("pop","dph1");
1058             emitcode ("pop","dpl1");
1059         }
1060         break;
1061     case AOP_DPTR:
1062         if (_G.dptrInUse) {
1063             emitcode ("pop","dpx");
1064             emitcode ("pop","dph");
1065             emitcode ("pop","dpl");
1066         }
1067         break;
1068     }
1069 dealloc:
1070   /* all other cases just dealloc */
1071   if (op)
1072     {
1073       op->aop = NULL;
1074       if (IS_SYMOP (op))
1075         {
1076           OP_SYMBOL (op)->aop = NULL;
1077           /* if the symbol has a spill */
1078           if (SPIL_LOC (op))
1079             SPIL_LOC (op)->aop = NULL;
1080         }
1081     }
1082 }
1083
1084 /*-------------------------------------------------------------------*/
1085 /* aopGet - for fetching value of the aop                            */
1086 /*                                                                   */
1087 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1088 /* in the accumulator. Set it to the name of a free register         */
1089 /* if acc must be preserved; the register will be used to preserve   */
1090 /* acc temporarily and to return the result byte.                    */
1091 /*-------------------------------------------------------------------*/
1092
1093 static char *
1094 aopGet (asmop *aop,
1095         int   offset,
1096         bool  bit16,
1097         bool  dname,
1098         char  *saveAcc)
1099 {
1100   /* offset is greater than
1101      size then zero */
1102   if (offset > (aop->size - 1) &&
1103       aop->type != AOP_LIT)
1104     return zero;
1105
1106   /* depending on type */
1107   switch (aop->type)
1108     {
1109
1110     case AOP_R0:
1111     case AOP_R1:
1112       /* if we need to increment it */
1113       while (offset > aop->coff)
1114         {
1115           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1116           aop->coff++;
1117         }
1118
1119       while (offset < aop->coff)
1120         {
1121           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1122           aop->coff--;
1123         }
1124
1125       aop->coff = offset;
1126       if (aop->paged)
1127         {
1128           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1129           return (dname ? "acc" : "a");
1130         }
1131       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1132       return Safe_strdup(buffer);       
1133
1134     case AOP_DPTRn:
1135         assert(offset <= 3);
1136         return dptrn[aop->aopu.dptr][offset];
1137
1138     case AOP_DPTR:
1139     case AOP_DPTR2:
1140
1141       if (aop->type == AOP_DPTR2)
1142         {
1143           genSetDPTR (1);
1144           if (saveAcc)
1145             {
1146                     TR_AP("#1");
1147                     emitcode ("xch", "a, %s", saveAcc);
1148             }
1149         }
1150
1151       _flushLazyDPS ();
1152
1153       while (offset > aop->coff)
1154         {
1155           emitcode ("inc", "dptr");
1156           aop->coff++;
1157         }
1158
1159       while (offset < aop->coff)
1160         {
1161           emitcode ("lcall", "__decdptr");
1162           aop->coff--;
1163         }
1164
1165       aop->coff = offset;
1166       if (aop->code)
1167         {
1168           emitcode ("clr", "a");
1169           emitcode ("movc", "a,@a+dptr");
1170         }
1171       else
1172         {
1173           emitcode ("movx", "a,@dptr");
1174         }
1175
1176       if (aop->type == AOP_DPTR2)
1177         {
1178           genSetDPTR (0);
1179           if (saveAcc)
1180             {
1181        TR_AP("#2");
1182               emitcode ("xch", "a, %s", saveAcc);
1183               return saveAcc;
1184             }
1185         }
1186       return (dname ? "acc" : "a");
1187
1188     case AOP_IMMD:
1189       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1190       {
1191           SNPRINTF(buffer, sizeof(buffer), 
1192                    "%s",aop->aopu.aop_immd.aop_immd2);
1193       } 
1194       else if (bit16)
1195       {
1196          SNPRINTF(buffer, sizeof(buffer), 
1197                   "#%s", aop->aopu.aop_immd.aop_immd1);
1198       }
1199       else if (offset) 
1200       {
1201           switch (offset) {
1202           case 1:
1203               tsprintf(buffer, sizeof(buffer),
1204                        "#!his",aop->aopu.aop_immd.aop_immd1);
1205               break;
1206           case 2:
1207               tsprintf(buffer, sizeof(buffer), 
1208                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1209               break;
1210           case 3:
1211               tsprintf(buffer, sizeof(buffer),
1212                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1213               break;
1214           default: /* should not need this (just in case) */
1215               SNPRINTF (buffer, sizeof(buffer), 
1216                         "#(%s >> %d)",
1217                        aop->aopu.aop_immd.aop_immd1,
1218                        offset * 8);
1219           }
1220       }
1221       else
1222       {
1223         SNPRINTF (buffer, sizeof(buffer), 
1224                   "#%s", aop->aopu.aop_immd.aop_immd1);
1225       }
1226       return Safe_strdup(buffer);       
1227
1228     case AOP_DIR:
1229       if (offset)
1230       {
1231         SNPRINTF (buffer, sizeof(buffer),
1232                   "(%s + %d)",
1233                  aop->aopu.aop_dir,
1234                  offset);
1235       }
1236       else
1237       {
1238         SNPRINTF(buffer, sizeof(buffer), 
1239                  "%s", aop->aopu.aop_dir);
1240       }
1241
1242       return Safe_strdup(buffer);
1243
1244     case AOP_REG:
1245       if (dname)
1246         return aop->aopu.aop_reg[offset]->dname;
1247       else
1248         return aop->aopu.aop_reg[offset]->name;
1249
1250     case AOP_CRY:
1251       emitcode ("clr", "a");
1252       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1253       emitcode ("rlc", "a");
1254       return (dname ? "acc" : "a");
1255
1256     case AOP_ACC:
1257       if (!offset && dname)
1258         return "acc";
1259       return aop->aopu.aop_str[offset];
1260
1261     case AOP_LIT:
1262       return aopLiteral (aop->aopu.aop_lit, offset);
1263
1264     case AOP_STR:
1265       aop->coff = offset;
1266       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1267           dname)
1268         return "acc";
1269
1270       return aop->aopu.aop_str[offset];
1271
1272     }
1273
1274   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1275           "aopget got unsupported aop->type");
1276   exit (1);
1277     
1278   return NULL;  // not reached, but makes compiler happy.
1279 }
1280 /*-----------------------------------------------------------------*/
1281 /* aopPut - puts a string for a aop                                */
1282 /*-----------------------------------------------------------------*/
1283 static void
1284 aopPut (asmop * aop, char *s, int offset)
1285 {
1286   if (aop->size && offset > (aop->size - 1))
1287     {
1288       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1289               "aopPut got offset > aop->size");
1290       exit (1);
1291     }
1292
1293   /* will assign value to value */
1294   /* depending on where it is ofcourse */
1295   switch (aop->type)
1296     {
1297     case AOP_DIR:
1298         if (offset)
1299         {
1300             SNPRINTF (buffer, sizeof(buffer),
1301                       "(%s + %d)",
1302                       aop->aopu.aop_dir, offset);
1303         }
1304         else
1305         {
1306             SNPRINTF (buffer, sizeof(buffer), 
1307                      "%s", aop->aopu.aop_dir);
1308         }
1309         
1310
1311         if (strcmp (buffer, s))
1312         {
1313             emitcode ("mov", "%s,%s", buffer, s);
1314         }
1315       break;
1316
1317     case AOP_REG:
1318       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1319           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1320         {
1321           if (*s == '@' ||
1322               strcmp (s, "r0") == 0 ||
1323               strcmp (s, "r1") == 0 ||
1324               strcmp (s, "r2") == 0 ||
1325               strcmp (s, "r3") == 0 ||
1326               strcmp (s, "r4") == 0 ||
1327               strcmp (s, "r5") == 0 ||
1328               strcmp (s, "r6") == 0 ||
1329               strcmp (s, "r7") == 0)
1330             {
1331                 emitcode ("mov", "%s,%s",
1332                           aop->aopu.aop_reg[offset]->dname, s);
1333             }
1334             else
1335             {
1336                 emitcode ("mov", "%s,%s",
1337                           aop->aopu.aop_reg[offset]->name, s);
1338             }
1339         }
1340       break;
1341
1342     case AOP_DPTRn:
1343         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1344         break;
1345
1346     case AOP_DPTR:
1347     case AOP_DPTR2:
1348
1349       if (aop->type == AOP_DPTR2)
1350         {
1351           genSetDPTR (1);
1352         }
1353       _flushLazyDPS ();
1354
1355       if (aop->code)
1356         {
1357           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1358                   "aopPut writting to code space");
1359           exit (1);
1360         }
1361
1362       while (offset > aop->coff)
1363         {
1364           aop->coff++;
1365           emitcode ("inc", "dptr");
1366         }
1367
1368       while (offset < aop->coff)
1369         {
1370           aop->coff--;
1371           emitcode ("lcall", "__decdptr");
1372         }
1373
1374       aop->coff = offset;
1375
1376       /* if not in accumulater */
1377       MOVA (s);
1378
1379       emitcode ("movx", "@dptr,a");
1380
1381       if (aop->type == AOP_DPTR2)
1382         {
1383           genSetDPTR (0);
1384         }
1385       break;
1386
1387     case AOP_R0:
1388     case AOP_R1:
1389       while (offset > aop->coff)
1390         {
1391           aop->coff++;
1392           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1393         }
1394       while (offset < aop->coff)
1395         {
1396           aop->coff--;
1397           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1398         }
1399       aop->coff = offset;
1400
1401       if (aop->paged)
1402         {
1403           MOVA (s);
1404           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1405
1406         }
1407       else if (*s == '@')
1408         {
1409           MOVA (s);
1410           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1411         }
1412       else if (strcmp (s, "r0") == 0 ||
1413                strcmp (s, "r1") == 0 ||
1414                strcmp (s, "r2") == 0 ||
1415                strcmp (s, "r3") == 0 ||
1416                strcmp (s, "r4") == 0 ||
1417                strcmp (s, "r5") == 0 ||
1418                strcmp (s, "r6") == 0 ||
1419                strcmp (s, "r7") == 0)
1420         {
1421           char buff[10];
1422           SNPRINTF(buff, sizeof(buff), 
1423                    "a%s", s);
1424           emitcode ("mov", "@%s,%s",
1425                     aop->aopu.aop_ptr->name, buff);
1426         }
1427         else
1428         {
1429             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1430         }
1431       break;
1432
1433     case AOP_STK:
1434       if (strcmp (s, "a") == 0)
1435         emitcode ("push", "acc");
1436       else
1437         if (*s=='@') {
1438           MOVA(s);
1439           emitcode ("push", "acc");
1440         } else {
1441           emitcode ("push", s);
1442         }
1443
1444       break;
1445
1446     case AOP_CRY:
1447       /* if bit variable */
1448       if (!aop->aopu.aop_dir)
1449         {
1450           emitcode ("clr", "a");
1451           emitcode ("rlc", "a");
1452         }
1453       else
1454         {
1455           if (s == zero)
1456             emitcode ("clr", "%s", aop->aopu.aop_dir);
1457           else if (s == one)
1458             emitcode ("setb", "%s", aop->aopu.aop_dir);
1459           else if (!strcmp (s, "c"))
1460             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1461           else
1462             {
1463               if (strcmp (s, "a"))
1464                 {
1465                   MOVA (s);
1466                 }
1467               {
1468                 /* set C, if a >= 1 */
1469                 emitcode ("add", "a,#!constbyte",0xff);
1470                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1471               }
1472             }
1473         }
1474       break;
1475
1476     case AOP_STR:
1477       aop->coff = offset;
1478       if (strcmp (aop->aopu.aop_str[offset], s))
1479         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1480       break;
1481
1482     case AOP_ACC:
1483       aop->coff = offset;
1484       if (!offset && (strcmp (s, "acc") == 0))
1485         break;
1486
1487       if (strcmp (aop->aopu.aop_str[offset], s))
1488         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1489       break;
1490
1491     default:
1492       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1493               "aopPut got unsupported aop->type");
1494       exit (1);
1495     }
1496
1497 }
1498
1499
1500 /*--------------------------------------------------------------------*/
1501 /* reAdjustPreg - points a register back to where it should (coff==0) */
1502 /*--------------------------------------------------------------------*/
1503 static void
1504 reAdjustPreg (asmop * aop)
1505 {
1506   if ((aop->coff==0) || (aop->size <= 1)) {
1507     return;
1508   }
1509
1510   switch (aop->type)
1511     {
1512     case AOP_R0:
1513     case AOP_R1:
1514       while (aop->coff--)
1515         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1516       break;
1517     case AOP_DPTR:
1518     case AOP_DPTR2:
1519       if (aop->type == AOP_DPTR2)
1520         {
1521           genSetDPTR (1);
1522           _flushLazyDPS ();
1523         }
1524       while (aop->coff--)
1525         {
1526           emitcode ("lcall", "__decdptr");
1527         }
1528
1529       if (aop->type == AOP_DPTR2)
1530         {
1531           genSetDPTR (0);
1532         }
1533       break;
1534
1535     }
1536   aop->coff=0;
1537 }
1538
1539 #define AOP(op) op->aop
1540 #define AOP_TYPE(op) AOP(op)->type
1541 #define AOP_SIZE(op) AOP(op)->size
1542 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1543                        AOP_TYPE(x) == AOP_R0))
1544
1545 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1546                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1547                          AOP(x)->paged))
1548
1549 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1550                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1551                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1552 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1553 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1554 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1555
1556 // The following two macros can be used even if the aop has not yet been aopOp'd.
1557 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1558 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1559
1560 /* Workaround for DS80C390 bug: div ab may return bogus results
1561  * if A is accessed in instruction immediately before the div.
1562  *
1563  * Will be fixed in B4 rev of processor, Dallas claims.
1564  */
1565
1566 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1567     if (!AOP_NEEDSACC(RIGHT))         \
1568     {               \
1569       /* We can load A first, then B, since     \
1570        * B (the RIGHT operand) won't clobber A,   \
1571        * thus avoiding touching A right before the div. \
1572        */             \
1573       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1574       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1575       MOVA(L);            \
1576       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1577       MOVB(L); \
1578     }               \
1579     else              \
1580     {               \
1581       /* Just stuff in a nop after loading A. */    \
1582       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1583       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1584       MOVA(L);            \
1585       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1586     }
1587
1588 /*-----------------------------------------------------------------*/
1589 /* genNotFloat - generates not for float operations              */
1590 /*-----------------------------------------------------------------*/
1591 static void
1592 genNotFloat (operand * op, operand * res)
1593 {
1594   int size, offset;
1595   char *l;
1596   symbol *tlbl;
1597
1598   D (emitcode (";", "genNotFloat "););
1599
1600   /* we will put 127 in the first byte of
1601      the result */
1602   aopPut (AOP (res), "#127", 0);
1603   size = AOP_SIZE (op) - 1;
1604   offset = 1;
1605
1606   _startLazyDPSEvaluation ();
1607   l = aopGet (op->aop, offset++, FALSE, FALSE, NULL);
1608   MOVA (l);
1609
1610   while (size--)
1611     {
1612       emitcode ("orl", "a,%s",
1613                 aopGet (op->aop,
1614                         offset++, FALSE, FALSE,
1615                         DP2_RESULT_REG));
1616     }
1617   _endLazyDPSEvaluation ();
1618
1619   tlbl = newiTempLabel (NULL);
1620   aopPut (res->aop, one, 1);
1621   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1622   aopPut (res->aop, zero, 1);
1623   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1624
1625   size = res->aop->size - 2;
1626   offset = 2;
1627   /* put zeros in the rest */
1628   while (size--)
1629     aopPut (res->aop, zero, offset++);
1630 }
1631
1632 /*-----------------------------------------------------------------*/
1633 /* opIsGptr: returns non-zero if the passed operand is       */
1634 /* a generic pointer type.             */
1635 /*-----------------------------------------------------------------*/
1636 static int
1637 opIsGptr (operand * op)
1638 {
1639   sym_link *type = operandType (op);
1640
1641   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1642     {
1643       return 1;
1644     }
1645   return 0;
1646 }
1647
1648 /*-----------------------------------------------------------------*/
1649 /* getDataSize - get the operand data size                         */
1650 /*-----------------------------------------------------------------*/
1651 static int
1652 getDataSize (operand * op)
1653 {
1654   int size;
1655   size = AOP_SIZE (op);
1656   if (size == GPTRSIZE)
1657     {
1658       sym_link *type = operandType (op);
1659       if (IS_GENPTR (type))
1660         {
1661           /* generic pointer; arithmetic operations
1662            * should ignore the high byte (pointer type).
1663            */
1664           size--;
1665         }
1666     }
1667   return size;
1668 }
1669
1670 /*-----------------------------------------------------------------*/
1671 /* outAcc - output Acc                                             */
1672 /*-----------------------------------------------------------------*/
1673 static void
1674 outAcc (operand * result)
1675 {
1676   int size, offset;
1677   size = getDataSize (result);
1678   if (size)
1679     {
1680       aopPut (AOP (result), "a", 0);
1681       size--;
1682       offset = 1;
1683       /* unsigned or positive */
1684       while (size--)
1685         {
1686           aopPut (AOP (result), zero, offset++);
1687         }
1688     }
1689 }
1690
1691 /*-----------------------------------------------------------------*/
1692 /* outBitC - output a bit C                                        */
1693 /*-----------------------------------------------------------------*/
1694 static void
1695 outBitC (operand * result)
1696 {
1697   /* if the result is bit */
1698   if (AOP_TYPE (result) == AOP_CRY)
1699     {
1700       aopPut (AOP (result), "c", 0);
1701     }
1702   else
1703     {
1704       emitcode ("clr", "a");
1705       emitcode ("rlc", "a");
1706       outAcc (result);
1707     }
1708 }
1709
1710 /*-----------------------------------------------------------------*/
1711 /* toBoolean - emit code for orl a,operator(sizeop)                */
1712 /*-----------------------------------------------------------------*/
1713 static void
1714 toBoolean (operand * oper)
1715 {
1716   int   size = AOP_SIZE (oper) - 1;
1717   int   offset = 1;
1718   bool usedB = FALSE;
1719
1720   /* The generic part of a generic pointer should
1721    * not participate in it's truth value.
1722    *
1723    * i.e. 0x10000000 is zero.
1724    */
1725   if (opIsGptr (oper))
1726     {
1727       D (emitcode (";", "toBoolean: generic ptr special case."););
1728       size--;
1729     }
1730
1731   _startLazyDPSEvaluation ();
1732   if (AOP_NEEDSACC (oper) && size)
1733     {
1734       usedB = TRUE;
1735       emitcode ("push", "b");
1736       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, "b"));
1737     }
1738   else
1739     {
1740       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1741     }
1742     
1743   while (size--)
1744     {
1745       if (usedB)
1746         {
1747           emitcode ("orl", "b,%s",
1748                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1749         }
1750       else
1751         {
1752           emitcode ("orl", "a,%s",
1753                     aopGet (AOP (oper), offset++, FALSE, FALSE, DP2_RESULT_REG));
1754         }
1755     }
1756   _endLazyDPSEvaluation ();
1757
1758   if (usedB)
1759     {
1760       emitcode ("mov", "a,b");
1761       emitcode ("pop", "b");
1762     }
1763 }
1764
1765
1766 /*-----------------------------------------------------------------*/
1767 /* genNot - generate code for ! operation                          */
1768 /*-----------------------------------------------------------------*/
1769 static void
1770 genNot (iCode * ic)
1771 {
1772   symbol *tlbl;
1773   sym_link *optype = operandType (IC_LEFT (ic));
1774
1775   D (emitcode (";", "genNot "););
1776
1777   /* assign asmOps to operand & result */
1778   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1779   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1780
1781   /* if in bit space then a special case */
1782   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1783     {
1784       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1785       emitcode ("cpl", "c");
1786       outBitC (IC_RESULT (ic));
1787       goto release;
1788     }
1789
1790   /* if type float then do float */
1791   if (IS_FLOAT (optype))
1792     {
1793       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1794       goto release;
1795     }
1796
1797   toBoolean (IC_LEFT (ic));
1798
1799   tlbl = newiTempLabel (NULL);
1800   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1801   emitcode ("", "!tlabeldef", tlbl->key + 100);
1802   outBitC (IC_RESULT (ic));
1803
1804 release:
1805   /* release the aops */
1806   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1807   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1808 }
1809
1810
1811 /*-----------------------------------------------------------------*/
1812 /* genCpl - generate code for complement                           */
1813 /*-----------------------------------------------------------------*/
1814 static void
1815 genCpl (iCode * ic)
1816 {
1817   int offset = 0;
1818   int size;
1819   symbol *tlbl;
1820
1821   D (emitcode (";", "genCpl "););
1822
1823
1824   /* assign asmOps to operand & result */
1825   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1826   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1827
1828   /* special case if in bit space */
1829   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1830     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1831       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1832       emitcode ("cpl", "c");
1833       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1834       goto release;
1835     }
1836     tlbl=newiTempLabel(NULL);
1837     emitcode ("cjne", "%s,#0x01,%05d$", 
1838               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1839     emitcode ("", "%05d$:", tlbl->key+100);
1840     outBitC (IC_RESULT(ic));
1841     goto release;
1842   }
1843
1844   size = AOP_SIZE (IC_RESULT (ic));
1845   _startLazyDPSEvaluation ();
1846   while (size--)
1847     {
1848       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1849       emitcode ("cpl", "a");
1850       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1851     }
1852   _endLazyDPSEvaluation ();
1853
1854
1855 release:
1856   /* release the aops */
1857   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1858   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* genUminusFloat - unary minus for floating points                */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 genUminusFloat (operand * op, operand * result)
1866 {
1867   int size, offset = 0;
1868     
1869   D(emitcode (";", "genUminusFloat"););
1870   
1871   /* for this we just copy and then flip the bit */
1872     
1873   _startLazyDPSEvaluation ();
1874   size = AOP_SIZE (op) - 1;
1875
1876   while (size--)
1877   {
1878       aopPut (AOP (result),
1879               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1880               offset);
1881       offset++;
1882     }
1883   
1884   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1885
1886   emitcode ("cpl", "acc.7");
1887   aopPut (AOP (result), "a", offset);    
1888   _endLazyDPSEvaluation ();
1889 }
1890
1891 /*-----------------------------------------------------------------*/
1892 /* genUminus - unary minus code generation                         */
1893 /*-----------------------------------------------------------------*/
1894 static void
1895 genUminus (iCode * ic)
1896 {
1897   int offset, size;
1898   sym_link *optype;
1899
1900   D (emitcode (";", "genUminus "););
1901
1902   /* assign asmops */
1903   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1904   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1905
1906   /* if both in bit space then special
1907      case */
1908   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1909       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1910     {
1911
1912       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1913       emitcode ("cpl", "c");
1914       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1915       goto release;
1916     }
1917
1918   optype = operandType (IC_LEFT (ic));
1919
1920   /* if float then do float stuff */
1921   if (IS_FLOAT (optype))
1922     {
1923       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1924       goto release;
1925     }
1926
1927   /* otherwise subtract from zero */
1928   size = AOP_SIZE (IC_LEFT (ic));
1929   offset = 0;
1930   _startLazyDPSEvaluation ();
1931   while (size--)
1932     {
1933       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1934       if (!strcmp (l, "a"))
1935         {
1936           if (offset == 0)
1937             SETC;
1938           emitcode ("cpl", "a");
1939           emitcode ("addc", "a,#0");
1940         }
1941       else
1942         {
1943           if (offset == 0)
1944             CLRC;
1945           emitcode ("clr", "a");
1946           emitcode ("subb", "a,%s", l);
1947         }
1948       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1949     }
1950   _endLazyDPSEvaluation ();
1951
1952   /* if any remaining bytes in the result */
1953   /* we just need to propagate the sign   */
1954   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1955     {
1956       emitcode ("rlc", "a");
1957       emitcode ("subb", "a,acc");
1958       while (size--)
1959         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1960     }
1961
1962 release:
1963   /* release the aops */
1964   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1965   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* savermask - saves registers in the mask                         */
1970 /*-----------------------------------------------------------------*/
1971 static void savermask(bitVect *rs_mask)
1972 {
1973     int i;
1974     if (options.useXstack) {
1975         if (bitVectBitValue (rs_mask, R0_IDX))
1976             emitcode ("mov", "b,r0");
1977         emitcode ("mov", "r0,%s", spname);
1978         for (i = 0; i < ds390_nRegs; i++) {
1979             if (bitVectBitValue (rs_mask, i)) {
1980                 if (i == R0_IDX)
1981                     emitcode ("mov", "a,b");
1982                 else
1983                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1984                 emitcode ("movx", "@r0,a");
1985                 emitcode ("inc", "r0");
1986             }
1987         }
1988         emitcode ("mov", "%s,r0", spname);
1989         if (bitVectBitValue (rs_mask, R0_IDX))
1990             emitcode ("mov", "r0,b");
1991     } else {
1992         for (i = 0; i < ds390_nRegs; i++) {
1993             if (bitVectBitValue (rs_mask, i))
1994                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1995         }
1996     }
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* saveRegisters - will look for a call and save the registers     */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 saveRegisters (iCode * lic)
2004 {
2005   iCode *ic;
2006   bitVect *rsave;
2007
2008   /* look for call */
2009   for (ic = lic; ic; ic = ic->next)
2010     if (ic->op == CALL || ic->op == PCALL)
2011       break;
2012
2013   if (!ic)
2014     {
2015       fprintf (stderr, "found parameter push with no function call\n");
2016       return;
2017     }
2018
2019   /* if the registers have been saved already then
2020      do nothing */
2021   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2022
2023   /* special case if DPTR alive across a function call then must save it 
2024      even though callee saves */
2025   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2026       int i;
2027       rsave = newBitVect(ic->rMask->size);
2028       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2029           if (bitVectBitValue(ic->rMask,i))
2030               rsave = bitVectSetBit(rsave,i);
2031       }
2032       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2033   } else {
2034     /* safe the registers in use at this time but skip the
2035        ones for the result */
2036     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2037                            ds390_rUmaskForOp (IC_RESULT(ic)));
2038   }
2039   ic->regsSaved = 1;
2040   savermask(rsave);
2041 }
2042
2043 /*-----------------------------------------------------------------*/
2044 /* usavermask - restore registers with mask                        */
2045 /*-----------------------------------------------------------------*/
2046 static void unsavermask(bitVect *rs_mask)
2047 {
2048     int i;
2049     if (options.useXstack) {
2050         emitcode ("mov", "r0,%s", spname);
2051         for (i = ds390_nRegs; i >= 0; i--) {
2052             if (bitVectBitValue (rs_mask, i)) {
2053                 emitcode ("dec", "r0");
2054                 emitcode ("movx", "a,@r0");
2055                 if (i == R0_IDX)
2056                     emitcode ("mov", "b,a");
2057                 else
2058                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2059             }       
2060         }
2061         emitcode ("mov", "%s,r0", spname);
2062         if (bitVectBitValue (rs_mask, R0_IDX))
2063             emitcode ("mov", "r0,b");
2064     } else {
2065         for (i = ds390_nRegs; i >= 0; i--) {
2066             if (bitVectBitValue (rs_mask, i))
2067                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2068         }
2069     }
2070 }
2071
2072 /*-----------------------------------------------------------------*/
2073 /* unsaveRegisters - pop the pushed registers                      */
2074 /*-----------------------------------------------------------------*/
2075 static void
2076 unsaveRegisters (iCode * ic)
2077 {
2078   bitVect *rsave;
2079
2080   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2081       int i;
2082       rsave = newBitVect(ic->rMask->size);
2083       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2084           if (bitVectBitValue(ic->rMask,i))
2085               rsave = bitVectSetBit(rsave,i);
2086       }
2087       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2088   } else {
2089     /* restore the registers in use at this time but skip the
2090        ones for the result */
2091     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2092                            ds390_rUmaskForOp (IC_RESULT(ic)));
2093   }
2094   unsavermask(rsave);
2095 }
2096
2097
2098 /*-----------------------------------------------------------------*/
2099 /* pushSide -                */
2100 /*-----------------------------------------------------------------*/
2101 static void
2102 pushSide (operand * oper, int size)
2103 {
2104   int offset = 0;
2105   _startLazyDPSEvaluation ();
2106   while (size--)
2107     {
2108       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2109       if (AOP_TYPE (oper) != AOP_REG &&
2110           AOP_TYPE (oper) != AOP_DIR &&
2111           strcmp (l, "a"))
2112         {
2113           emitcode ("mov", "a,%s", l);
2114           emitcode ("push", "acc");
2115         }
2116       else
2117         emitcode ("push", "%s", l);
2118     }
2119   _endLazyDPSEvaluation ();
2120 }
2121
2122 /*-----------------------------------------------------------------*/
2123 /* assignResultValue -               */
2124 /*-----------------------------------------------------------------*/
2125 static void
2126 assignResultValue (operand * oper)
2127 {
2128   int offset = 0;
2129   int size = AOP_SIZE (oper);
2130
2131   _startLazyDPSEvaluation ();
2132   while (size--)
2133     {
2134       aopPut (AOP (oper), fReturn[offset], offset);
2135       offset++;
2136     }
2137   _endLazyDPSEvaluation ();
2138 }
2139
2140
2141 /*-----------------------------------------------------------------*/
2142 /* genXpush - pushes onto the external stack                       */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 genXpush (iCode * ic)
2146 {
2147   asmop *aop = newAsmop (0);
2148   regs *r;
2149   int size, offset = 0;
2150
2151   D (emitcode (";", "genXpush ");
2152     );
2153
2154   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2155   r = getFreePtr (ic, &aop, FALSE);
2156
2157
2158   emitcode ("mov", "%s,_spx", r->name);
2159
2160   size = AOP_SIZE (IC_LEFT (ic));
2161   _startLazyDPSEvaluation ();
2162   while (size--)
2163     {
2164
2165       MOVA (aopGet (AOP (IC_LEFT (ic)),
2166                         offset++, FALSE, FALSE, NULL));
2167       emitcode ("movx", "@%s,a", r->name);
2168       emitcode ("inc", "%s", r->name);
2169
2170     }
2171   _endLazyDPSEvaluation ();
2172
2173
2174   emitcode ("mov", "_spx,%s", r->name);
2175
2176   freeAsmop (NULL, aop, ic, TRUE);
2177   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2178 }
2179
2180 /*-----------------------------------------------------------------*/
2181 /* genIpush - generate code for pushing this gets a little complex  */
2182 /*-----------------------------------------------------------------*/
2183 static void
2184 genIpush (iCode * ic)
2185 {
2186   int size, offset = 0;
2187   char *l;
2188
2189   D (emitcode (";", "genIpush ");
2190     );
2191
2192   /* if this is not a parm push : ie. it is spill push
2193      and spill push is always done on the local stack */
2194   if (!ic->parmPush)
2195     {
2196
2197       /* and the item is spilt then do nothing */
2198       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2199         return;
2200
2201       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2202       size = AOP_SIZE (IC_LEFT (ic));
2203       /* push it on the stack */
2204       _startLazyDPSEvaluation ();
2205       while (size--)
2206         {
2207           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2208           if (*l == '#')
2209             {
2210               MOVA (l);
2211               l = "acc";
2212             }
2213           emitcode ("push", "%s", l);
2214         }
2215       _endLazyDPSEvaluation ();
2216       return;
2217     }
2218
2219   /* this is a paramter push: in this case we call
2220      the routine to find the call and save those
2221      registers that need to be saved */
2222   saveRegisters (ic);
2223
2224   /* if use external stack then call the external
2225      stack pushing routine */
2226   if (options.useXstack)
2227     {
2228       genXpush (ic);
2229       return;
2230     }
2231
2232   /* then do the push */
2233   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2234
2235   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2236   size = AOP_SIZE (IC_LEFT (ic));
2237
2238   _startLazyDPSEvaluation ();
2239   while (size--)
2240     {
2241       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2242       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2243           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2244           strcmp (l, "acc"))
2245         {
2246           emitcode ("mov", "a,%s", l);
2247           emitcode ("push", "acc");
2248         }
2249       else
2250         {
2251             emitcode ("push", "%s", l);
2252         }
2253     }
2254   _endLazyDPSEvaluation ();
2255
2256   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2257 }
2258
2259 /*-----------------------------------------------------------------*/
2260 /* genIpop - recover the registers: can happen only for spilling   */
2261 /*-----------------------------------------------------------------*/
2262 static void
2263 genIpop (iCode * ic)
2264 {
2265   int size, offset;
2266
2267   D (emitcode (";", "genIpop ");
2268     );
2269
2270
2271   /* if the temp was not pushed then */
2272   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2273     return;
2274
2275   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2276   size = AOP_SIZE (IC_LEFT (ic));
2277   offset = (size - 1);
2278   _startLazyDPSEvaluation ();
2279   while (size--)
2280     {
2281       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2282                                      FALSE, TRUE, NULL));
2283     }
2284   _endLazyDPSEvaluation ();
2285
2286   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2287 }
2288
2289 /*-----------------------------------------------------------------*/
2290 /* unsaveRBank - restores the resgister bank from stack            */
2291 /*-----------------------------------------------------------------*/
2292 static void
2293 unsaveRBank (int bank, iCode * ic, bool popPsw)
2294 {
2295   int i;
2296   asmop *aop = NULL;
2297   regs *r = NULL;
2298
2299   if (options.useXstack)
2300   {
2301       if (!ic)
2302       {
2303           /* Assume r0 is available for use. */
2304           r = ds390_regWithIdx (R0_IDX);;          
2305       } 
2306       else
2307       {
2308           aop = newAsmop (0);
2309           r = getFreePtr (ic, &aop, FALSE);
2310       }
2311       emitcode ("mov", "%s,_spx", r->name);      
2312   }
2313   
2314   if (popPsw)
2315     {
2316       if (options.useXstack)
2317       {
2318           emitcode ("movx", "a,@%s", r->name);
2319           emitcode ("mov", "psw,a");
2320           emitcode ("dec", "%s", r->name);
2321         }
2322       else
2323       {
2324         emitcode ("pop", "psw");
2325       }
2326     }
2327
2328   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2329     {
2330       if (options.useXstack)
2331         {
2332           emitcode ("movx", "a,@%s", r->name);
2333           emitcode ("mov", "(%s+%d),a",
2334                     regs390[i].base, 8 * bank + regs390[i].offset);
2335           emitcode ("dec", "%s", r->name);
2336
2337         }
2338       else
2339         emitcode ("pop", "(%s+%d)",
2340                   regs390[i].base, 8 * bank + regs390[i].offset);
2341     }
2342
2343   if (options.useXstack)
2344     {
2345       emitcode ("mov", "_spx,%s", r->name);
2346     }
2347     
2348   if (aop)
2349   {
2350       freeAsmop (NULL, aop, ic, TRUE);  
2351   }    
2352 }
2353
2354 /*-----------------------------------------------------------------*/
2355 /* saveRBank - saves an entire register bank on the stack          */
2356 /*-----------------------------------------------------------------*/
2357 static void
2358 saveRBank (int bank, iCode * ic, bool pushPsw)
2359 {
2360   int i;
2361   asmop *aop = NULL;
2362   regs *r = NULL;
2363
2364   if (options.useXstack)
2365     {
2366         if (!ic)
2367         {
2368           /* Assume r0 is available for use. */
2369                   r = ds390_regWithIdx (R0_IDX);;
2370         }
2371         else
2372         {
2373           aop = newAsmop (0);
2374           r = getFreePtr (ic, &aop, FALSE);
2375         }
2376         emitcode ("mov", "%s,_spx", r->name);    
2377     }
2378
2379   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2380     {
2381       if (options.useXstack)
2382         {
2383           emitcode ("inc", "%s", r->name);
2384           emitcode ("mov", "a,(%s+%d)",
2385                     regs390[i].base, 8 * bank + regs390[i].offset);
2386           emitcode ("movx", "@%s,a", r->name);
2387         }
2388       else
2389         emitcode ("push", "(%s+%d)",
2390                   regs390[i].base, 8 * bank + regs390[i].offset);
2391     }
2392
2393   if (pushPsw)
2394     {
2395       if (options.useXstack)
2396         {
2397           emitcode ("mov", "a,psw");
2398           emitcode ("movx", "@%s,a", r->name);
2399           emitcode ("inc", "%s", r->name);
2400           emitcode ("mov", "_spx,%s", r->name);
2401         }
2402       else
2403       {
2404         emitcode ("push", "psw");
2405       }
2406
2407       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2408     }
2409   
2410   if (aop)
2411   {
2412        freeAsmop (NULL, aop, ic, TRUE);
2413   }    
2414     
2415   if (ic)
2416   {  
2417       ic->bankSaved = 1;
2418   }
2419 }
2420
2421 /*-----------------------------------------------------------------*/
2422 /* genSend - gen code for SEND                                     */
2423 /*-----------------------------------------------------------------*/
2424 static void genSend(set *sendSet)
2425 {
2426     iCode *sic;
2427     int sendCount = 0 ;
2428     static int rb1_count = 0;
2429
2430     for (sic = setFirstItem (sendSet); sic;
2431          sic = setNextItem (sendSet)) {     
2432         int size, offset = 0;
2433         
2434         size=getSize(operandType(IC_LEFT(sic)));
2435         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2436         if (sendCount == 0) { /* first parameter */
2437             // we know that dpl(hxb) is the result, so
2438             rb1_count = 0 ;
2439             _startLazyDPSEvaluation ();
2440             if (size>1) {
2441                 aopOp (IC_LEFT (sic), sic, FALSE, 
2442                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2443             } else {
2444                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2445             }
2446             while (size--) {
2447                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2448                                   FALSE, FALSE, NULL);
2449                 if (strcmp (l, fReturn[offset])) {
2450                     emitcode ("mov", "%s,%s",
2451                               fReturn[offset],
2452                               l);
2453                 }
2454                 offset++;
2455             }
2456             _endLazyDPSEvaluation ();
2457             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2458             rb1_count =0;
2459         } else { /* if more parameter in registers */
2460             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2461             while (size--) {
2462                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2463                                                                 FALSE, FALSE, NULL));
2464             }
2465             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2466         }
2467         sendCount++;
2468     }
2469 }
2470
2471 /*-----------------------------------------------------------------*/
2472 /* genCall - generates a call statement                            */
2473 /*-----------------------------------------------------------------*/
2474 static void
2475 genCall (iCode * ic)
2476 {
2477   sym_link *dtype;
2478   bool restoreBank = FALSE;
2479   bool swapBanks = FALSE;
2480
2481   D (emitcode (";", "genCall "););
2482
2483   /* if we are calling a not _naked function that is not using
2484      the same register bank then we need to save the
2485      destination registers on the stack */
2486   dtype = operandType (IC_LEFT (ic));
2487   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2488       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2489       IFFUNC_ISISR (currFunc->type))
2490   {
2491       if (!ic->bankSaved) 
2492       {
2493            /* This is unexpected; the bank should have been saved in
2494             * genFunction.
2495             */
2496            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2497            restoreBank = TRUE;
2498       }
2499       swapBanks = TRUE;
2500   }
2501   
2502     /* if caller saves & we have not saved then */
2503     if (!ic->regsSaved)
2504       saveRegisters (ic);
2505   
2506   /* if send set is not empty the assign */
2507   /* We've saved all the registers we care about;
2508   * therefore, we may clobber any register not used
2509   * in the calling convention (i.e. anything not in
2510   * fReturn.
2511   */
2512   if (_G.sendSet)
2513     {
2514         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2515             genSend(reverseSet(_G.sendSet));
2516         } else {
2517             genSend(_G.sendSet);
2518         }
2519       _G.sendSet = NULL;
2520     }  
2521     
2522   if (swapBanks)
2523   {
2524         emitcode ("mov", "psw,#!constbyte", 
2525            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2526   }
2527
2528   /* make the call */
2529   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2530                             OP_SYMBOL (IC_LEFT (ic))->rname :
2531                             OP_SYMBOL (IC_LEFT (ic))->name));
2532
2533   if (swapBanks)
2534   {
2535        emitcode ("mov", "psw,#!constbyte", 
2536           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2537   }
2538
2539   /* if we need assign a result value */
2540   if ((IS_ITEMP (IC_RESULT (ic)) &&
2541        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2542         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2543         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2544       IS_TRUE_SYMOP (IC_RESULT (ic)))
2545     {
2546       if (isOperandInFarSpace (IC_RESULT (ic))
2547           && getSize (operandType (IC_RESULT (ic))) <= 2)
2548         {
2549           int size = getSize (operandType (IC_RESULT (ic)));
2550
2551           /* Special case for 1 or 2 byte return in far space. */
2552           MOVA (fReturn[0]);
2553           if (size > 1)
2554             {
2555               emitcode ("mov", "b,%s", fReturn[1]);
2556             }
2557
2558           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2559           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2560
2561           if (size > 1)
2562             {
2563               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2564             }
2565           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2566         }
2567       else
2568         {
2569           _G.accInUse++;
2570           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2571           _G.accInUse--;
2572
2573           assignResultValue (IC_RESULT (ic));
2574
2575           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2576         }
2577     }
2578
2579   /* adjust the stack for parameters if
2580      required */
2581   if (ic->parmBytes) {
2582       int i;
2583       if (options.stack10bit) {
2584           if (ic->parmBytes <= 10) {
2585               emitcode(";","stack adjustment for parms");
2586               for (i=0; i < ic->parmBytes ; i++) {
2587                   emitcode("pop","acc");
2588               }
2589           } else {            
2590               PROTECT_SP;
2591               emitcode ("clr","c");
2592               emitcode ("mov","a,sp");
2593               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2594               emitcode ("mov","sp,a");
2595               emitcode ("mov","a,esp");
2596               emitcode ("anl","a,#3");
2597               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2598               emitcode ("mov","esp,a");   
2599               UNPROTECT_SP;
2600           }
2601       } else {
2602           if (ic->parmBytes > 3) {
2603               emitcode ("mov", "a,%s", spname);
2604               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2605               emitcode ("mov", "%s,a", spname);
2606           } else
2607               for (i = 0; i < ic->parmBytes; i++)
2608                   emitcode ("dec", "%s", spname);
2609       }
2610   }
2611
2612   /* if we hade saved some registers then unsave them */
2613   if (ic->regsSaved)
2614     unsaveRegisters (ic);
2615
2616   /* if register bank was saved then pop them */
2617   if (restoreBank)
2618     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2619 }
2620
2621 /*-----------------------------------------------------------------*/
2622 /* genPcall - generates a call by pointer statement                */
2623 /*-----------------------------------------------------------------*/
2624 static void
2625 genPcall (iCode * ic)
2626 {
2627   sym_link *dtype;
2628   symbol *rlbl = newiTempLabel (NULL);
2629   bool restoreBank=FALSE;
2630
2631   D (emitcode (";", "genPcall ");
2632     );
2633
2634
2635   /* if caller saves & we have not saved then */
2636   if (!ic->regsSaved)
2637     saveRegisters (ic);
2638
2639   /* if we are calling a function that is not using
2640      the same register bank then we need to save the
2641      destination registers on the stack */
2642   dtype = operandType (IC_LEFT (ic));
2643   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2644       IFFUNC_ISISR (currFunc->type) &&
2645       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2646     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2647     restoreBank=TRUE;
2648   }
2649
2650   /* push the return address on to the stack */
2651   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2652   emitcode ("push", "acc");
2653   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2654   emitcode ("push", "acc");
2655
2656   if (options.model == MODEL_FLAT24)
2657     {
2658       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2659       emitcode ("push", "acc");
2660     }
2661
2662   /* now push the calling address */
2663   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2664
2665   pushSide (IC_LEFT (ic), FPTRSIZE);
2666
2667   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2668
2669   /* if send set is not empty the assign */
2670   if (_G.sendSet)
2671     {
2672         genSend(reverseSet(_G.sendSet));
2673         _G.sendSet = NULL;
2674     }
2675
2676   emitcode ("ret", "");
2677   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2678
2679
2680   /* if we need assign a result value */
2681   if ((IS_ITEMP (IC_RESULT (ic)) &&
2682        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2683         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2684       IS_TRUE_SYMOP (IC_RESULT (ic)))
2685     {
2686
2687       _G.accInUse++;
2688       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2689       _G.accInUse--;
2690
2691       assignResultValue (IC_RESULT (ic));
2692
2693       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2694     }
2695
2696   /* adjust the stack for parameters if
2697      required */
2698   if (ic->parmBytes)
2699     {
2700       int i;
2701       if (options.stack10bit) {
2702           if (ic->parmBytes <= 10) {
2703               emitcode(";","stack adjustment for parms");
2704               for (i=0; i < ic->parmBytes ; i++) {
2705                   emitcode("pop","acc");
2706               }
2707           } else {            
2708               PROTECT_SP;
2709               emitcode ("clr","c");
2710               emitcode ("mov","a,sp");
2711               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2712               emitcode ("mov","sp,a");
2713               emitcode ("mov","a,esp");
2714               emitcode ("anl","a,#3");
2715               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2716               emitcode ("mov","esp,a");   
2717               UNPROTECT_SP;
2718           }
2719       } else {
2720           if (ic->parmBytes > 3) {
2721               emitcode ("mov", "a,%s", spname);
2722               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2723               emitcode ("mov", "%s,a", spname);
2724           }
2725           else
2726               for (i = 0; i < ic->parmBytes; i++)
2727                   emitcode ("dec", "%s", spname);
2728           
2729       }
2730     }
2731   /* if register bank was saved then unsave them */
2732   if (restoreBank)
2733     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2734   
2735   /* if we hade saved some registers then
2736      unsave them */
2737   if (ic->regsSaved)
2738     unsaveRegisters (ic);
2739
2740 }
2741
2742 /*-----------------------------------------------------------------*/
2743 /* resultRemat - result  is rematerializable                       */
2744 /*-----------------------------------------------------------------*/
2745 static int
2746 resultRemat (iCode * ic)
2747 {
2748   if (SKIP_IC (ic) || ic->op == IFX)
2749     return 0;
2750
2751   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2752     {
2753       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2754       if (sym->remat && !POINTER_SET (ic))
2755         return 1;
2756     }
2757
2758   return 0;
2759 }
2760
2761 #if defined(__BORLANDC__) || defined(_MSC_VER)
2762 #define STRCASECMP stricmp
2763 #else
2764 #define STRCASECMP strcasecmp
2765 #endif
2766
2767 /*-----------------------------------------------------------------*/
2768 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2769 /*-----------------------------------------------------------------*/
2770 static bool
2771 inExcludeList (char *s)
2772 {
2773   int i = 0;
2774
2775   if (options.excludeRegs[i] &&
2776       STRCASECMP (options.excludeRegs[i], "none") == 0)
2777     return FALSE;
2778
2779   for (i = 0; options.excludeRegs[i]; i++)
2780     {
2781       if (options.excludeRegs[i] &&
2782           STRCASECMP (s, options.excludeRegs[i]) == 0)
2783         return TRUE;
2784     }
2785   return FALSE;
2786 }
2787
2788 /*-----------------------------------------------------------------*/
2789 /* genFunction - generated code for function entry                 */
2790 /*-----------------------------------------------------------------*/
2791 static void
2792 genFunction (iCode * ic)
2793 {
2794   symbol *sym;
2795   sym_link *ftype;
2796   bool   switchedPSW = FALSE;
2797
2798   D (emitcode (";", "genFunction "););
2799
2800   _G.nRegsSaved = 0;
2801   /* create the function header */
2802   emitcode (";", "-----------------------------------------");
2803   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2804   emitcode (";", "-----------------------------------------");
2805
2806   emitcode ("", "%s:", sym->rname);
2807   ftype = operandType (IC_LEFT (ic));
2808
2809   if (IFFUNC_ISNAKED(ftype))
2810   {
2811       emitcode(";", "naked function: no prologue.");
2812       return;
2813   }
2814   
2815   if (options.stack_probe) 
2816       emitcode ("lcall","__stack_probe");
2817   /* if critical function then turn interrupts off */
2818   if (IFFUNC_ISCRITICAL (ftype))
2819     emitcode ("clr", "ea");
2820
2821   /* here we need to generate the equates for the
2822      register bank if required */
2823   if (FUNC_REGBANK (ftype) != rbank)
2824     {
2825       int i;
2826
2827       rbank = FUNC_REGBANK (ftype);
2828       for (i = 0; i < ds390_nRegs; i++)
2829         {
2830           if (regs390[i].print) {
2831               if (strcmp (regs390[i].base, "0") == 0)
2832                   emitcode ("", "%s !equ !constbyte",
2833                             regs390[i].dname,
2834                             8 * rbank + regs390[i].offset);
2835               else
2836                   emitcode ("", "%s !equ %s + !constbyte",
2837                             regs390[i].dname,
2838                             regs390[i].base,
2839                             8 * rbank + regs390[i].offset);
2840           }
2841         }
2842     }
2843
2844   /* if this is an interrupt service routine then
2845      save acc, b, dpl, dph  */
2846   if (IFFUNC_ISISR (sym->type))
2847       { /* is ISR */
2848       if (!inExcludeList ("acc"))
2849         emitcode ("push", "acc");
2850       if (!inExcludeList ("b"))
2851         emitcode ("push", "b");
2852       if (!inExcludeList ("dpl"))
2853         emitcode ("push", "dpl");
2854       if (!inExcludeList ("dph"))
2855         emitcode ("push", "dph");
2856       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2857         {
2858           emitcode ("push", "dpx");
2859           /* Make sure we're using standard DPTR */
2860           emitcode ("push", "dps");
2861           emitcode ("mov", "dps,#0");
2862           if (options.stack10bit)
2863             {
2864               /* This ISR could conceivably use DPTR2. Better save it. */
2865               emitcode ("push", "dpl1");
2866               emitcode ("push", "dph1");
2867               emitcode ("push", "dpx1");
2868               emitcode ("push",  DP2_RESULT_REG);
2869             }
2870         }
2871       /* if this isr has no bank i.e. is going to
2872          run with bank 0 , then we need to save more
2873          registers :-) */
2874       if (!FUNC_REGBANK (sym->type))
2875         {
2876             int i;
2877
2878           /* if this function does not call any other
2879              function then we can be economical and
2880              save only those registers that are used */
2881           if (!IFFUNC_HASFCALL(sym->type))
2882             {
2883
2884               /* if any registers used */
2885               if (sym->regsUsed)
2886                 {
2887                   /* save the registers used */
2888                   for (i = 0; i < sym->regsUsed->size; i++)
2889                     {
2890                       if (bitVectBitValue (sym->regsUsed, i) ||
2891                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2892                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2893                     }
2894                 }
2895
2896             }
2897           else
2898             {
2899               /* this function has  a function call cannot
2900                  determines register usage so we will have to push the
2901                  entire bank */
2902               saveRBank (0, ic, FALSE);
2903               if (options.parms_in_bank1) {
2904                   for (i=0; i < 8 ; i++ ) {
2905                       emitcode ("push","%s",rb1regs[i]);
2906                   }
2907               }
2908             }
2909         }
2910         else
2911         {
2912             /* This ISR uses a non-zero bank.
2913              *
2914              * We assume that the bank is available for our
2915              * exclusive use.
2916              *
2917              * However, if this ISR calls a function which uses some
2918              * other bank, we must save that bank entirely.
2919              */
2920             unsigned long banksToSave = 0;
2921             
2922             if (IFFUNC_HASFCALL(sym->type))
2923             {
2924
2925 #define MAX_REGISTER_BANKS 4
2926
2927                 iCode *i;
2928                 int ix;
2929
2930                 for (i = ic; i; i = i->next)
2931                 {
2932                     if (i->op == ENDFUNCTION)
2933                     {
2934                         /* we got to the end OK. */
2935                         break;
2936                     }
2937                     
2938                     if (i->op == CALL)
2939                     {
2940                         sym_link *dtype;
2941                         
2942                         dtype = operandType (IC_LEFT(i));
2943                         if (dtype 
2944                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2945                         {
2946                              /* Mark this bank for saving. */
2947                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2948                              {
2949                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2950                              }
2951                              else
2952                              {
2953                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2954                              }
2955                              
2956                              /* And note that we don't need to do it in 
2957                               * genCall.
2958                               */
2959                              i->bankSaved = 1;
2960                         }
2961                     }
2962                     if (i->op == PCALL)
2963                     {
2964                         /* This is a mess; we have no idea what
2965                          * register bank the called function might
2966                          * use.
2967                          *
2968                          * The only thing I can think of to do is
2969                          * throw a warning and hope.
2970                          */
2971                         werror(W_FUNCPTR_IN_USING_ISR);   
2972                     }
2973                 }
2974
2975                 if (banksToSave && options.useXstack)
2976                 {
2977                     /* Since we aren't passing it an ic, 
2978                      * saveRBank will assume r0 is available to abuse.
2979                      *
2980                      * So switch to our (trashable) bank now, so
2981                      * the caller's R0 isn't trashed.
2982                      */
2983                     emitcode ("push", "psw");
2984                     emitcode ("mov", "psw,#!constbyte", 
2985                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2986                     switchedPSW = TRUE;
2987                 }
2988                 
2989                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2990                 {
2991                      if (banksToSave & (1 << ix))
2992                      {
2993                          saveRBank(ix, NULL, FALSE);
2994                      }
2995                 }
2996             }
2997             // jwk: this needs a closer look
2998             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2999         }
3000     }
3001   else
3002     {
3003       /* if callee-save to be used for this function
3004          then save the registers being used in this function */
3005       if (IFFUNC_CALLEESAVES(sym->type))
3006         {
3007           int i;
3008
3009           /* if any registers used */
3010           if (sym->regsUsed)
3011             {
3012               /* save the registers used */
3013               for (i = 0; i < sym->regsUsed->size; i++)
3014                 {
3015                   if (bitVectBitValue (sym->regsUsed, i) ||
3016                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3017                     {
3018                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3019                       _G.nRegsSaved++;
3020                     }
3021                 }
3022             }
3023         }
3024     }
3025
3026   /* set the register bank to the desired value */
3027   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3028    && !switchedPSW)
3029     {
3030       emitcode ("push", "psw");
3031       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3032     }
3033
3034   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3035        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3036       if (options.stack10bit) {
3037           emitcode ("push","_bpx");
3038           emitcode ("push","_bpx+1");
3039           emitcode ("mov","_bpx,%s",spname);
3040           emitcode ("mov","_bpx+1,esp");
3041           emitcode ("anl","_bpx+1,#3");
3042       } else {
3043           if (options.useXstack) {
3044               emitcode ("mov", "r0,%s", spname);
3045               emitcode ("mov", "a,_bp");
3046               emitcode ("movx", "@r0,a");
3047               emitcode ("inc", "%s", spname);
3048           } else {
3049               /* set up the stack */
3050               emitcode ("push", "_bp"); /* save the callers stack  */
3051           }
3052           emitcode ("mov", "_bp,%s", spname);
3053       }
3054   }
3055
3056   /* adjust the stack for the function */
3057   if (sym->stack) {
3058       int i = sym->stack;
3059       if (options.stack10bit) {
3060           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3061           assert (sym->recvSize <= 4);
3062           if (sym->stack <= 8) {
3063               while (i--) emitcode ("push","acc");
3064           } else {
3065               PROTECT_SP;
3066               emitcode ("mov","a,sp");
3067               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3068               emitcode ("mov","sp,a");
3069               emitcode ("mov","a,esp");
3070               emitcode ("anl","a,#3");
3071               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3072               emitcode ("mov","esp,a");
3073               UNPROTECT_SP;
3074           }
3075       } else {
3076           if (i > 256)
3077               werror (W_STACK_OVERFLOW, sym->name);
3078           
3079           if (i > 3 && sym->recvSize < 4) {
3080               
3081               emitcode ("mov", "a,sp");
3082               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3083               emitcode ("mov", "sp,a");
3084               
3085           } else
3086               while (i--)
3087                   emitcode ("inc", "sp");
3088       }
3089   }
3090
3091   if (sym->xstack)
3092     {
3093
3094       emitcode ("mov", "a,_spx");
3095       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3096       emitcode ("mov", "_spx,a");
3097     }
3098
3099 }
3100
3101 /*-----------------------------------------------------------------*/
3102 /* genEndFunction - generates epilogue for functions               */
3103 /*-----------------------------------------------------------------*/
3104 static void
3105 genEndFunction (iCode * ic)
3106 {
3107   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3108
3109   D (emitcode (";", "genEndFunction "););
3110
3111   if (IFFUNC_ISNAKED(sym->type))
3112   {
3113       emitcode(";", "naked function: no epilogue.");
3114       return;
3115   }
3116
3117   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3118        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3119
3120       if (options.stack10bit) {
3121           PROTECT_SP;     
3122           emitcode ("mov", "sp,_bpx", spname);
3123           emitcode ("mov", "esp,_bpx+1", spname);
3124           UNPROTECT_SP;
3125       } else {
3126           emitcode ("mov", "%s,_bp", spname);
3127       }
3128   }
3129
3130   /* if use external stack but some variables were
3131      added to the local stack then decrement the
3132      local stack */
3133   if (options.useXstack && sym->stack) {
3134       emitcode ("mov", "a,sp");
3135       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3136       emitcode ("mov", "sp,a");
3137   }
3138
3139
3140   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3141        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3142
3143       if (options.useXstack) {
3144           emitcode ("mov", "r0,%s", spname);
3145           emitcode ("movx", "a,@r0");
3146           emitcode ("mov", "_bp,a");
3147           emitcode ("dec", "%s", spname);
3148       } else {
3149           if (options.stack10bit) {
3150               emitcode ("pop", "_bpx+1");
3151               emitcode ("pop", "_bpx");
3152           } else {
3153               emitcode ("pop", "_bp");
3154           }
3155       }
3156   }
3157
3158   /* restore the register bank  */
3159   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3160   {
3161     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3162      || !options.useXstack)
3163     {
3164         /* Special case of ISR using non-zero bank with useXstack
3165          * is handled below.
3166          */
3167         emitcode ("pop", "psw");
3168     }
3169   } 
3170
3171   if (IFFUNC_ISISR (sym->type))
3172       { /* is ISR */  
3173
3174       /* now we need to restore the registers */
3175       /* if this isr has no bank i.e. is going to
3176          run with bank 0 , then we need to save more
3177          registers :-) */
3178       if (!FUNC_REGBANK (sym->type))
3179         {
3180             int i;
3181           /* if this function does not call any other
3182              function then we can be economical and
3183              save only those registers that are used */
3184           if (!IFFUNC_HASFCALL(sym->type))
3185             {
3186
3187               /* if any registers used */
3188               if (sym->regsUsed)
3189                 {
3190                   /* save the registers used */
3191                   for (i = sym->regsUsed->size; i >= 0; i--)
3192                     {
3193                       if (bitVectBitValue (sym->regsUsed, i) ||
3194                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3195                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3196                     }
3197                 }
3198
3199             }
3200           else
3201             {
3202               /* this function has  a function call cannot
3203                  determines register usage so we will have to pop the
3204                  entire bank */
3205               if (options.parms_in_bank1) {
3206                   for (i = 7 ; i >= 0 ; i-- ) {
3207                       emitcode ("pop","%s",rb1regs[i]);
3208                   }
3209               }
3210               unsaveRBank (0, ic, FALSE);
3211             }
3212         }
3213         else
3214         {
3215             /* This ISR uses a non-zero bank.
3216              *
3217              * Restore any register banks saved by genFunction
3218              * in reverse order.
3219              */
3220           // jwk: this needs a closer look
3221             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3222             int ix;
3223           
3224             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3225             {
3226                 if (savedBanks & (1 << ix))
3227                 {
3228                     unsaveRBank(ix, NULL, FALSE);
3229                 }
3230             }
3231             
3232             if (options.useXstack)
3233             {
3234                 /* Restore bank AFTER calling unsaveRBank,
3235                  * since it can trash r0.
3236                  */
3237                 emitcode ("pop", "psw");
3238             }
3239         }
3240
3241       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3242         {
3243           if (options.stack10bit)
3244             {
3245               emitcode ("pop", DP2_RESULT_REG);
3246               emitcode ("pop", "dpx1");
3247               emitcode ("pop", "dph1");
3248               emitcode ("pop", "dpl1");
3249             }
3250           emitcode ("pop", "dps");
3251           emitcode ("pop", "dpx");
3252         }
3253       if (!inExcludeList ("dph"))
3254         emitcode ("pop", "dph");
3255       if (!inExcludeList ("dpl"))
3256         emitcode ("pop", "dpl");
3257       if (!inExcludeList ("b"))
3258         emitcode ("pop", "b");
3259       if (!inExcludeList ("acc"))
3260         emitcode ("pop", "acc");
3261
3262       if (IFFUNC_ISCRITICAL (sym->type))
3263         emitcode ("setb", "ea");
3264
3265       /* if debug then send end of function */
3266       if (options.debug && currFunc) {
3267           _G.debugLine = 1;
3268           emitcode ("", "C$%s$%d$%d$%d ==.",
3269                     FileBaseName (ic->filename), currFunc->lastLine,
3270                     ic->level, ic->block);
3271           if (IS_STATIC (currFunc->etype))
3272             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3273           else
3274             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3275           _G.debugLine = 0;
3276         }
3277
3278       emitcode ("reti", "");
3279     }
3280   else
3281     {
3282       if (IFFUNC_ISCRITICAL (sym->type))
3283         emitcode ("setb", "ea");
3284
3285       if (IFFUNC_CALLEESAVES(sym->type))
3286         {
3287           int i;
3288
3289           /* if any registers used */
3290           if (sym->regsUsed)
3291             {
3292               /* save the registers used */
3293               for (i = sym->regsUsed->size; i >= 0; i--)
3294                 {
3295                   if (bitVectBitValue (sym->regsUsed, i) ||
3296                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3297                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3298                 }
3299             }
3300
3301         }
3302
3303       /* if debug then send end of function */
3304       if (options.debug && currFunc)
3305         {
3306           _G.debugLine = 1;
3307           emitcode ("", "C$%s$%d$%d$%d ==.",
3308                     FileBaseName (ic->filename), currFunc->lastLine,
3309                     ic->level, ic->block);
3310           if (IS_STATIC (currFunc->etype))
3311             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3312           else
3313             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3314           _G.debugLine = 0;
3315         }
3316
3317       emitcode ("ret", "");
3318     }
3319
3320 }
3321
3322 /*-----------------------------------------------------------------*/
3323 /* genJavaNativeRet - generate code for return JavaNative          */
3324 /*-----------------------------------------------------------------*/
3325 static void genJavaNativeRet(iCode *ic)
3326 {
3327     int i, size;
3328
3329     aopOp (IC_LEFT (ic), ic, FALSE, 
3330            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3331     size = AOP_SIZE (IC_LEFT (ic));
3332
3333     assert (size <= 4);
3334
3335     /* it is assigned to GPR0-R3 then push them */
3336     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3337         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3338         for (i = 0 ; i < size ; i++ ) {
3339             emitcode ("push","%s",
3340                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3341         }
3342         for (i = (size-1) ; i >= 0 ; i--) {
3343             emitcode ("pop","a%s",javaRet[i]);
3344         }
3345     } else {
3346         for (i = 0 ; i < size ; i++) 
3347             emitcode ("mov","%s,%s",javaRet[i],
3348                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3349     }
3350     for (i = size ; i < 4 ; i++ )
3351             emitcode ("mov","%s,#0",javaRet[i]);
3352     return;
3353 }
3354
3355 /*-----------------------------------------------------------------*/
3356 /* genRet - generate code for return statement                     */
3357 /*-----------------------------------------------------------------*/
3358 static void
3359 genRet (iCode * ic)
3360 {
3361   int size, offset = 0, pushed = 0;
3362
3363   D (emitcode (";", "genRet "););
3364
3365   /* if we have no return value then
3366      just generate the "ret" */
3367   if (!IC_LEFT (ic))
3368     goto jumpret;
3369
3370   /* if this is a JavaNative function then return 
3371      value in different register */
3372   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3373       genJavaNativeRet(ic);
3374       goto jumpret;
3375   }
3376   /* we have something to return then
3377      move the return value into place */
3378   aopOp (IC_LEFT (ic), ic, FALSE, 
3379          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3380   size = AOP_SIZE (IC_LEFT (ic));
3381
3382   _startLazyDPSEvaluation ();
3383   while (size--)
3384     {
3385       char *l;
3386       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3387         {
3388           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3389                       FALSE, TRUE, NULL);
3390           emitcode ("push", "%s", l);
3391           pushed++;
3392         }
3393       else
3394         {
3395           /* Since A is the last element of fReturn,
3396            * is is OK to clobber it in the aopGet.
3397            */
3398           l = aopGet (AOP (IC_LEFT (ic)), offset,
3399                       FALSE, FALSE, NULL);
3400           if (strcmp (fReturn[offset], l))
3401             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3402         }
3403     }
3404   _endLazyDPSEvaluation ();
3405
3406   if (pushed)
3407     {
3408       while (pushed)
3409         {
3410           pushed--;
3411           if (strcmp (fReturn[pushed], "a"))
3412             emitcode ("pop", fReturn[pushed]);
3413           else
3414             emitcode ("pop", "acc");
3415         }
3416     }
3417   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3418
3419 jumpret:
3420   /* generate a jump to the return label
3421      if the next is not the return statement */
3422   if (!(ic->next && ic->next->op == LABEL &&
3423         IC_LABEL (ic->next) == returnLabel))
3424
3425     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3426
3427 }
3428
3429 /*-----------------------------------------------------------------*/
3430 /* genLabel - generates a label                                    */
3431 /*-----------------------------------------------------------------*/
3432 static void
3433 genLabel (iCode * ic)
3434 {
3435   /* special case never generate */
3436   if (IC_LABEL (ic) == entryLabel)
3437     return;
3438
3439   D (emitcode (";", "genLabel ");
3440     );
3441
3442   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3443 }
3444
3445 /*-----------------------------------------------------------------*/
3446 /* genGoto - generates a ljmp                                      */
3447 /*-----------------------------------------------------------------*/
3448 static void
3449 genGoto (iCode * ic)
3450 {
3451   D (emitcode (";", "genGoto ");
3452     );
3453   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3454 }
3455
3456 /*-----------------------------------------------------------------*/
3457 /* findLabelBackwards: walks back through the iCode chain looking  */
3458 /* for the given label. Returns number of iCode instructions     */
3459 /* between that label and given ic.          */
3460 /* Returns zero if label not found.          */
3461 /*-----------------------------------------------------------------*/
3462 static int
3463 findLabelBackwards (iCode * ic, int key)
3464 {
3465   int count = 0;
3466
3467   while (ic->prev)
3468     {
3469       ic = ic->prev;
3470       count++;
3471
3472       /* If we have any pushes or pops, we cannot predict the distance.
3473          I don't like this at all, this should be dealt with in the 
3474          back-end */
3475       if (ic->op == IPUSH || ic->op == IPOP) {
3476         return 0;
3477       }
3478
3479       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3480         {
3481           /* printf("findLabelBackwards = %d\n", count); */
3482           return count;
3483         }
3484     }
3485
3486   return 0;
3487 }
3488
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusIncr :- does addition with increment if possible         */
3491 /*-----------------------------------------------------------------*/
3492 static bool
3493 genPlusIncr (iCode * ic)
3494 {
3495   unsigned int icount;
3496   unsigned int size = getDataSize (IC_RESULT (ic));
3497
3498   /* will try to generate an increment */
3499   /* if the right side is not a literal
3500      we cannot */
3501   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3502     return FALSE;
3503
3504   /* if the literal value of the right hand side
3505      is greater than 4 then it is not worth it */
3506   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3507     return FALSE;
3508
3509   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3510       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3511       while (icount--) {
3512           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3513       }
3514       return TRUE;
3515   }
3516   /* if increment 16 bits in register */
3517   if (
3518        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3519        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3520        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3521        (size > 1) &&
3522        (icount == 1))
3523     {
3524       symbol  *tlbl;
3525       int     emitTlbl;
3526       int     labelRange;
3527       char    *l;
3528
3529       /* If the next instruction is a goto and the goto target
3530        * is <= 5 instructions previous to this, we can generate
3531        * jumps straight to that target.
3532        */
3533       if (ic->next && ic->next->op == GOTO
3534           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3535           && labelRange <= 5)
3536         {
3537           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3538           tlbl = IC_LABEL (ic->next);
3539           emitTlbl = 0;
3540         }
3541       else
3542         {
3543           tlbl = newiTempLabel (NULL);
3544           emitTlbl = 1;
3545         }
3546         
3547       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3548       emitcode ("inc", "%s", l);
3549       
3550       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3551           IS_AOP_PREG (IC_RESULT (ic)))
3552       {   
3553         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3554       }
3555       else
3556       {
3557           emitcode ("clr", "a");
3558           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3559       }
3560
3561       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3562       emitcode ("inc", "%s", l);
3563       if (size > 2)
3564         {
3565             if (!strcmp(l, "acc"))
3566             {
3567                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3568             }
3569             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3570                      IS_AOP_PREG (IC_RESULT (ic)))
3571             {
3572                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3573             }
3574             else
3575             {
3576                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3577             }
3578
3579             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3580             emitcode ("inc", "%s", l);
3581         }
3582       if (size > 3)
3583         {
3584             if (!strcmp(l, "acc"))
3585             {
3586                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3587             }
3588             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3589                      IS_AOP_PREG (IC_RESULT (ic)))
3590             {
3591                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3592             }
3593             else
3594             {
3595                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3596             }
3597
3598             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3599             emitcode ("inc", "%s", l);  }
3600
3601       if (emitTlbl)
3602         {
3603           emitcode ("", "!tlabeldef", tlbl->key + 100);
3604         }
3605       return TRUE;
3606     }
3607
3608   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3609       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3610       options.model == MODEL_FLAT24 ) {
3611
3612       switch (size) {
3613       case 3:
3614           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3615       case 2:
3616           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3617       case 1:
3618           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3619           break;
3620       }
3621       while (icount--) emitcode ("inc","dptr");      
3622       return TRUE;
3623   }
3624
3625   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3626       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3627       icount <= 5 ) {
3628       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3629       while (icount--) emitcode ("inc","dptr");
3630       emitcode ("mov","dps,#0");
3631       return TRUE;
3632   }
3633
3634   /* if the sizes are greater than 1 then we cannot */
3635   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3636       AOP_SIZE (IC_LEFT (ic)) > 1)
3637     return FALSE;
3638
3639   /* we can if the aops of the left & result match or
3640      if they are in registers and the registers are the
3641      same */
3642   if (
3643        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3644        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3645        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3646     {
3647
3648       if (icount > 3)
3649         {
3650           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3651           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3652           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3653         }
3654       else
3655         {
3656
3657           _startLazyDPSEvaluation ();
3658           while (icount--)
3659             {
3660               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3661             }
3662           _endLazyDPSEvaluation ();
3663         }
3664
3665       return TRUE;
3666     }
3667
3668   return FALSE;
3669 }
3670
3671 /*-----------------------------------------------------------------*/
3672 /* outBitAcc - output a bit in acc                                 */
3673 /*-----------------------------------------------------------------*/
3674 static void
3675 outBitAcc (operand * result)
3676 {
3677   symbol *tlbl = newiTempLabel (NULL);
3678   /* if the result is a bit */
3679   if (AOP_TYPE (result) == AOP_CRY)
3680     {
3681       aopPut (AOP (result), "a", 0);
3682     }
3683   else
3684     {
3685       emitcode ("jz", "!tlabel", tlbl->key + 100);
3686       emitcode ("mov", "a,%s", one);
3687       emitcode ("", "!tlabeldef", tlbl->key + 100);
3688       outAcc (result);
3689     }
3690 }
3691
3692 /*-----------------------------------------------------------------*/
3693 /* genPlusBits - generates code for addition of two bits           */
3694 /*-----------------------------------------------------------------*/
3695 static void
3696 genPlusBits (iCode * ic)
3697 {
3698   D (emitcode (";", "genPlusBits "););
3699     
3700   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3701     {
3702       symbol *lbl = newiTempLabel (NULL);
3703       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3704       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3705       emitcode ("cpl", "c");
3706       emitcode ("", "!tlabeldef", (lbl->key + 100));
3707       outBitC (IC_RESULT (ic));
3708     }
3709   else
3710     {
3711       emitcode ("clr", "a");
3712       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3713       emitcode ("rlc", "a");
3714       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3715       emitcode ("addc", "a,#0");
3716       outAcc (IC_RESULT (ic));
3717     }
3718 }
3719
3720 static void
3721 adjustArithmeticResult (iCode * ic)
3722 {
3723   if (opIsGptr (IC_RESULT (ic)) &&
3724       opIsGptr (IC_LEFT (ic)) &&
3725       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3726     {
3727       aopPut (AOP (IC_RESULT (ic)),
3728               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3729               GPTRSIZE - 1);
3730     }
3731
3732   if (opIsGptr (IC_RESULT (ic)) &&
3733       opIsGptr (IC_RIGHT (ic)) &&
3734       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3735     {
3736       aopPut (AOP (IC_RESULT (ic)),
3737             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3738               GPTRSIZE - 1);
3739     }
3740
3741   if (opIsGptr (IC_RESULT (ic)) &&
3742       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3743       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3744       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3745       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3746     {
3747       char buff[5];
3748       SNPRINTF (buff, sizeof(buff), 
3749                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3750       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3751     }
3752 }
3753
3754 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3755 // generates the result if possible. If result is generated, returns TRUE; otherwise
3756 // returns false and caller must deal with fact that result isn't aopOp'd.
3757 bool aopOp3(iCode * ic)
3758 {
3759     bool dp1InUse, dp2InUse;
3760     bool useDp2;
3761     
3762     // First, generate the right opcode. DPTR may be used if neither left nor result are
3763     // of type AOP_STR.
3764     
3765 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3766 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3767 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3768 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3769 //      );
3770 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3771 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3772 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3773 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3774 //      );      
3775
3776     
3777     // Right uses DPTR unless left or result is an AOP_STR.
3778     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3779     
3780     // if the right used DPTR, left MUST use DPTR2.
3781     // if the right used DPTR2, left MUST use DPTR.
3782     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3783     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3784     // enabling us to assign DPTR to result.
3785      
3786     if (AOP_USESDPTR(IC_RIGHT(ic)))
3787     {
3788         useDp2 = TRUE;
3789     }
3790     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3791     {
3792         useDp2 = FALSE;
3793     }
3794     else
3795     {
3796         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3797         {
3798             useDp2 = TRUE;
3799         }
3800         else
3801         {
3802             useDp2 = FALSE;
3803         }
3804     }
3805
3806     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3807     
3808     // We've op'd the left & right. So, if left or right are the same operand as result, 
3809     // we know aopOp will succeed, and we can just do it & bail.
3810     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3811         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3812     {
3813 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3814         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3815         return TRUE;
3816     }
3817     
3818     // Note which dptrs are currently in use.
3819     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3820     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3821     
3822     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3823     // generate it.
3824     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3825     {
3826         return FALSE;
3827     }
3828     
3829     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3830     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3831     {
3832         return FALSE;
3833     }
3834     
3835     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3836     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3837     {
3838         return FALSE;
3839     }
3840
3841     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3842
3843     // Some sanity checking...
3844     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3845     {
3846         fprintf(stderr,
3847                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3848                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3849         emitcode(";", ">>> unexpected DPTR here.");
3850     }
3851     
3852     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3853     {
3854         fprintf(stderr,
3855                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3856                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3857         emitcode(";", ">>> unexpected DPTR2 here.");
3858     }    
3859     
3860     return TRUE;
3861 }
3862
3863 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3864 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3865 // will be set TRUE. The caller must then handle the case specially, noting
3866 // that the IC_RESULT operand is not aopOp'd.
3867 // 
3868 #define AOP_OP_3_NOFATAL(ic, rc) \
3869             do { rc = !aopOp3(ic); } while (0)
3870
3871 // aopOp the left & right operands of an ic.
3872 #define AOP_OP_2(ic) \
3873     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3874     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3875
3876 // convienience macro.
3877 #define AOP_SET_LOCALS(ic) \
3878     left = IC_LEFT(ic); \
3879     right = IC_RIGHT(ic); \
3880     result = IC_RESULT(ic);
3881
3882
3883 // Given an integer value of pushedSize bytes on the stack,
3884 // adjust it to be resultSize bytes, either by discarding
3885 // the most significant bytes or by zero-padding.
3886 //
3887 // On exit from this macro, pushedSize will have been adjusted to
3888 // equal resultSize, and ACC may be trashed.
3889 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3890       /* If the pushed data is bigger than the result,          \
3891        * simply discard unused bytes. Icky, but works.          \
3892        */                                                       \
3893       while (pushedSize > resultSize)                           \
3894       {                                                         \
3895           D (emitcode (";", "discarding unused result byte."););\
3896           emitcode ("pop", "acc");                              \
3897           pushedSize--;                                         \
3898       }                                                         \
3899       if (pushedSize < resultSize)                              \
3900       {                                                         \
3901           emitcode ("clr", "a");                                \
3902           /* Conversly, we haven't pushed enough here.          \
3903            * just zero-pad, and all is well.                    \
3904            */                                                   \
3905           while (pushedSize < resultSize)                       \
3906           {                                                     \
3907               emitcode("push", "acc");                          \
3908               pushedSize++;                                     \
3909           }                                                     \
3910       }                                                         \
3911       assert(pushedSize == resultSize);
3912
3913 /*-----------------------------------------------------------------*/
3914 /* genPlus - generates code for addition                           */
3915 /*-----------------------------------------------------------------*/
3916 static void
3917 genPlus (iCode * ic)
3918 {
3919   int size, offset = 0;
3920   bool pushResult;
3921   int rSize;
3922
3923   D (emitcode (";", "genPlus "););
3924
3925   /* special cases :- */
3926   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3927       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3928       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3929       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3930       if (size <= 9) {
3931           while (size--) emitcode ("inc","dptr");
3932       } else {
3933           emitcode ("mov","a,dpl");
3934           emitcode ("add","a,#!constbyte",size & 0xff);
3935           emitcode ("mov","dpl,a");
3936           emitcode ("mov","a,dph");
3937           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3938           emitcode ("mov","dph,a");
3939           emitcode ("mov","a,dpx");
3940           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3941           emitcode ("mov","dpx,a");
3942       }
3943       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3944       return ;
3945   }
3946   if ( IS_SYMOP(IC_LEFT(ic)) && 
3947        OP_SYMBOL(IC_LEFT(ic))->remat &&
3948        isOperandInFarSpace(IC_RIGHT(ic))) {
3949       operand *op = IC_RIGHT(ic);
3950       IC_RIGHT(ic) = IC_LEFT(ic);
3951       IC_LEFT(ic) = op;
3952   }
3953                 
3954   AOP_OP_3_NOFATAL (ic, pushResult);
3955     
3956   if (pushResult)
3957     {
3958       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3959     }
3960
3961   if (!pushResult)
3962     {
3963       /* if literal, literal on the right or
3964          if left requires ACC or right is already
3965          in ACC */
3966       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3967        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3968           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3969         {
3970           operand *t = IC_RIGHT (ic);
3971           IC_RIGHT (ic) = IC_LEFT (ic);
3972           IC_LEFT (ic) = t;
3973           emitcode (";", "Swapped plus args.");
3974         }
3975
3976       /* if both left & right are in bit
3977          space */
3978       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3979           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3980         {
3981           genPlusBits (ic);
3982           goto release;
3983         }
3984
3985       /* if left in bit space & right literal */
3986       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3987           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3988         {
3989           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3990           /* if result in bit space */
3991           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3992             {
3993               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3994                 emitcode ("cpl", "c");
3995               outBitC (IC_RESULT (ic));
3996             }
3997           else
3998             {
3999               size = getDataSize (IC_RESULT (ic));
4000               _startLazyDPSEvaluation ();
4001               while (size--)
4002                 {
4003                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4004                   emitcode ("addc", "a,#0");
4005                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4006                 }
4007               _endLazyDPSEvaluation ();
4008             }
4009           goto release;
4010         }
4011
4012       /* if I can do an increment instead
4013          of add then GOOD for ME */
4014       if (genPlusIncr (ic) == TRUE)
4015         {
4016           emitcode (";", "did genPlusIncr");
4017           goto release;
4018         }
4019
4020     }
4021   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4022
4023   _startLazyDPSEvaluation ();
4024   while (size--)
4025     {
4026       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4027         {
4028           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4029           if (offset == 0)
4030             emitcode ("add", "a,%s",
4031                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4032           else
4033             emitcode ("addc", "a,%s",
4034                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4035         }
4036       else
4037         {
4038           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4039           {
4040               /* right is going to use ACC or we would have taken the
4041                * above branch.
4042                */
4043               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4044        TR_AP("#3");
4045               D(emitcode(";", "+ AOP_ACC special case."););
4046               emitcode("xch", "a, %s", DP2_RESULT_REG);
4047           }
4048           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4049           if (offset == 0)
4050           {
4051             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4052             {
4053          TR_AP("#4");
4054                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4055             }
4056             else
4057             {
4058                 emitcode ("add", "a,%s",
4059                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4060                                   DP2_RESULT_REG));
4061             }
4062           }
4063           else
4064           {
4065             emitcode ("addc", "a,%s",
4066                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4067                           DP2_RESULT_REG));
4068           }
4069         }
4070       if (!pushResult)
4071         {
4072           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4073         }
4074       else
4075         {
4076           emitcode ("push", "acc");
4077         }
4078       offset++;
4079     }
4080   _endLazyDPSEvaluation ();
4081
4082   if (pushResult)
4083     {
4084       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4085
4086       size = getDataSize (IC_LEFT (ic));
4087       rSize = getDataSize (IC_RESULT (ic));
4088
4089       ADJUST_PUSHED_RESULT(size, rSize);
4090
4091       _startLazyDPSEvaluation ();
4092       while (size--)
4093         {
4094           emitcode ("pop", "acc");
4095           aopPut (AOP (IC_RESULT (ic)), "a", size);
4096         }
4097       _endLazyDPSEvaluation ();
4098     }
4099
4100   adjustArithmeticResult (ic);
4101
4102 release:
4103   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4104   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4106 }
4107
4108 /*-----------------------------------------------------------------*/
4109 /* genMinusDec :- does subtraction with deccrement if possible     */
4110 /*-----------------------------------------------------------------*/
4111 static bool
4112 genMinusDec (iCode * ic)
4113 {
4114   unsigned int icount;
4115   unsigned int size = getDataSize (IC_RESULT (ic));
4116
4117   /* will try to generate an increment */
4118   /* if the right side is not a literal
4119      we cannot */
4120   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4121     return FALSE;
4122
4123   /* if the literal value of the right hand side
4124      is greater than 4 then it is not worth it */
4125   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4126     return FALSE;
4127
4128   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4129       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4130       while (icount--) {
4131           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4132       }
4133       return TRUE;
4134   }
4135   /* if decrement 16 bits in register */
4136   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4137       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4138       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4139       (size > 1) &&
4140       (icount == 1))
4141     {
4142       symbol *tlbl;
4143       int    emitTlbl;
4144       int    labelRange;
4145       char   *l;
4146
4147       /* If the next instruction is a goto and the goto target
4148          * is <= 5 instructions previous to this, we can generate
4149          * jumps straight to that target.
4150        */
4151       if (ic->next && ic->next->op == GOTO
4152           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4153           && labelRange <= 5)
4154         {
4155           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4156           tlbl = IC_LABEL (ic->next);
4157           emitTlbl = 0;
4158         }
4159       else
4160         {
4161           tlbl = newiTempLabel (NULL);
4162           emitTlbl = 1;
4163         }
4164
4165       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4166       emitcode ("dec", "%s", l);
4167  
4168       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4169           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4170           IS_AOP_PREG (IC_RESULT (ic)))
4171       {     
4172           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4173       }
4174       else
4175       {
4176           emitcode ("mov", "a,#!constbyte",0xff);
4177           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4178       }
4179       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, NULL, NULL);
4180       emitcode ("dec", "%s", l);
4181       if (size > 2)
4182         {
4183             if (!strcmp(l, "acc"))
4184             {
4185                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4186             }
4187             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4188                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4189                      IS_AOP_PREG (IC_RESULT (ic)))
4190             {       
4191                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4192             }
4193             else
4194             {
4195                 emitcode ("mov", "a,#!constbyte",0xff);
4196                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4197             }
4198             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, NULL, NULL);
4199             emitcode ("dec", "%s", l);
4200         }
4201       if (size > 3)
4202         {
4203             if (!strcmp(l, "acc"))
4204             {
4205                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4206             }
4207             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4209                      IS_AOP_PREG (IC_RESULT (ic)))
4210             {       
4211                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4212             }
4213             else
4214             {
4215                 emitcode ("mov", "a,#!constbyte",0xff);
4216                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4217             }       
4218             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, NULL, NULL);
4219             emitcode ("dec", "%s", l);
4220         }
4221       if (emitTlbl)
4222         {
4223           emitcode ("", "!tlabeldef", tlbl->key + 100);
4224         }
4225       return TRUE;
4226     }
4227
4228   /* if the sizes are greater than 1 then we cannot */
4229   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4230       AOP_SIZE (IC_LEFT (ic)) > 1)
4231     return FALSE;
4232
4233   /* we can if the aops of the left & result match or
4234      if they are in registers and the registers are the
4235      same */
4236   if (
4237        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4238        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4239        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4240     {
4241
4242       _startLazyDPSEvaluation ();
4243       while (icount--)
4244         {
4245           emitcode ("dec", "%s",
4246                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4247         }
4248       _endLazyDPSEvaluation ();
4249
4250       return TRUE;
4251     }
4252
4253   return FALSE;
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* addSign - complete with sign                                    */
4258 /*-----------------------------------------------------------------*/
4259 static void
4260 addSign (operand * result, int offset, int sign)
4261 {
4262   int size = (getDataSize (result) - offset);
4263   if (size > 0)
4264     {
4265       _startLazyDPSEvaluation();
4266       if (sign)
4267         {
4268           emitcode ("rlc", "a");
4269           emitcode ("subb", "a,acc");
4270           while (size--)
4271           {
4272             aopPut (AOP (result), "a", offset++);
4273           }
4274         }
4275       else
4276       {
4277         while (size--)
4278         {
4279           aopPut (AOP (result), zero, offset++);
4280         }
4281       }
4282       _endLazyDPSEvaluation();
4283     }
4284 }
4285
4286 /*-----------------------------------------------------------------*/
4287 /* genMinusBits - generates code for subtraction  of two bits      */
4288 /*-----------------------------------------------------------------*/
4289 static void
4290 genMinusBits (iCode * ic)
4291 {
4292   symbol *lbl = newiTempLabel (NULL);
4293
4294   D (emitcode (";", "genMinusBits "););
4295
4296   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4297     {
4298       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4299       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4300       emitcode ("cpl", "c");
4301       emitcode ("", "!tlabeldef", (lbl->key + 100));
4302       outBitC (IC_RESULT (ic));
4303     }
4304   else
4305     {
4306       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4307       emitcode ("subb", "a,acc");
4308       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4309       emitcode ("inc", "a");
4310       emitcode ("", "!tlabeldef", (lbl->key + 100));
4311       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4312       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4313     }
4314 }
4315
4316 /*-----------------------------------------------------------------*/
4317 /* genMinus - generates code for subtraction                       */
4318 /*-----------------------------------------------------------------*/
4319 static void
4320 genMinus (iCode * ic)
4321 {
4322     int size, offset = 0;
4323     int rSize;
4324     long lit = 0L;
4325     bool pushResult;
4326
4327     D (emitcode (";", "genMinus "););
4328
4329     AOP_OP_3_NOFATAL(ic, pushResult);   
4330
4331     if (!pushResult)
4332     {
4333       /* special cases :- */
4334       /* if both left & right are in bit space */
4335       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4336           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4337         {
4338           genMinusBits (ic);
4339           goto release;
4340         }
4341
4342       /* if I can do an decrement instead
4343          of subtract then GOOD for ME */
4344       if (genMinusDec (ic) == TRUE)
4345         goto release;
4346
4347     }
4348
4349   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4350
4351   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4352     {
4353       CLRC;
4354     }
4355   else
4356     {
4357       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4358       lit = -lit;
4359     }
4360
4361
4362   /* if literal, add a,#-lit, else normal subb */
4363   _startLazyDPSEvaluation ();
4364   while (size--) {
4365       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4366           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4367               emitcode ("mov","b,%s",
4368                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4369               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4370               emitcode ("subb","a,b");
4371           } else {
4372               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4373               emitcode ("subb", "a,%s",
4374                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4375                                 DP2_RESULT_REG));
4376           }
4377       } else {
4378           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4379           /* first add without previous c */
4380           if (!offset) {
4381               if (!size && lit==-1) {
4382                   emitcode ("dec", "a");
4383               } else {
4384                   emitcode ("add", "a,#!constbyte",
4385                             (unsigned int) (lit & 0x0FFL));
4386               }
4387           } else {
4388               emitcode ("addc", "a,#!constbyte",
4389                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4390           }
4391       }
4392       
4393       if (pushResult) {
4394           emitcode ("push", "acc");
4395       } else {
4396           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4397       }
4398       offset++;
4399   }
4400   _endLazyDPSEvaluation ();
4401   
4402   if (pushResult)
4403     {
4404       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4405
4406       size = getDataSize (IC_LEFT (ic));
4407       rSize = getDataSize (IC_RESULT (ic));
4408
4409       ADJUST_PUSHED_RESULT(size, rSize);
4410
4411       _startLazyDPSEvaluation ();
4412       while (size--)
4413         {
4414           emitcode ("pop", "acc");
4415           aopPut (AOP (IC_RESULT (ic)), "a", size);
4416         }
4417       _endLazyDPSEvaluation ();
4418     }
4419
4420   adjustArithmeticResult (ic);
4421
4422 release:
4423   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4425   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4426 }
4427
4428
4429 /*-----------------------------------------------------------------*/
4430 /* genMultbits :- multiplication of bits                           */
4431 /*-----------------------------------------------------------------*/
4432 static void
4433 genMultbits (operand * left,
4434              operand * right,
4435              operand * result,
4436              iCode   * ic)
4437 {
4438   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4439   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4440   aopOp(result, ic, TRUE, FALSE);
4441   outBitC (result);
4442 }
4443
4444
4445 /*-----------------------------------------------------------------*/
4446 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4447 /*-----------------------------------------------------------------*/
4448 static void
4449 genMultOneByte (operand * left,
4450                 operand * right,
4451                 operand * result,
4452                 iCode   * ic)
4453 {
4454   sym_link *opetype = operandType (result);
4455   symbol *lbl;
4456
4457
4458   /* (if two literals: the value is computed before) */
4459   /* if one literal, literal on the right */
4460   if (AOP_TYPE (left) == AOP_LIT)
4461     {
4462       operand *t = right;
4463       right = left;
4464       left = t;
4465       emitcode (";", "swapped left and right");
4466     }
4467
4468   if (SPEC_USIGN(opetype)
4469       // ignore the sign of left and right, what else can we do?
4470       || (SPEC_USIGN(operandType(left)) && 
4471           SPEC_USIGN(operandType(right)))) {
4472     // just an unsigned 8*8=8/16 multiply
4473     //emitcode (";","unsigned");
4474     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4475     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4476     emitcode ("mul", "ab");
4477    
4478     _G.accInUse++; _G.bInUse++;
4479     aopOp(result, ic, TRUE, FALSE);
4480       
4481       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4482       {
4483           // this should never happen
4484           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4485                    AOP_SIZE(result), __FILE__, lineno);
4486           exit (1);
4487       }      
4488       
4489     aopPut (AOP (result), "a", 0);
4490     _G.accInUse--; _G.bInUse--;
4491     if (AOP_SIZE(result)==2) 
4492     {
4493       aopPut (AOP (result), "b", 1);
4494     }
4495     return;
4496   }
4497
4498   // we have to do a signed multiply
4499
4500   emitcode (";", "signed");
4501   emitcode ("clr", "F0"); // reset sign flag
4502   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4503
4504   lbl=newiTempLabel(NULL);
4505   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4506   // left side is negative, 8-bit two's complement, this fails for -128
4507   emitcode ("setb", "F0"); // set sign flag
4508   emitcode ("cpl", "a");
4509   emitcode ("inc", "a");
4510
4511   emitcode ("", "!tlabeldef", lbl->key+100);
4512
4513   /* if literal */
4514   if (AOP_TYPE(right)==AOP_LIT) {
4515     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4516     /* AND literal negative */
4517     if ((int) val < 0) {
4518       emitcode ("cpl", "F0"); // complement sign flag
4519       emitcode ("mov", "b,#!constbyte", -val);
4520     } else {
4521       emitcode ("mov", "b,#!constbyte", val);
4522     }
4523   } else {
4524     lbl=newiTempLabel(NULL);
4525     emitcode ("mov", "b,a");
4526     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4527     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4528     // right side is negative, 8-bit two's complement
4529     emitcode ("cpl", "F0"); // complement sign flag
4530     emitcode ("cpl", "a");
4531     emitcode ("inc", "a");
4532     emitcode ("", "!tlabeldef", lbl->key+100);
4533   }
4534   emitcode ("mul", "ab");
4535     
4536   _G.accInUse++;_G.bInUse++;
4537   aopOp(result, ic, TRUE, FALSE);
4538     
4539   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4540   {
4541     // this should never happen
4542       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4543                AOP_SIZE(result), __FILE__, lineno);
4544       exit (1);
4545   }    
4546     
4547   lbl=newiTempLabel(NULL);
4548   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4549   // only ONE op was negative, we have to do a 8/16-bit two's complement
4550   emitcode ("cpl", "a"); // lsb
4551   if (AOP_SIZE(result)==1) {
4552     emitcode ("inc", "a");
4553   } else {
4554     emitcode ("add", "a,#1");
4555     emitcode ("xch", "a,b");
4556     emitcode ("cpl", "a"); // msb
4557     emitcode ("addc", "a,#0");
4558     emitcode ("xch", "a,b");
4559   }
4560
4561   emitcode ("", "!tlabeldef", lbl->key+100);
4562   aopPut (AOP (result), "a", 0);
4563   _G.accInUse--;_G.bInUse--;
4564   if (AOP_SIZE(result)==2) {
4565     aopPut (AOP (result), "b", 1);
4566   }
4567 }
4568
4569 /*-----------------------------------------------------------------*/
4570 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4571 /*-----------------------------------------------------------------*/
4572 static void genMultTwoByte (operand *left, operand *right, 
4573                             operand *result, iCode *ic)
4574 {
4575         sym_link *retype = getSpec(operandType(right));
4576         sym_link *letype = getSpec(operandType(left));
4577         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4578         symbol *lbl;
4579
4580         if (AOP_TYPE (left) == AOP_LIT) {
4581                 operand *t = right;
4582                 right = left;
4583                 left = t;
4584         }
4585         /* save EA bit in F1 */
4586         lbl = newiTempLabel(NULL);
4587         emitcode ("setb","F1");
4588         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4589         emitcode ("clr","F1");
4590         emitcode("","!tlabeldef",lbl->key+100);
4591
4592         /* load up MB with right */
4593         if (!umult) {
4594                 emitcode("clr","F0");
4595                 if (AOP_TYPE(right) == AOP_LIT) {
4596                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4597                         if (val < 0) {
4598                                 emitcode("setb","F0");
4599                                 val = -val;
4600                         }
4601                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4602                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4603                 } else {
4604                         lbl = newiTempLabel(NULL);
4605                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4606                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4607                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4608                         emitcode ("xch", "a,b");
4609                         emitcode ("cpl","a");
4610                         emitcode ("add", "a,#1");
4611                         emitcode ("xch", "a,b");
4612                         emitcode ("cpl", "a"); // msb
4613                         emitcode ("addc", "a,#0");
4614                         emitcode ("setb","F0");
4615                         emitcode ("","!tlabeldef",lbl->key+100);
4616                         emitcode ("mov","mb,b");
4617                         emitcode ("mov","mb,a");
4618                 }
4619         } else {
4620                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4621                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4622         }
4623         /* load up MA with left */
4624         if (!umult) {
4625                 lbl = newiTempLabel(NULL);
4626                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4627                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4628                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4629                 emitcode ("xch", "a,b");
4630                 emitcode ("cpl","a");
4631                 emitcode ("add", "a,#1");
4632                 emitcode ("xch", "a,b");
4633                 emitcode ("cpl", "a"); // msb
4634                 emitcode ("addc","a,#0");
4635                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4636                 emitcode ("setb","F0");
4637                 emitcode ("","!tlabeldef",lbl->key+100);
4638                 emitcode ("mov","ma,b");
4639                 emitcode ("mov","ma,a");
4640         } else {
4641                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4642                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4643         }
4644         /* wait for multiplication to finish */
4645         lbl = newiTempLabel(NULL);
4646         emitcode("","!tlabeldef", lbl->key+100);
4647         emitcode("mov","a,mcnt1");
4648         emitcode("anl","a,#!constbyte",0x80);
4649         emitcode("jnz","!tlabel",lbl->key+100);
4650         
4651         freeAsmop (left, NULL, ic, TRUE);
4652         freeAsmop (right, NULL, ic,TRUE);
4653         aopOp(result, ic, TRUE, FALSE);
4654
4655         /* if unsigned then simple */   
4656         if (umult) {
4657                 emitcode ("mov","a,ma");
4658                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4659                 emitcode ("mov","a,ma");
4660                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4661                 aopPut(AOP(result),"ma",1);
4662                 aopPut(AOP(result),"ma",0);
4663         } else {
4664                 emitcode("push","ma");
4665                 emitcode("push","ma");
4666                 emitcode("push","ma");
4667                 MOVA("ma");
4668                 /* negate result if needed */
4669                 lbl = newiTempLabel(NULL);      
4670                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4671                 emitcode("cpl","a");
4672                 emitcode("add","a,#1");
4673                 emitcode("","!tlabeldef", lbl->key+100);
4674                 if (AOP_TYPE(result) == AOP_ACC)
4675                 {
4676                     D(emitcode(";", "ACC special case."););
4677                     /* We know result is the only live aop, and 
4678                      * it's obviously not a DPTR2, so AP is available.
4679                      */
4680                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4681                 }
4682                 else
4683                 {
4684                     aopPut(AOP(result),"a",0);
4685                 }
4686             
4687                 emitcode("pop","acc");
4688                 lbl = newiTempLabel(NULL);      
4689                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4690                 emitcode("cpl","a");
4691                 emitcode("addc","a,#0");
4692                 emitcode("","!tlabeldef", lbl->key+100);
4693                 aopPut(AOP(result),"a",1);
4694                 emitcode("pop","acc");
4695                 if (AOP_SIZE(result) >= 3) {
4696                         lbl = newiTempLabel(NULL);      
4697                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4698                         emitcode("cpl","a");
4699                         emitcode("addc","a,#0");                        
4700                         emitcode("","!tlabeldef", lbl->key+100);
4701                         aopPut(AOP(result),"a",2);
4702                 }
4703                 emitcode("pop","acc");
4704                 if (AOP_SIZE(result) >= 4) {
4705                         lbl = newiTempLabel(NULL);      
4706                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4707                         emitcode("cpl","a");
4708                         emitcode("addc","a,#0");                        
4709                         emitcode("","!tlabeldef", lbl->key+100);
4710                         aopPut(AOP(result),"a",3);
4711                 }
4712                 if (AOP_TYPE(result) == AOP_ACC)
4713                 {
4714                     /* We stashed the result away above. */
4715                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4716                 }           
4717                 
4718         }
4719         freeAsmop (result, NULL, ic, TRUE);
4720
4721         /* restore EA bit in F1 */
4722         lbl = newiTempLabel(NULL);
4723         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4724         emitcode ("setb","EA");
4725         emitcode("","!tlabeldef",lbl->key+100);
4726         return ;
4727 }
4728
4729 /*-----------------------------------------------------------------*/
4730 /* genMult - generates code for multiplication                     */
4731 /*-----------------------------------------------------------------*/
4732 static void
4733 genMult (iCode * ic)
4734 {
4735   operand *left = IC_LEFT (ic);
4736   operand *right = IC_RIGHT (ic);
4737   operand *result = IC_RESULT (ic);
4738
4739   D (emitcode (";", "genMult "););
4740
4741   /* assign the amsops */
4742   AOP_OP_2 (ic);
4743
4744   /* special cases first */
4745   /* both are bits */
4746   if (AOP_TYPE (left) == AOP_CRY &&
4747       AOP_TYPE (right) == AOP_CRY)
4748     {
4749       genMultbits (left, right, result, ic);
4750       goto release;
4751     }
4752
4753   /* if both are of size == 1 */
4754   if (AOP_SIZE (left) == 1 &&
4755       AOP_SIZE (right) == 1)
4756     {
4757       genMultOneByte (left, right, result, ic);
4758       goto release;
4759     }
4760
4761   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4762           /* use the ds390 ARITHMETIC accel UNIT */
4763           genMultTwoByte (left, right, result, ic);
4764           return ;
4765   }
4766   /* should have been converted to function call */
4767   assert (0);
4768
4769 release:
4770   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772   freeAsmop (result, NULL, ic, TRUE);
4773 }
4774
4775 /*-----------------------------------------------------------------*/
4776 /* genDivbits :- division of bits                                  */
4777 /*-----------------------------------------------------------------*/
4778 static void
4779 genDivbits (operand * left,
4780             operand * right,
4781             operand * result,
4782             iCode   * ic)
4783 {
4784
4785   char *l;
4786
4787   /* the result must be bit */
4788   LOAD_AB_FOR_DIV (left, right, l);
4789   emitcode ("div", "ab");
4790   emitcode ("rrc", "a");
4791   aopOp(result, ic, TRUE, FALSE);
4792     
4793   aopPut (AOP (result), "c", 0);
4794 }
4795
4796 /*-----------------------------------------------------------------*/
4797 /* genDivOneByte : 8 bit division                                  */
4798 /*-----------------------------------------------------------------*/
4799 static void
4800 genDivOneByte (operand * left,
4801                operand * right,
4802                operand * result,
4803                iCode   * ic)
4804 {
4805   sym_link *opetype = operandType (result);
4806   char *l;
4807   symbol *lbl;
4808   int size, offset;
4809
4810   offset = 1;
4811   /* signed or unsigned */
4812   if (SPEC_USIGN (opetype))
4813     {
4814         /* unsigned is easy */
4815         LOAD_AB_FOR_DIV (left, right, l);
4816         emitcode ("div", "ab");
4817
4818         _G.accInUse++;
4819         aopOp(result, ic, TRUE, FALSE);
4820         aopPut (AOP (result), "a", 0);
4821         _G.accInUse--;
4822
4823         size = AOP_SIZE (result) - 1;
4824         
4825         while (size--)
4826         {
4827             aopPut (AOP (result), zero, offset++);
4828         }
4829       return;
4830     }
4831
4832   /* signed is a little bit more difficult */
4833
4834   /* save the signs of the operands */
4835   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4836   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4837   emitcode ("push", "acc");     /* save it on the stack */
4838
4839   /* now sign adjust for both left & right */
4840   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4841   lbl = newiTempLabel (NULL);
4842   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4843   emitcode ("cpl", "a");
4844   emitcode ("inc", "a");
4845   emitcode ("", "!tlabeldef", (lbl->key + 100));
4846   emitcode ("mov", "b,a");
4847
4848   /* sign adjust left side */
4849   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4850
4851   lbl = newiTempLabel (NULL);
4852   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4853   emitcode ("cpl", "a");
4854   emitcode ("inc", "a");
4855   emitcode ("", "!tlabeldef", (lbl->key + 100));
4856
4857   /* now the division */
4858   emitcode ("nop", "; workaround for DS80C390 div bug.");
4859   emitcode ("div", "ab");
4860   /* we are interested in the lower order
4861      only */
4862   emitcode ("mov", "b,a");
4863   lbl = newiTempLabel (NULL);
4864   emitcode ("pop", "acc");
4865   /* if there was an over flow we don't
4866      adjust the sign of the result */
4867   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4868   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4869   CLRC;
4870   emitcode ("clr", "a");
4871   emitcode ("subb", "a,b");
4872   emitcode ("mov", "b,a");
4873   emitcode ("", "!tlabeldef", (lbl->key + 100));
4874
4875   /* now we are done */
4876   _G.accInUse++;     _G.bInUse++;
4877     aopOp(result, ic, TRUE, FALSE);
4878     
4879     aopPut (AOP (result), "b", 0);
4880     
4881     size = AOP_SIZE (result) - 1;
4882     
4883     if (size > 0)
4884     {
4885       emitcode ("mov", "c,b.7");
4886       emitcode ("subb", "a,acc");
4887     }
4888     while (size--)
4889     {
4890         aopPut (AOP (result), "a", offset++);
4891     }
4892     _G.accInUse--;     _G.bInUse--;
4893
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4898 /*-----------------------------------------------------------------*/
4899 static void genDivTwoByte (operand *left, operand *right, 
4900                             operand *result, iCode *ic)
4901 {
4902         sym_link *retype = getSpec(operandType(right));
4903         sym_link *letype = getSpec(operandType(left));
4904         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4905         symbol *lbl;
4906
4907         /* save EA bit in F1 */
4908         lbl = newiTempLabel(NULL);
4909         emitcode ("setb","F1");
4910         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4911         emitcode ("clr","F1");
4912         emitcode("","!tlabeldef",lbl->key+100);
4913
4914         /* load up MA with left */
4915         if (!umult) {
4916                 emitcode("clr","F0");
4917                 lbl = newiTempLabel(NULL);
4918                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4919                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4920                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4921                 emitcode ("xch", "a,b");
4922                 emitcode ("cpl","a");
4923                 emitcode ("add", "a,#1");
4924                 emitcode ("xch", "a,b");
4925                 emitcode ("cpl", "a"); // msb
4926                 emitcode ("addc","a,#0");
4927                 emitcode ("setb","F0");
4928                 emitcode ("","!tlabeldef",lbl->key+100);
4929                 emitcode ("mov","ma,b");
4930                 emitcode ("mov","ma,a");
4931         } else {
4932                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4933                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4934         }
4935
4936         /* load up MB with right */
4937         if (!umult) {
4938                 if (AOP_TYPE(right) == AOP_LIT) {
4939                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4940                         if (val < 0) {
4941                                 lbl = newiTempLabel(NULL);
4942                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4943                                 emitcode("setb","F0");
4944                                 emitcode ("","!tlabeldef",lbl->key+100);
4945                                 val = -val;
4946                         } 
4947                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4948                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4949                 } else {
4950                         lbl = newiTempLabel(NULL);
4951                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4952                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4953                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4954                         emitcode ("xch", "a,b");
4955                         emitcode ("cpl","a");
4956                         emitcode ("add", "a,#1");
4957                         emitcode ("xch", "a,b");
4958                         emitcode ("cpl", "a"); // msb
4959                         emitcode ("addc", "a,#0");
4960                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4961                         emitcode ("setb","F0");
4962                         emitcode ("","!tlabeldef",lbl->key+100);
4963                         emitcode ("mov","mb,b");
4964                         emitcode ("mov","mb,a");
4965                 }
4966         } else {
4967                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4968                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4969         }
4970
4971         /* wait for multiplication to finish */
4972         lbl = newiTempLabel(NULL);
4973         emitcode("","!tlabeldef", lbl->key+100);
4974         emitcode("mov","a,mcnt1");
4975         emitcode("anl","a,#!constbyte",0x80);
4976         emitcode("jnz","!tlabel",lbl->key+100);
4977         
4978         freeAsmop (left, NULL, ic, TRUE);
4979         freeAsmop (right, NULL, ic,TRUE);
4980         aopOp(result, ic, TRUE, FALSE);
4981
4982         /* if unsigned then simple */   
4983         if (umult) {
4984                 aopPut(AOP(result),"ma",1);
4985                 aopPut(AOP(result),"ma",0);
4986         } else {
4987                 emitcode("push","ma");
4988                 MOVA("ma");
4989                 /* negate result if needed */
4990                 lbl = newiTempLabel(NULL);      
4991                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4992                 emitcode("cpl","a");
4993                 emitcode("add","a,#1");
4994                 emitcode("","!tlabeldef", lbl->key+100);
4995                 aopPut(AOP(result),"a",0);
4996                 emitcode("pop","acc");
4997                 lbl = newiTempLabel(NULL);      
4998                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4999                 emitcode("cpl","a");
5000                 emitcode("addc","a,#0");
5001                 emitcode("","!tlabeldef", lbl->key+100);
5002                 aopPut(AOP(result),"a",1);
5003         }
5004         freeAsmop (result, NULL, ic, TRUE);
5005         /* restore EA bit in F1 */
5006         lbl = newiTempLabel(NULL);
5007         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5008         emitcode ("setb","EA");
5009         emitcode("","!tlabeldef",lbl->key+100);
5010         return ;
5011 }
5012
5013 /*-----------------------------------------------------------------*/
5014 /* genDiv - generates code for division                            */
5015 /*-----------------------------------------------------------------*/
5016 static void
5017 genDiv (iCode * ic)
5018 {
5019   operand *left = IC_LEFT (ic);
5020   operand *right = IC_RIGHT (ic);
5021   operand *result = IC_RESULT (ic);
5022
5023   D (emitcode (";", "genDiv "););
5024
5025   /* assign the amsops */
5026   AOP_OP_2 (ic);
5027
5028   /* special cases first */
5029   /* both are bits */
5030   if (AOP_TYPE (left) == AOP_CRY &&
5031       AOP_TYPE (right) == AOP_CRY)
5032     {
5033       genDivbits (left, right, result, ic);
5034       goto release;
5035     }
5036
5037   /* if both are of size == 1 */
5038   if (AOP_SIZE (left) == 1 &&
5039       AOP_SIZE (right) == 1)
5040     {
5041       genDivOneByte (left, right, result, ic);
5042       goto release;
5043     }
5044
5045   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5046           /* use the ds390 ARITHMETIC accel UNIT */
5047           genDivTwoByte (left, right, result, ic);
5048           return ;
5049   }
5050   /* should have been converted to function call */
5051   assert (0);
5052 release:
5053   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5054   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5055   freeAsmop (result, NULL, ic, TRUE);
5056 }
5057
5058 /*-----------------------------------------------------------------*/
5059 /* genModbits :- modulus of bits                                   */
5060 /*-----------------------------------------------------------------*/
5061 static void
5062 genModbits (operand * left,
5063             operand * right,
5064             operand * result,
5065             iCode   * ic)
5066 {
5067
5068   char *l;
5069
5070   /* the result must be bit */
5071   LOAD_AB_FOR_DIV (left, right, l);
5072   emitcode ("div", "ab");
5073   emitcode ("mov", "a,b");
5074   emitcode ("rrc", "a");
5075   aopOp(result, ic, TRUE, FALSE);
5076   aopPut (AOP (result), "c", 0);
5077 }
5078
5079 /*-----------------------------------------------------------------*/
5080 /* genModOneByte : 8 bit modulus                                   */
5081 /*-----------------------------------------------------------------*/
5082 static void
5083 genModOneByte (operand * left,
5084                operand * right,
5085                operand * result,
5086                iCode   * ic)
5087 {
5088   sym_link *opetype = operandType (result);
5089   char *l;
5090   symbol *lbl;
5091
5092   /* signed or unsigned */
5093   if (SPEC_USIGN (opetype))
5094     {
5095       /* unsigned is easy */
5096       LOAD_AB_FOR_DIV (left, right, l);
5097       emitcode ("div", "ab");
5098       aopOp(result, ic, TRUE, FALSE);   
5099       aopPut (AOP (result), "b", 0);
5100       return;
5101     }
5102
5103   /* signed is a little bit more difficult */
5104
5105   /* save the signs of the operands */
5106   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5107
5108   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5109   emitcode ("push", "acc");     /* save it on the stack */
5110
5111   /* now sign adjust for both left & right */
5112   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5113
5114   lbl = newiTempLabel (NULL);
5115   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5116   emitcode ("cpl", "a");
5117   emitcode ("inc", "a");
5118   emitcode ("", "!tlabeldef", (lbl->key + 100));
5119   emitcode ("mov", "b,a");
5120
5121   /* sign adjust left side */
5122   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5123
5124   lbl = newiTempLabel (NULL);
5125   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5126   emitcode ("cpl", "a");
5127   emitcode ("inc", "a");
5128   emitcode ("", "!tlabeldef", (lbl->key + 100));
5129
5130   /* now the multiplication */
5131   emitcode ("nop", "; workaround for DS80C390 div bug.");
5132   emitcode ("div", "ab");
5133   /* we are interested in the lower order
5134      only */
5135   lbl = newiTempLabel (NULL);
5136   emitcode ("pop", "acc");
5137   /* if there was an over flow we don't
5138      adjust the sign of the result */
5139   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5140   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5141   CLRC;
5142   emitcode ("clr", "a");
5143   emitcode ("subb", "a,b");
5144   emitcode ("mov", "b,a");
5145   emitcode ("", "!tlabeldef", (lbl->key + 100));
5146   
5147   _G.bInUse++;
5148   /* now we are done */
5149   aopOp(result, ic, TRUE, FALSE);    
5150   aopPut (AOP (result), "b", 0);
5151   _G.bInUse--;
5152
5153 }
5154
5155 /*-----------------------------------------------------------------*/
5156 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5157 /*-----------------------------------------------------------------*/
5158 static void genModTwoByte (operand *left, operand *right, 
5159                             operand *result, iCode *ic)
5160 {
5161         sym_link *retype = getSpec(operandType(right));
5162         sym_link *letype = getSpec(operandType(left));
5163         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5164         symbol *lbl;
5165
5166         /* load up MA with left */
5167         /* save EA bit in F1 */
5168         lbl = newiTempLabel(NULL);
5169         emitcode ("setb","F1");
5170         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5171         emitcode ("clr","F1");
5172         emitcode("","!tlabeldef",lbl->key+100);
5173
5174         if (!umult) {
5175                 lbl = newiTempLabel(NULL);
5176                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5177                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5178                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5179                 emitcode ("xch", "a,b");
5180                 emitcode ("cpl","a");
5181                 emitcode ("add", "a,#1");
5182                 emitcode ("xch", "a,b");
5183                 emitcode ("cpl", "a"); // msb
5184                 emitcode ("addc","a,#0");
5185                 emitcode ("","!tlabeldef",lbl->key+100);
5186                 emitcode ("mov","ma,b");
5187                 emitcode ("mov","ma,a");
5188         } else {
5189                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5190                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5191         }
5192
5193         /* load up MB with right */
5194         if (!umult) {
5195                 if (AOP_TYPE(right) == AOP_LIT) {
5196                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5197                         if (val < 0) {
5198                                 val = -val;
5199                         } 
5200                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5201                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5202                 } else {
5203                         lbl = newiTempLabel(NULL);
5204                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5205                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5206                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5207                         emitcode ("xch", "a,b");
5208                         emitcode ("cpl","a");
5209                         emitcode ("add", "a,#1");
5210                         emitcode ("xch", "a,b");
5211                         emitcode ("cpl", "a"); // msb
5212                         emitcode ("addc", "a,#0");
5213                         emitcode ("","!tlabeldef",lbl->key+100);
5214                         emitcode ("mov","mb,b");
5215                         emitcode ("mov","mb,a");
5216                 }
5217         } else {
5218                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5219                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5220         }
5221
5222         /* wait for multiplication to finish */
5223         lbl = newiTempLabel(NULL);
5224         emitcode("","!tlabeldef", lbl->key+100);
5225         emitcode("mov","a,mcnt1");
5226         emitcode("anl","a,#!constbyte",0x80);
5227         emitcode("jnz","!tlabel",lbl->key+100);
5228         
5229         freeAsmop (left, NULL, ic, TRUE);
5230         freeAsmop (right, NULL, ic,TRUE);
5231         aopOp(result, ic, TRUE, FALSE);
5232
5233         aopPut(AOP(result),"mb",1);
5234         aopPut(AOP(result),"mb",0);
5235         freeAsmop (result, NULL, ic, TRUE);
5236
5237         /* restore EA bit in F1 */
5238         lbl = newiTempLabel(NULL);
5239         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5240         emitcode ("setb","EA");
5241         emitcode("","!tlabeldef",lbl->key+100);
5242         return ;
5243 }
5244
5245 /*-----------------------------------------------------------------*/
5246 /* genMod - generates code for division                            */
5247 /*-----------------------------------------------------------------*/
5248 static void
5249 genMod (iCode * ic)
5250 {
5251   operand *left = IC_LEFT (ic);
5252   operand *right = IC_RIGHT (ic);
5253   operand *result = IC_RESULT (ic);
5254
5255   D (emitcode (";", "genMod "); );
5256
5257   /* assign the amsops */
5258   AOP_OP_2 (ic);
5259
5260   /* special cases first */
5261   /* both are bits */
5262   if (AOP_TYPE (left) == AOP_CRY &&
5263       AOP_TYPE (right) == AOP_CRY)
5264     {
5265       genModbits (left, right, result, ic);
5266       goto release;
5267     }
5268
5269   /* if both are of size == 1 */
5270   if (AOP_SIZE (left) == 1 &&
5271       AOP_SIZE (right) == 1)
5272     {
5273       genModOneByte (left, right, result, ic);
5274       goto release;
5275     }
5276
5277   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5278           /* use the ds390 ARITHMETIC accel UNIT */
5279           genModTwoByte (left, right, result, ic);
5280           return ;
5281   }
5282
5283   /* should have been converted to function call */
5284   assert (0);
5285
5286 release:
5287   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5288   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5289   freeAsmop (result, NULL, ic, TRUE);
5290 }
5291
5292 /*-----------------------------------------------------------------*/
5293 /* genIfxJump :- will create a jump depending on the ifx           */
5294 /*-----------------------------------------------------------------*/
5295 static void
5296 genIfxJump (iCode * ic, char *jval)
5297 {
5298   symbol *jlbl;
5299   symbol *tlbl = newiTempLabel (NULL);
5300   char *inst;
5301
5302   D (emitcode (";", "genIfxJump"););
5303
5304   /* if true label then we jump if condition
5305      supplied is true */
5306   if (IC_TRUE (ic))
5307     {
5308       jlbl = IC_TRUE (ic);
5309       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5310                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5311     }
5312   else
5313     {
5314       /* false label is present */
5315       jlbl = IC_FALSE (ic);
5316       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5317                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5318     }
5319   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5320     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5321   else
5322     emitcode (inst, "!tlabel", tlbl->key + 100);
5323   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5324   emitcode ("", "!tlabeldef", tlbl->key + 100);
5325
5326   /* mark the icode as generated */
5327   ic->generated = 1;
5328 }
5329
5330 /*-----------------------------------------------------------------*/
5331 /* genCmp :- greater or less than comparison                       */
5332 /*-----------------------------------------------------------------*/
5333 static void
5334 genCmp (operand * left, operand * right,
5335         iCode * ic, iCode * ifx, int sign)
5336 {
5337   int size, offset = 0;
5338   unsigned long lit = 0L;
5339   operand *result;
5340
5341   D (emitcode (";", "genCmp"););
5342
5343   result = IC_RESULT (ic);
5344
5345   /* if left & right are bit variables */
5346   if (AOP_TYPE (left) == AOP_CRY &&
5347       AOP_TYPE (right) == AOP_CRY)
5348     {
5349       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5350       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5351     }
5352   else
5353     {
5354       /* subtract right from left if at the
5355          end the carry flag is set then we know that
5356          left is greater than right */
5357       size = max (AOP_SIZE (left), AOP_SIZE (right));
5358
5359       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5360       if ((size == 1) && !sign 
5361           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5362         {
5363           symbol *lbl = newiTempLabel (NULL);
5364           emitcode ("cjne", "%s,%s,!tlabel",
5365                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5366                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5367                     lbl->key + 100);
5368           emitcode ("", "!tlabeldef", lbl->key + 100);
5369         }
5370       else
5371         {
5372           if (AOP_TYPE (right) == AOP_LIT)
5373             {
5374               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5375               /* optimize if(x < 0) or if(x >= 0) */
5376               if (lit == 0L)
5377                 {
5378                   if (!sign)
5379                     {
5380                       CLRC;
5381                     }
5382                   else
5383                     {
5384                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5385
5386                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5387                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5388
5389                       aopOp (result, ic, FALSE, FALSE);
5390
5391                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5392                         {
5393                           freeAsmop (result, NULL, ic, TRUE);
5394                           genIfxJump (ifx, "acc.7");
5395                           return;
5396                         }
5397                       else
5398                         {
5399                           emitcode ("rlc", "a");
5400                         }
5401                       goto release_freedLR;
5402                     }
5403                   goto release;
5404                 }
5405             }
5406           CLRC;
5407           while (size--)
5408             {
5409               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5410               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5411               //emitcode (";", "genCmp #2");
5412               if (sign && (size == 0))
5413                 {
5414                     //emitcode (";", "genCmp #3");
5415                   emitcode ("xrl", "a,#!constbyte",0x80);
5416                   if (AOP_TYPE (right) == AOP_LIT)
5417                     {
5418                       unsigned long lit = (unsigned long)
5419                       floatFromVal (AOP (right)->aopu.aop_lit);
5420                       //emitcode (";", "genCmp #3.1");
5421                       emitcode ("subb", "a,#!constbyte",
5422                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5423                     }
5424                   else
5425                     {
5426                       //emitcode (";", "genCmp #3.2");
5427                       if (AOP_NEEDSACC (right) && AOP_TYPE(right) != AOP_DPTR2)
5428                         {
5429                           emitcode ("push", "acc");
5430                         }
5431                         
5432                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5433                       emitcode ("xrl", "b,#!constbyte",0x80);
5434                         
5435                       if (AOP_NEEDSACC (right) && AOP_TYPE(right) != AOP_DPTR2)
5436                         {
5437                           emitcode ("pop", "acc");
5438                         }
5439                       emitcode ("subb", "a,b");
5440                     }
5441                 }
5442               else
5443                 {
5444                   const char *s;
5445
5446                   //emitcode (";", "genCmp #4");
5447                   if (AOP_NEEDSACC (right))
5448                     {
5449                       /* Yuck!! */
5450                       //emitcode (";", "genCmp #4.1");
5451                       emitcode ("xch", "a, b");
5452                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
5453                       emitcode ("xch", "a, b"); 
5454                       s = "b";
5455                     }
5456                   else
5457                     {
5458                       //emitcode (";", "genCmp #4.2");
5459                       s = aopGet (AOP (right), offset++, FALSE, FALSE, DP2_RESULT_REG);
5460                     }
5461
5462                   emitcode ("subb", "a,%s", s);
5463                 }
5464             }
5465         }
5466     }
5467
5468 release:
5469 /* Don't need the left & right operands any more; do need the result. */
5470   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5471   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472
5473   aopOp (result, ic, FALSE, FALSE);
5474
5475 release_freedLR:
5476
5477   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5478     {
5479       outBitC (result);
5480     }
5481   else
5482     {
5483       /* if the result is used in the next
5484          ifx conditional branch then generate
5485          code a little differently */
5486       if (ifx)
5487         {
5488           genIfxJump (ifx, "c");
5489         }
5490       else
5491         {
5492           outBitC (result);
5493         }
5494       /* leave the result in acc */
5495     }
5496   freeAsmop (result, NULL, ic, TRUE);
5497 }
5498
5499 /*-----------------------------------------------------------------*/
5500 /* genCmpGt :- greater than comparison                             */
5501 /*-----------------------------------------------------------------*/
5502 static void
5503 genCmpGt (iCode * ic, iCode * ifx)
5504 {
5505   operand *left, *right;
5506   sym_link *letype, *retype;
5507   int sign;
5508
5509   D (emitcode (";", "genCmpGt ");
5510     );
5511
5512   left = IC_LEFT (ic);
5513   right = IC_RIGHT (ic);
5514
5515   letype = getSpec (operandType (left));
5516   retype = getSpec (operandType (right));
5517   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5518
5519   /* assign the left & right amsops */
5520   AOP_OP_2 (ic);
5521
5522   genCmp (right, left, ic, ifx, sign);
5523 }
5524
5525 /*-----------------------------------------------------------------*/
5526 /* genCmpLt - less than comparisons                                */
5527 /*-----------------------------------------------------------------*/
5528 static void
5529 genCmpLt (iCode * ic, iCode * ifx)
5530 {
5531   operand *left, *right;
5532   sym_link *letype, *retype;
5533   int sign;
5534
5535   D (emitcode (";", "genCmpLt "););
5536
5537   left = IC_LEFT (ic);
5538   right = IC_RIGHT (ic);
5539
5540   letype = getSpec (operandType (left));
5541   retype = getSpec (operandType (right));
5542   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5543
5544   /* assign the left & right amsops */
5545   AOP_OP_2 (ic);
5546
5547   genCmp (left, right, ic, ifx, sign);
5548 }
5549
5550 /*-----------------------------------------------------------------*/
5551 /* gencjneshort - compare and jump if not equal                    */
5552 /*-----------------------------------------------------------------*/
5553 static void
5554 gencjneshort (operand * left, operand * right, symbol * lbl)
5555 {
5556   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5557   int offset = 0;
5558   unsigned long lit = 0L;
5559
5560   D (emitcode (";", "gencjneshort");
5561     );
5562
5563   /* if the left side is a literal or
5564      if the right is in a pointer register and left
5565      is not */
5566   if ((AOP_TYPE (left) == AOP_LIT) ||
5567       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5568     {
5569       operand *t = right;
5570       right = left;
5571       left = t;
5572     }
5573
5574   if (AOP_TYPE (right) == AOP_LIT)
5575     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5576
5577   if (opIsGptr (left) || opIsGptr (right))
5578     {
5579       /* We are comparing a generic pointer to something.
5580        * Exclude the generic type byte from the comparison.
5581        */
5582       size--;
5583       D (emitcode (";", "cjneshort: generic ptr special case."););
5584     }
5585
5586
5587   /* if the right side is a literal then anything goes */
5588   if (AOP_TYPE (right) == AOP_LIT &&
5589       AOP_TYPE (left) != AOP_DIR)
5590     {
5591       while (size--)
5592         {
5593           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5594           emitcode ("cjne", "a,%s,!tlabel",
5595                     aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG),
5596                     lbl->key + 100);
5597           offset++;
5598         }
5599     }
5600
5601   /* if the right side is in a register or in direct space or
5602      if the left is a pointer register & right is not */
5603   else if (AOP_TYPE (right) == AOP_REG ||
5604            AOP_TYPE (right) == AOP_DIR ||
5605            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5606            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5607     {
5608       while (size--)
5609         {
5610           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5611           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5612               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5613             emitcode ("jnz", "!tlabel", lbl->key + 100);
5614           else
5615             emitcode ("cjne", "a,%s,!tlabel",
5616                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5617                       lbl->key + 100);
5618           offset++;
5619         }
5620     }
5621   else
5622     {
5623       /* right is a pointer reg need both a & b */
5624       while (size--)
5625         {
5626           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5627           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5628           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5629           offset++;
5630         }
5631     }
5632 }
5633
5634 /*-----------------------------------------------------------------*/
5635 /* gencjne - compare and jump if not equal                         */
5636 /*-----------------------------------------------------------------*/
5637 static void
5638 gencjne (operand * left, operand * right, symbol * lbl)
5639 {
5640   symbol *tlbl = newiTempLabel (NULL);
5641
5642   D (emitcode (";", "gencjne");
5643     );
5644
5645   gencjneshort (left, right, lbl);
5646
5647   emitcode ("mov", "a,%s", one);
5648   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5649   emitcode ("", "!tlabeldef", lbl->key + 100);
5650   emitcode ("clr", "a");
5651   emitcode ("", "!tlabeldef", tlbl->key + 100);
5652 }
5653
5654 /*-----------------------------------------------------------------*/
5655 /* genCmpEq - generates code for equal to                          */
5656 /*-----------------------------------------------------------------*/
5657 static void
5658 genCmpEq (iCode * ic, iCode * ifx)
5659 {
5660   operand *left, *right, *result;
5661
5662   D (emitcode (";", "genCmpEq ");
5663     );
5664
5665   AOP_OP_2 (ic);
5666   AOP_SET_LOCALS (ic);
5667
5668   /* if literal, literal on the right or
5669      if the right is in a pointer register and left
5670      is not */
5671   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5672       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5673     {
5674       operand *t = IC_RIGHT (ic);
5675       IC_RIGHT (ic) = IC_LEFT (ic);
5676       IC_LEFT (ic) = t;
5677     }
5678
5679   if (ifx &&                    /* !AOP_SIZE(result) */
5680       OP_SYMBOL (result) &&
5681       OP_SYMBOL (result)->regType == REG_CND)
5682     {
5683       symbol *tlbl;
5684       /* if they are both bit variables */
5685       if (AOP_TYPE (left) == AOP_CRY &&
5686           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5687         {
5688           if (AOP_TYPE (right) == AOP_LIT)
5689             {
5690               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5691               if (lit == 0L)
5692                 {
5693                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5694                   emitcode ("cpl", "c");
5695                 }
5696               else if (lit == 1L)
5697                 {
5698                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5699                 }
5700               else
5701                 {
5702                   emitcode ("clr", "c");
5703                 }
5704               /* AOP_TYPE(right) == AOP_CRY */
5705             }
5706           else
5707             {
5708               symbol *lbl = newiTempLabel (NULL);
5709               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5710               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5711               emitcode ("cpl", "c");
5712               emitcode ("", "!tlabeldef", (lbl->key + 100));
5713             }
5714           /* if true label then we jump if condition
5715              supplied is true */
5716           tlbl = newiTempLabel (NULL);
5717           if (IC_TRUE (ifx))
5718             {
5719               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5720               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5721             }
5722           else
5723             {
5724               emitcode ("jc", "!tlabel", tlbl->key + 100);
5725               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5726             }
5727           emitcode ("", "!tlabeldef", tlbl->key + 100);
5728         }
5729       else
5730         {
5731           tlbl = newiTempLabel (NULL);
5732           gencjneshort (left, right, tlbl);
5733           if (IC_TRUE (ifx))
5734             {
5735               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5736               emitcode ("", "!tlabeldef", tlbl->key + 100);
5737             }
5738           else
5739             {
5740               symbol *lbl = newiTempLabel (NULL);
5741               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5742               emitcode ("", "!tlabeldef", tlbl->key + 100);
5743               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5744               emitcode ("", "!tlabeldef", lbl->key + 100);
5745             }
5746         }
5747       /* mark the icode as generated */
5748       ifx->generated = 1;
5749
5750       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5751       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5752       return;
5753     }
5754
5755   /* if they are both bit variables */
5756   if (AOP_TYPE (left) == AOP_CRY &&
5757       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5758     {
5759       if (AOP_TYPE (right) == AOP_LIT)
5760         {
5761           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5762           if (lit == 0L)
5763             {
5764               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765               emitcode ("cpl", "c");
5766             }
5767           else if (lit == 1L)
5768             {
5769               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5770             }
5771           else
5772             {
5773               emitcode ("clr", "c");
5774             }
5775           /* AOP_TYPE(right) == AOP_CRY */
5776         }
5777       else
5778         {
5779           symbol *lbl = newiTempLabel (NULL);
5780           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5781           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5782           emitcode ("cpl", "c");
5783           emitcode ("", "!tlabeldef", (lbl->key + 100));
5784         }
5785
5786       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5787       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5788
5789       aopOp (result, ic, TRUE, FALSE);
5790
5791       /* c = 1 if egal */
5792       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5793         {
5794           outBitC (result);
5795           goto release;
5796         }
5797       if (ifx)
5798         {
5799           genIfxJump (ifx, "c");
5800           goto release;
5801         }
5802       /* if the result is used in an arithmetic operation
5803          then put the result in place */
5804       outBitC (result);
5805     }
5806   else
5807     {
5808       gencjne (left, right, newiTempLabel (NULL));
5809
5810       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5812
5813       aopOp (result, ic, TRUE, FALSE);
5814
5815       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5816         {
5817           aopPut (AOP (result), "a", 0);
5818           goto release;
5819         }
5820       if (ifx)
5821         {
5822           genIfxJump (ifx, "a");
5823           goto release;
5824         }
5825       /* if the result is used in an arithmetic operation
5826          then put the result in place */
5827       if (AOP_TYPE (result) != AOP_CRY)
5828         outAcc (result);
5829       /* leave the result in acc */
5830     }
5831
5832 release:
5833   freeAsmop (result, NULL, ic, TRUE);
5834 }
5835
5836 /*-----------------------------------------------------------------*/
5837 /* ifxForOp - returns the icode containing the ifx for operand     */
5838 /*-----------------------------------------------------------------*/
5839 static iCode *
5840 ifxForOp (operand * op, iCode * ic)
5841 {
5842   /* if true symbol then needs to be assigned */
5843   if (IS_TRUE_SYMOP (op))
5844     return NULL;
5845
5846   /* if this has register type condition and
5847      the next instruction is ifx with the same operand
5848      and live to of the operand is upto the ifx only then */
5849   if (ic->next &&
5850       ic->next->op == IFX &&
5851       IC_COND (ic->next)->key == op->key &&
5852       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5853     return ic->next;
5854
5855   return NULL;
5856 }
5857 /*-----------------------------------------------------------------*/
5858 /* hasInc - operand is incremented before any other use            */
5859 /*-----------------------------------------------------------------*/
5860 static iCode *
5861 hasInc (operand *op, iCode *ic, int osize)
5862 {
5863   sym_link *type = operandType(op);
5864   sym_link *retype = getSpec (type);
5865   iCode *lic = ic->next;
5866   int isize ;
5867   
5868   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5869   if (!IS_SYMOP(op)) return NULL;
5870
5871   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5872   if (IS_AGGREGATE(type->next)) return NULL;
5873   if (osize != (isize = getSize(type->next))) return NULL;
5874
5875   while (lic) {
5876       /* if operand of the form op = op + <sizeof *op> */
5877       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5878           isOperandEqual(IC_RESULT(lic),op) && 
5879           isOperandLiteral(IC_RIGHT(lic)) &&
5880           operandLitValue(IC_RIGHT(lic)) == isize) {
5881           return lic;
5882       }
5883       /* if the operand used or deffed */
5884       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5885           return NULL;
5886       }
5887       /* if GOTO or IFX */
5888       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5889       lic = lic->next;
5890   }
5891   return NULL;
5892 }
5893
5894 /*-----------------------------------------------------------------*/
5895 /* genAndOp - for && operation                                     */
5896 /*-----------------------------------------------------------------*/
5897 static void
5898 genAndOp (iCode * ic)
5899 {
5900   operand *left, *right, *result;
5901   symbol *tlbl;
5902
5903   D (emitcode (";", "genAndOp "););
5904
5905   /* note here that && operations that are in an
5906      if statement are taken away by backPatchLabels
5907      only those used in arthmetic operations remain */
5908   AOP_OP_2 (ic);
5909   AOP_SET_LOCALS (ic);
5910
5911   /* if both are bit variables */
5912   if (AOP_TYPE (left) == AOP_CRY &&
5913       AOP_TYPE (right) == AOP_CRY)
5914     {
5915       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5916       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5917       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5919   
5920       aopOp (result,ic,FALSE, FALSE);
5921       outBitC (result);
5922     }
5923   else
5924     {
5925       tlbl = newiTempLabel (NULL);
5926       toBoolean (left);
5927       emitcode ("jz", "!tlabel", tlbl->key + 100);
5928       toBoolean (right);
5929       emitcode ("", "!tlabeldef", tlbl->key + 100);
5930       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5932   
5933       aopOp (result,ic,FALSE, FALSE);
5934       outBitAcc (result);
5935     }
5936     freeAsmop (result, NULL, ic, TRUE);
5937 }
5938
5939
5940 /*-----------------------------------------------------------------*/
5941 /* genOrOp - for || operation                                      */
5942 /*-----------------------------------------------------------------*/
5943 static void
5944 genOrOp (iCode * ic)
5945 {
5946   operand *left, *right, *result;
5947   symbol *tlbl;
5948
5949   D (emitcode (";", "genOrOp "););
5950
5951   /* note here that || operations that are in an
5952      if statement are taken away by backPatchLabels
5953      only those used in arthmetic operations remain */
5954   AOP_OP_2 (ic);
5955   AOP_SET_LOCALS (ic);
5956
5957   /* if both are bit variables */
5958   if (AOP_TYPE (left) == AOP_CRY &&
5959       AOP_TYPE (right) == AOP_CRY)
5960     {
5961       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5962       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5963       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5964       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5965   
5966       aopOp (result,ic,FALSE, FALSE);
5967       
5968       outBitC (result);
5969     }
5970   else
5971     {
5972       tlbl = newiTempLabel (NULL);
5973       toBoolean (left);
5974       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5975       toBoolean (right);
5976       emitcode ("", "!tlabeldef", tlbl->key + 100);
5977       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5978       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5979   
5980       aopOp (result,ic,FALSE, FALSE);
5981       
5982       outBitAcc (result);
5983     }
5984
5985   freeAsmop (result, NULL, ic, TRUE);
5986 }
5987
5988 /*-----------------------------------------------------------------*/
5989 /* isLiteralBit - test if lit == 2^n                               */
5990 /*-----------------------------------------------------------------*/
5991 static int
5992 isLiteralBit (unsigned long lit)
5993 {
5994   unsigned long pw[32] =
5995   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5996    0x100L, 0x200L, 0x400L, 0x800L,
5997    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5998    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5999    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6000    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6001    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6002   int idx;
6003
6004   for (idx = 0; idx < 32; idx++)
6005     if (lit == pw[idx])
6006       return idx + 1;
6007   return 0;
6008 }
6009
6010 /*-----------------------------------------------------------------*/
6011 /* continueIfTrue -                                                */
6012 /*-----------------------------------------------------------------*/
6013 static void
6014 continueIfTrue (iCode * ic)
6015 {
6016   if (IC_TRUE (ic))
6017     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6018   ic->generated = 1;
6019 }
6020
6021 /*-----------------------------------------------------------------*/
6022 /* jmpIfTrue -                                                     */
6023 /*-----------------------------------------------------------------*/
6024 static void
6025 jumpIfTrue (iCode * ic)
6026 {
6027   if (!IC_TRUE (ic))
6028     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6029   ic->generated = 1;
6030 }
6031
6032 /*-----------------------------------------------------------------*/
6033 /* jmpTrueOrFalse -                                                */
6034 /*-----------------------------------------------------------------*/
6035 static void
6036 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6037 {
6038   // ugly but optimized by peephole
6039   if (IC_TRUE (ic))
6040     {
6041       symbol *nlbl = newiTempLabel (NULL);
6042       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6043       emitcode ("", "!tlabeldef", tlbl->key + 100);
6044       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6045       emitcode ("", "!tlabeldef", nlbl->key + 100);
6046     }
6047   else
6048     {
6049       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6050       emitcode ("", "!tlabeldef", tlbl->key + 100);
6051     }
6052   ic->generated = 1;
6053 }
6054
6055 // Generate code to perform a bit-wise logic operation
6056 // on two operands in far space (assumed to already have been 
6057 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6058 // in far space. This requires pushing the result on the stack
6059 // then popping it into the result.
6060 static void
6061 genFarFarLogicOp(iCode *ic, char *logicOp)
6062 {
6063       int size, resultSize, compSize;
6064       int offset = 0;
6065       
6066       TR_AP("#5");
6067       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6068       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6069                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6070       
6071       _startLazyDPSEvaluation();
6072       for (size = compSize; (size--); offset++)
6073       {
6074           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6075           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6076           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6077           
6078           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6079           emitcode ("push", "acc");
6080       }
6081       _endLazyDPSEvaluation();
6082      
6083       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6084       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6085       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6086      
6087       resultSize = AOP_SIZE(IC_RESULT(ic));
6088
6089       ADJUST_PUSHED_RESULT(compSize, resultSize);
6090
6091       _startLazyDPSEvaluation();
6092       while (compSize--)
6093       {
6094           emitcode ("pop", "acc");
6095           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6096       }
6097       _endLazyDPSEvaluation();
6098       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6099 }
6100
6101
6102 /*-----------------------------------------------------------------*/
6103 /* genAnd  - code for and                                          */
6104 /*-----------------------------------------------------------------*/
6105 static void
6106 genAnd (iCode * ic, iCode * ifx)
6107 {
6108   operand *left, *right, *result;
6109   int size, offset = 0;
6110   unsigned long lit = 0L;
6111   int bytelit;
6112   char buff[10];
6113   bool pushResult;
6114
6115   D (emitcode (";", "genAnd "););
6116
6117   AOP_OP_3_NOFATAL (ic, pushResult);
6118   AOP_SET_LOCALS (ic);
6119
6120   if (pushResult)
6121   {
6122       genFarFarLogicOp(ic, "anl");
6123       return;
6124   }  
6125
6126 #ifdef DEBUG_TYPE
6127   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6128             AOP_TYPE (result),
6129             AOP_TYPE (left), AOP_TYPE (right));
6130   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6131             AOP_SIZE (result),
6132             AOP_SIZE (left), AOP_SIZE (right));
6133 #endif
6134
6135   /* if left is a literal & right is not then exchange them */
6136   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6137 #ifdef LOGIC_OPS_BROKEN      
6138     ||  AOP_NEEDSACC (left)
6139 #endif
6140     )
6141     {
6142       operand *tmp = right;
6143       right = left;
6144       left = tmp;
6145     }
6146
6147   /* if result = right then exchange them */
6148   if (sameRegs (AOP (result), AOP (right)))
6149     {
6150       operand *tmp = right;
6151       right = left;
6152       left = tmp;
6153     }
6154
6155   /* if right is bit then exchange them */
6156   if (AOP_TYPE (right) == AOP_CRY &&
6157       AOP_TYPE (left) != AOP_CRY)
6158     {
6159       operand *tmp = right;
6160       right = left;
6161       left = tmp;
6162     }
6163   if (AOP_TYPE (right) == AOP_LIT)
6164     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6165
6166   size = AOP_SIZE (result);
6167
6168   // if(bit & yy)
6169   // result = bit & yy;
6170   if (AOP_TYPE (left) == AOP_CRY)
6171     {
6172       // c = bit & literal;
6173       if (AOP_TYPE (right) == AOP_LIT)
6174         {
6175           if (lit & 1)
6176             {
6177               if (size && sameRegs (AOP (result), AOP (left)))
6178                 // no change
6179                 goto release;
6180               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6181             }
6182           else
6183             {
6184               // bit(result) = 0;
6185               if (size && (AOP_TYPE (result) == AOP_CRY))
6186                 {
6187                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6188                   goto release;
6189                 }
6190               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6191                 {
6192                   jumpIfTrue (ifx);
6193                   goto release;
6194                 }
6195               emitcode ("clr", "c");
6196             }
6197         }
6198       else
6199         {
6200           if (AOP_TYPE (right) == AOP_CRY)
6201             {
6202               // c = bit & bit;
6203               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6204               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6205             }
6206           else
6207             {
6208               // c = bit & val;
6209               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6210               // c = lsb
6211               emitcode ("rrc", "a");
6212               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6213             }
6214         }
6215       // bit = c
6216       // val = c
6217       if (size)
6218         outBitC (result);
6219       // if(bit & ...)
6220       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6221         genIfxJump (ifx, "c");
6222       goto release;
6223     }
6224
6225   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6226   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6227   if ((AOP_TYPE (right) == AOP_LIT) &&
6228       (AOP_TYPE (result) == AOP_CRY) &&
6229       (AOP_TYPE (left) != AOP_CRY))
6230     {
6231       int posbit = isLiteralBit (lit);
6232       /* left &  2^n */
6233       if (posbit)
6234         {
6235           posbit--;
6236           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6237           // bit = left & 2^n
6238           if (size)
6239             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6240           // if(left &  2^n)
6241           else
6242             {
6243               if (ifx)
6244                 {
6245                   SNPRINTF (buff, sizeof(buff), 
6246                             "acc.%d", posbit & 0x07);
6247                   genIfxJump (ifx, buff);
6248                 }
6249               else 
6250                   {
6251                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6252                   }
6253               goto release;
6254             }
6255         }
6256       else
6257         {
6258           symbol *tlbl = newiTempLabel (NULL);
6259           int sizel = AOP_SIZE (left);
6260           if (size)
6261             emitcode ("setb", "c");
6262           while (sizel--)
6263             {
6264               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6265                 {
6266                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6267                   // byte ==  2^n ?
6268                   if ((posbit = isLiteralBit (bytelit)) != 0)
6269                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6270                   else
6271                     {
6272                       if (bytelit != 0x0FFL)
6273                         emitcode ("anl", "a,%s",
6274                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6275                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6276                     }
6277                 }
6278               offset++;
6279             }
6280           // bit = left & literal
6281           if (size)
6282             {
6283               emitcode ("clr", "c");
6284               emitcode ("", "!tlabeldef", tlbl->key + 100);
6285             }
6286           // if(left & literal)
6287           else
6288             {
6289               if (ifx)
6290                 jmpTrueOrFalse (ifx, tlbl);
6291               goto release;
6292             }
6293         }
6294       outBitC (result);
6295       goto release;
6296     }
6297
6298   /* if left is same as result */
6299   if (sameRegs (AOP (result), AOP (left)))
6300     {
6301       for (; size--; offset++)
6302         {
6303           if (AOP_TYPE (right) == AOP_LIT)
6304             {
6305               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6306                 continue;
6307               else if (bytelit == 0)
6308                 aopPut (AOP (result), zero, offset);
6309               else if (IS_AOP_PREG (result))
6310                 {
6311                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6312                   emitcode ("anl", "a,%s",
6313                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6314                   aopPut (AOP (result), "a", offset);
6315                 }
6316               else
6317                 emitcode ("anl", "%s,%s",
6318                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6319                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6320             }
6321           else
6322             {
6323               if (AOP_TYPE (left) == AOP_ACC)
6324                 emitcode ("anl", "a,%s",
6325                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6326               else
6327                 {
6328                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6329                   if (IS_AOP_PREG (result))
6330                     {
6331                       emitcode ("anl", "a,%s",
6332                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6333                       aopPut (AOP (result), "a", offset);
6334                     }
6335                   else
6336                     emitcode ("anl", "%s,a",
6337                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6338                 }
6339             }
6340         }
6341     }
6342   else
6343     {
6344       // left & result in different registers
6345       if (AOP_TYPE (result) == AOP_CRY)
6346         {
6347           // result = bit
6348           // if(size), result in bit
6349           // if(!size && ifx), conditional oper: if(left & right)
6350           symbol *tlbl = newiTempLabel (NULL);
6351           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6352           if (size)
6353             emitcode ("setb", "c");
6354           while (sizer--)
6355             {
6356               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6357                 emitcode ("anl", "a,%s",
6358                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6359               } else {
6360                 if (AOP_TYPE(left)==AOP_ACC) {
6361                   emitcode("mov", "b,a");
6362                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6363                   emitcode("anl", "a,b");
6364                 }else {
6365                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6366                   emitcode ("anl", "a,%s",
6367                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6368                 }
6369               }
6370               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6371               offset++;
6372             }
6373           if (size)
6374             {
6375               CLRC;
6376               emitcode ("", "!tlabeldef", tlbl->key + 100);
6377               outBitC (result);
6378             }
6379           else if (ifx)
6380             jmpTrueOrFalse (ifx, tlbl);
6381         }
6382       else
6383         {
6384           for (; (size--); offset++)
6385             {
6386               // normal case
6387               // result = left & right
6388               if (AOP_TYPE (right) == AOP_LIT)
6389                 {
6390                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6391                     {
6392                       aopPut (AOP (result),
6393                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6394                               offset);
6395                       continue;
6396                     }
6397                   else if (bytelit == 0)
6398                     {
6399                       aopPut (AOP (result), zero, offset);
6400                       continue;
6401                     }
6402                   D (emitcode (";", "better literal AND."););
6403                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6404                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6405                                                     FALSE, FALSE, DP2_RESULT_REG));
6406
6407                 }
6408               else
6409                 {
6410                   // faster than result <- left, anl result,right
6411                   // and better if result is SFR
6412                   if (AOP_TYPE (left) == AOP_ACC)
6413                     {
6414                       emitcode ("anl", "a,%s", 
6415                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6416                     }
6417                   else
6418                     {
6419                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6420                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6421                       {
6422                           emitcode("mov", "b,a");
6423                           rOp = "b";
6424                       }
6425                         
6426                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6427                       emitcode ("anl", "a,%s", rOp);
6428                     }                   
6429                 }
6430               aopPut (AOP (result), "a", offset);
6431             }
6432         }
6433     }
6434
6435 release:
6436   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6437   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6438   freeAsmop (result, NULL, ic, TRUE);
6439 }
6440
6441
6442 /*-----------------------------------------------------------------*/
6443 /* genOr  - code for or                                            */
6444 /*-----------------------------------------------------------------*/
6445 static void
6446 genOr (iCode * ic, iCode * ifx)
6447 {
6448   operand *left, *right, *result;
6449   int size, offset = 0;
6450   unsigned long lit = 0L;
6451   bool     pushResult;
6452
6453   D (emitcode (";", "genOr "););
6454
6455   AOP_OP_3_NOFATAL (ic, pushResult);
6456   AOP_SET_LOCALS (ic);
6457
6458   if (pushResult)
6459   {
6460       genFarFarLogicOp(ic, "orl");
6461       return;
6462   }
6463
6464
6465 #ifdef DEBUG_TYPE
6466   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6467             AOP_TYPE (result),
6468             AOP_TYPE (left), AOP_TYPE (right));
6469   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6470             AOP_SIZE (result),
6471             AOP_SIZE (left), AOP_SIZE (right));
6472 #endif
6473
6474   /* if left is a literal & right is not then exchange them */
6475   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6476 #ifdef LOGIC_OPS_BROKEN
6477    || AOP_NEEDSACC (left) // I think this is a net loss now.
6478 #endif      
6479       )
6480     {
6481       operand *tmp = right;
6482       right = left;
6483       left = tmp;
6484     }
6485
6486   /* if result = right then exchange them */
6487   if (sameRegs (AOP (result), AOP (right)))
6488     {
6489       operand *tmp = right;
6490       right = left;
6491       left = tmp;
6492     }
6493
6494   /* if right is bit then exchange them */
6495   if (AOP_TYPE (right) == AOP_CRY &&
6496       AOP_TYPE (left) != AOP_CRY)
6497     {
6498       operand *tmp = right;
6499       right = left;
6500       left = tmp;
6501     }
6502   if (AOP_TYPE (right) == AOP_LIT)
6503     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6504
6505   size = AOP_SIZE (result);
6506
6507   // if(bit | yy)
6508   // xx = bit | yy;
6509   if (AOP_TYPE (left) == AOP_CRY)
6510     {
6511       if (AOP_TYPE (right) == AOP_LIT)
6512         {
6513           // c = bit & literal;
6514           if (lit)
6515             {
6516               // lit != 0 => result = 1
6517               if (AOP_TYPE (result) == AOP_CRY)
6518                 {
6519                   if (size)
6520                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6521                   else if (ifx)
6522                     continueIfTrue (ifx);
6523                   goto release;
6524                 }
6525               emitcode ("setb", "c");
6526             }
6527           else
6528             {
6529               // lit == 0 => result = left
6530               if (size && sameRegs (AOP (result), AOP (left)))
6531                 goto release;
6532               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6533             }
6534         }
6535       else
6536         {
6537           if (AOP_TYPE (right) == AOP_CRY)
6538             {
6539               // c = bit | bit;
6540               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6541               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6542             }
6543           else
6544             {
6545               // c = bit | val;
6546               symbol *tlbl = newiTempLabel (NULL);
6547               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6548                 emitcode ("setb", "c");
6549               emitcode ("jb", "%s,!tlabel",
6550                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6551               toBoolean (right);
6552               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6553               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6554                 {
6555                   jmpTrueOrFalse (ifx, tlbl);
6556                   goto release;
6557                 }
6558               else
6559                 {
6560                   CLRC;
6561                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6562                 }
6563             }
6564         }
6565       // bit = c
6566       // val = c
6567       if (size)
6568         outBitC (result);
6569       // if(bit | ...)
6570       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6571            genIfxJump (ifx, "c");
6572       goto release;
6573     }
6574
6575   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6576   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6577   if ((AOP_TYPE (right) == AOP_LIT) &&
6578       (AOP_TYPE (result) == AOP_CRY) &&
6579       (AOP_TYPE (left) != AOP_CRY))
6580     {
6581       if (lit)
6582         {
6583           // result = 1
6584           if (size)
6585             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6586           else
6587             continueIfTrue (ifx);
6588           goto release;
6589         }
6590       else
6591         {
6592           // lit = 0, result = boolean(left)
6593           if (size)
6594             emitcode ("setb", "c");
6595           toBoolean (right);
6596           if (size)
6597             {
6598               symbol *tlbl = newiTempLabel (NULL);
6599               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6600               CLRC;
6601               emitcode ("", "!tlabeldef", tlbl->key + 100);
6602             }
6603           else
6604             {
6605               genIfxJump (ifx, "a");
6606               goto release;
6607             }
6608         }
6609       outBitC (result);
6610       goto release;
6611     }
6612
6613   /* if left is same as result */
6614   if (sameRegs (AOP (result), AOP (left)))
6615     {
6616       for (; size--; offset++)
6617         {
6618           if (AOP_TYPE (right) == AOP_LIT)
6619             {
6620               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6621                 {
6622                   continue;
6623                 }
6624               else
6625                 {
6626                   if (IS_AOP_PREG (left))
6627                     {
6628                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6629                       emitcode ("orl", "a,%s",
6630                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6631                       aopPut (AOP (result), "a", offset);
6632                     }
6633                   else
6634                     {
6635                       emitcode ("orl", "%s,%s",
6636                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6637                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6638                     }
6639                 }
6640             }
6641           else
6642             {
6643               if (AOP_TYPE (left) == AOP_ACC)
6644                 {
6645                   emitcode ("orl", "a,%s",
6646                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6647                 }
6648               else
6649                 {
6650                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6651                   if (IS_AOP_PREG (left))
6652                     {
6653                       emitcode ("orl", "a,%s", 
6654                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6655                       aopPut (AOP (result), "a", offset);
6656                     }
6657                   else
6658                     {
6659                       emitcode ("orl", "%s,a",
6660                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6661                     }
6662                 }
6663             }
6664         }
6665     }
6666   else
6667     {
6668       // left & result in different registers
6669       if (AOP_TYPE (result) == AOP_CRY)
6670         {
6671           // result = bit
6672           // if(size), result in bit
6673           // if(!size && ifx), conditional oper: if(left | right)
6674           symbol *tlbl = newiTempLabel (NULL);
6675           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6676           if (size)
6677             emitcode ("setb", "c");
6678           while (sizer--)
6679             {
6680               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6681                 emitcode ("orl", "a,%s",
6682                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6683               } else {
6684                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6685                 emitcode ("orl", "a,%s",
6686                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6687               }
6688               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6689               offset++;
6690             }
6691           if (size)
6692             {
6693               CLRC;
6694               emitcode ("", "!tlabeldef", tlbl->key + 100);
6695               outBitC (result);
6696             }
6697           else if (ifx)
6698             jmpTrueOrFalse (ifx, tlbl);
6699         }
6700       else
6701         {
6702             _startLazyDPSEvaluation();
6703           for (; (size--); offset++)
6704             {
6705               // normal case
6706               // result = left & right
6707               if (AOP_TYPE (right) == AOP_LIT)
6708                 {
6709                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6710                     {
6711                       aopPut (AOP (result),
6712                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6713                               offset);
6714                       continue;
6715                     }
6716                   D (emitcode (";", "better literal OR."););
6717                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6718                   emitcode ("orl", "a, %s",
6719                             aopGet (AOP (right), offset,
6720                                     FALSE, FALSE, DP2_RESULT_REG));
6721
6722                 }
6723               else
6724                 {
6725                   // faster than result <- left, anl result,right
6726                   // and better if result is SFR
6727                   if (AOP_TYPE (left) == AOP_ACC)
6728                     {
6729                       emitcode ("orl", "a,%s",
6730                                 aopGet (AOP (right), offset,
6731                                         FALSE, FALSE, DP2_RESULT_REG));
6732                     }
6733                   else
6734                     {
6735                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6736                         
6737                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6738                       {
6739                           emitcode("mov", "b,a");
6740                           rOp = "b";
6741                       }
6742                         
6743                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6744                       emitcode ("orl", "a,%s", rOp);
6745                     }
6746                 }
6747               aopPut (AOP (result), "a", offset);
6748             }
6749             _endLazyDPSEvaluation();
6750         }
6751     }
6752
6753 release:
6754   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6755   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6756   freeAsmop (result, NULL, ic, TRUE);
6757 }
6758
6759 /*-----------------------------------------------------------------*/
6760 /* genXor - code for xclusive or                                   */
6761 /*-----------------------------------------------------------------*/
6762 static void
6763 genXor (iCode * ic, iCode * ifx)
6764 {
6765   operand *left, *right, *result;
6766   int size, offset = 0;
6767   unsigned long lit = 0L;
6768   bool pushResult;
6769
6770   D (emitcode (";", "genXor "););
6771
6772   AOP_OP_3_NOFATAL (ic, pushResult);
6773   AOP_SET_LOCALS (ic);
6774
6775   if (pushResult)
6776   {
6777       genFarFarLogicOp(ic, "xrl");
6778       return;
6779   }  
6780
6781 #ifdef DEBUG_TYPE
6782   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6783             AOP_TYPE (result),
6784             AOP_TYPE (left), AOP_TYPE (right));
6785   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6786             AOP_SIZE (result),
6787             AOP_SIZE (left), AOP_SIZE (right));
6788 #endif
6789
6790   /* if left is a literal & right is not ||
6791      if left needs acc & right does not */
6792   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6793 #ifdef LOGIC_OPS_BROKEN      
6794       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6795 #endif
6796      )
6797     {
6798       operand *tmp = right;
6799       right = left;
6800       left = tmp;
6801     }
6802
6803   /* if result = right then exchange them */
6804   if (sameRegs (AOP (result), AOP (right)))
6805     {
6806       operand *tmp = right;
6807       right = left;
6808       left = tmp;
6809     }
6810
6811   /* if right is bit then exchange them */
6812   if (AOP_TYPE (right) == AOP_CRY &&
6813       AOP_TYPE (left) != AOP_CRY)
6814     {
6815       operand *tmp = right;
6816       right = left;
6817       left = tmp;
6818     }
6819   if (AOP_TYPE (right) == AOP_LIT)
6820     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6821
6822   size = AOP_SIZE (result);
6823
6824   // if(bit ^ yy)
6825   // xx = bit ^ yy;
6826   if (AOP_TYPE (left) == AOP_CRY)
6827     {
6828       if (AOP_TYPE (right) == AOP_LIT)
6829         {
6830           // c = bit & literal;
6831           if (lit >> 1)
6832             {
6833               // lit>>1  != 0 => result = 1
6834               if (AOP_TYPE (result) == AOP_CRY)
6835                 {
6836                   if (size)
6837                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6838                   else if (ifx)
6839                     continueIfTrue (ifx);
6840                   goto release;
6841                 }
6842               emitcode ("setb", "c");
6843             }
6844           else
6845             {
6846               // lit == (0 or 1)
6847               if (lit == 0)
6848                 {
6849                   // lit == 0, result = left
6850                   if (size && sameRegs (AOP (result), AOP (left)))
6851                     goto release;
6852                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6853                 }
6854               else
6855                 {
6856                   // lit == 1, result = not(left)
6857                   if (size && sameRegs (AOP (result), AOP (left)))
6858                     {
6859                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6860                       goto release;
6861                     }
6862                   else
6863                     {
6864                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6865                       emitcode ("cpl", "c");
6866                     }
6867                 }
6868             }
6869
6870         }
6871       else
6872         {
6873           // right != literal
6874           symbol *tlbl = newiTempLabel (NULL);
6875           if (AOP_TYPE (right) == AOP_CRY)
6876             {
6877               // c = bit ^ bit;
6878               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6879             }
6880           else
6881             {
6882               int sizer = AOP_SIZE (right);
6883               // c = bit ^ val
6884               // if val>>1 != 0, result = 1
6885               emitcode ("setb", "c");
6886               while (sizer)
6887                 {
6888                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6889                   if (sizer == 1)
6890                     // test the msb of the lsb
6891                     emitcode ("anl", "a,#!constbyte",0xfe);
6892                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6893                   sizer--;
6894                 }
6895               // val = (0,1)
6896               emitcode ("rrc", "a");
6897             }
6898           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6899           emitcode ("cpl", "c");
6900           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6901         }
6902       // bit = c
6903       // val = c
6904       if (size)
6905         outBitC (result);
6906       // if(bit | ...)
6907       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6908         genIfxJump (ifx, "c");
6909       goto release;
6910     }
6911
6912   if (sameRegs (AOP (result), AOP (left)))
6913     {
6914       /* if left is same as result */
6915       for (; size--; offset++)
6916         {
6917           if (AOP_TYPE (right) == AOP_LIT)
6918             {
6919               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6920                 continue;
6921               else if (IS_AOP_PREG (left))
6922                 {
6923                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6924                   emitcode ("xrl", "a,%s",
6925                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6926                   aopPut (AOP (result), "a", offset);
6927                 }
6928               else
6929                 emitcode ("xrl", "%s,%s",
6930                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6931                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6932             }
6933           else
6934             {
6935               if (AOP_TYPE (left) == AOP_ACC)
6936                 emitcode ("xrl", "a,%s",
6937                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6938               else
6939                 {
6940                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6941                   if (IS_AOP_PREG (left))
6942                     {
6943                       emitcode ("xrl", "a,%s",
6944                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6945                       aopPut (AOP (result), "a", offset);
6946                     }
6947                   else
6948                     emitcode ("xrl", "%s,a",
6949                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6950                 }
6951             }
6952         }
6953     }
6954   else
6955     {
6956       // left & result in different registers
6957       if (AOP_TYPE (result) == AOP_CRY)
6958         {
6959           // result = bit
6960           // if(size), result in bit
6961           // if(!size && ifx), conditional oper: if(left ^ right)
6962           symbol *tlbl = newiTempLabel (NULL);
6963           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6964                   
6965           if (size)
6966             emitcode ("setb", "c");
6967           while (sizer--)
6968             {
6969               if ((AOP_TYPE (right) == AOP_LIT) &&
6970                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6971                 {
6972                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6973                 }
6974               else
6975                 {
6976                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6977                     emitcode ("xrl", "a,%s",
6978                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6979                   } else {
6980                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6981                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6982                       {
6983                           emitcode("mov", "b,a");
6984                           rOp = "b";
6985                       }
6986                         
6987                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6988                       emitcode ("xrl", "a,%s", rOp);                  
6989                   }
6990                 }
6991               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6992               offset++;
6993             }
6994           if (size)
6995             {
6996               CLRC;
6997               emitcode ("", "!tlabeldef", tlbl->key + 100);
6998               outBitC (result);
6999             }
7000           else if (ifx)
7001             jmpTrueOrFalse (ifx, tlbl);
7002         }
7003       else
7004         {
7005         for (; (size--); offset++)
7006           {
7007             // normal case
7008             // result = left & right
7009             if (AOP_TYPE (right) == AOP_LIT)
7010               {
7011                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7012                   {
7013                     aopPut (AOP (result),
7014                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7015                             offset);
7016                     continue;
7017                   }
7018                 D (emitcode (";", "better literal XOR."););
7019                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7020                 emitcode ("xrl", "a, %s",
7021                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7022               }
7023             else
7024               {
7025                 // faster than result <- left, anl result,right
7026                 // and better if result is SFR
7027                 if (AOP_TYPE (left) == AOP_ACC)
7028                   {
7029                     emitcode ("xrl", "a,%s",
7030                               aopGet (AOP (right), offset,
7031                                       FALSE, FALSE, DP2_RESULT_REG));
7032                   }
7033                 else
7034                   {
7035                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7037                       {
7038                           emitcode("mov", "b,a");
7039                           rOp = "b";
7040                       }
7041                         
7042                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043                       emitcode ("xrl", "a,%s", rOp);
7044                   }
7045               }
7046             aopPut (AOP (result), "a", offset);
7047           }
7048         }
7049         
7050     }
7051
7052 release:
7053   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7054   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7055   freeAsmop (result, NULL, ic, TRUE);
7056 }
7057
7058 /*-----------------------------------------------------------------*/
7059 /* genInline - write the inline code out                           */
7060 /*-----------------------------------------------------------------*/
7061 static void
7062 genInline (iCode * ic)
7063 {
7064   char *buffer, *bp, *bp1;
7065
7066   D (emitcode (";", "genInline "); );
7067
7068   _G.inLine += (!options.asmpeep);
7069
7070   buffer = Safe_strdup(IC_INLINE(ic));
7071   bp = buffer;
7072   bp1 = buffer;
7073
7074   /* emit each line as a code */
7075   while (*bp)
7076     {
7077       if (*bp == '\n')
7078         {
7079           *bp++ = '\0';
7080           emitcode (bp1, "");
7081           bp1 = bp;
7082         }
7083       else
7084         {
7085           if (*bp == ':')
7086             {
7087               bp++;
7088               *bp = '\0';
7089               bp++;
7090               emitcode (bp1, "");
7091               bp1 = bp;
7092             }
7093           else
7094             bp++;
7095         }
7096     }
7097   if (bp1 != bp)
7098     emitcode (bp1, "");
7099   /*     emitcode("",buffer); */
7100   _G.inLine -= (!options.asmpeep);
7101 }
7102
7103 /*-----------------------------------------------------------------*/
7104 /* genRRC - rotate right with carry                                */
7105 /*-----------------------------------------------------------------*/
7106 static void
7107 genRRC (iCode * ic)
7108 {
7109   operand *left, *result;
7110   int     size, offset;
7111
7112   D (emitcode (";", "genRRC "););
7113
7114   /* rotate right with carry */
7115   left = IC_LEFT (ic);
7116   result = IC_RESULT (ic);
7117   aopOp (left, ic, FALSE, FALSE);
7118   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7119
7120   /* move it to the result */
7121   size = AOP_SIZE (result);
7122   offset = size - 1;
7123   CLRC;
7124
7125   _startLazyDPSEvaluation ();
7126   while (size--)
7127     {
7128       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7129       emitcode ("rrc", "a");
7130       if (AOP_SIZE (result) > 1)
7131         aopPut (AOP (result), "a", offset--);
7132     }
7133   _endLazyDPSEvaluation ();
7134
7135   /* now we need to put the carry into the
7136      highest order byte of the result */
7137   if (AOP_SIZE (result) > 1)
7138     {
7139       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7140     }
7141   emitcode ("mov", "acc.7,c");
7142   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7143   freeAsmop (left, NULL, ic, TRUE);
7144   freeAsmop (result, NULL, ic, TRUE);
7145 }
7146
7147 /*-----------------------------------------------------------------*/
7148 /* genRLC - generate code for rotate left with carry               */
7149 /*-----------------------------------------------------------------*/
7150 static void
7151 genRLC (iCode * ic)
7152 {
7153   operand *left, *result;
7154   int size, offset;
7155   char *l;
7156
7157   D (emitcode (";", "genRLC "););
7158
7159   /* rotate right with carry */
7160   left = IC_LEFT (ic);
7161   result = IC_RESULT (ic);
7162   aopOp (left, ic, FALSE, FALSE);
7163   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7164
7165   /* move it to the result */
7166   size = AOP_SIZE (result);
7167   offset = 0;
7168   if (size--)
7169     {
7170       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7171       MOVA (l);
7172       emitcode ("add", "a,acc");
7173       if (AOP_SIZE (result) > 1)
7174         {
7175           aopPut (AOP (result), "a", offset++);
7176         }
7177
7178       _startLazyDPSEvaluation ();
7179       while (size--)
7180         {
7181           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7182           MOVA (l);
7183           emitcode ("rlc", "a");
7184           if (AOP_SIZE (result) > 1)
7185             aopPut (AOP (result), "a", offset++);
7186         }
7187       _endLazyDPSEvaluation ();
7188     }
7189   /* now we need to put the carry into the
7190      highest order byte of the result */
7191   if (AOP_SIZE (result) > 1)
7192     {
7193       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7194       MOVA (l);
7195     }
7196   emitcode ("mov", "acc.0,c");
7197   aopPut (AOP (result), "a", 0);
7198   freeAsmop (left, NULL, ic, TRUE);
7199   freeAsmop (result, NULL, ic, TRUE);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genGetHbit - generates code get highest order bit               */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genGetHbit (iCode * ic)
7207 {
7208   operand *left, *result;
7209   left = IC_LEFT (ic);
7210   result = IC_RESULT (ic);
7211   aopOp (left, ic, FALSE, FALSE);
7212   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7213
7214   D (emitcode (";", "genGetHbit "););
7215
7216   /* get the highest order byte into a */
7217   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7218   if (AOP_TYPE (result) == AOP_CRY)
7219     {
7220       emitcode ("rlc", "a");
7221       outBitC (result);
7222     }
7223   else
7224     {
7225       emitcode ("rl", "a");
7226       emitcode ("anl", "a,#1");
7227       outAcc (result);
7228     }
7229
7230
7231   freeAsmop (left, NULL, ic, TRUE);
7232   freeAsmop (result, NULL, ic, TRUE);
7233 }
7234
7235 /*-----------------------------------------------------------------*/
7236 /* AccRol - rotate left accumulator by known count                 */
7237 /*-----------------------------------------------------------------*/
7238 static void
7239 AccRol (int shCount)
7240 {
7241   shCount &= 0x0007;            // shCount : 0..7
7242
7243   switch (shCount)
7244     {
7245     case 0:
7246       break;
7247     case 1:
7248       emitcode ("rl", "a");
7249       break;
7250     case 2:
7251       emitcode ("rl", "a");
7252       emitcode ("rl", "a");
7253       break;
7254     case 3:
7255       emitcode ("swap", "a");
7256       emitcode ("rr", "a");
7257       break;
7258     case 4:
7259       emitcode ("swap", "a");
7260       break;
7261     case 5:
7262       emitcode ("swap", "a");
7263       emitcode ("rl", "a");
7264       break;
7265     case 6:
7266       emitcode ("rr", "a");
7267       emitcode ("rr", "a");
7268       break;
7269     case 7:
7270       emitcode ("rr", "a");
7271       break;
7272     }
7273 }
7274
7275 /*-----------------------------------------------------------------*/
7276 /* AccLsh - left shift accumulator by known count                  */
7277 /*-----------------------------------------------------------------*/
7278 static void
7279 AccLsh (int shCount)
7280 {
7281   if (shCount != 0)
7282     {
7283       if (shCount == 1)
7284         emitcode ("add", "a,acc");
7285       else if (shCount == 2)
7286         {
7287           emitcode ("add", "a,acc");
7288           emitcode ("add", "a,acc");
7289         }
7290       else
7291         {
7292           /* rotate left accumulator */
7293           AccRol (shCount);
7294           /* and kill the lower order bits */
7295           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7296         }
7297     }
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* AccRsh - right shift accumulator by known count                 */
7302 /*-----------------------------------------------------------------*/
7303 static void
7304 AccRsh (int shCount)
7305 {
7306   if (shCount != 0)
7307     {
7308       if (shCount == 1)
7309         {
7310           CLRC;
7311           emitcode ("rrc", "a");
7312         }
7313       else
7314         {
7315           /* rotate right accumulator */
7316           AccRol (8 - shCount);
7317           /* and kill the higher order bits */
7318           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7319         }
7320     }
7321 }
7322
7323 #ifdef BETTER_LITERAL_SHIFT
7324 /*-----------------------------------------------------------------*/
7325 /* AccSRsh - signed right shift accumulator by known count                 */
7326 /*-----------------------------------------------------------------*/
7327 static void
7328 AccSRsh (int shCount)
7329 {
7330   symbol *tlbl;
7331   if (shCount != 0)
7332     {
7333       if (shCount == 1)
7334         {
7335           emitcode ("mov", "c,acc.7");
7336           emitcode ("rrc", "a");
7337         }
7338       else if (shCount == 2)
7339         {
7340           emitcode ("mov", "c,acc.7");
7341           emitcode ("rrc", "a");
7342           emitcode ("mov", "c,acc.7");
7343           emitcode ("rrc", "a");
7344         }
7345       else
7346         {
7347           tlbl = newiTempLabel (NULL);
7348           /* rotate right accumulator */
7349           AccRol (8 - shCount);
7350           /* and kill the higher order bits */
7351           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7352           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7353           emitcode ("orl", "a,#!constbyte",
7354                     (unsigned char) ~SRMask[shCount]);
7355           emitcode ("", "!tlabeldef", tlbl->key + 100);
7356         }
7357     }
7358 }
7359 #endif
7360
7361 #ifdef BETTER_LITERAL_SHIFT
7362 /*-----------------------------------------------------------------*/
7363 /* shiftR1Left2Result - shift right one byte from left to result   */
7364 /*-----------------------------------------------------------------*/
7365 static void
7366 shiftR1Left2Result (operand * left, int offl,
7367                     operand * result, int offr,
7368                     int shCount, int sign)
7369 {
7370   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7371   /* shift right accumulator */
7372   if (sign)
7373     AccSRsh (shCount);
7374   else
7375     AccRsh (shCount);
7376   aopPut (AOP (result), "a", offr);
7377 }
7378 #endif
7379
7380 #ifdef BETTER_LITERAL_SHIFT
7381 /*-----------------------------------------------------------------*/
7382 /* shiftL1Left2Result - shift left one byte from left to result    */
7383 /*-----------------------------------------------------------------*/
7384 static void
7385 shiftL1Left2Result (operand * left, int offl,
7386                     operand * result, int offr, int shCount)
7387 {
7388   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7389   /* shift left accumulator */
7390   AccLsh (shCount);
7391   aopPut (AOP (result), "a", offr);
7392 }
7393 #endif
7394
7395 #ifdef BETTER_LITERAL_SHIFT
7396 /*-----------------------------------------------------------------*/
7397 /* movLeft2Result - move byte from left to result                  */
7398 /*-----------------------------------------------------------------*/
7399 static void
7400 movLeft2Result (operand * left, int offl,
7401                 operand * result, int offr, int sign)
7402 {
7403   char *l;
7404   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7405   {
7406       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7407
7408       if (*l == '@' && (IS_AOP_PREG (result)))
7409       {
7410           emitcode ("mov", "a,%s", l);
7411           aopPut (AOP (result), "a", offr);
7412       }
7413       else
7414       {
7415           if (!sign)
7416           {
7417             aopPut (AOP (result), l, offr);
7418           }
7419           else
7420             {
7421               /* MSB sign in acc.7 ! */
7422               if (getDataSize (left) == offl + 1)
7423                 {
7424                   emitcode ("mov", "a,%s", l);
7425                   aopPut (AOP (result), "a", offr);
7426                 }
7427             }
7428       }
7429   }
7430 }
7431 #endif
7432
7433 #ifdef BETTER_LITERAL_SHIFT
7434 /*-----------------------------------------------------------------*/
7435 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7436 /*-----------------------------------------------------------------*/
7437 static void
7438 AccAXRrl1 (char *x)
7439 {
7440   emitcode ("rrc", "a");
7441   emitcode ("xch", "a,%s", x);
7442   emitcode ("rrc", "a");
7443   emitcode ("xch", "a,%s", x);
7444 }
7445 #endif
7446
7447 #ifdef BETTER_LITERAL_SHIFT
7448 //REMOVE ME!!!
7449 /*-----------------------------------------------------------------*/
7450 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7451 /*-----------------------------------------------------------------*/
7452 static void
7453 AccAXLrl1 (char *x)
7454 {
7455   emitcode ("xch", "a,%s", x);
7456   emitcode ("rlc", "a");
7457   emitcode ("xch", "a,%s", x);
7458   emitcode ("rlc", "a");
7459 }
7460 #endif
7461
7462 #ifdef BETTER_LITERAL_SHIFT
7463 /*-----------------------------------------------------------------*/
7464 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7465 /*-----------------------------------------------------------------*/
7466 static void
7467 AccAXLsh1 (char *x)
7468 {
7469   emitcode ("xch", "a,%s", x);
7470   emitcode ("add", "a,acc");
7471   emitcode ("xch", "a,%s", x);
7472   emitcode ("rlc", "a");
7473 }
7474 #endif
7475
7476 #ifdef BETTER_LITERAL_SHIFT
7477 /*-----------------------------------------------------------------*/
7478 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7479 /*-----------------------------------------------------------------*/
7480 static void
7481 AccAXLsh (char *x, int shCount)
7482 {
7483   switch (shCount)
7484     {
7485     case 0:
7486       break;
7487     case 1:
7488       AccAXLsh1 (x);
7489       break;
7490     case 2:
7491       AccAXLsh1 (x);
7492       AccAXLsh1 (x);
7493       break;
7494     case 3:
7495     case 4:
7496     case 5:                     // AAAAABBB:CCCCCDDD
7497
7498       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7499
7500       emitcode ("anl", "a,#!constbyte",
7501                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7502
7503       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7504
7505       AccRol (shCount);         // DDDCCCCC:BBB00000
7506
7507       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7508
7509       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7510
7511       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7512
7513       emitcode ("anl", "a,#!constbyte",
7514                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7515
7516       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7517
7518       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7519
7520       break;
7521     case 6:                     // AAAAAABB:CCCCCCDD
7522       emitcode ("anl", "a,#!constbyte",
7523                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7524       emitcode ("mov", "c,acc.0");      // c = B
7525       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7526 #if 0
7527       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7528       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7529 #else
7530       emitcode("rrc","a"); 
7531       emitcode("xch","a,%s", x); 
7532       emitcode("rrc","a"); 
7533       emitcode("mov","c,acc.0"); //<< get correct bit 
7534       emitcode("xch","a,%s", x); 
7535
7536       emitcode("rrc","a"); 
7537       emitcode("xch","a,%s", x); 
7538       emitcode("rrc","a"); 
7539       emitcode("xch","a,%s", x); 
7540 #endif
7541       break;
7542     case 7:                     // a:x <<= 7
7543
7544       emitcode ("anl", "a,#!constbyte",
7545                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7546
7547       emitcode ("mov", "c,acc.0");      // c = B
7548
7549       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7550
7551       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7552
7553       break;
7554     default:
7555       break;
7556     }
7557 }
7558 #endif
7559
7560 #ifdef BETTER_LITERAL_SHIFT
7561 //REMOVE ME!!!
7562 /*-----------------------------------------------------------------*/
7563 /* AccAXRsh - right shift a:x known count (0..7)                   */
7564 /*-----------------------------------------------------------------*/
7565 static void
7566 AccAXRsh (char *x, int shCount)
7567 {
7568   switch (shCount)
7569     {
7570     case 0:
7571       break;
7572     case 1:
7573       CLRC;
7574       AccAXRrl1 (x);            // 0->a:x
7575
7576       break;
7577     case 2:
7578       CLRC;
7579       AccAXRrl1 (x);            // 0->a:x
7580
7581       CLRC;
7582       AccAXRrl1 (x);            // 0->a:x
7583
7584       break;
7585     case 3:
7586     case 4:
7587     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7588
7589       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7590
7591       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7592
7593       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7594
7595       emitcode ("anl", "a,#!constbyte",
7596                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7597
7598       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7599
7600       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7601
7602       emitcode ("anl", "a,#!constbyte",
7603                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7604
7605       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7606
7607       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7608
7609       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7610
7611       break;
7612     case 6:                     // AABBBBBB:CCDDDDDD
7613
7614       emitcode ("mov", "c,acc.7");
7615       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7616
7617       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7618
7619       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7620
7621       emitcode ("anl", "a,#!constbyte",
7622                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7623
7624       break;
7625     case 7:                     // ABBBBBBB:CDDDDDDD
7626
7627       emitcode ("mov", "c,acc.7");      // c = A
7628
7629       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7630
7631       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7632
7633       emitcode ("anl", "a,#!constbyte",
7634                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7635
7636       break;
7637     default:
7638       break;
7639     }
7640 }
7641 #endif
7642
7643 #ifdef BETTER_LITERAL_SHIFT
7644 /*-----------------------------------------------------------------*/
7645 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7646 /*-----------------------------------------------------------------*/
7647 static void
7648 AccAXRshS (char *x, int shCount)
7649 {
7650   symbol *tlbl;
7651   switch (shCount)
7652     {
7653     case 0:
7654       break;
7655     case 1:
7656       emitcode ("mov", "c,acc.7");
7657       AccAXRrl1 (x);            // s->a:x
7658
7659       break;
7660     case 2:
7661       emitcode ("mov", "c,acc.7");
7662       AccAXRrl1 (x);            // s->a:x
7663
7664       emitcode ("mov", "c,acc.7");
7665       AccAXRrl1 (x);            // s->a:x
7666
7667       break;
7668     case 3:
7669     case 4:
7670     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7671
7672       tlbl = newiTempLabel (NULL);
7673       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7674
7675       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7676
7677       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7678
7679       emitcode ("anl", "a,#!constbyte",
7680                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7681
7682       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7683
7684       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7685
7686       emitcode ("anl", "a,#!constbyte",
7687                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7688
7689       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7690
7691       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7692
7693       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7694
7695       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7696       emitcode ("orl", "a,#!constbyte",
7697                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7698
7699       emitcode ("", "!tlabeldef", tlbl->key + 100);
7700       break;                    // SSSSAAAA:BBBCCCCC
7701
7702     case 6:                     // AABBBBBB:CCDDDDDD
7703
7704       tlbl = newiTempLabel (NULL);
7705       emitcode ("mov", "c,acc.7");
7706       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7707
7708       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7709
7710       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7711
7712       emitcode ("anl", "a,#!constbyte",
7713                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7714
7715       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7716       emitcode ("orl", "a,#!constbyte",
7717                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7718
7719       emitcode ("", "!tlabeldef", tlbl->key + 100);
7720       break;
7721     case 7:                     // ABBBBBBB:CDDDDDDD
7722
7723       tlbl = newiTempLabel (NULL);
7724       emitcode ("mov", "c,acc.7");      // c = A
7725
7726       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7727
7728       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7729
7730       emitcode ("anl", "a,#!constbyte",
7731                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7732
7733       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7734       emitcode ("orl", "a,#!constbyte",
7735                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7736
7737       emitcode ("", "!tlabeldef", tlbl->key + 100);
7738       break;
7739     default:
7740       break;
7741     }
7742 }
7743 #endif
7744
7745 #ifdef BETTER_LITERAL_SHIFT
7746 static void
7747 _loadLeftIntoAx(char    **lsb, 
7748                 operand *left, 
7749                 operand *result,
7750                 int     offl,
7751                 int     offr)
7752 {
7753   // Get the initial value from left into a pair of registers.
7754   // MSB must be in A, LSB can be any register.
7755   //
7756   // If the result is held in registers, it is an optimization
7757   // if the LSB can be held in the register which will hold the,
7758   // result LSB since this saves us from having to copy it into
7759   // the result following AccAXLsh.
7760   //
7761   // If the result is addressed indirectly, this is not a gain.
7762   if (AOP_NEEDSACC(result))
7763   {
7764        char *leftByte;
7765        
7766        _startLazyDPSEvaluation();
7767       if (AOP_TYPE(left) == AOP_DPTR2)
7768        {
7769            // Get MSB in A.
7770            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7771            // get LSB in DP2_RESULT_REG.
7772            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7773            assert(!strcmp(leftByte, DP2_RESULT_REG));
7774        }
7775        else
7776        {
7777            // get LSB into DP2_RESULT_REG
7778            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7779            if (strcmp(leftByte, DP2_RESULT_REG))
7780            {
7781                TR_AP("#7");
7782                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7783            }
7784            // And MSB in A.
7785            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7786            assert(strcmp(leftByte, DP2_RESULT_REG));
7787            MOVA(leftByte);
7788        }
7789        _endLazyDPSEvaluation();
7790        *lsb = DP2_RESULT_REG;
7791   }
7792   else
7793   {
7794       if (sameRegs (AOP (result), AOP (left)) &&
7795         ((offl + MSB16) == offr))
7796       {
7797           /* don't crash result[offr] */
7798           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7799           emitcode ("xch", "a,%s", 
7800                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7801       }
7802       else
7803       {
7804           movLeft2Result (left, offl, result, offr, 0);
7805           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7806       }
7807       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7808       assert(strcmp(*lsb,"a"));      
7809   }
7810 }
7811
7812 static void
7813 _storeAxResults(char    *lsb,
7814                 operand *result,
7815                 int     offr)
7816 {
7817   _startLazyDPSEvaluation();
7818   if (AOP_NEEDSACC(result))
7819   {
7820       /* We have to explicitly update the result LSB.
7821        */
7822       emitcode("xch","a,%s", lsb);
7823       aopPut(AOP(result), "a", offr);
7824       emitcode("mov","a,%s", lsb);
7825   }
7826   if (getDataSize (result) > 1)
7827   {
7828       aopPut (AOP (result), "a", offr + MSB16);
7829   }
7830   _endLazyDPSEvaluation();
7831 }
7832
7833 /*-----------------------------------------------------------------*/
7834 /* shiftL2Left2Result - shift left two bytes from left to result   */
7835 /*-----------------------------------------------------------------*/
7836 static void
7837 shiftL2Left2Result (operand * left, int offl,
7838                     operand * result, int offr, int shCount)
7839 {
7840   char *lsb;
7841
7842   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7843   
7844   AccAXLsh (lsb, shCount);
7845   
7846   _storeAxResults(lsb, result, offr);
7847 }
7848 #endif
7849
7850 #ifdef BETTER_LITERAL_SHIFT
7851 /*-----------------------------------------------------------------*/
7852 /* shiftR2Left2Result - shift right two bytes from left to result  */
7853 /*-----------------------------------------------------------------*/
7854 static void
7855 shiftR2Left2Result (operand * left, int offl,
7856                     operand * result, int offr,
7857                     int shCount, int sign)
7858 {
7859   char *lsb;
7860   
7861   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7862   
7863   /* a:x >> shCount (x = lsb(result)) */
7864   if (sign)
7865   {
7866      AccAXRshS(lsb, shCount);
7867   }
7868   else
7869   {
7870     AccAXRsh(lsb, shCount);
7871   }
7872   
7873   _storeAxResults(lsb, result, offr);
7874 }
7875 #endif
7876
7877 #if 0
7878 //REMOVE ME!!!
7879 /*-----------------------------------------------------------------*/
7880 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7881 /*-----------------------------------------------------------------*/
7882 static void
7883 shiftLLeftOrResult (operand * left, int offl,
7884                     operand * result, int offr, int shCount)
7885 {
7886   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7887   /* shift left accumulator */
7888   AccLsh (shCount);
7889   /* or with result */
7890   emitcode ("orl", "a,%s",
7891             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7892   /* back to result */
7893   aopPut (AOP (result), "a", offr);
7894 }
7895 #endif
7896
7897 #if 0
7898 //REMOVE ME!!!
7899 /*-----------------------------------------------------------------*/
7900 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7901 /*-----------------------------------------------------------------*/
7902 static void
7903 shiftRLeftOrResult (operand * left, int offl,
7904                     operand * result, int offr, int shCount)
7905 {
7906   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7907   /* shift right accumulator */
7908   AccRsh (shCount);
7909   /* or with result */
7910   emitcode ("orl", "a,%s",
7911             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7912   /* back to result */
7913   aopPut (AOP (result), "a", offr);
7914 }
7915 #endif
7916
7917 #ifdef BETTER_LITERAL_SHIFT
7918 /*-----------------------------------------------------------------*/
7919 /* genlshOne - left shift a one byte quantity by known count       */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genlshOne (operand * result, operand * left, int shCount)
7923 {
7924   D (emitcode (";", "genlshOne "););
7925   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7926 }
7927 #endif
7928
7929 #ifdef BETTER_LITERAL_SHIFT
7930 /*-----------------------------------------------------------------*/
7931 /* genlshTwo - left shift two bytes by known amount != 0           */
7932 /*-----------------------------------------------------------------*/
7933 static void
7934 genlshTwo (operand * result, operand * left, int shCount)
7935 {
7936   int size;
7937
7938   D (emitcode (";", "genlshTwo "););
7939
7940   size = getDataSize (result);
7941
7942   /* if shCount >= 8 */
7943   if (shCount >= 8)
7944   {
7945       shCount -= 8;
7946
7947       _startLazyDPSEvaluation();
7948
7949       if (size > 1)
7950         {
7951           if (shCount)
7952           {
7953             _endLazyDPSEvaluation();
7954             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7955             aopPut (AOP (result), zero, LSB);       
7956           }
7957           else
7958           {
7959             movLeft2Result (left, LSB, result, MSB16, 0);
7960             aopPut (AOP (result), zero, LSB);
7961             _endLazyDPSEvaluation();
7962           }
7963         }
7964         else
7965         {
7966           aopPut (AOP (result), zero, LSB);
7967           _endLazyDPSEvaluation();
7968         }
7969   }
7970
7971   /*  1 <= shCount <= 7 */
7972   else
7973     {
7974       if (size == 1)
7975       {
7976         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7977       }
7978       else
7979       {
7980         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7981       }
7982     }
7983 }
7984 #endif
7985
7986 #if 0
7987 //REMOVE ME!!!
7988 /*-----------------------------------------------------------------*/
7989 /* shiftLLong - shift left one long from left to result            */
7990 /* offl = LSB or MSB16                                             */
7991 /*-----------------------------------------------------------------*/
7992 static void
7993 shiftLLong (operand * left, operand * result, int offr)
7994 {
7995   char *l;
7996   int size = AOP_SIZE (result);
7997
7998   if (size >= LSB + offr)
7999     {
8000       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8001       MOVA (l);
8002       emitcode ("add", "a,acc");
8003       if (sameRegs (AOP (left), AOP (result)) &&
8004           size >= MSB16 + offr && offr != LSB)
8005         emitcode ("xch", "a,%s",
8006                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8007       else
8008         aopPut (AOP (result), "a", LSB + offr);
8009     }
8010
8011   if (size >= MSB16 + offr)
8012     {
8013       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8014         {
8015           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8016         }
8017       emitcode ("rlc", "a");
8018       if (sameRegs (AOP (left), AOP (result)) &&
8019           size >= MSB24 + offr && offr != LSB)
8020         emitcode ("xch", "a,%s",
8021                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8022       else
8023         aopPut (AOP (result), "a", MSB16 + offr);
8024     }
8025
8026   if (size >= MSB24 + offr)
8027     {
8028       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8029         {
8030           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8031         }
8032       emitcode ("rlc", "a");
8033       if (sameRegs (AOP (left), AOP (result)) &&
8034           size >= MSB32 + offr && offr != LSB)
8035         emitcode ("xch", "a,%s",
8036                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8037       else
8038         aopPut (AOP (result), "a", MSB24 + offr);
8039     }
8040
8041   if (size > MSB32 + offr)
8042     {
8043       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8044         {
8045           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8046         }
8047       emitcode ("rlc", "a");
8048       aopPut (AOP (result), "a", MSB32 + offr);
8049     }
8050   if (offr != LSB)
8051     aopPut (AOP (result), zero, LSB);
8052 }
8053 #endif
8054
8055 #if 0
8056 //REMOVE ME!!!
8057 /*-----------------------------------------------------------------*/
8058 /* genlshFour - shift four byte by a known amount != 0             */
8059 /*-----------------------------------------------------------------*/
8060 static void
8061 genlshFour (operand * result, operand * left, int shCount)
8062 {
8063   int size;
8064
8065   D (emitcode (";", "genlshFour ");
8066     );
8067
8068   size = AOP_SIZE (result);
8069
8070   /* if shifting more that 3 bytes */
8071   if (shCount >= 24)
8072     {
8073       shCount -= 24;
8074       if (shCount)
8075         /* lowest order of left goes to the highest
8076            order of the destination */
8077         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8078       else
8079         movLeft2Result (left, LSB, result, MSB32, 0);
8080       aopPut (AOP (result), zero, LSB);
8081       aopPut (AOP (result), zero, MSB16);
8082       aopPut (AOP (result), zero, MSB24);
8083       return;
8084     }
8085
8086   /* more than two bytes */
8087   else if (shCount >= 16)
8088     {
8089       /* lower order two bytes goes to higher order two bytes */
8090       shCount -= 16;
8091       /* if some more remaining */
8092       if (shCount)
8093         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8094       else
8095         {
8096           movLeft2Result (left, MSB16, result, MSB32, 0);
8097           movLeft2Result (left, LSB, result, MSB24, 0);
8098         }
8099       aopPut (AOP (result), zero, MSB16);
8100       aopPut (AOP (result), zero, LSB);
8101       return;
8102     }
8103
8104   /* if more than 1 byte */
8105   else if (shCount >= 8)
8106     {
8107       /* lower order three bytes goes to higher order  three bytes */
8108       shCount -= 8;
8109       if (size == 2)
8110         {
8111           if (shCount)
8112             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8113           else
8114             movLeft2Result (left, LSB, result, MSB16, 0);
8115         }
8116       else
8117         {                       /* size = 4 */
8118           if (shCount == 0)
8119             {
8120               movLeft2Result (left, MSB24, result, MSB32, 0);
8121               movLeft2Result (left, MSB16, result, MSB24, 0);
8122               movLeft2Result (left, LSB, result, MSB16, 0);
8123               aopPut (AOP (result), zero, LSB);
8124             }
8125           else if (shCount == 1)
8126             shiftLLong (left, result, MSB16);
8127           else
8128             {
8129               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8130               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8131               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8132               aopPut (AOP (result), zero, LSB);
8133             }
8134         }
8135     }
8136
8137   /* 1 <= shCount <= 7 */
8138   else if (shCount <= 2)
8139     {
8140       shiftLLong (left, result, LSB);
8141       if (shCount == 2)
8142         shiftLLong (result, result, LSB);
8143     }
8144   /* 3 <= shCount <= 7, optimize */
8145   else
8146     {
8147       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8148       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8149       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8150     }
8151 }
8152 #endif
8153
8154 #ifdef BETTER_LITERAL_SHIFT
8155 /*-----------------------------------------------------------------*/
8156 /* genLeftShiftLiteral - left shifting by known count              */
8157 /*-----------------------------------------------------------------*/
8158 static bool
8159 genLeftShiftLiteral (operand * left,
8160                      operand * right,
8161                      operand * result,
8162                      iCode * ic)
8163 {
8164   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8165   int size;
8166
8167   size = getSize (operandType (result));
8168
8169   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8170
8171   /* We only handle certain easy cases so far. */
8172   if ((shCount != 0)
8173    && (shCount < (size * 8))
8174    && (size != 1)
8175    && (size != 2))
8176   {
8177       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8178       return FALSE;
8179   }
8180
8181   freeAsmop (right, NULL, ic, TRUE);
8182
8183   aopOp(left, ic, FALSE, FALSE);
8184   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8185
8186 #if 0 // debug spew
8187   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8188   {
8189         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8190         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8191         {
8192            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8193         }
8194   }
8195   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8196   {
8197         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8198         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8199         {
8200            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8201         }       
8202   }  
8203 #endif
8204   
8205 #if VIEW_SIZE
8206   emitcode ("; shift left ", "result %d, left %d", size,
8207             AOP_SIZE (left));
8208 #endif
8209
8210   /* I suppose that the left size >= result size */
8211   if (shCount == 0)
8212   {
8213         _startLazyDPSEvaluation();
8214         while (size--)
8215         {
8216           movLeft2Result (left, size, result, size, 0);
8217         }
8218         _endLazyDPSEvaluation();
8219   }
8220   else if (shCount >= (size * 8))
8221   {
8222     _startLazyDPSEvaluation();
8223     while (size--)
8224     {
8225       aopPut (AOP (result), zero, size);
8226     }
8227     _endLazyDPSEvaluation();
8228   }
8229   else
8230   {
8231       switch (size)
8232         {
8233         case 1:
8234           genlshOne (result, left, shCount);
8235           break;
8236
8237         case 2:
8238           genlshTwo (result, left, shCount);
8239           break;
8240 #if 0
8241         case 4:
8242           genlshFour (result, left, shCount);
8243           break;
8244 #endif
8245         default:
8246           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8247           break;
8248         }
8249     }
8250   freeAsmop (left, NULL, ic, TRUE);
8251   freeAsmop (result, NULL, ic, TRUE);
8252   return TRUE;
8253 }
8254 #endif
8255
8256 /*-----------------------------------------------------------------*/
8257 /* genLeftShift - generates code for left shifting                 */
8258 /*-----------------------------------------------------------------*/
8259 static void
8260 genLeftShift (iCode * ic)
8261 {
8262   operand *left, *right, *result;
8263   int size, offset;
8264   char *l;
8265   symbol *tlbl, *tlbl1;
8266
8267   D (emitcode (";", "genLeftShift "););
8268
8269   right = IC_RIGHT (ic);
8270   left = IC_LEFT (ic);
8271   result = IC_RESULT (ic);
8272
8273   aopOp (right, ic, FALSE, FALSE);
8274
8275
8276 #ifdef BETTER_LITERAL_SHIFT
8277   /* if the shift count is known then do it
8278      as efficiently as possible */
8279   if (AOP_TYPE (right) == AOP_LIT)
8280     {
8281       if (genLeftShiftLiteral (left, right, result, ic))
8282       {
8283         return;
8284       }
8285     }
8286 #endif
8287
8288   /* shift count is unknown then we have to form
8289      a loop get the loop count in B : Note: we take
8290      only the lower order byte since shifting
8291      more that 32 bits make no sense anyway, ( the
8292      largest size of an object can be only 32 bits ) */
8293
8294   if (AOP_TYPE (right) == AOP_LIT)
8295   {
8296       /* Really should be handled by genLeftShiftLiteral,
8297        * but since I'm too lazy to fix that today, at least we can make
8298        * some small improvement.
8299        */
8300        emitcode("mov", "b,#!constbyte",
8301                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8302   }
8303   else
8304   {
8305       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8306       emitcode ("inc", "b");
8307   }
8308   freeAsmop (right, NULL, ic, TRUE);
8309   aopOp (left, ic, FALSE, FALSE);
8310   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8311
8312   /* now move the left to the result if they are not the
8313      same */
8314   if (!sameRegs (AOP (left), AOP (result)) &&
8315       AOP_SIZE (result) > 1)
8316     {
8317
8318       size = AOP_SIZE (result);
8319       offset = 0;
8320       _startLazyDPSEvaluation ();
8321       while (size--)
8322         {
8323           l = aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG);
8324           if (*l == '@' && (IS_AOP_PREG (result)))
8325             {
8326
8327               emitcode ("mov", "a,%s", l);
8328               aopPut (AOP (result), "a", offset);
8329             }
8330           else
8331             aopPut (AOP (result), l, offset);
8332           offset++;
8333         }
8334       _endLazyDPSEvaluation ();
8335     }
8336
8337   tlbl = newiTempLabel (NULL);
8338   size = AOP_SIZE (result);
8339   offset = 0;
8340   tlbl1 = newiTempLabel (NULL);
8341
8342   /* if it is only one byte then */
8343   if (size == 1)
8344     {
8345       symbol *tlbl1 = newiTempLabel (NULL);
8346
8347       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8348       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8349       emitcode ("", "!tlabeldef", tlbl->key + 100);
8350       emitcode ("add", "a,acc");
8351       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8352       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8353       aopPut (AOP (result), "a", 0);
8354       goto release;
8355     }
8356
8357   reAdjustPreg (AOP (result));
8358
8359   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8360   emitcode ("", "!tlabeldef", tlbl->key + 100);
8361   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8362   emitcode ("add", "a,acc");
8363   aopPut (AOP (result), "a", offset++);
8364   _startLazyDPSEvaluation ();
8365   while (--size)
8366     {
8367       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8368       emitcode ("rlc", "a");
8369       aopPut (AOP (result), "a", offset++);
8370     }
8371   _endLazyDPSEvaluation ();
8372   reAdjustPreg (AOP (result));
8373
8374   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8375   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8376 release:
8377   freeAsmop (left, NULL, ic, TRUE);
8378   freeAsmop (result, NULL, ic, TRUE);
8379 }
8380
8381 #ifdef BETTER_LITERAL_SHIFT
8382 /*-----------------------------------------------------------------*/
8383 /* genrshOne - right shift a one byte quantity by known count      */
8384 /*-----------------------------------------------------------------*/
8385 static void
8386 genrshOne (operand * result, operand * left,
8387            int shCount, int sign)
8388 {
8389   D (emitcode (";", "genrshOne"););
8390   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8391 }
8392 #endif
8393
8394 #ifdef BETTER_LITERAL_SHIFT
8395 /*-----------------------------------------------------------------*/
8396 /* genrshTwo - right shift two bytes by known amount != 0          */
8397 /*-----------------------------------------------------------------*/
8398 static void
8399 genrshTwo (operand * result, operand * left,
8400            int shCount, int sign)
8401 {
8402   D (emitcode (";", "genrshTwo"););
8403
8404   /* if shCount >= 8 */
8405   if (shCount >= 8)
8406     {
8407       shCount -= 8;
8408       _startLazyDPSEvaluation();
8409       if (shCount)
8410       {
8411         shiftR1Left2Result (left, MSB16, result, LSB,
8412                             shCount, sign);
8413       }                     
8414       else
8415       {
8416         movLeft2Result (left, MSB16, result, LSB, sign);
8417       }
8418       addSign (result, MSB16, sign);
8419       _endLazyDPSEvaluation();
8420     }
8421
8422   /*  1 <= shCount <= 7 */
8423   else
8424   {
8425     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8426   }
8427 }
8428 #endif
8429
8430 #if 0
8431 //REMOVE ME!!!
8432 /*-----------------------------------------------------------------*/
8433 /* shiftRLong - shift right one long from left to result           */
8434 /* offl = LSB or MSB16                                             */
8435 /*-----------------------------------------------------------------*/
8436 static void
8437 shiftRLong (operand * left, int offl,
8438             operand * result, int sign)
8439 {
8440   int isSameRegs=sameRegs(AOP(left),AOP(result));
8441
8442   if (isSameRegs && offl>1) {
8443     // we are in big trouble, but this shouldn't happen
8444     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8445   }
8446
8447   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8448   
8449   if (offl==MSB16) {
8450     // shift is > 8
8451     if (sign) {
8452       emitcode ("rlc", "a");
8453       emitcode ("subb", "a,acc");
8454       emitcode ("xch", "a,%s",
8455                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8456     } else {
8457       aopPut (AOP(result), zero, MSB32);
8458     }
8459   }
8460
8461   if (!sign) {
8462     emitcode ("clr", "c");
8463   } else {
8464     emitcode ("mov", "c,acc.7");
8465   }
8466
8467   emitcode ("rrc", "a");
8468
8469   if (isSameRegs && offl==MSB16) {
8470     emitcode ("xch",
8471               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8472   } else {
8473     aopPut (AOP (result), "a", MSB32);
8474     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8475   }
8476
8477   emitcode ("rrc", "a");
8478   if (isSameRegs && offl==1) {
8479     emitcode ("xch", "a,%s",
8480               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8481   } else {
8482     aopPut (AOP (result), "a", MSB24);
8483     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8484   }
8485   emitcode ("rrc", "a");
8486   aopPut (AOP (result), "a", MSB16 - offl);
8487
8488   if (offl == LSB)
8489     {
8490       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8491       emitcode ("rrc", "a");
8492       aopPut (AOP (result), "a", LSB);
8493     }
8494 }
8495 #endif
8496
8497 #if 0
8498 //REMOVE ME!!!
8499 /*-----------------------------------------------------------------*/
8500 /* genrshFour - shift four byte by a known amount != 0             */
8501 /*-----------------------------------------------------------------*/
8502 static void
8503 genrshFour (operand * result, operand * left,
8504             int shCount, int sign)
8505 {
8506   D (emitcode (";", "genrshFour");
8507     );
8508
8509   /* if shifting more that 3 bytes */
8510   if (shCount >= 24)
8511     {
8512       shCount -= 24;
8513       if (shCount)
8514         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8515       else
8516         movLeft2Result (left, MSB32, result, LSB, sign);
8517       addSign (result, MSB16, sign);
8518     }
8519   else if (shCount >= 16)
8520     {
8521       shCount -= 16;
8522       if (shCount)
8523         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8524       else
8525         {
8526           movLeft2Result (left, MSB24, result, LSB, 0);
8527           movLeft2Result (left, MSB32, result, MSB16, sign);
8528         }
8529       addSign (result, MSB24, sign);
8530     }
8531   else if (shCount >= 8)
8532     {
8533       shCount -= 8;
8534       if (shCount == 1)
8535         shiftRLong (left, MSB16, result, sign);
8536       else if (shCount == 0)
8537         {
8538           movLeft2Result (left, MSB16, result, LSB, 0);
8539           movLeft2Result (left, MSB24, result, MSB16, 0);
8540           movLeft2Result (left, MSB32, result, MSB24, sign);
8541           addSign (result, MSB32, sign);
8542         }
8543       else
8544         {
8545           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8546           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8547           /* the last shift is signed */
8548           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8549           addSign (result, MSB32, sign);
8550         }
8551     }
8552   else
8553     {                           /* 1 <= shCount <= 7 */
8554       if (shCount <= 2)
8555         {
8556           shiftRLong (left, LSB, result, sign);
8557           if (shCount == 2)
8558             shiftRLong (result, LSB, result, sign);
8559         }
8560       else
8561         {
8562           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8563           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8564           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8565         }
8566     }
8567 }
8568 #endif
8569
8570 #ifdef BETTER_LITERAL_SHIFT
8571 /*-----------------------------------------------------------------*/
8572 /* genRightShiftLiteral - right shifting by known count            */
8573 /*-----------------------------------------------------------------*/
8574 static bool
8575 genRightShiftLiteral (operand * left,
8576                       operand * right,
8577                       operand * result,
8578                       iCode * ic,
8579                       int sign)
8580 {
8581   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8582   int size;
8583
8584   size = getSize (operandType (result));
8585
8586   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8587
8588   /* We only handle certain easy cases so far. */
8589   if ((shCount != 0)
8590    && (shCount < (size * 8))
8591    && (size != 1)
8592    && (size != 2))
8593   {
8594       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8595       return FALSE;
8596   }
8597
8598   freeAsmop (right, NULL, ic, TRUE);
8599
8600   aopOp (left, ic, FALSE, FALSE);
8601   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8602
8603 #if VIEW_SIZE
8604   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8605             AOP_SIZE (left));
8606 #endif
8607
8608   /* test the LEFT size !!! */
8609
8610   /* I suppose that the left size >= result size */
8611   if (shCount == 0)
8612   {
8613       size = getDataSize (result);
8614       _startLazyDPSEvaluation();
8615       while (size--)
8616       {
8617         movLeft2Result (left, size, result, size, 0);
8618       }
8619       _endLazyDPSEvaluation();
8620   }
8621   else if (shCount >= (size * 8))
8622     {
8623       if (sign)
8624       {
8625         /* get sign in acc.7 */
8626         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8627       }
8628       addSign (result, LSB, sign);
8629     }
8630   else
8631     {
8632       switch (size)
8633         {
8634         case 1:
8635           genrshOne (result, left, shCount, sign);
8636           break;
8637
8638         case 2:
8639           genrshTwo (result, left, shCount, sign);
8640           break;
8641 #if 0
8642         case 4:
8643           genrshFour (result, left, shCount, sign);
8644           break;
8645 #endif    
8646         default:
8647           break;
8648         }
8649     }
8650   freeAsmop (left, NULL, ic, TRUE);
8651   freeAsmop (result, NULL, ic, TRUE);
8652   
8653   return TRUE;
8654 }
8655 #endif
8656
8657 /*-----------------------------------------------------------------*/
8658 /* genSignedRightShift - right shift of signed number              */
8659 /*-----------------------------------------------------------------*/
8660 static void
8661 genSignedRightShift (iCode * ic)
8662 {
8663   operand *right, *left, *result;
8664   int size, offset;
8665   char *l;
8666   symbol *tlbl, *tlbl1;
8667
8668   D (emitcode (";", "genSignedRightShift "););
8669
8670   /* we do it the hard way put the shift count in b
8671      and loop thru preserving the sign */
8672
8673   right = IC_RIGHT (ic);
8674   left = IC_LEFT (ic);
8675   result = IC_RESULT (ic);
8676
8677   aopOp (right, ic, FALSE, FALSE);
8678
8679 #ifdef BETTER_LITERAL_SHIFT
8680   if (AOP_TYPE (right) == AOP_LIT)
8681     {
8682       if (genRightShiftLiteral (left, right, result, ic, 1))
8683       {
8684         return;
8685       }
8686     }
8687 #endif
8688   /* shift count is unknown then we have to form
8689      a loop get the loop count in B : Note: we take
8690      only the lower order byte since shifting
8691      more that 32 bits make no sense anyway, ( the
8692      largest size of an object can be only 32 bits ) */
8693
8694   if (AOP_TYPE (right) == AOP_LIT)
8695   {
8696       /* Really should be handled by genRightShiftLiteral,
8697        * but since I'm too lazy to fix that today, at least we can make
8698        * some small improvement.
8699        */
8700        emitcode("mov", "b,#!constbyte",
8701                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8702   }
8703   else
8704   {
8705         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8706         emitcode ("inc", "b");
8707   }
8708   freeAsmop (right, NULL, ic, TRUE);
8709   aopOp (left, ic, FALSE, FALSE);
8710   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8711
8712   /* now move the left to the result if they are not the
8713      same */
8714   if (!sameRegs (AOP (left), AOP (result)) &&
8715       AOP_SIZE (result) > 1)
8716     {
8717
8718       size = AOP_SIZE (result);
8719       offset = 0;
8720       _startLazyDPSEvaluation ();
8721       while (size--)
8722         {
8723           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8724           if (*l == '@' && IS_AOP_PREG (result))
8725             {
8726
8727               emitcode ("mov", "a,%s", l);
8728               aopPut (AOP (result), "a", offset);
8729             }
8730           else
8731             aopPut (AOP (result), l, offset);
8732           offset++;
8733         }
8734       _endLazyDPSEvaluation ();
8735     }
8736
8737   /* mov the highest order bit to OVR */
8738   tlbl = newiTempLabel (NULL);
8739   tlbl1 = newiTempLabel (NULL);
8740
8741   size = AOP_SIZE (result);
8742   offset = size - 1;
8743   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8744   emitcode ("rlc", "a");
8745   emitcode ("mov", "ov,c");
8746   /* if it is only one byte then */
8747   if (size == 1)
8748     {
8749       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8750       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8751       emitcode ("", "!tlabeldef", tlbl->key + 100);
8752       emitcode ("mov", "c,ov");
8753       emitcode ("rrc", "a");
8754       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8755       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8756       aopPut (AOP (result), "a", 0);
8757       goto release;
8758     }
8759
8760   reAdjustPreg (AOP (result));
8761   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8762   emitcode ("", "!tlabeldef", tlbl->key + 100);
8763   emitcode ("mov", "c,ov");
8764   _startLazyDPSEvaluation ();
8765   while (size--)
8766     {
8767       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8768       emitcode ("rrc", "a");
8769       aopPut (AOP (result), "a", offset--);
8770     }
8771   _endLazyDPSEvaluation ();
8772   reAdjustPreg (AOP (result));
8773   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8774   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8775
8776 release:
8777   freeAsmop (left, NULL, ic, TRUE);
8778   freeAsmop (result, NULL, ic, TRUE);
8779 }
8780
8781 /*-----------------------------------------------------------------*/
8782 /* genRightShift - generate code for right shifting                */
8783 /*-----------------------------------------------------------------*/
8784 static void
8785 genRightShift (iCode * ic)
8786 {
8787   operand *right, *left, *result;
8788   sym_link *retype;
8789   int size, offset;
8790   char *l;
8791   symbol *tlbl, *tlbl1;
8792
8793   D (emitcode (";", "genRightShift "););
8794
8795   /* if signed then we do it the hard way preserve the
8796      sign bit moving it inwards */
8797   retype = getSpec (operandType (IC_RESULT (ic)));
8798
8799   if (!SPEC_USIGN (retype))
8800     {
8801       genSignedRightShift (ic);
8802       return;
8803     }
8804
8805   /* signed & unsigned types are treated the same : i.e. the
8806      signed is NOT propagated inwards : quoting from the
8807      ANSI - standard : "for E1 >> E2, is equivalent to division
8808      by 2**E2 if unsigned or if it has a non-negative value,
8809      otherwise the result is implementation defined ", MY definition
8810      is that the sign does not get propagated */
8811
8812   right = IC_RIGHT (ic);
8813   left = IC_LEFT (ic);
8814   result = IC_RESULT (ic);
8815
8816   aopOp (right, ic, FALSE, FALSE);
8817
8818 #ifdef BETTER_LITERAL_SHIFT
8819   /* if the shift count is known then do it
8820      as efficiently as possible */
8821   if (AOP_TYPE (right) == AOP_LIT)
8822     {
8823       if (genRightShiftLiteral (left, right, result, ic, 0))
8824       {
8825         return;
8826       }
8827     }
8828 #endif
8829
8830   /* shift count is unknown then we have to form
8831      a loop get the loop count in B : Note: we take
8832      only the lower order byte since shifting
8833      more that 32 bits make no sense anyway, ( the
8834      largest size of an object can be only 32 bits ) */
8835   
8836   if (AOP_TYPE (right) == AOP_LIT)
8837   {
8838       /* Really should be handled by genRightShiftLiteral,
8839        * but since I'm too lazy to fix that today, at least we can make
8840        * some small improvement.
8841        */
8842        emitcode("mov", "b,#!constbyte",
8843                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8844   }
8845   else
8846   {
8847       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8848       emitcode ("inc", "b");
8849   }
8850   freeAsmop (right, NULL, ic, TRUE);
8851   aopOp (left, ic, FALSE, FALSE);
8852   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8853
8854   /* now move the left to the result if they are not the
8855      same */
8856   if (!sameRegs (AOP (left), AOP (result)) &&
8857       AOP_SIZE (result) > 1)
8858     {
8859
8860       size = AOP_SIZE (result);
8861       offset = 0;
8862       _startLazyDPSEvaluation ();
8863       while (size--)
8864         {
8865           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8866           if (*l == '@' && IS_AOP_PREG (result))
8867             {
8868
8869               emitcode ("mov", "a,%s", l);
8870               aopPut (AOP (result), "a", offset);
8871             }
8872           else
8873             aopPut (AOP (result), l, offset);
8874           offset++;
8875         }
8876       _endLazyDPSEvaluation ();
8877     }
8878
8879   tlbl = newiTempLabel (NULL);
8880   tlbl1 = newiTempLabel (NULL);
8881   size = AOP_SIZE (result);
8882   offset = size - 1;
8883
8884   /* if it is only one byte then */
8885   if (size == 1)
8886     {
8887       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8888       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8889       emitcode ("", "!tlabeldef", tlbl->key + 100);
8890       CLRC;
8891       emitcode ("rrc", "a");
8892       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8893       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8894       aopPut (AOP (result), "a", 0);
8895       goto release;
8896     }
8897
8898   reAdjustPreg (AOP (result));
8899   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8900   emitcode ("", "!tlabeldef", tlbl->key + 100);
8901   CLRC;
8902   _startLazyDPSEvaluation ();
8903   while (size--)
8904     {
8905       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8906       emitcode ("rrc", "a");
8907       aopPut (AOP (result), "a", offset--);
8908     }
8909   _endLazyDPSEvaluation ();
8910   reAdjustPreg (AOP (result));
8911
8912   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8914
8915 release:
8916   freeAsmop (left, NULL, ic, TRUE);
8917   freeAsmop (result, NULL, ic, TRUE);
8918 }
8919
8920 /*-----------------------------------------------------------------*/
8921 /* genUnpackBits - generates code for unpacking bits               */
8922 /*-----------------------------------------------------------------*/
8923 static void
8924 genUnpackBits (operand * result, char *rname, int ptype)
8925 {
8926   int shCnt;
8927   int rlen;
8928   sym_link *etype;
8929   int offset = 0;
8930
8931   D (emitcode (";", "genUnpackBits "););
8932
8933   etype = getSpec (operandType (result));
8934
8935   /* read the first byte  */
8936   switch (ptype)
8937     {
8938
8939     case POINTER:
8940     case IPOINTER:
8941       emitcode ("mov", "a,@%s", rname);
8942       break;
8943
8944     case PPOINTER:
8945       emitcode ("movx", "a,@%s", rname);
8946       break;
8947
8948     case FPOINTER:
8949       emitcode ("movx", "a,@dptr");
8950       break;
8951
8952     case CPOINTER:
8953       emitcode ("clr", "a");
8954       emitcode ("movc", "a,@a+dptr");
8955       break;
8956
8957     case GPOINTER:
8958       emitcode ("lcall", "__gptrget");
8959       break;
8960     }
8961
8962   /* if we have bitdisplacement then it fits   */
8963   /* into this byte completely or if length is */
8964   /* less than a byte                          */
8965   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8966     {
8967
8968       /* shift right acc */
8969       AccRsh (shCnt);
8970
8971       emitcode ("anl", "a,#!constbyte",
8972                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8973       aopPut (AOP (result), "a", offset);
8974       return;
8975     }
8976
8977   /* bit field did not fit in a byte  */
8978   rlen = SPEC_BLEN (etype) - 8;
8979   aopPut (AOP (result), "a", offset++);
8980
8981   while (1)
8982     {
8983
8984       switch (ptype)
8985         {
8986         case POINTER:
8987         case IPOINTER:
8988           emitcode ("inc", "%s", rname);
8989           emitcode ("mov", "a,@%s", rname);
8990           break;
8991
8992         case PPOINTER:
8993           emitcode ("inc", "%s", rname);
8994           emitcode ("movx", "a,@%s", rname);
8995           break;
8996
8997         case FPOINTER:
8998           emitcode ("inc", "dptr");
8999           emitcode ("movx", "a,@dptr");
9000           break;
9001
9002         case CPOINTER:
9003           emitcode ("clr", "a");
9004           emitcode ("inc", "dptr");
9005           emitcode ("movc", "a,@a+dptr");
9006           break;
9007
9008         case GPOINTER:
9009           emitcode ("inc", "dptr");
9010           emitcode ("lcall", "__gptrget");
9011           break;
9012         }
9013
9014       rlen -= 8;
9015       /* if we are done */
9016       if (rlen < 8)
9017         break;
9018
9019       aopPut (AOP (result), "a", offset++);
9020
9021     }
9022
9023   if (rlen)
9024     {
9025       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9026       aopPut (AOP (result), "a", offset);
9027     }
9028
9029   return;
9030 }
9031
9032
9033 /*-----------------------------------------------------------------*/
9034 /* genDataPointerGet - generates code when ptr offset is known     */
9035 /*-----------------------------------------------------------------*/
9036 static void
9037 genDataPointerGet (operand * left,
9038                    operand * result,
9039                    iCode * ic)
9040 {
9041   char *l;
9042   char buff[256];
9043   int size, offset = 0;
9044   aopOp (result, ic, TRUE, FALSE);
9045
9046   /* get the string representation of the name */
9047   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9048   size = AOP_SIZE (result);
9049   _startLazyDPSEvaluation ();
9050   while (size--)
9051     {
9052         if (offset)
9053         {
9054             SNPRINTF (buff, sizeof(buff), 
9055                       "(%s + %d)", l + 1, offset);
9056         }
9057         else
9058         {
9059             SNPRINTF (buff, sizeof(buff), 
9060                       "%s", l + 1);
9061         }
9062       aopPut (AOP (result), buff, offset++);
9063     }
9064   _endLazyDPSEvaluation ();
9065
9066   freeAsmop (left, NULL, ic, TRUE);
9067   freeAsmop (result, NULL, ic, TRUE);
9068 }
9069
9070 /*-----------------------------------------------------------------*/
9071 /* genNearPointerGet - emitcode for near pointer fetch             */
9072 /*-----------------------------------------------------------------*/
9073 static void
9074 genNearPointerGet (operand * left,
9075                    operand * result,
9076                    iCode * ic,
9077                    iCode *pi)
9078 {
9079   asmop *aop = NULL;
9080   regs *preg;
9081   char *rname;
9082   sym_link *rtype, *retype, *letype;
9083   sym_link *ltype = operandType (left);
9084   char buff[80];
9085
9086   rtype = operandType (result);
9087   retype = getSpec (rtype);
9088   letype = getSpec (ltype);
9089
9090   aopOp (left, ic, FALSE, FALSE);
9091
9092   /* if left is rematerialisable and
9093      result is not bit variable type and
9094      the left is pointer to data space i.e
9095      lower 128 bytes of space */
9096   if (AOP_TYPE (left) == AOP_IMMD &&
9097       !IS_BITVAR (retype) &&
9098       !IS_BITVAR (letype) &&
9099       DCL_TYPE (ltype) == POINTER)
9100     {
9101       genDataPointerGet (left, result, ic);
9102       return;
9103     }
9104
9105   /* if the value is already in a pointer register
9106      then don't need anything more */
9107   if (!AOP_INPREG (AOP (left)))
9108     {
9109       /* otherwise get a free pointer register */
9110       aop = newAsmop (0);
9111       preg = getFreePtr (ic, &aop, FALSE);
9112       emitcode ("mov", "%s,%s",
9113                 preg->name,
9114                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9115       rname = preg->name;
9116     }
9117   else
9118     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9119
9120   freeAsmop (left, NULL, ic, TRUE);
9121   aopOp (result, ic, FALSE, FALSE);
9122
9123   /* if bitfield then unpack the bits */
9124   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9125     genUnpackBits (result, rname, POINTER);
9126   else
9127     {
9128       /* we have can just get the values */
9129       int size = AOP_SIZE (result);
9130       int offset = 0;
9131
9132       while (size--)
9133         {
9134           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9135             {
9136
9137               emitcode ("mov", "a,@%s", rname);
9138               aopPut (AOP (result), "a", offset);
9139             }
9140           else
9141             {
9142               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9143               aopPut (AOP (result), buff, offset);
9144             }
9145           offset++;
9146           if (size || pi)
9147             {
9148                 emitcode ("inc", "%s", rname);
9149             }
9150         }
9151     }
9152
9153   /* now some housekeeping stuff */
9154   if (aop)
9155     {
9156       /* we had to allocate for this iCode */
9157       if (pi) { /* post increment present */
9158         aopPut(AOP ( left ),rname,0);
9159       }
9160       freeAsmop (NULL, aop, ic, TRUE);
9161     }
9162   else
9163     {
9164       /* we did not allocate which means left
9165          already in a pointer register, then
9166          if size > 0 && this could be used again
9167          we have to point it back to where it
9168          belongs */
9169       if (AOP_SIZE (result) > 1 &&
9170           !OP_SYMBOL (left)->remat &&
9171           (OP_SYMBOL (left)->liveTo > ic->seq ||
9172            ic->depth) &&
9173           !pi)
9174         {
9175           int size = AOP_SIZE (result) - 1;
9176           while (size--)
9177             emitcode ("dec", "%s", rname);
9178         }
9179     }
9180
9181   /* done */
9182   freeAsmop (result, NULL, ic, TRUE);
9183   if (pi) pi->generated = 1;
9184 }
9185
9186 /*-----------------------------------------------------------------*/
9187 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9188 /*-----------------------------------------------------------------*/
9189 static void
9190 genPagedPointerGet (operand * left,
9191                     operand * result,
9192                     iCode * ic,
9193                     iCode * pi)
9194 {
9195   asmop *aop = NULL;
9196   regs *preg;
9197   char *rname;
9198   sym_link *rtype, *retype, *letype;
9199
9200   rtype = operandType (result);
9201   retype = getSpec (rtype);
9202   letype = getSpec (operandType (left));
9203   aopOp (left, ic, FALSE, FALSE);
9204
9205   /* if the value is already in a pointer register
9206      then don't need anything more */
9207   if (!AOP_INPREG (AOP (left)))
9208     {
9209       /* otherwise get a free pointer register */
9210       aop = newAsmop (0);
9211       preg = getFreePtr (ic, &aop, FALSE);
9212       emitcode ("mov", "%s,%s",
9213                 preg->name,
9214                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9215       rname = preg->name;
9216     }
9217   else
9218     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9219
9220   freeAsmop (left, NULL, ic, TRUE);
9221   aopOp (result, ic, FALSE, FALSE);
9222
9223   /* if bitfield then unpack the bits */
9224   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9225     genUnpackBits (result, rname, PPOINTER);
9226   else
9227     {
9228       /* we have can just get the values */
9229       int size = AOP_SIZE (result);
9230       int offset = 0;
9231
9232       while (size--)
9233         {
9234
9235           emitcode ("movx", "a,@%s", rname);
9236           aopPut (AOP (result), "a", offset);
9237
9238           offset++;
9239
9240           if (size || pi)
9241             emitcode ("inc", "%s", rname);
9242         }
9243     }
9244
9245   /* now some housekeeping stuff */
9246   if (aop)
9247     {
9248       /* we had to allocate for this iCode */
9249       if (pi) aopPut ( AOP (left), rname, 0);
9250       freeAsmop (NULL, aop, ic, TRUE);
9251     }
9252   else
9253     {
9254       /* we did not allocate which means left
9255          already in a pointer register, then
9256          if size > 0 && this could be used again
9257          we have to point it back to where it
9258          belongs */
9259       if (AOP_SIZE (result) > 1 &&
9260           !OP_SYMBOL (left)->remat &&
9261           (OP_SYMBOL (left)->liveTo > ic->seq ||
9262            ic->depth) &&
9263           !pi)
9264         {
9265           int size = AOP_SIZE (result) - 1;
9266           while (size--)
9267             emitcode ("dec", "%s", rname);
9268         }
9269     }
9270
9271   /* done */
9272   freeAsmop (result, NULL, ic, TRUE);
9273   if (pi) pi->generated = 1;
9274 }
9275
9276 /*-----------------------------------------------------------------*/
9277 /* genFarPointerGet - gget value from far space                    */
9278 /*-----------------------------------------------------------------*/
9279 static void
9280 genFarPointerGet (operand * left,
9281                   operand * result, iCode * ic, iCode *pi)
9282 {
9283     int size, offset, dopi=1;
9284   sym_link *retype = getSpec (operandType (result));
9285   sym_link *letype = getSpec (operandType (left));
9286   D (emitcode (";", "genFarPointerGet"););
9287
9288   aopOp (left, ic, FALSE, FALSE);
9289
9290   /* if the operand is already in dptr
9291      then we do nothing else we move the value to dptr */
9292   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9293     {
9294       /* if this is remateriazable */
9295       if (AOP_TYPE (left) == AOP_IMMD)
9296         {
9297           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9298         }
9299       else
9300         {
9301           /* we need to get it byte by byte */
9302           _startLazyDPSEvaluation ();
9303           if (AOP_TYPE (left) != AOP_DPTR)
9304             {
9305               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9306               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9307               if (options.model == MODEL_FLAT24)
9308                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9309             }
9310           else
9311             {
9312               /* We need to generate a load to DPTR indirect through DPTR. */
9313               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9314                 );
9315               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9316               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9317               if (options.model == MODEL_FLAT24)
9318                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9319               emitcode ("pop", "dph");
9320               emitcode ("pop", "dpl");
9321               dopi =0;
9322             }
9323           _endLazyDPSEvaluation ();
9324         }
9325     }
9326   /* so dptr know contains the address */
9327   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9328
9329   /* if bit then unpack */
9330   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9331       if (AOP_INDPTRn(left)) {
9332           genSetDPTR(AOP(left)->aopu.dptr);
9333       }
9334       genUnpackBits (result, "dptr", FPOINTER);
9335       if (AOP_INDPTRn(left)) {
9336           genSetDPTR(0);
9337       }
9338   } else
9339     {
9340       size = AOP_SIZE (result);
9341       offset = 0;
9342
9343       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9344           while (size--) {
9345               genSetDPTR(AOP(left)->aopu.dptr);
9346               emitcode ("movx", "a,@dptr");
9347               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9348                   emitcode ("inc", "dptr");
9349               genSetDPTR (0);
9350               aopPut (AOP (result), "a", offset++);
9351           }
9352       } else {
9353           _startLazyDPSEvaluation ();
9354           while (size--) {
9355               if (AOP_INDPTRn(left)) {
9356                   genSetDPTR(AOP(left)->aopu.dptr);
9357               } else {
9358                   genSetDPTR (0);
9359               }
9360               _flushLazyDPS ();
9361               
9362               emitcode ("movx", "a,@dptr");
9363               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9364                   emitcode ("inc", "dptr");
9365               
9366               aopPut (AOP (result), "a", offset++);
9367           }
9368           _endLazyDPSEvaluation ();
9369       }
9370     }
9371   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9372       if (!AOP_INDPTRn(left)) {
9373           aopPut ( AOP (left), "dpl", 0);
9374           aopPut ( AOP (left), "dph", 1);
9375           if (options.model == MODEL_FLAT24)
9376               aopPut ( AOP (left), "dpx", 2);
9377       }
9378     pi->generated = 1;
9379   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9380              AOP_SIZE(result) > 1 &&
9381              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9382       
9383       size = AOP_SIZE (result) - 1;
9384       if (AOP_INDPTRn(left)) {
9385           genSetDPTR(AOP(left)->aopu.dptr);
9386       }
9387       while (size--) emitcode ("lcall","__decdptr");
9388       if (AOP_INDPTRn(left)) {
9389           genSetDPTR(0);
9390       }
9391   }
9392
9393   freeAsmop (left, NULL, ic, TRUE);
9394   freeAsmop (result, NULL, ic, TRUE);
9395 }
9396
9397 /*-----------------------------------------------------------------*/
9398 /* genCodePointerGet - get value from code space                  */
9399 /*-----------------------------------------------------------------*/
9400 static void
9401 genCodePointerGet (operand * left,
9402                     operand * result, iCode * ic, iCode *pi)
9403 {
9404   int size, offset, dopi=1;
9405   sym_link *retype = getSpec (operandType (result));
9406
9407   aopOp (left, ic, FALSE, FALSE);
9408
9409   /* if the operand is already in dptr
9410      then we do nothing else we move the value to dptr */
9411   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9412     {
9413       /* if this is remateriazable */
9414       if (AOP_TYPE (left) == AOP_IMMD)
9415         {
9416           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9417         }
9418       else
9419         {                       /* we need to get it byte by byte */
9420           _startLazyDPSEvaluation ();
9421           if (AOP_TYPE (left) != AOP_DPTR)
9422             {
9423               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9424               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9425               if (options.model == MODEL_FLAT24)
9426                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9427             }
9428           else
9429             {
9430               /* We need to generate a load to DPTR indirect through DPTR. */
9431               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9432                 );
9433               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9434               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9435               if (options.model == MODEL_FLAT24)
9436                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9437               emitcode ("pop", "dph");
9438               emitcode ("pop", "dpl");
9439               dopi=0;
9440             }
9441           _endLazyDPSEvaluation ();
9442         }
9443     }
9444   /* so dptr know contains the address */
9445   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9446
9447   /* if bit then unpack */
9448   if (IS_BITVAR (retype)) {
9449       if (AOP_INDPTRn(left)) {
9450           genSetDPTR(AOP(left)->aopu.dptr);
9451       }
9452       genUnpackBits (result, "dptr", CPOINTER);
9453       if (AOP_INDPTRn(left)) {
9454           genSetDPTR(0);
9455       }
9456   } else
9457     {
9458       size = AOP_SIZE (result);
9459       offset = 0;
9460       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9461           while (size--) {
9462               genSetDPTR(AOP(left)->aopu.dptr);
9463               emitcode ("clr", "a");
9464               emitcode ("movc", "a,@a+dptr");
9465               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9466                   emitcode ("inc", "dptr");
9467               genSetDPTR (0);
9468               aopPut (AOP (result), "a", offset++);
9469           }
9470       } else {
9471           _startLazyDPSEvaluation ();
9472           while (size--)
9473               {
9474                   if (AOP_INDPTRn(left)) {
9475                       genSetDPTR(AOP(left)->aopu.dptr);
9476                   } else {
9477                       genSetDPTR (0);
9478                   }
9479                   _flushLazyDPS ();
9480                   
9481                   emitcode ("clr", "a");
9482                   emitcode ("movc", "a,@a+dptr");
9483                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9484                       emitcode ("inc", "dptr");
9485                   aopPut (AOP (result), "a", offset++);
9486               }
9487           _endLazyDPSEvaluation ();
9488       }
9489     }
9490   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9491       if (!AOP_INDPTRn(left)) {
9492           aopPut ( AOP (left), "dpl", 0);
9493           aopPut ( AOP (left), "dph", 1);
9494           if (options.model == MODEL_FLAT24)
9495               aopPut ( AOP (left), "dpx", 2);
9496       }
9497       pi->generated = 1;
9498   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9499              AOP_SIZE(result) > 1 &&
9500              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9501       
9502       size = AOP_SIZE (result) - 1;
9503       if (AOP_INDPTRn(left)) {
9504           genSetDPTR(AOP(left)->aopu.dptr);
9505       }
9506       while (size--) emitcode ("lcall","__decdptr");
9507       if (AOP_INDPTRn(left)) {
9508           genSetDPTR(0);
9509       }
9510   }
9511   
9512   freeAsmop (left, NULL, ic, TRUE);
9513   freeAsmop (result, NULL, ic, TRUE);
9514 }
9515
9516 /*-----------------------------------------------------------------*/
9517 /* genGenPointerGet - gget value from generic pointer space        */
9518 /*-----------------------------------------------------------------*/
9519 static void
9520 genGenPointerGet (operand * left,
9521                   operand * result, iCode * ic, iCode * pi)
9522 {
9523   int size, offset;
9524   sym_link *retype = getSpec (operandType (result));
9525   sym_link *letype = getSpec (operandType (left));
9526
9527   D (emitcode (";", "genGenPointerGet "); );
9528
9529   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9530
9531   /* if the operand is already in dptr
9532      then we do nothing else we move the value to dptr */
9533   if (AOP_TYPE (left) != AOP_STR)
9534     {
9535       /* if this is remateriazable */
9536       if (AOP_TYPE (left) == AOP_IMMD)
9537         {
9538           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9539           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9540             {
9541                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9542             }
9543             else
9544             {
9545                 emitcode ("mov", "b,#%d", pointerCode (retype));
9546             }
9547         }
9548       else
9549         {                       /* we need to get it byte by byte */
9550             _startLazyDPSEvaluation ();
9551             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9552             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9553             if (options.model == MODEL_FLAT24) {
9554                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9555                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9556             } else {
9557                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9558             }
9559             _endLazyDPSEvaluation ();
9560         }
9561     }
9562
9563   /* so dptr-b now contains the address */
9564   _G.bInUse++;
9565   aopOp (result, ic, FALSE, TRUE);
9566   _G.bInUse--;
9567
9568   /* if bit then unpack */
9569   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9570   {
9571     genUnpackBits (result, "dptr", GPOINTER);
9572   }
9573   else
9574     {
9575         size = AOP_SIZE (result);
9576         offset = 0;
9577
9578         while (size--)
9579         {
9580             if (size)
9581             {
9582                 // Get two bytes at a time, results in _AP & A.
9583                 // dptr will be incremented ONCE by __gptrgetWord.
9584                 //
9585                 // Note: any change here must be coordinated
9586                 // with the implementation of __gptrgetWord
9587                 // in device/lib/_gptrget.c
9588                 emitcode ("lcall", "__gptrgetWord");
9589                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9590                 aopPut (AOP (result), "a", offset++);
9591                 size--;
9592             }
9593             else
9594             {
9595                 // Only one byte to get.
9596                 emitcode ("lcall", "__gptrget");
9597                 aopPut (AOP (result), "a", offset++);
9598             }
9599             
9600             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9601             {
9602                 emitcode ("inc", "dptr");
9603             }
9604         }
9605     }
9606
9607   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9608     aopPut ( AOP (left), "dpl", 0);
9609     aopPut ( AOP (left), "dph", 1);
9610     if (options.model == MODEL_FLAT24) {
9611         aopPut ( AOP (left), "dpx", 2);
9612         aopPut ( AOP (left), "b", 3);   
9613     } else  aopPut ( AOP (left), "b", 2);       
9614     pi->generated = 1;
9615   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9616              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9617       
9618       size = AOP_SIZE (result) - 1;
9619       while (size--) emitcode ("lcall","__decdptr");
9620   }
9621
9622   freeAsmop (left, NULL, ic, TRUE);
9623   freeAsmop (result, NULL, ic, TRUE);
9624 }
9625
9626 /*-----------------------------------------------------------------*/
9627 /* genPointerGet - generate code for pointer get                   */
9628 /*-----------------------------------------------------------------*/
9629 static void
9630 genPointerGet (iCode * ic, iCode *pi)
9631 {
9632   operand *left, *result;
9633   sym_link *type, *etype;
9634   int p_type;
9635
9636   D (emitcode (";", "genPointerGet ");
9637     );
9638
9639   left = IC_LEFT (ic);
9640   result = IC_RESULT (ic);
9641
9642   /* depending on the type of pointer we need to
9643      move it to the correct pointer register */
9644   type = operandType (left);
9645   etype = getSpec (type);
9646   /* if left is of type of pointer then it is simple */
9647   if (IS_PTR (type) && !IS_FUNC (type->next))
9648     p_type = DCL_TYPE (type);
9649   else
9650     {
9651       /* we have to go by the storage class */
9652       p_type = PTR_TYPE (SPEC_OCLS (etype));
9653     }
9654   /* special case when cast remat */
9655   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9656       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9657           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9658           type = operandType (left);
9659           p_type = DCL_TYPE (type);
9660   }
9661   /* now that we have the pointer type we assign
9662      the pointer values */
9663   switch (p_type)
9664     {
9665
9666     case POINTER:
9667     case IPOINTER:
9668       genNearPointerGet (left, result, ic, pi);
9669       break;
9670
9671     case PPOINTER:
9672       genPagedPointerGet (left, result, ic, pi);
9673       break;
9674
9675     case FPOINTER:
9676       genFarPointerGet (left, result, ic, pi);
9677       break;
9678
9679     case CPOINTER:
9680       genCodePointerGet (left, result, ic, pi);
9681       break;
9682
9683     case GPOINTER:
9684       genGenPointerGet (left, result, ic, pi);
9685       break;
9686     }
9687
9688 }
9689
9690 /*-----------------------------------------------------------------*/
9691 /* genPackBits - generates code for packed bit storage             */
9692 /*-----------------------------------------------------------------*/
9693 static void
9694 genPackBits (sym_link * etype,
9695              operand * right,
9696              char *rname, int p_type)
9697 {
9698   int offset = 0;
9699   int rLen;
9700   int blen, bstr;
9701   char *l;
9702
9703   blen = SPEC_BLEN (etype);
9704   bstr = SPEC_BSTR (etype);
9705
9706   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9707
9708   /* if the bit lenth is less than or    */
9709   /* it exactly fits a byte then         */
9710   if (SPEC_BLEN (etype) <= 8)
9711     {
9712       /* shift left acc */
9713       AccLsh (SPEC_BSTR (etype));
9714
9715       if (SPEC_BLEN (etype) < 8)
9716         {                       /* if smaller than a byte */
9717
9718
9719           switch (p_type)
9720             {
9721             case POINTER:
9722               emitcode ("mov", "b,a");
9723               emitcode ("mov", "a,@%s", rname);
9724               break;
9725
9726             case FPOINTER:
9727               emitcode ("mov", "b,a");
9728               emitcode ("movx", "a,@dptr");
9729               break;
9730
9731             case GPOINTER:
9732               emitcode ("push", "b");
9733               emitcode ("push", "acc");
9734               emitcode ("lcall", "__gptrget");
9735               emitcode ("pop", "b");
9736               break;
9737             }
9738
9739           emitcode ("anl", "a,#!constbyte", (unsigned char)
9740                     ((unsigned char) (0xFF << (blen + bstr)) |
9741                      (unsigned char) (0xFF >> (8 - bstr))));
9742           emitcode ("orl", "a,b");
9743           if (p_type == GPOINTER)
9744             emitcode ("pop", "b");
9745         }
9746     }
9747
9748   switch (p_type)
9749     {
9750     case POINTER:
9751       emitcode ("mov", "@%s,a", rname);
9752       break;
9753
9754     case FPOINTER:
9755       emitcode ("movx", "@dptr,a");
9756       break;
9757
9758     case GPOINTER:
9759       emitcode ("lcall", "__gptrput");
9760       break;
9761     }
9762
9763   /* if we r done */
9764   if (SPEC_BLEN (etype) <= 8)
9765     return;
9766
9767   emitcode ("inc", "%s", rname);
9768   rLen = SPEC_BLEN (etype);
9769
9770   /* now generate for lengths greater than one byte */
9771   while (1)
9772     {
9773
9774       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9775
9776       rLen -= 8;
9777       if (rLen < 8)
9778         break;
9779
9780       switch (p_type)
9781         {
9782         case POINTER:
9783           if (*l == '@')
9784             {
9785               MOVA (l);
9786               emitcode ("mov", "@%s,a", rname);
9787             }
9788           else
9789             emitcode ("mov", "@%s,%s", rname, l);
9790           break;
9791
9792         case FPOINTER:
9793           MOVA (l);
9794           emitcode ("movx", "@dptr,a");
9795           break;
9796
9797         case GPOINTER:
9798           MOVA (l);
9799           emitcode ("lcall", "__gptrput");
9800           break;
9801         }
9802       emitcode ("inc", "%s", rname);
9803     }
9804
9805   MOVA (l);
9806
9807   /* last last was not complete */
9808   if (rLen)
9809     {
9810       /* save the byte & read byte */
9811       switch (p_type)
9812         {
9813         case POINTER:
9814           emitcode ("mov", "b,a");
9815           emitcode ("mov", "a,@%s", rname);
9816           break;
9817
9818         case FPOINTER:
9819           emitcode ("mov", "b,a");
9820           emitcode ("movx", "a,@dptr");
9821           break;
9822
9823         case GPOINTER:
9824           emitcode ("push", "b");
9825           emitcode ("push", "acc");
9826           emitcode ("lcall", "__gptrget");
9827           emitcode ("pop", "b");
9828           break;
9829         }
9830
9831       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9832       emitcode ("orl", "a,b");
9833     }
9834
9835   if (p_type == GPOINTER)
9836     emitcode ("pop", "b");
9837
9838   switch (p_type)
9839     {
9840
9841     case POINTER:
9842       emitcode ("mov", "@%s,a", rname);
9843       break;
9844
9845     case FPOINTER:
9846       emitcode ("movx", "@dptr,a");
9847       break;
9848
9849     case GPOINTER:
9850       emitcode ("lcall", "__gptrput");
9851       break;
9852     }
9853 }
9854 /*-----------------------------------------------------------------*/
9855 /* genDataPointerSet - remat pointer to data space                 */
9856 /*-----------------------------------------------------------------*/
9857 static void
9858 genDataPointerSet (operand * right,
9859                    operand * result,
9860                    iCode * ic)
9861 {
9862   int size, offset = 0;
9863   char *l, buff[256];
9864
9865   aopOp (right, ic, FALSE, FALSE);
9866
9867   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9868   size = AOP_SIZE (right);
9869   while (size--)
9870     {
9871       if (offset)
9872         {
9873             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9874         }
9875       else
9876         {
9877             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9878         }
9879         
9880       emitcode ("mov", "%s,%s", buff,
9881                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9882     }
9883
9884   freeAsmop (right, NULL, ic, TRUE);
9885   freeAsmop (result, NULL, ic, TRUE);
9886 }
9887
9888 /*-----------------------------------------------------------------*/
9889 /* genNearPointerSet - emitcode for near pointer put                */
9890 /*-----------------------------------------------------------------*/
9891 static void
9892 genNearPointerSet (operand * right,
9893                    operand * result,
9894                    iCode * ic,
9895                    iCode * pi)
9896 {
9897   asmop *aop = NULL;
9898   char *rname, *l;
9899   sym_link *retype, *letype;
9900   sym_link *ptype = operandType (result);
9901
9902   retype = getSpec (operandType (right));
9903   letype = getSpec (ptype);
9904
9905   aopOp (result, ic, FALSE, FALSE);
9906
9907   /* if the result is rematerializable &
9908      in data space & not a bit variable */
9909   if (AOP_TYPE (result) == AOP_IMMD &&
9910       DCL_TYPE (ptype) == POINTER &&
9911       !IS_BITVAR (retype) &&
9912       !IS_BITVAR (letype))
9913     {
9914       genDataPointerSet (right, result, ic);
9915       return;
9916     }
9917
9918   /* if the value is already in a pointer register
9919      then don't need anything more */
9920   if (!AOP_INPREG (AOP (result)))
9921     {
9922       /* otherwise get a free pointer register */
9923       regs *preg;
9924         
9925       aop = newAsmop (0);
9926       preg = getFreePtr (ic, &aop, FALSE);
9927       emitcode ("mov", "%s,%s",
9928                 preg->name,
9929                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9930       rname = preg->name;
9931     }
9932   else
9933     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9934
9935   aopOp (right, ic, FALSE, FALSE);
9936
9937   /* if bitfield then unpack the bits */
9938   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9939     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9940   else
9941     {
9942       /* we have can just get the values */
9943       int size = AOP_SIZE (right);
9944       int offset = 0;
9945
9946       while (size--)
9947         {
9948           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9949           if (*l == '@')
9950             {
9951               MOVA (l);
9952               emitcode ("mov", "@%s,a", rname);
9953             }
9954           else
9955             emitcode ("mov", "@%s,%s", rname, l);
9956           if (size || pi)
9957             emitcode ("inc", "%s", rname);
9958           offset++;
9959         }
9960     }
9961
9962   /* now some housekeeping stuff */
9963   if (aop)
9964     {
9965       /* we had to allocate for this iCode */
9966       if (pi) aopPut (AOP (result),rname,0);
9967       freeAsmop (NULL, aop, ic, TRUE);
9968     }
9969   else
9970     {
9971       /* we did not allocate which means left
9972          already in a pointer register, then
9973          if size > 0 && this could be used again
9974          we have to point it back to where it
9975          belongs */
9976       if (AOP_SIZE (right) > 1 &&
9977           !OP_SYMBOL (result)->remat &&
9978           (OP_SYMBOL (result)->liveTo > ic->seq ||
9979            ic->depth) &&
9980           !pi)
9981         {
9982           int size = AOP_SIZE (right) - 1;
9983           while (size--)
9984             emitcode ("dec", "%s", rname);
9985         }
9986     }
9987
9988   /* done */
9989   if (pi) pi->generated = 1;
9990   freeAsmop (result, NULL, ic, TRUE);
9991   freeAsmop (right, NULL, ic, TRUE);
9992
9993
9994 }
9995
9996 /*-----------------------------------------------------------------*/
9997 /* genPagedPointerSet - emitcode for Paged pointer put             */
9998 /*-----------------------------------------------------------------*/
9999 static void
10000 genPagedPointerSet (operand * right,
10001                     operand * result,
10002                     iCode * ic,
10003                     iCode *pi)
10004 {
10005   asmop *aop = NULL;
10006   char *rname;
10007   sym_link *retype, *letype;
10008
10009   retype = getSpec (operandType (right));
10010   letype = getSpec (operandType (result));
10011
10012   aopOp (result, ic, FALSE, FALSE);
10013
10014   /* if the value is already in a pointer register
10015      then don't need anything more */
10016   if (!AOP_INPREG (AOP (result)))
10017     {
10018       /* otherwise get a free pointer register */
10019       regs *preg;
10020         
10021       aop = newAsmop (0);
10022       preg = getFreePtr (ic, &aop, FALSE);
10023       emitcode ("mov", "%s,%s",
10024                 preg->name,
10025                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10026       rname = preg->name;
10027     }
10028   else
10029     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10030
10031   aopOp (right, ic, FALSE, FALSE);
10032
10033   /* if bitfield then unpack the bits */
10034   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10035     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10036   else
10037     {
10038       /* we have can just get the values */
10039       int size = AOP_SIZE (right);
10040       int offset = 0;
10041
10042       while (size--)
10043         {
10044           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10045
10046           emitcode ("movx", "@%s,a", rname);
10047
10048           if (size || pi)
10049             emitcode ("inc", "%s", rname);
10050
10051           offset++;
10052         }
10053     }
10054
10055   /* now some housekeeping stuff */
10056   if (aop)
10057     {
10058       if (pi) aopPut (AOP (result),rname,0);
10059       /* we had to allocate for this iCode */
10060       freeAsmop (NULL, aop, ic, TRUE);
10061     }
10062   else
10063     {
10064       /* we did not allocate which means left
10065          already in a pointer register, then
10066          if size > 0 && this could be used again
10067          we have to point it back to where it
10068          belongs */
10069       if (AOP_SIZE (right) > 1 &&
10070           !OP_SYMBOL (result)->remat &&
10071           (OP_SYMBOL (result)->liveTo > ic->seq ||
10072            ic->depth) &&
10073           !pi)
10074         {
10075           int size = AOP_SIZE (right) - 1;
10076           while (size--)
10077             emitcode ("dec", "%s", rname);
10078         }
10079     }
10080
10081   /* done */
10082   if (pi) pi->generated = 1;
10083   freeAsmop (result, NULL, ic, TRUE);
10084   freeAsmop (right, NULL, ic, TRUE);
10085
10086
10087 }
10088
10089 /*-----------------------------------------------------------------*/
10090 /* genFarPointerSet - set value from far space                     */
10091 /*-----------------------------------------------------------------*/
10092 static void
10093 genFarPointerSet (operand * right,
10094                   operand * result, iCode * ic, iCode *pi)
10095 {
10096   int size, offset, dopi=1;
10097   sym_link *retype = getSpec (operandType (right));
10098   sym_link *letype = getSpec (operandType (result));
10099
10100   aopOp (result, ic, FALSE, FALSE);
10101
10102   /* if the operand is already in dptr
10103      then we do nothing else we move the value to dptr */
10104   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10105     {
10106       /* if this is remateriazable */
10107       if (AOP_TYPE (result) == AOP_IMMD)
10108         emitcode ("mov", "dptr,%s", 
10109                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10110       else
10111         {
10112           /* we need to get it byte by byte */
10113           _startLazyDPSEvaluation ();
10114           if (AOP_TYPE (result) != AOP_DPTR)
10115             {
10116               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10117               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10118               if (options.model == MODEL_FLAT24)
10119                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10120             }
10121           else
10122             {
10123               /* We need to generate a load to DPTR indirect through DPTR. */
10124               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10125                 
10126               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10127               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10128               if (options.model == MODEL_FLAT24)
10129                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10130               emitcode ("pop", "dph");
10131               emitcode ("pop", "dpl");
10132               dopi=0;
10133             }
10134           _endLazyDPSEvaluation ();
10135         }
10136     }
10137   /* so dptr know contains the address */
10138   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10139
10140   /* if bit then unpack */
10141   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10142       if (AOP_INDPTRn(result)) {
10143           genSetDPTR(AOP(result)->aopu.dptr);
10144       }
10145       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10146       if (AOP_INDPTRn(result)) {
10147           genSetDPTR(0);
10148       }
10149   } else {
10150       size = AOP_SIZE (right);
10151       offset = 0;
10152       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10153           while (size--) {
10154               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10155               
10156               genSetDPTR(AOP(result)->aopu.dptr);
10157               emitcode ("movx", "@dptr,a");
10158               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10159                   emitcode ("inc", "dptr");
10160               genSetDPTR (0);
10161           }
10162       } else {
10163           _startLazyDPSEvaluation ();
10164           while (size--) {
10165               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10166               
10167               if (AOP_INDPTRn(result)) {
10168                   genSetDPTR(AOP(result)->aopu.dptr);
10169               } else {
10170                   genSetDPTR (0);
10171               }
10172               _flushLazyDPS ();
10173               
10174               emitcode ("movx", "@dptr,a");
10175               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10176                   emitcode ("inc", "dptr");
10177           }
10178           _endLazyDPSEvaluation ();
10179       }
10180   }
10181   
10182   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10183       if (!AOP_INDPTRn(result)) {
10184           aopPut (AOP(result),"dpl",0);
10185           aopPut (AOP(result),"dph",1);
10186           if (options.model == MODEL_FLAT24)
10187               aopPut (AOP(result),"dpx",2);
10188       }
10189       pi->generated=1;
10190   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10191              AOP_SIZE(right) > 1 &&
10192              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10193       
10194       size = AOP_SIZE (right) - 1;
10195       if (AOP_INDPTRn(result)) {
10196           genSetDPTR(AOP(result)->aopu.dptr);
10197       } 
10198       while (size--) emitcode ("lcall","__decdptr");
10199       if (AOP_INDPTRn(result)) {
10200           genSetDPTR(0);
10201       }
10202   }
10203   freeAsmop (result, NULL, ic, TRUE);
10204   freeAsmop (right, NULL, ic, TRUE);
10205 }
10206
10207 /*-----------------------------------------------------------------*/
10208 /* genGenPointerSet - set value from generic pointer space         */
10209 /*-----------------------------------------------------------------*/
10210 static void
10211 genGenPointerSet (operand * right,
10212                   operand * result, iCode * ic, iCode *pi)
10213 {
10214   int size, offset;
10215   sym_link *retype = getSpec (operandType (right));
10216   sym_link *letype = getSpec (operandType (result));
10217
10218   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10219
10220   /* if the operand is already in dptr
10221      then we do nothing else we move the value to dptr */
10222   if (AOP_TYPE (result) != AOP_STR)
10223     {
10224       _startLazyDPSEvaluation ();
10225       /* if this is remateriazable */
10226       if (AOP_TYPE (result) == AOP_IMMD)
10227         {
10228           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10229           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10230           {
10231               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10232           }
10233           else
10234           {
10235               emitcode ("mov", 
10236                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10237           }
10238         }
10239       else
10240         {                       /* we need to get it byte by byte */
10241           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10242           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10243           if (options.model == MODEL_FLAT24) {
10244             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10245             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10246           } else {
10247             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10248           }
10249         }
10250       _endLazyDPSEvaluation ();
10251     }
10252   /* so dptr know contains the address */
10253   aopOp (right, ic, FALSE, TRUE);
10254
10255   /* if bit then unpack */
10256   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10257     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10258   else
10259     {
10260       size = AOP_SIZE (right);
10261       offset = 0;
10262
10263       _startLazyDPSEvaluation ();
10264       while (size--)
10265         {
10266           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10267
10268           genSetDPTR (0);
10269           _flushLazyDPS ();
10270
10271           emitcode ("lcall", "__gptrput");
10272           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10273             emitcode ("inc", "dptr");
10274         }
10275       _endLazyDPSEvaluation ();
10276     }
10277
10278   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10279       aopPut (AOP(result),"dpl",0);
10280       aopPut (AOP(result),"dph",1);
10281       if (options.model == MODEL_FLAT24) {
10282           aopPut (AOP(result),"dpx",2);
10283           aopPut (AOP(result),"b",3);
10284       } else {
10285           aopPut (AOP(result),"b",2);
10286       }
10287       pi->generated=1;
10288   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10289              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10290       
10291       size = AOP_SIZE (right) - 1;
10292       while (size--) emitcode ("lcall","__decdptr");
10293   }
10294   freeAsmop (result, NULL, ic, TRUE);
10295   freeAsmop (right, NULL, ic, TRUE);
10296 }
10297
10298 /*-----------------------------------------------------------------*/
10299 /* genPointerSet - stores the value into a pointer location        */
10300 /*-----------------------------------------------------------------*/
10301 static void
10302 genPointerSet (iCode * ic, iCode *pi)
10303 {
10304   operand *right, *result;
10305   sym_link *type, *etype;
10306   int p_type;
10307
10308   D (emitcode (";", "genPointerSet "););
10309
10310   right = IC_RIGHT (ic);
10311   result = IC_RESULT (ic);
10312
10313   /* depending on the type of pointer we need to
10314      move it to the correct pointer register */
10315   type = operandType (result);
10316   etype = getSpec (type);
10317   /* if left is of type of pointer then it is simple */
10318   if (IS_PTR (type) && !IS_FUNC (type->next))
10319     {
10320       p_type = DCL_TYPE (type);
10321     }
10322   else
10323     {
10324       /* we have to go by the storage class */
10325       p_type = PTR_TYPE (SPEC_OCLS (etype));
10326     }
10327   /* special case when cast remat */
10328   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10329       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10330           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10331           type = operandType (result);
10332           p_type = DCL_TYPE (type);
10333   }
10334
10335   /* now that we have the pointer type we assign
10336      the pointer values */
10337   switch (p_type)
10338     {
10339
10340     case POINTER:
10341     case IPOINTER:
10342       genNearPointerSet (right, result, ic, pi);
10343       break;
10344
10345     case PPOINTER:
10346       genPagedPointerSet (right, result, ic, pi);
10347       break;
10348
10349     case FPOINTER:
10350       genFarPointerSet (right, result, ic, pi);
10351       break;
10352
10353     case GPOINTER:
10354       genGenPointerSet (right, result, ic, pi);
10355       break;
10356
10357     default:
10358       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10359               "genPointerSet: illegal pointer type");
10360     }
10361
10362 }
10363
10364 /*-----------------------------------------------------------------*/
10365 /* genIfx - generate code for Ifx statement                        */
10366 /*-----------------------------------------------------------------*/
10367 static void
10368 genIfx (iCode * ic, iCode * popIc)
10369 {
10370   operand *cond = IC_COND (ic);
10371   int isbit = 0;
10372
10373   D (emitcode (";", "genIfx "););
10374
10375   aopOp (cond, ic, FALSE, FALSE);
10376
10377   /* get the value into acc */
10378   if (AOP_TYPE (cond) != AOP_CRY)
10379     {
10380         toBoolean (cond);
10381     }
10382   else
10383     {
10384         isbit = 1;
10385     }
10386     
10387   /* the result is now in the accumulator */
10388   freeAsmop (cond, NULL, ic, TRUE);
10389
10390   /* if there was something to be popped then do it */
10391   if (popIc)
10392     genIpop (popIc);
10393
10394   /* if the condition is  a bit variable */
10395   if (isbit && IS_ITEMP (cond) &&
10396       SPIL_LOC (cond))
10397     {
10398         genIfxJump (ic, SPIL_LOC (cond)->rname);
10399     }
10400   else if (isbit && !IS_ITEMP (cond))
10401     {
10402         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10403     }
10404   else
10405     {
10406         genIfxJump (ic, "a");
10407     }
10408
10409   ic->generated = 1;
10410 }
10411
10412 /*-----------------------------------------------------------------*/
10413 /* genAddrOf - generates code for address of                       */
10414 /*-----------------------------------------------------------------*/
10415 static void
10416 genAddrOf (iCode * ic)
10417 {
10418   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10419   int size, offset;
10420
10421   D (emitcode (";", "genAddrOf ");
10422     );
10423
10424   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10425
10426   /* if the operand is on the stack then we
10427      need to get the stack offset of this
10428      variable */
10429   if (sym->onStack) {
10430       
10431       /* if 10 bit stack */
10432       if (options.stack10bit) {
10433           char buff[10];
10434           tsprintf(buff, sizeof(buff), 
10435                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10436           /* if it has an offset then we need to compute it */
10437 /*        emitcode ("subb", "a,#!constbyte", */
10438 /*                  -((sym->stack < 0) ? */
10439 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10440 /*                    ((short) sym->stack)) & 0xff); */
10441 /*        emitcode ("mov","b,a"); */
10442 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10443 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10444 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10445           if (sym->stack) {
10446               emitcode ("mov", "a,_bpx");
10447               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10448                                              ((char) (sym->stack - _G.nRegsSaved)) :
10449                                              ((char) sym->stack )) & 0xff);
10450               emitcode ("mov", "b,a");
10451               emitcode ("mov", "a,_bpx+1");
10452               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10453                                               ((short) (sym->stack - _G.nRegsSaved)) :
10454                                               ((short) sym->stack )) >> 8) & 0xff);
10455               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10456               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10457               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10458           } else {
10459               /* we can just move _bp */
10460               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10461               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10462               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10463           }       
10464       } else {
10465           /* if it has an offset then we need to compute it */
10466           if (sym->stack) {
10467               emitcode ("mov", "a,_bp");
10468               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10469               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10470           } else {
10471               /* we can just move _bp */
10472               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10473           }
10474           /* fill the result with zero */
10475           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10476           
10477           
10478           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10479               fprintf (stderr,
10480                        "*** warning: pointer to stack var truncated.\n");
10481           }
10482
10483           offset = 1;
10484           while (size--) {
10485               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10486           }      
10487       }
10488       goto release;
10489   }
10490
10491   /* object not on stack then we need the name */
10492   size = AOP_SIZE (IC_RESULT (ic));
10493   offset = 0;
10494
10495   while (size--)
10496     {
10497       char s[SDCC_NAME_MAX];
10498       if (offset) {
10499           switch (offset) {
10500           case 1:
10501               tsprintf(s, sizeof(s), "!his",sym->rname);
10502               break;
10503           case 2:
10504               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10505               break;
10506           case 3:
10507               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10508               break;
10509           default: /* should not need this (just in case) */
10510               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10511                        sym->rname,
10512                        offset * 8);
10513           }
10514       } 
10515       else
10516       {
10517           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10518       }
10519         
10520       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10521     }
10522
10523 release:
10524   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10525
10526 }
10527
10528 /*-----------------------------------------------------------------*/
10529 /* genArrayInit - generates code for address of                       */
10530 /*-----------------------------------------------------------------*/
10531 static void
10532 genArrayInit (iCode * ic)
10533 {
10534     literalList *iLoop;
10535     int         ix, count;
10536     int         elementSize = 0, eIndex;
10537     unsigned    val, lastVal;
10538     sym_link    *type;
10539     operand     *left=IC_LEFT(ic);
10540     
10541     D (emitcode (";", "genArrayInit "););
10542
10543     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10544     
10545     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10546     {
10547         // Load immediate value into DPTR.
10548         emitcode("mov", "dptr, %s",
10549              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10550     }
10551     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10552     {
10553 #if 0
10554       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10555               "Unexpected operand to genArrayInit.\n");
10556       exit(1);
10557 #else
10558       // a regression because of SDCCcse.c:1.52
10559       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10560       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10561       if (options.model == MODEL_FLAT24)
10562         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10563 #endif
10564     }
10565     
10566     type = operandType(IC_LEFT(ic));
10567     
10568     if (type && type->next)
10569     {
10570         elementSize = getSize(type->next);
10571     }
10572     else
10573     {
10574         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10575                                 "can't determine element size in genArrayInit.\n");
10576         exit(1);
10577     }
10578     
10579     iLoop = IC_ARRAYILIST(ic);
10580     lastVal = 0xffff;
10581     
10582     while (iLoop)
10583     {
10584         bool firstpass = TRUE;
10585         
10586         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10587                  iLoop->count, (int)iLoop->literalValue, elementSize);
10588         
10589         ix = iLoop->count;
10590         
10591         while (ix)
10592         {
10593             symbol *tlbl = NULL;
10594             
10595             count = ix > 256 ? 256 : ix;
10596             
10597             if (count > 1)
10598             {
10599                 tlbl = newiTempLabel (NULL);
10600                 if (firstpass || (count & 0xff))
10601                 {
10602                     emitcode("mov", "b, #!constbyte", count & 0xff);
10603                 }
10604                 
10605                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10606             }
10607             
10608             firstpass = FALSE;
10609                 
10610             for (eIndex = 0; eIndex < elementSize; eIndex++)
10611             {
10612                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10613                 if (val != lastVal)
10614                 {
10615                     emitcode("mov", "a, #!constbyte", val);
10616                     lastVal = val;
10617                 }
10618                 
10619                 emitcode("movx", "@dptr, a");
10620                 emitcode("inc", "dptr");
10621             }
10622             
10623             if (count > 1)
10624             {
10625                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10626             }
10627             
10628             ix -= count;
10629         }
10630         
10631         iLoop = iLoop->next;
10632     }
10633     
10634     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10635 }
10636
10637 /*-----------------------------------------------------------------*/
10638 /* genFarFarAssign - assignment when both are in far space         */
10639 /*-----------------------------------------------------------------*/
10640 static void
10641 genFarFarAssign (operand * result, operand * right, iCode * ic)
10642 {
10643   int size = AOP_SIZE (right);
10644   int offset = 0;
10645   symbol *rSym = NULL;
10646
10647   if (size == 1)
10648   {
10649       /* quick & easy case. */
10650       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10651       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10652       freeAsmop (right, NULL, ic, FALSE);
10653       /* now assign DPTR to result */
10654       _G.accInUse++;
10655       aopOp(result, ic, FALSE, FALSE);
10656       _G.accInUse--;
10657       aopPut(AOP(result), "a", 0);
10658       freeAsmop(result, NULL, ic, FALSE);
10659       return;
10660   }
10661   
10662   /* See if we've got an underlying symbol to abuse. */
10663   if (IS_SYMOP(result) && OP_SYMBOL(result))
10664   {
10665       if (IS_TRUE_SYMOP(result))
10666       {
10667           rSym = OP_SYMBOL(result);
10668       }
10669       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10670       {
10671           rSym = OP_SYMBOL(result)->usl.spillLoc;
10672       }
10673   }
10674              
10675   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10676   {
10677       /* We can use the '390 auto-toggle feature to good effect here. */
10678       
10679       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10680       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10681       emitcode ("mov", "dptr,#%s", rSym->rname); 
10682       /* DP2 = result, DP1 = right, DP1 is current. */
10683       while (size)
10684       {
10685           emitcode("movx", "a,@dptr");
10686           emitcode("movx", "@dptr,a");
10687           if (--size)
10688           {
10689                emitcode("inc", "dptr");
10690                emitcode("inc", "dptr");
10691           }
10692       }
10693       emitcode("mov", "dps,#0");
10694       freeAsmop (right, NULL, ic, FALSE);
10695 #if 0
10696 some alternative code for processors without auto-toggle
10697 no time to test now, so later well put in...kpb
10698         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10699         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10700         emitcode ("mov", "dptr,#%s", rSym->rname); 
10701         /* DP2 = result, DP1 = right, DP1 is current. */
10702         while (size)
10703         {
10704           --size;
10705           emitcode("movx", "a,@dptr");
10706           if (size)
10707             emitcode("inc", "dptr");
10708           emitcode("inc", "dps");
10709           emitcode("movx", "@dptr,a");
10710           if (size)
10711             emitcode("inc", "dptr");
10712           emitcode("inc", "dps");
10713         }
10714         emitcode("mov", "dps,#0");
10715         freeAsmop (right, NULL, ic, FALSE);
10716 #endif
10717   }
10718   else
10719   {
10720       D (emitcode (";", "genFarFarAssign"););
10721       aopOp (result, ic, TRUE, TRUE);
10722
10723       _startLazyDPSEvaluation ();
10724       
10725       while (size--)
10726         {
10727           aopPut (AOP (result),
10728                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10729           offset++;
10730         }
10731       _endLazyDPSEvaluation ();
10732       freeAsmop (result, NULL, ic, FALSE);
10733       freeAsmop (right, NULL, ic, FALSE);
10734   }
10735 }
10736
10737 /*-----------------------------------------------------------------*/
10738 /* genAssign - generate code for assignment                        */
10739 /*-----------------------------------------------------------------*/
10740 static void
10741 genAssign (iCode * ic)
10742 {
10743   operand *result, *right;
10744   int size, offset;
10745   unsigned long lit = 0L;
10746
10747   D (emitcode (";", "genAssign ");
10748     );
10749
10750   result = IC_RESULT (ic);
10751   right = IC_RIGHT (ic);
10752
10753   /* if they are the same */
10754   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10755     return;
10756
10757   aopOp (right, ic, FALSE, FALSE);
10758
10759   emitcode (";", "genAssign: resultIsFar = %s",
10760             isOperandInFarSpace (result) ?
10761             "TRUE" : "FALSE");
10762
10763   /* special case both in far space */
10764   if ((AOP_TYPE (right) == AOP_DPTR ||
10765        AOP_TYPE (right) == AOP_DPTR2) &&
10766   /* IS_TRUE_SYMOP(result)       && */
10767       isOperandInFarSpace (result))
10768     {
10769       genFarFarAssign (result, right, ic);
10770       return;
10771     }
10772
10773   aopOp (result, ic, TRUE, FALSE);
10774
10775   /* if they are the same registers */
10776   if (sameRegs (AOP (right), AOP (result)))
10777     goto release;
10778
10779   /* if the result is a bit */
10780   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10781     {
10782       /* if the right size is a literal then
10783          we know what the value is */
10784       if (AOP_TYPE (right) == AOP_LIT)
10785         {
10786           if (((int) operandLitValue (right)))
10787             aopPut (AOP (result), one, 0);
10788           else
10789             aopPut (AOP (result), zero, 0);
10790           goto release;
10791         }
10792
10793       /* the right is also a bit variable */
10794       if (AOP_TYPE (right) == AOP_CRY)
10795         {
10796           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10797           aopPut (AOP (result), "c", 0);
10798           goto release;
10799         }
10800
10801       /* we need to or */
10802       toBoolean (right);
10803       aopPut (AOP (result), "a", 0);
10804       goto release;
10805     }
10806
10807   /* bit variables done */
10808   /* general case */
10809   size = AOP_SIZE (result);
10810   offset = 0;
10811   if (AOP_TYPE (right) == AOP_LIT)
10812     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10813
10814   if ((size > 1) &&
10815       (AOP_TYPE (result) != AOP_REG) &&
10816       (AOP_TYPE (right) == AOP_LIT) &&
10817       !IS_FLOAT (operandType (right)))
10818     {
10819       _startLazyDPSEvaluation ();
10820       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10821         {
10822           aopPut (AOP (result),
10823                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10824                   offset);
10825           offset++;
10826           size--;
10827         }
10828       /* And now fill the rest with zeros. */
10829       if (size)
10830         {
10831           emitcode ("clr", "a");
10832         }
10833       while (size--)
10834         {
10835           aopPut (AOP (result), "a", offset++);
10836         }
10837       _endLazyDPSEvaluation ();
10838     }
10839   else
10840     {
10841       _startLazyDPSEvaluation ();
10842       while (size--)
10843         {
10844           aopPut (AOP (result),
10845                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10846                   offset);
10847           offset++;
10848         }
10849       _endLazyDPSEvaluation ();
10850     }
10851
10852 release:
10853   freeAsmop (right, NULL, ic, FALSE);
10854   freeAsmop (result, NULL, ic, TRUE);
10855 }
10856
10857 /*-----------------------------------------------------------------*/
10858 /* genJumpTab - generates code for jump table                      */
10859 /*-----------------------------------------------------------------*/
10860 static void
10861 genJumpTab (iCode * ic)
10862 {
10863   symbol *jtab;
10864   char *l;
10865
10866   D (emitcode (";", "genJumpTab ");
10867     );
10868
10869   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10870   /* get the condition into accumulator */
10871   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10872   MOVA (l);
10873   /* multiply by four! */
10874   emitcode ("add", "a,acc");
10875   emitcode ("add", "a,acc");
10876   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10877
10878   jtab = newiTempLabel (NULL);
10879   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10880   emitcode ("jmp", "@a+dptr");
10881   emitcode ("", "!tlabeldef", jtab->key + 100);
10882   /* now generate the jump labels */
10883   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10884        jtab = setNextItem (IC_JTLABELS (ic)))
10885     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10886
10887 }
10888
10889 /*-----------------------------------------------------------------*/
10890 /* genCast - gen code for casting                                  */
10891 /*-----------------------------------------------------------------*/
10892 static void
10893 genCast (iCode * ic)
10894 {
10895   operand *result = IC_RESULT (ic);
10896   sym_link *ctype = operandType (IC_LEFT (ic));
10897   sym_link *rtype = operandType (IC_RIGHT (ic));
10898   operand *right = IC_RIGHT (ic);
10899   int size, offset;
10900
10901   D (emitcode (";", "genCast "););
10902
10903   /* if they are equivalent then do nothing */
10904   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10905     return;
10906
10907   aopOp (right, ic, FALSE, FALSE);
10908   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10909
10910   /* if the result is a bit */
10911   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10912   if (IS_BITVAR(OP_SYMBOL(result)->type))
10913     {
10914       /* if the right size is a literal then
10915          we know what the value is */
10916       if (AOP_TYPE (right) == AOP_LIT)
10917         {
10918           if (((int) operandLitValue (right)))
10919             aopPut (AOP (result), one, 0);
10920           else
10921             aopPut (AOP (result), zero, 0);
10922
10923           goto release;
10924         }
10925
10926       /* the right is also a bit variable */
10927       if (AOP_TYPE (right) == AOP_CRY)
10928         {
10929           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10930           aopPut (AOP (result), "c", 0);
10931           goto release;
10932         }
10933
10934       /* we need to or */
10935       toBoolean (right);
10936       aopPut (AOP (result), "a", 0);
10937       goto release;
10938     }
10939
10940   /* if they are the same size : or less */
10941   if (AOP_SIZE (result) <= AOP_SIZE (right))
10942     {
10943
10944       /* if they are in the same place */
10945       if (sameRegs (AOP (right), AOP (result)))
10946         goto release;
10947
10948       /* if they in different places then copy */
10949       size = AOP_SIZE (result);
10950       offset = 0;
10951       _startLazyDPSEvaluation ();
10952       while (size--)
10953         {
10954           aopPut (AOP (result),
10955                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10956                   offset);
10957           offset++;
10958         }
10959       _endLazyDPSEvaluation ();
10960       goto release;
10961     }
10962
10963
10964   /* if the result is of type pointer */
10965   if (IS_PTR (ctype))
10966     {
10967
10968       int p_type;
10969       sym_link *type = operandType (right);
10970
10971       /* pointer to generic pointer */
10972       if (IS_GENPTR (ctype))
10973         {
10974           if (IS_PTR (type))
10975             {
10976               p_type = DCL_TYPE (type);
10977             }
10978           else
10979             {
10980 #if OLD_CAST_BEHAVIOR
10981               /* KV: we are converting a non-pointer type to
10982                * a generic pointer. This (ifdef'd out) code
10983                * says that the resulting generic pointer
10984                * should have the same class as the storage
10985                * location of the non-pointer variable.
10986                *
10987                * For example, converting an int (which happens
10988                * to be stored in DATA space) to a pointer results
10989                * in a DATA generic pointer; if the original int
10990                * in XDATA space, so will be the resulting pointer.
10991                *
10992                * I don't like that behavior, and thus this change:
10993                * all such conversions will be forced to XDATA and
10994                * throw a warning. If you want some non-XDATA
10995                * type, or you want to suppress the warning, you
10996                * must go through an intermediate cast, like so:
10997                *
10998                * char _generic *gp = (char _xdata *)(intVar);
10999                */
11000               sym_link *etype = getSpec (type);
11001
11002               /* we have to go by the storage class */
11003               if (SPEC_OCLS (etype) != generic)
11004                 {
11005                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11006                 }
11007               else
11008 #endif
11009                 {
11010                   /* Converting unknown class (i.e. register variable)
11011                    * to generic pointer. This is not good, but
11012                    * we'll make a guess (and throw a warning).
11013                    */
11014                   p_type = FPOINTER;
11015                   werror (W_INT_TO_GEN_PTR_CAST);
11016                 }
11017             }
11018
11019           /* the first two bytes are known */
11020           size = GPTRSIZE - 1;
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
11032           /* the last byte depending on type */
11033             {
11034                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11035                 char gpValStr[10];
11036             
11037                 if (gpVal == -1)
11038                 {
11039                     // pointerTypeToGPByte will have bitched.
11040                     exit(1);
11041                 }
11042             
11043                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11044                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11045             }
11046           goto release;
11047         }
11048
11049       /* just copy the pointers */
11050       size = AOP_SIZE (result);
11051       offset = 0;
11052       _startLazyDPSEvaluation ();
11053       while (size--)
11054         {
11055           aopPut (AOP (result),
11056                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11057                   offset);
11058           offset++;
11059         }
11060       _endLazyDPSEvaluation ();
11061       goto release;
11062     }
11063
11064   /* so we now know that the size of destination is greater
11065      than the size of the source */
11066   /* we move to result for the size of source */
11067   size = AOP_SIZE (right);
11068   offset = 0;
11069   _startLazyDPSEvaluation ();
11070   while (size--)
11071     {
11072       aopPut (AOP (result),
11073               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11074               offset);
11075       offset++;
11076     }
11077   _endLazyDPSEvaluation ();
11078
11079   /* now depending on the sign of the source && destination */
11080   size = AOP_SIZE (result) - AOP_SIZE (right);
11081   /* if unsigned or not an integral type */
11082   /* also, if the source is a bit, we don't need to sign extend, because
11083    * it can't possibly have set the sign bit.
11084    */
11085   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11086     {
11087       while (size--)
11088         {
11089           aopPut (AOP (result), zero, offset++);
11090         }
11091     }
11092   else
11093     {
11094       /* we need to extend the sign :{ */
11095       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11096                         FALSE, FALSE, NULL));
11097       emitcode ("rlc", "a");
11098       emitcode ("subb", "a,acc");
11099       while (size--)
11100         aopPut (AOP (result), "a", offset++);
11101     }
11102
11103   /* we are done hurray !!!! */
11104
11105 release:
11106   freeAsmop (right, NULL, ic, TRUE);
11107   freeAsmop (result, NULL, ic, TRUE);
11108
11109 }
11110
11111 /*-----------------------------------------------------------------*/
11112 /* genDjnz - generate decrement & jump if not zero instrucion      */
11113 /*-----------------------------------------------------------------*/
11114 static int
11115 genDjnz (iCode * ic, iCode * ifx)
11116 {
11117   symbol *lbl, *lbl1;
11118   if (!ifx)
11119     return 0;
11120
11121   /* if the if condition has a false label
11122      then we cannot save */
11123   if (IC_FALSE (ifx))
11124     return 0;
11125
11126   /* if the minus is not of the form
11127      a = a - 1 */
11128   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11129       !IS_OP_LITERAL (IC_RIGHT (ic)))
11130     return 0;
11131
11132   if (operandLitValue (IC_RIGHT (ic)) != 1)
11133     return 0;
11134
11135   /* if the size of this greater than one then no
11136      saving */
11137   if (getSize (operandType (IC_RESULT (ic))) > 1)
11138     return 0;
11139
11140   /* otherwise we can save BIG */
11141   D(emitcode(";", "genDjnz"););
11142
11143   lbl = newiTempLabel (NULL);
11144   lbl1 = newiTempLabel (NULL);
11145
11146   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11147
11148   if (AOP_NEEDSACC(IC_RESULT(ic)))
11149   {
11150       /* If the result is accessed indirectly via
11151        * the accumulator, we must explicitly write
11152        * it back after the decrement.
11153        */
11154       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11155       
11156       if (strcmp(rByte, "a"))
11157       {
11158            /* Something is hopelessly wrong */
11159            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11160                    __FILE__, __LINE__);
11161            /* We can just give up; the generated code will be inefficient,
11162             * but what the hey.
11163             */
11164            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11165            return 0;
11166       }
11167       emitcode ("dec", "%s", rByte);
11168       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11169       emitcode ("jnz", "!tlabel", lbl->key + 100);
11170   }
11171   else if (IS_AOP_PREG (IC_RESULT (ic)))
11172     {
11173       emitcode ("dec", "%s",
11174                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11175       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11176       emitcode ("jnz", "!tlabel", lbl->key + 100);
11177     }
11178   else
11179     {
11180       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11181                 lbl->key + 100);
11182     }
11183   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11184   emitcode ("", "!tlabeldef", lbl->key + 100);
11185   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11186   emitcode ("", "!tlabeldef", lbl1->key + 100);
11187
11188   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11189   ifx->generated = 1;
11190   return 1;
11191 }
11192
11193 /*-----------------------------------------------------------------*/
11194 /* genReceive - generate code for a receive iCode                  */
11195 /*-----------------------------------------------------------------*/
11196 static void
11197 genReceive (iCode * ic)
11198 {
11199
11200     int size = getSize (operandType (IC_RESULT (ic)));
11201     int offset = 0;
11202     int rb1off ;
11203     
11204     D (emitcode (";", "genReceive ");
11205        );
11206
11207   if (ic->argreg == 1) { /* first parameter */
11208       if (isOperandInFarSpace (IC_RESULT (ic)) &&
11209           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11210            IS_TRUE_SYMOP (IC_RESULT (ic))))
11211           {
11212               offset = fReturnSizeDS390 - size;
11213               while (size--)
11214                   {
11215                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11216                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11217                       offset++;
11218                   }
11219               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11220               size = AOP_SIZE (IC_RESULT (ic));
11221               offset = 0;
11222               while (size--)
11223                   {
11224                       emitcode ("pop", "acc");
11225                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11226                   }
11227               
11228           } else {
11229               _G.accInUse++;
11230               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11231               _G.accInUse--;
11232               assignResultValue (IC_RESULT (ic));
11233           }
11234   } else { /* second receive onwards */
11235       /* this gets a little tricky since unused recevies will be
11236          eliminated, we have saved the reg in the type field . and
11237          we use that to figure out which register to use */
11238       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11239       rb1off = ic->argreg;
11240       while (size--) {
11241           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11242       }
11243       
11244   }
11245   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11250 /*-----------------------------------------------------------------*/
11251 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11252 {
11253     operand *from , *to , *count;
11254     symbol *lbl;
11255     bitVect *rsave;
11256     int i;
11257
11258     /* we know it has to be 3 parameters */
11259     assert (nparms == 3);
11260     
11261     rsave = newBitVect(16);
11262     /* save DPTR if it needs to be saved */
11263     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11264             if (bitVectBitValue(ic->rMask,i))
11265                     rsave = bitVectSetBit(rsave,i);
11266     }
11267     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11268                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11269     savermask(rsave);
11270     
11271     to = parms[0];
11272     from = parms[1];
11273     count = parms[2];
11274
11275     aopOp (from, ic->next, FALSE, FALSE);
11276
11277     /* get from into DPTR1 */
11278     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11279     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11280     if (options.model == MODEL_FLAT24) {
11281         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11282     }
11283
11284     freeAsmop (from, NULL, ic, FALSE);
11285     aopOp (to, ic, FALSE, FALSE);
11286     /* get "to" into DPTR */
11287     /* if the operand is already in dptr
11288        then we do nothing else we move the value to dptr */
11289     if (AOP_TYPE (to) != AOP_STR) {
11290         /* if already in DPTR then we need to push */
11291         if (AOP_TYPE(to) == AOP_DPTR) {
11292             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11293             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11294             if (options.model == MODEL_FLAT24)
11295                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11296             emitcode ("pop", "dph");
11297             emitcode ("pop", "dpl");        
11298         } else {
11299             _startLazyDPSEvaluation ();
11300             /* if this is remateriazable */
11301             if (AOP_TYPE (to) == AOP_IMMD) {
11302                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11303             } else {                    /* we need to get it byte by byte */
11304                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11305                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11306                 if (options.model == MODEL_FLAT24) {
11307                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11308                 }
11309             }
11310             _endLazyDPSEvaluation ();
11311         }
11312     }
11313     freeAsmop (to, NULL, ic, FALSE);
11314     _G.dptrInUse = _G.dptr1InUse = 1;
11315     aopOp (count, ic->next->next, FALSE,FALSE);
11316     lbl =newiTempLabel(NULL);
11317
11318     /* now for the actual copy */
11319     if (AOP_TYPE(count) == AOP_LIT && 
11320         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11321         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11322         if (fromc) {
11323             emitcode ("lcall","__bi_memcpyc2x_s");
11324         } else {
11325             emitcode ("lcall","__bi_memcpyx2x_s");
11326         }
11327         freeAsmop (count, NULL, ic, FALSE);
11328     } else {
11329         symbol *lbl1 = newiTempLabel(NULL);
11330         
11331         emitcode (";"," Auto increment but no djnz");
11332         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11333         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11334         freeAsmop (count, NULL, ic, FALSE);
11335         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11336         emitcode ("","!tlabeldef",lbl->key+100);
11337         if (fromc) {
11338             emitcode ("clr","a");
11339             emitcode ("movc", "a,@a+dptr");
11340         } else 
11341             emitcode ("movx", "a,@dptr");
11342         emitcode ("movx", "@dptr,a");
11343         emitcode ("inc", "dptr");
11344         emitcode ("inc", "dptr");
11345         emitcode ("mov","a,b");
11346         emitcode ("orl","a,_ap");
11347         emitcode ("jz","!tlabel",lbl1->key+100);
11348         emitcode ("mov","a,_ap");
11349         emitcode ("add","a,#!constbyte",0xFF);
11350         emitcode ("mov","_ap,a");
11351         emitcode ("mov","a,b");
11352         emitcode ("addc","a,#!constbyte",0xFF);
11353         emitcode ("mov","b,a");
11354         emitcode ("sjmp","!tlabel",lbl->key+100);
11355         emitcode ("","!tlabeldef",lbl1->key+100);
11356     }
11357     emitcode ("mov", "dps,#0"); 
11358     _G.dptrInUse = _G.dptr1InUse = 0;
11359     unsavermask(rsave);
11360
11361 }
11362
11363 /*-----------------------------------------------------------------*/
11364 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11365 /*-----------------------------------------------------------------*/
11366 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11367 {
11368     operand *from , *to , *count;
11369     symbol *lbl,*lbl2;
11370     bitVect *rsave;
11371     int i;
11372
11373     /* we know it has to be 3 parameters */
11374     assert (nparms == 3);
11375     
11376     rsave = newBitVect(16);
11377     /* save DPTR if it needs to be saved */
11378     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11379             if (bitVectBitValue(ic->rMask,i))
11380                     rsave = bitVectSetBit(rsave,i);
11381     }
11382     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11383                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11384     savermask(rsave);
11385     
11386     to = parms[0];
11387     from = parms[1];
11388     count = parms[2];
11389
11390     aopOp (from, ic->next, FALSE, FALSE);
11391
11392     /* get from into DPTR1 */
11393     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11394     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11395     if (options.model == MODEL_FLAT24) {
11396         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11397     }
11398
11399     freeAsmop (from, NULL, ic, FALSE);
11400     aopOp (to, ic, FALSE, FALSE);
11401     /* get "to" into DPTR */
11402     /* if the operand is already in dptr
11403        then we do nothing else we move the value to dptr */
11404     if (AOP_TYPE (to) != AOP_STR) {
11405         /* if already in DPTR then we need to push */
11406         if (AOP_TYPE(to) == AOP_DPTR) {
11407             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11408             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11409             if (options.model == MODEL_FLAT24)
11410                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11411             emitcode ("pop", "dph");
11412             emitcode ("pop", "dpl");        
11413         } else {
11414             _startLazyDPSEvaluation ();
11415             /* if this is remateriazable */
11416             if (AOP_TYPE (to) == AOP_IMMD) {
11417                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11418             } else {                    /* we need to get it byte by byte */
11419                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11420                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11421                 if (options.model == MODEL_FLAT24) {
11422                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11423                 }
11424             }
11425             _endLazyDPSEvaluation ();
11426         }
11427     }
11428     freeAsmop (to, NULL, ic, FALSE);
11429     _G.dptrInUse = _G.dptr1InUse = 1;
11430     aopOp (count, ic->next->next, FALSE,FALSE);
11431     lbl =newiTempLabel(NULL);
11432     lbl2 =newiTempLabel(NULL);
11433
11434     /* now for the actual compare */
11435     if (AOP_TYPE(count) == AOP_LIT && 
11436         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11437         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11438         if (fromc)
11439             emitcode("lcall","__bi_memcmpc2x_s");
11440         else
11441             emitcode("lcall","__bi_memcmpx2x_s");
11442         freeAsmop (count, NULL, ic, FALSE);
11443         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11444         aopPut(AOP(IC_RESULT(ic)),"a",0);
11445         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11446     } else {
11447         symbol *lbl1 = newiTempLabel(NULL);
11448
11449         emitcode("push","ar0");         
11450         emitcode (";"," Auto increment but no djnz");
11451         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11452         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11453         freeAsmop (count, NULL, ic, FALSE);
11454         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11455         emitcode ("","!tlabeldef",lbl->key+100);
11456         if (fromc) {
11457             emitcode ("clr","a");
11458             emitcode ("movc", "a,@a+dptr");
11459         } else 
11460             emitcode ("movx", "a,@dptr");
11461         emitcode ("mov","r0,a");
11462         emitcode ("movx", "a,@dptr");
11463         emitcode ("clr","c");
11464         emitcode ("subb","a,r0");
11465         emitcode ("jnz","!tlabel",lbl2->key+100);
11466         emitcode ("inc", "dptr");
11467         emitcode ("inc", "dptr");
11468         emitcode ("mov","a,b");
11469         emitcode ("orl","a,_ap");
11470         emitcode ("jz","!tlabel",lbl1->key+100);
11471         emitcode ("mov","a,_ap");
11472         emitcode ("add","a,#!constbyte",0xFF);
11473         emitcode ("mov","_ap,a");
11474         emitcode ("mov","a,b");
11475         emitcode ("addc","a,#!constbyte",0xFF);
11476         emitcode ("mov","b,a");
11477         emitcode ("sjmp","!tlabel",lbl->key+100);
11478         emitcode ("","!tlabeldef",lbl1->key+100);
11479         emitcode ("clr","a");
11480         emitcode ("","!tlabeldef",lbl2->key+100);
11481         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11482         aopPut(AOP(IC_RESULT(ic)),"a",0);
11483         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11484         emitcode("pop","ar0");
11485         emitcode ("mov", "dps,#0");      
11486     }
11487     _G.dptrInUse = _G.dptr1InUse = 0;
11488     unsavermask(rsave);
11489
11490 }
11491
11492 /*-----------------------------------------------------------------*/
11493 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11494 /* port, first parameter output area second parameter pointer to   */
11495 /* port third parameter count                                      */
11496 /*-----------------------------------------------------------------*/
11497 static void genInp( iCode *ic, int nparms, operand **parms)
11498 {
11499     operand *from , *to , *count;
11500     symbol *lbl;
11501     bitVect *rsave;
11502     int i;
11503
11504     /* we know it has to be 3 parameters */
11505     assert (nparms == 3);
11506     
11507     rsave = newBitVect(16);
11508     /* save DPTR if it needs to be saved */
11509     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11510             if (bitVectBitValue(ic->rMask,i))
11511                     rsave = bitVectSetBit(rsave,i);
11512     }
11513     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11514                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11515     savermask(rsave);
11516     
11517     to = parms[0];
11518     from = parms[1];
11519     count = parms[2];
11520
11521     aopOp (from, ic->next, FALSE, FALSE);
11522
11523     /* get from into DPTR1 */
11524     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11525     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11526     if (options.model == MODEL_FLAT24) {
11527         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11528     }
11529
11530     freeAsmop (from, NULL, ic, FALSE);
11531     aopOp (to, ic, FALSE, FALSE);
11532     /* get "to" into DPTR */
11533     /* if the operand is already in dptr
11534        then we do nothing else we move the value to dptr */
11535     if (AOP_TYPE (to) != AOP_STR) {
11536         /* if already in DPTR then we need to push */
11537         if (AOP_TYPE(to) == AOP_DPTR) {
11538             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11539             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11540             if (options.model == MODEL_FLAT24)
11541                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11542             emitcode ("pop", "dph");
11543             emitcode ("pop", "dpl");        
11544         } else {
11545             _startLazyDPSEvaluation ();
11546             /* if this is remateriazable */
11547             if (AOP_TYPE (to) == AOP_IMMD) {
11548                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11549             } else {                    /* we need to get it byte by byte */
11550                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11551                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11552                 if (options.model == MODEL_FLAT24) {
11553                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11554                 }
11555             }
11556             _endLazyDPSEvaluation ();
11557         }
11558     }
11559     freeAsmop (to, NULL, ic, FALSE);
11560
11561     _G.dptrInUse = _G.dptr1InUse = 1;
11562     aopOp (count, ic->next->next, FALSE,FALSE);
11563     lbl =newiTempLabel(NULL);
11564
11565     /* now for the actual copy */
11566     if (AOP_TYPE(count) == AOP_LIT && 
11567         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11568         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11569         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11570         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11571         freeAsmop (count, NULL, ic, FALSE);
11572         emitcode ("","!tlabeldef",lbl->key+100);
11573         emitcode ("movx", "a,@dptr");   /* read data from port */
11574         emitcode ("dec","dps");         /* switch to DPTR */
11575         emitcode ("movx", "@dptr,a");   /* save into location */
11576         emitcode ("inc", "dptr");       /* point to next area */
11577         emitcode ("inc","dps");         /* switch to DPTR2 */
11578         emitcode ("djnz","b,!tlabel",lbl->key+100);
11579     } else {
11580         symbol *lbl1 = newiTempLabel(NULL);
11581         
11582         emitcode (";"," Auto increment but no djnz");
11583         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11584         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11585         freeAsmop (count, NULL, ic, FALSE);
11586         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11587         emitcode ("","!tlabeldef",lbl->key+100);
11588         emitcode ("movx", "a,@dptr");
11589         emitcode ("dec","dps");         /* switch to DPTR */
11590         emitcode ("movx", "@dptr,a");
11591         emitcode ("inc", "dptr");
11592         emitcode ("inc","dps");         /* switch to DPTR2 */
11593 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11594 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11595         emitcode ("mov","a,b");
11596         emitcode ("orl","a,_ap");
11597         emitcode ("jz","!tlabel",lbl1->key+100);
11598         emitcode ("mov","a,_ap");
11599         emitcode ("add","a,#!constbyte",0xFF);
11600         emitcode ("mov","_ap,a");
11601         emitcode ("mov","a,b");
11602         emitcode ("addc","a,#!constbyte",0xFF);
11603         emitcode ("mov","b,a");
11604         emitcode ("sjmp","!tlabel",lbl->key+100);
11605         emitcode ("","!tlabeldef",lbl1->key+100);
11606     }
11607     emitcode ("mov", "dps,#0"); 
11608     _G.dptrInUse = _G.dptr1InUse = 0;
11609     unsavermask(rsave);
11610
11611 }
11612
11613 /*-----------------------------------------------------------------*/
11614 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11615 /* port, first parameter output area second parameter pointer to   */
11616 /* port third parameter count                                      */
11617 /*-----------------------------------------------------------------*/
11618 static void genOutp( iCode *ic, int nparms, operand **parms)
11619 {
11620     operand *from , *to , *count;
11621     symbol *lbl;
11622     bitVect *rsave;
11623     int i;
11624
11625     /* we know it has to be 3 parameters */
11626     assert (nparms == 3);
11627     
11628     rsave = newBitVect(16);
11629     /* save DPTR if it needs to be saved */
11630     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11631             if (bitVectBitValue(ic->rMask,i))
11632                     rsave = bitVectSetBit(rsave,i);
11633     }
11634     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11635                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11636     savermask(rsave);
11637     
11638     to = parms[0];
11639     from = parms[1];
11640     count = parms[2];
11641
11642     aopOp (from, ic->next, FALSE, FALSE);
11643
11644     /* get from into DPTR1 */
11645     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11646     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11647     if (options.model == MODEL_FLAT24) {
11648         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11649     }
11650
11651     freeAsmop (from, NULL, ic, FALSE);
11652     aopOp (to, ic, FALSE, FALSE);
11653     /* get "to" into DPTR */
11654     /* if the operand is already in dptr
11655        then we do nothing else we move the value to dptr */
11656     if (AOP_TYPE (to) != AOP_STR) {
11657         /* if already in DPTR then we need to push */
11658         if (AOP_TYPE(to) == AOP_DPTR) {
11659             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11660             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11661             if (options.model == MODEL_FLAT24)
11662                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11663             emitcode ("pop", "dph");
11664             emitcode ("pop", "dpl");        
11665         } else {
11666             _startLazyDPSEvaluation ();
11667             /* if this is remateriazable */
11668             if (AOP_TYPE (to) == AOP_IMMD) {
11669                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11670             } else {                    /* we need to get it byte by byte */
11671                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11672                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11673                 if (options.model == MODEL_FLAT24) {
11674                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11675                 }
11676             }
11677             _endLazyDPSEvaluation ();
11678         }
11679     }
11680     freeAsmop (to, NULL, ic, FALSE);
11681
11682     _G.dptrInUse = _G.dptr1InUse = 1;
11683     aopOp (count, ic->next->next, FALSE,FALSE);
11684     lbl =newiTempLabel(NULL);
11685
11686     /* now for the actual copy */
11687     if (AOP_TYPE(count) == AOP_LIT && 
11688         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11689         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11690         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11691         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11692         emitcode ("","!tlabeldef",lbl->key+100);
11693         emitcode ("movx", "a,@dptr");   /* read data from port */
11694         emitcode ("inc","dps");         /* switch to DPTR2 */
11695         emitcode ("movx", "@dptr,a");   /* save into location */
11696         emitcode ("inc", "dptr");       /* point to next area */
11697         emitcode ("dec","dps");         /* switch to DPTR */
11698         emitcode ("djnz","b,!tlabel",lbl->key+100);
11699         freeAsmop (count, NULL, ic, FALSE);
11700     } else {
11701         symbol *lbl1 = newiTempLabel(NULL);
11702         
11703         emitcode (";"," Auto increment but no djnz");
11704         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11705         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11706         freeAsmop (count, NULL, ic, FALSE);
11707         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11708         emitcode ("","!tlabeldef",lbl->key+100);
11709         emitcode ("movx", "a,@dptr");
11710         emitcode ("inc", "dptr");
11711         emitcode ("inc","dps");         /* switch to DPTR2 */
11712         emitcode ("movx", "@dptr,a");
11713         emitcode ("dec","dps");         /* switch to DPTR */
11714         emitcode ("mov","a,b");
11715         emitcode ("orl","a,_ap");
11716         emitcode ("jz","!tlabel",lbl1->key+100);
11717         emitcode ("mov","a,_ap");
11718         emitcode ("add","a,#!constbyte",0xFF);
11719         emitcode ("mov","_ap,a");
11720         emitcode ("mov","a,b");
11721         emitcode ("addc","a,#!constbyte",0xFF);
11722         emitcode ("mov","b,a");
11723         emitcode ("sjmp","!tlabel",lbl->key+100);
11724         emitcode ("","!tlabeldef",lbl1->key+100);
11725     }
11726     emitcode ("mov", "dps,#0"); 
11727     _G.dptrInUse = _G.dptr1InUse = 0;
11728     unsavermask(rsave);
11729
11730 }
11731
11732 /*-----------------------------------------------------------------*/
11733 /* genSwapW - swap lower & high order bytes                        */
11734 /*-----------------------------------------------------------------*/
11735 static void genSwapW(iCode *ic, int nparms, operand **parms)
11736 {
11737     operand *dest;
11738     operand *src;
11739     assert (nparms==1);
11740
11741     src = parms[0];
11742     dest=IC_RESULT(ic);
11743
11744     assert(getSize(operandType(src))==2);
11745
11746     aopOp (src, ic, FALSE, FALSE);
11747     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11748     _G.accInUse++;
11749     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11750     _G.accInUse--;
11751     freeAsmop (src, NULL, ic, FALSE);
11752     
11753     aopOp (dest,ic, FALSE, FALSE);
11754     aopPut(AOP(dest),"b",0);
11755     aopPut(AOP(dest),"a",1);
11756     freeAsmop (dest, NULL, ic, FALSE);    
11757 }
11758
11759 /*-----------------------------------------------------------------*/
11760 /* genMemsetX - gencode for memSetX data                           */
11761 /*-----------------------------------------------------------------*/
11762 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11763 {
11764     operand *to , *val , *count;
11765     symbol *lbl;
11766     char *l;
11767     int i;
11768     bitVect *rsave;
11769
11770     /* we know it has to be 3 parameters */
11771     assert (nparms == 3);
11772     
11773     to = parms[0];
11774     val = parms[1];
11775     count = parms[2];
11776         
11777     /* save DPTR if it needs to be saved */
11778     rsave = newBitVect(16);
11779     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11780             if (bitVectBitValue(ic->rMask,i))
11781                     rsave = bitVectSetBit(rsave,i);
11782     }
11783     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11784                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11785     savermask(rsave);
11786
11787     aopOp (to, ic, FALSE, FALSE);
11788     /* get "to" into DPTR */
11789     /* if the operand is already in dptr
11790        then we do nothing else we move the value to dptr */
11791     if (AOP_TYPE (to) != AOP_STR) {
11792         /* if already in DPTR then we need to push */
11793         if (AOP_TYPE(to) == AOP_DPTR) {
11794             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11795             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11796             if (options.model == MODEL_FLAT24)
11797                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11798             emitcode ("pop", "dph");
11799             emitcode ("pop", "dpl");        
11800         } else {
11801             _startLazyDPSEvaluation ();
11802             /* if this is remateriazable */
11803             if (AOP_TYPE (to) == AOP_IMMD) {
11804                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11805             } else {                    /* we need to get it byte by byte */
11806                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11807                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11808                 if (options.model == MODEL_FLAT24) {
11809                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11810                 }
11811             }
11812             _endLazyDPSEvaluation ();
11813         }
11814     }
11815     freeAsmop (to, NULL, ic, FALSE);
11816
11817     aopOp (val, ic->next->next, FALSE,FALSE);
11818     aopOp (count, ic->next->next, FALSE,FALSE);    
11819     lbl =newiTempLabel(NULL);
11820     /* now for the actual copy */
11821     if (AOP_TYPE(count) == AOP_LIT && 
11822         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11823         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11824         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11825         MOVA(l);
11826         emitcode ("","!tlabeldef",lbl->key+100);
11827         emitcode ("movx", "@dptr,a");
11828         emitcode ("inc", "dptr");
11829         emitcode ("djnz","b,!tlabel",lbl->key+100);
11830     } else {
11831         symbol *lbl1 = newiTempLabel(NULL);
11832         
11833         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11834         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11835         emitcode ("","!tlabeldef",lbl->key+100);
11836         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11837         emitcode ("movx", "@dptr,a");
11838         emitcode ("inc", "dptr");
11839         emitcode ("mov","a,b");
11840         emitcode ("orl","a,_ap");
11841         emitcode ("jz","!tlabel",lbl1->key+100);
11842         emitcode ("mov","a,_ap");
11843         emitcode ("add","a,#!constbyte",0xFF);
11844         emitcode ("mov","_ap,a");
11845         emitcode ("mov","a,b");
11846         emitcode ("addc","a,#!constbyte",0xFF);
11847         emitcode ("mov","b,a");
11848         emitcode ("sjmp","!tlabel",lbl->key+100);
11849         emitcode ("","!tlabeldef",lbl1->key+100);
11850     }
11851     freeAsmop (count, NULL, ic, FALSE);
11852     unsavermask(rsave);
11853 }
11854
11855 /*-----------------------------------------------------------------*/
11856 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11857 /*-----------------------------------------------------------------*/
11858 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11859 {
11860         bitVect *rsave ;
11861         operand *pnum, *result;
11862         int i;
11863     
11864         assert (nparms==1);
11865         /* save registers that need to be saved */
11866         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11867                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11868     
11869         pnum = parms[0]; 
11870         aopOp (pnum, ic, FALSE, FALSE);
11871         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11872         freeAsmop (pnum, NULL, ic, FALSE);
11873         emitcode ("lcall","NatLib_LoadPrimitive");
11874         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11875         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11876             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11877                 for (i = (size-1) ; i >= 0 ; i-- ) {
11878                         emitcode ("push","a%s",javaRet[i]);
11879                 }
11880                 for (i=0; i < size ; i++ ) {
11881                         emitcode ("pop","a%s",
11882                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11883                 }
11884         } else {
11885                 for (i = 0 ; i < size ; i++ ) {
11886                         aopPut(AOP(result),javaRet[i],i);
11887                 }
11888         }    
11889         freeAsmop (result, NULL, ic, FALSE);
11890         unsavermask(rsave);
11891 }
11892
11893 /*-----------------------------------------------------------------*/
11894 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11895 /*-----------------------------------------------------------------*/
11896 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11897 {
11898         bitVect *rsave ;
11899         operand *pnum, *result;
11900         int size = 3;
11901         int i;
11902     
11903         assert (nparms==1);
11904         /* save registers that need to be saved */
11905         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11906                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11907     
11908         pnum = parms[0]; 
11909         aopOp (pnum, ic, FALSE, FALSE);
11910         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11911         freeAsmop (pnum, NULL, ic, FALSE);
11912         emitcode ("lcall","NatLib_LoadPointer");
11913         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11914         if (AOP_TYPE(result)!=AOP_STR) {
11915                 for (i = 0 ; i < size ; i++ ) {
11916                         aopPut(AOP(result),fReturn[i],i);
11917                 }
11918         }    
11919         freeAsmop (result, NULL, ic, FALSE);
11920         unsavermask(rsave);
11921 }
11922
11923 /*-----------------------------------------------------------------*/
11924 /* genNatLibInstallStateBlock -                                    */
11925 /*-----------------------------------------------------------------*/
11926 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11927                                        operand **parms, const char *name)
11928 {
11929         bitVect *rsave ;
11930         operand *psb, *handle;
11931         assert (nparms==2);
11932
11933         /* save registers that need to be saved */
11934         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11935                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11936         psb = parms[0];
11937         handle = parms[1];
11938
11939         /* put pointer to state block into DPTR1 */
11940         aopOp (psb, ic, FALSE, FALSE);
11941         if (AOP_TYPE (psb) == AOP_IMMD) {
11942                 emitcode ("mov","dps,#1");
11943                 emitcode ("mov", "dptr,%s",
11944                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
11945                 emitcode ("mov","dps,#0");
11946         } else {
11947                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
11948                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
11949                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
11950         }
11951         freeAsmop (psb, NULL, ic, FALSE);
11952
11953         /* put libraryID into DPTR */
11954         emitcode ("mov","dptr,#LibraryID");
11955
11956         /* put handle into r3:r2 */
11957         aopOp (handle, ic, FALSE, FALSE);
11958         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11959                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11960                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11961                 emitcode ("pop","ar3");
11962                 emitcode ("pop","ar2");
11963         } else {        
11964                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
11965                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11966         }
11967         freeAsmop (psb, NULL, ic, FALSE);
11968
11969         /* make the call */
11970         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11971
11972         /* put return value into place*/
11973         _G.accInUse++;
11974         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11975         _G.accInUse--;
11976         aopPut(AOP(IC_RESULT(ic)),"a",0);
11977         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11978         unsavermask(rsave);
11979 }
11980
11981 /*-----------------------------------------------------------------*/
11982 /* genNatLibRemoveStateBlock -                                     */
11983 /*-----------------------------------------------------------------*/
11984 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11985 {
11986         bitVect *rsave ;
11987
11988         assert(nparms==0);
11989
11990         /* save registers that need to be saved */
11991         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11992                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11993
11994         /* put libraryID into DPTR */
11995         emitcode ("mov","dptr,#LibraryID");
11996         /* make the call */
11997         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11998         unsavermask(rsave);
11999 }
12000
12001 /*-----------------------------------------------------------------*/
12002 /* genNatLibGetStateBlock -                                        */
12003 /*-----------------------------------------------------------------*/
12004 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12005                                    operand **parms,const char *name)
12006 {
12007         bitVect *rsave ;
12008         symbol *lbl = newiTempLabel(NULL);
12009         
12010         assert(nparms==0);
12011         /* save registers that need to be saved */
12012         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12013                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12014
12015         /* put libraryID into DPTR */
12016         emitcode ("mov","dptr,#LibraryID");
12017         /* make the call */
12018         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12019         emitcode ("jnz","!tlabel",lbl->key+100);
12020
12021         /* put return value into place */
12022         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12023         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12024                 emitcode ("push","ar3");
12025                 emitcode ("push","ar2");
12026                 emitcode ("pop","%s",
12027                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12028                 emitcode ("pop","%s",
12029                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12030         } else {
12031                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12032                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12033         }
12034         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12035         emitcode ("","!tlabeldef",lbl->key+100);
12036         unsavermask(rsave);
12037 }
12038
12039 /*-----------------------------------------------------------------*/
12040 /* genMMMalloc -                                                   */
12041 /*-----------------------------------------------------------------*/
12042 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12043                          int size, const char *name)
12044 {
12045         bitVect *rsave ;
12046         operand *bsize;
12047         symbol *rsym;
12048         symbol *lbl = newiTempLabel(NULL);
12049
12050         assert (nparms == 1);
12051         /* save registers that need to be saved */
12052         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12053                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12054         
12055         bsize=parms[0];
12056         aopOp (bsize,ic,FALSE,FALSE);
12057
12058         /* put the size in R4-R2 */
12059         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12060                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12061                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12062                 if (size==3) {
12063                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12064                         emitcode("pop","ar4");
12065                 }
12066                 emitcode("pop","ar3");
12067                 emitcode("pop","ar2");          
12068         } else {
12069                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12070                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12071                 if (size==3) {
12072                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12073                 }
12074         }
12075         freeAsmop (bsize, NULL, ic, FALSE);
12076
12077         /* make the call */
12078         emitcode ("lcall","MM_%s",name);
12079         emitcode ("jz","!tlabel",lbl->key+100);
12080         emitcode ("mov","r2,#!constbyte",0xff);
12081         emitcode ("mov","r3,#!constbyte",0xff);
12082         emitcode ("","!tlabeldef",lbl->key+100);
12083         /* we don't care about the pointer : we just save the handle */
12084         rsym = OP_SYMBOL(IC_RESULT(ic));
12085         if (rsym->liveFrom != rsym->liveTo) {
12086                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12087                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12088                         emitcode ("push","ar3");
12089                         emitcode ("push","ar2");
12090                         emitcode ("pop","%s",
12091                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12092                         emitcode ("pop","%s",
12093                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12094                 } else {
12095                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12096                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12097                 }
12098                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12099         }
12100         unsavermask(rsave);
12101 }
12102
12103 /*-----------------------------------------------------------------*/
12104 /* genMMDeref -                                                    */
12105 /*-----------------------------------------------------------------*/
12106 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12107 {
12108         bitVect *rsave ;
12109         operand *handle;
12110
12111         assert (nparms == 1);
12112         /* save registers that need to be saved */
12113         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12114                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12115         
12116         handle=parms[0];
12117         aopOp (handle,ic,FALSE,FALSE);
12118
12119         /* put the size in R4-R2 */
12120         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12121                 emitcode("push","%s",
12122                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12123                 emitcode("push","%s",
12124                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12125                 emitcode("pop","ar3");
12126                 emitcode("pop","ar2");          
12127         } else {
12128                 emitcode ("mov","r2,%s",
12129                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12130                 emitcode ("mov","r3,%s",
12131                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12132         }
12133         freeAsmop (handle, NULL, ic, FALSE);
12134
12135         /* make the call */
12136         emitcode ("lcall","MM_Deref");
12137         
12138         {
12139                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12140                 if (rsym->liveFrom != rsym->liveTo) {                   
12141                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12142                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12143                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12144                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12145                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12146                         }
12147                 }
12148         }
12149         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12150         unsavermask(rsave);
12151 }
12152
12153 /*-----------------------------------------------------------------*/
12154 /* genMMUnrestrictedPersist -                                      */
12155 /*-----------------------------------------------------------------*/
12156 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12157 {
12158         bitVect *rsave ;
12159         operand *handle;
12160
12161         assert (nparms == 1);
12162         /* save registers that need to be saved */
12163         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12164                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12165         
12166         handle=parms[0];
12167         aopOp (handle,ic,FALSE,FALSE);
12168
12169         /* put the size in R3-R2 */
12170         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12171                 emitcode("push","%s",
12172                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12173                 emitcode("push","%s",
12174                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12175                 emitcode("pop","ar3");
12176                 emitcode("pop","ar2");          
12177         } else {
12178                 emitcode ("mov","r2,%s",
12179                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12180                 emitcode ("mov","r3,%s",
12181                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12182         }
12183         freeAsmop (handle, NULL, ic, FALSE);
12184
12185         /* make the call */
12186         emitcode ("lcall","MM_UnrestrictedPersist");
12187
12188         {
12189                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12190                 if (rsym->liveFrom != rsym->liveTo) {   
12191                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12192                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12193                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12194                 }
12195         }
12196         unsavermask(rsave);
12197 }
12198
12199 /*-----------------------------------------------------------------*/
12200 /* genSystemExecJavaProcess -                                      */
12201 /*-----------------------------------------------------------------*/
12202 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12203 {
12204         bitVect *rsave ;
12205         operand *handle, *pp;
12206
12207         assert (nparms==2);
12208         /* save registers that need to be saved */
12209         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12210                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12211         
12212         pp = parms[0];
12213         handle = parms[1];
12214         
12215         /* put the handle in R3-R2 */
12216         aopOp (handle,ic,FALSE,FALSE);
12217         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12218                 emitcode("push","%s",
12219                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12220                 emitcode("push","%s",
12221                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12222                 emitcode("pop","ar3");
12223                 emitcode("pop","ar2");          
12224         } else {
12225                 emitcode ("mov","r2,%s",
12226                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12227                 emitcode ("mov","r3,%s",
12228                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12229         }
12230         freeAsmop (handle, NULL, ic, FALSE);
12231         
12232         /* put pointer in DPTR */
12233         aopOp (pp,ic,FALSE,FALSE);
12234         if (AOP_TYPE(pp) == AOP_IMMD) {
12235                 emitcode ("mov", "dptr,%s",
12236                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12237         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12238                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12239                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12240                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12241         }
12242         freeAsmop (handle, NULL, ic, FALSE);
12243
12244         /* make the call */
12245         emitcode ("lcall","System_ExecJavaProcess");
12246         
12247         /* put result in place */
12248         {
12249                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12250                 if (rsym->liveFrom != rsym->liveTo) {   
12251                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12252                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12253                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12254                 }
12255         }
12256         
12257         unsavermask(rsave);
12258 }
12259
12260 /*-----------------------------------------------------------------*/
12261 /* genSystemRTCRegisters -                                         */
12262 /*-----------------------------------------------------------------*/
12263 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12264                                   char *name)
12265 {
12266         bitVect *rsave ;
12267         operand *pp;
12268
12269         assert (nparms==1);
12270         /* save registers that need to be saved */
12271         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12272                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12273         
12274         pp=parms[0];
12275         /* put pointer in DPTR */
12276         aopOp (pp,ic,FALSE,FALSE);
12277         if (AOP_TYPE (pp) == AOP_IMMD) {
12278                 emitcode ("mov","dps,#1");
12279                 emitcode ("mov", "dptr,%s", 
12280                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12281                 emitcode ("mov","dps,#0");
12282         } else {
12283                 emitcode ("mov","dpl1,%s",
12284                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12285                 emitcode ("mov","dph1,%s",
12286                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12287                 emitcode ("mov","dpx1,%s",
12288                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12289         }
12290         freeAsmop (pp, NULL, ic, FALSE);
12291
12292         /* make the call */
12293         emitcode ("lcall","System_%sRTCRegisters",name);
12294
12295         unsavermask(rsave);
12296 }
12297
12298 /*-----------------------------------------------------------------*/
12299 /* genSystemThreadSleep -                                          */
12300 /*-----------------------------------------------------------------*/
12301 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12302 {
12303         bitVect *rsave ;
12304         operand *to, *s;
12305
12306         assert (nparms==1);
12307         /* save registers that need to be saved */
12308         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12309                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12310
12311         to = parms[0];
12312         aopOp(to,ic,FALSE,FALSE);
12313         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12314             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12315                 emitcode ("push","%s",
12316                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12317                 emitcode ("push","%s",
12318                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12319                 emitcode ("push","%s",
12320                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12321                 emitcode ("push","%s",
12322                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12323                 emitcode ("pop","ar3");
12324                 emitcode ("pop","ar2");
12325                 emitcode ("pop","ar1");
12326                 emitcode ("pop","ar0");
12327         } else {
12328                 emitcode ("mov","r0,%s",
12329                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12330                 emitcode ("mov","r1,%s",
12331                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12332                 emitcode ("mov","r2,%s",
12333                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12334                 emitcode ("mov","r3,%s",
12335                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12336         }
12337         freeAsmop (to, NULL, ic, FALSE);
12338
12339         /* suspend in acc */
12340         s = parms[1];
12341         aopOp(s,ic,FALSE,FALSE);
12342         emitcode ("mov","a,%s",
12343                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12344         freeAsmop (s, NULL, ic, FALSE);
12345
12346         /* make the call */
12347         emitcode ("lcall","System_%s",name);
12348
12349         unsavermask(rsave);
12350 }
12351
12352 /*-----------------------------------------------------------------*/
12353 /* genSystemThreadResume -                                         */
12354 /*-----------------------------------------------------------------*/
12355 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12356 {
12357         bitVect *rsave ;
12358         operand *tid,*pid;
12359
12360         assert (nparms==2);
12361         /* save registers that need to be saved */
12362         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12363                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12364         
12365         tid = parms[0];
12366         pid = parms[1];
12367         
12368         /* PID in R0 */
12369         aopOp(pid,ic,FALSE,FALSE);
12370         emitcode ("mov","r0,%s",
12371                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12372         freeAsmop (pid, NULL, ic, FALSE);
12373         
12374         /* tid into ACC */
12375         aopOp(tid,ic,FALSE,FALSE);
12376         emitcode ("mov","a,%s",
12377                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12378         freeAsmop (tid, NULL, ic, FALSE);
12379         
12380         emitcode ("lcall","System_ThreadResume");
12381
12382         /* put result into place */
12383         {
12384                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12385                 if (rsym->liveFrom != rsym->liveTo) {   
12386                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12387                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12388                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12389                 }
12390         }
12391         unsavermask(rsave);
12392 }
12393
12394 /*-----------------------------------------------------------------*/
12395 /* genSystemProcessResume -                                        */
12396 /*-----------------------------------------------------------------*/
12397 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12398 {
12399         bitVect *rsave ;
12400         operand *pid;
12401
12402         assert (nparms==1);
12403         /* save registers that need to be saved */
12404         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12405                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12406         
12407         pid = parms[0];
12408         
12409         /* pid into ACC */
12410         aopOp(pid,ic,FALSE,FALSE);
12411         emitcode ("mov","a,%s",
12412                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12413         freeAsmop (pid, NULL, ic, FALSE);
12414         
12415         emitcode ("lcall","System_ProcessResume");
12416
12417         unsavermask(rsave);
12418 }
12419
12420 /*-----------------------------------------------------------------*/
12421 /* genSystem -                                                     */
12422 /*-----------------------------------------------------------------*/
12423 static void genSystem (iCode *ic,int nparms,char *name)
12424 {
12425         assert(nparms == 0);
12426
12427         emitcode ("lcall","System_%s",name);
12428 }
12429
12430 /*-----------------------------------------------------------------*/
12431 /* genSystemPoll -                                                  */
12432 /*-----------------------------------------------------------------*/
12433 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12434 {
12435         bitVect *rsave ;
12436         operand *fp;
12437
12438         assert (nparms==1);
12439         /* save registers that need to be saved */
12440         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12441                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12442
12443         fp = parms[0];
12444         aopOp (fp,ic,FALSE,FALSE);
12445         if (AOP_TYPE (fp) == AOP_IMMD) {
12446                 emitcode ("mov", "dptr,%s", 
12447                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12448         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12449                 emitcode ("mov","dpl,%s",
12450                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12451                 emitcode ("mov","dph,%s",
12452                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12453                 emitcode ("mov","dpx,%s",
12454                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12455         }
12456         freeAsmop (fp, NULL, ic, FALSE);
12457
12458         emitcode ("lcall","System_%sPoll",name);
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 /* genSystemGetCurrentID -                                         */
12474 /*-----------------------------------------------------------------*/
12475 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12476 {
12477         assert (nparms==0);
12478
12479         emitcode ("lcall","System_GetCurrent%sId",name);
12480         /* put result into place */
12481         {
12482                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12483                 if (rsym->liveFrom != rsym->liveTo) {   
12484                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12485                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12486                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12487                 }
12488         }
12489 }
12490
12491 /*-----------------------------------------------------------------*/
12492 /* genBuiltIn - calls the appropriate function to  generating code */
12493 /* for a built in function                                         */
12494 /*-----------------------------------------------------------------*/
12495 static void genBuiltIn (iCode *ic)
12496 {
12497         operand *bi_parms[MAX_BUILTIN_ARGS];
12498         int nbi_parms;
12499         iCode *bi_iCode;
12500         symbol *bif;
12501
12502         /* get all the arguments for a built in function */
12503         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12504
12505         /* which function is it */
12506         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12507         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12508                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12509         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12510                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12511         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12512                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12513         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12514                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12515         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12516                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12517         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12518                 genInp(bi_iCode,nbi_parms,bi_parms);
12519         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12520                 genOutp(bi_iCode,nbi_parms,bi_parms);
12521         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12522                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12523                 /* JavaNative builtIns */               
12524         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12525                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12526         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12527                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12528         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12529                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12530         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12531                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12532         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12533                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12534         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12535                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12536         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12537                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12538         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12539                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12540         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12541                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12542         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12543                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12544         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12545                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12546         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12547                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12548         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12549                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12550         } else if (strcmp(bif->name,"MM_Free")==0) {
12551                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12552         } else if (strcmp(bif->name,"MM_Deref")==0) {
12553                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12554         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12555                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12556         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12557                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12558         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12559                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12560         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12561                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12562         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12563                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12564         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12565                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12566         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12567                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12568         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12569                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12570         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12571                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12572         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12573                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12574         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12575                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12576         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12577                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12578         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12579                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12580         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12581                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12582         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12583                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12584         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12585                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12586         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12587                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12588         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12589                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12590         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12591                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12592         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12593                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12594         } else {
12595                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12596                 return ;
12597         }
12598         return ;    
12599 }
12600
12601 /*-----------------------------------------------------------------*/
12602 /* gen390Code - generate code for Dallas 390 based controllers     */
12603 /*-----------------------------------------------------------------*/
12604 void
12605 gen390Code (iCode * lic)
12606 {
12607   iCode *ic;
12608   int cln = 0;
12609
12610   lineHead = lineCurr = NULL;
12611   dptrn[1][0] = "dpl1";
12612   dptrn[1][1] = "dph1";
12613   dptrn[1][2] = "dpx1";
12614   
12615   if (options.model == MODEL_FLAT24) {
12616     fReturnSizeDS390 = 5;
12617     fReturn = fReturn24;
12618   } else {
12619     fReturnSizeDS390 = 4;
12620     fReturn = fReturn16;
12621     options.stack10bit=0;
12622   }
12623 #if 1
12624   /* print the allocation information */
12625   if (allocInfo)
12626     printAllocInfo (currFunc, codeOutFile);
12627 #endif
12628   /* if debug information required */
12629   if (options.debug && currFunc)
12630     {
12631       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12632       _G.debugLine = 1;
12633       if (IS_STATIC (currFunc->etype))
12634         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12635       else
12636         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12637       _G.debugLine = 0;
12638     }
12639   /* stack pointer name */
12640   if (options.useXstack)
12641     spname = "_spx";
12642   else
12643     spname = "sp";
12644
12645
12646   for (ic = lic; ic; ic = ic->next)
12647     {
12648
12649       if (ic->lineno && cln != ic->lineno)
12650         {
12651           if (options.debug)
12652             {
12653               _G.debugLine = 1;
12654               emitcode ("", "C$%s$%d$%d$%d ==.",
12655                         FileBaseName (ic->filename), ic->lineno,
12656                         ic->level, ic->block);
12657               _G.debugLine = 0;
12658             }
12659           if (!options.noCcodeInAsm) {
12660             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12661                       printCLine(ic->filename, ic->lineno));
12662           }
12663           cln = ic->lineno;
12664         }
12665       if (options.iCodeInAsm) {
12666         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12667       }
12668       /* if the result is marked as
12669          spilt and rematerializable or code for
12670          this has already been generated then
12671          do nothing */
12672       if (resultRemat (ic) || ic->generated)
12673         continue;
12674
12675       /* depending on the operation */
12676       switch (ic->op)
12677         {
12678         case '!':
12679           genNot (ic);
12680           break;
12681
12682         case '~':
12683           genCpl (ic);
12684           break;
12685
12686         case UNARYMINUS:
12687           genUminus (ic);
12688           break;
12689
12690         case IPUSH:
12691           genIpush (ic);
12692           break;
12693
12694         case IPOP:
12695           /* IPOP happens only when trying to restore a
12696              spilt live range, if there is an ifx statement
12697              following this pop then the if statement might
12698              be using some of the registers being popped which
12699              would destory the contents of the register so
12700              we need to check for this condition and handle it */
12701           if (ic->next &&
12702               ic->next->op == IFX &&
12703               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12704             genIfx (ic->next, ic);
12705           else
12706             genIpop (ic);
12707           break;
12708
12709         case CALL:
12710           genCall (ic);
12711           break;
12712
12713         case PCALL:
12714           genPcall (ic);
12715           break;
12716
12717         case FUNCTION:
12718           genFunction (ic);
12719           break;
12720
12721         case ENDFUNCTION:
12722           genEndFunction (ic);
12723           break;
12724
12725         case RETURN:
12726           genRet (ic);
12727           break;
12728
12729         case LABEL:
12730           genLabel (ic);
12731           break;
12732
12733         case GOTO:
12734           genGoto (ic);
12735           break;
12736
12737         case '+':
12738           genPlus (ic);
12739           break;
12740
12741         case '-':
12742           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12743             genMinus (ic);
12744           break;
12745
12746         case '*':
12747           genMult (ic);
12748           break;
12749
12750         case '/':
12751           genDiv (ic);
12752           break;
12753
12754         case '%':
12755           genMod (ic);
12756           break;
12757
12758         case '>':
12759           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12760           break;
12761
12762         case '<':
12763           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12764           break;
12765
12766         case LE_OP:
12767         case GE_OP:
12768         case NE_OP:
12769
12770           /* note these two are xlated by algebraic equivalence
12771              during parsing SDCC.y */
12772           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12773                   "got '>=' or '<=' shouldn't have come here");
12774           break;
12775
12776         case EQ_OP:
12777           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12778           break;
12779
12780         case AND_OP:
12781           genAndOp (ic);
12782           break;
12783
12784         case OR_OP:
12785           genOrOp (ic);
12786           break;
12787
12788         case '^':
12789           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12790           break;
12791
12792         case '|':
12793           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12794           break;
12795
12796         case BITWISEAND:
12797           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12798           break;
12799
12800         case INLINEASM:
12801           genInline (ic);
12802           break;
12803
12804         case RRC:
12805           genRRC (ic);
12806           break;
12807
12808         case RLC:
12809           genRLC (ic);
12810           break;
12811
12812         case GETHBIT:
12813           genGetHbit (ic);
12814           break;
12815
12816         case LEFT_OP:
12817           genLeftShift (ic);
12818           break;
12819
12820         case RIGHT_OP:
12821           genRightShift (ic);
12822           break;
12823
12824         case GET_VALUE_AT_ADDRESS:
12825           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12826           break;
12827
12828         case '=':
12829           if (POINTER_SET (ic))
12830             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12831           else
12832             genAssign (ic);
12833           break;
12834
12835         case IFX:
12836           genIfx (ic, NULL);
12837           break;
12838
12839         case ADDRESS_OF:
12840           genAddrOf (ic);
12841           break;
12842
12843         case JUMPTABLE:
12844           genJumpTab (ic);
12845           break;
12846
12847         case CAST:
12848           genCast (ic);
12849           break;
12850
12851         case RECEIVE:
12852           genReceive (ic);
12853           break;
12854
12855         case SEND:
12856           if (ic->builtinSEND) genBuiltIn(ic);
12857           else addSet (&_G.sendSet, ic);
12858           break;
12859
12860         case ARRAYINIT:
12861             genArrayInit(ic);
12862             break;
12863             
12864         default:
12865           ic = ic;
12866         }
12867     }
12868
12869
12870   /* now we are ready to call the
12871      peep hole optimizer */
12872   if (!options.nopeep)
12873     peepHole (&lineHead);
12874
12875   /* now do the actual printing */
12876   printLine (lineHead, codeOutFile);
12877   return;
12878 }