More cleanups of _ap abuse.
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59 extern int allocInfo;
60
61 /* this is the down and dirty file with all kinds of
62    kludgy & hacky stuff. This is what it is all about
63    CODE GENERATION for a specific MCU . some of the
64    routines may be reusable, will have to see */
65
66 static char *zero = "#0";
67 static char *one = "#1";
68 static char *spname;
69
70 #define D(x) x
71
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74
75 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
82 {"a", "b"};
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
86
87 static struct
88   {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short bInUse;
93     short inLine;
94     short debugLine;
95     short nRegsSaved;
96     short dptrInUse;
97     short dptr1InUse;
98     set *sendSet;
99   }
100 _G;
101
102 static char *rb1regs[] = {
103     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
104 };
105
106 static void saveRBank (int, iCode *, bool);
107
108 #define RESULTONSTACK(x) \
109                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
110                          IC_RESULT(x)->aop->type == AOP_STK )
111
112 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { \
114                  char *_mova_tmp = strdup(x); \
115                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
116                  { \
117                     emitcode("mov","a,%s",_mova_tmp); \
118                  } \
119                  free(_mova_tmp); \
120                 }
121 #define MOVB(x) { char *_movb_tmp = strdup(x); \
122                  if (strcmp(_movb_tmp,"b")) \
123                  { \
124                     emitcode("mov","b,%s",_movb_tmp); \
125                  } \
126                  free(_movb_tmp); \
127                 }
128 #define CLRC    emitcode("clr","c")
129 #define SETC    emitcode("setb","c")
130
131 // A scratch register which will be used to hold
132 // result bytes from operands in far space via DPTR2.
133 #define DP2_RESULT_REG  "_ap"
134
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
137
138 static unsigned char SLMask[] =
139 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
140  0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char SRMask[] =
142 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
143  0x07, 0x03, 0x01, 0x00};
144
145 #define LSB     0
146 #define MSB16   1
147 #define MSB24   2
148 #define MSB32   3
149 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
150                                 symbol *lbl = newiTempLabel(NULL);              \
151                                 emitcode ("setb","F1");                         \
152                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
153                                 emitcode ("clr","F1");                          \
154                                 emitcode ("","!tlabeldef",lbl->key+100);        \
155                         }}
156 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
157                                 symbol *lbl = newiTempLabel(NULL);              \
158                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
159                                 emitcode ("setb","EA");                         \
160                                 emitcode ("","!tlabeldef",lbl->key+100);        \
161                         }}
162
163
164 /*-----------------------------------------------------------------*/
165 /* emitcode - writes the code into a file : for now it is simple    */
166 /*-----------------------------------------------------------------*/
167 static void
168 emitcode (char *inst, char *fmt,...)
169 {
170     va_list ap;
171     char lb[INITIAL_INLINEASM];
172     char *lbp = lb;
173     
174     va_start (ap, fmt);
175     
176     if (inst && *inst)
177     {
178         if (fmt && *fmt)
179         {
180             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
181         }
182         else
183         {
184             SNPRINTF (lb, sizeof(lb), "%s", inst);
185         }
186         
187         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
188                    fmt, ap);
189     }
190     else
191     {
192         tvsprintf (lb, sizeof(lb), fmt, ap);
193     }
194     
195
196     while (isspace (*lbp))
197     {
198         lbp++;
199     }
200
201     if (lbp && *lbp)
202     {
203         lineCurr = (lineCurr ?
204                     connectLine (lineCurr, newLineNode (lb)) :
205                     (lineHead = newLineNode (lb)));
206     }
207     
208     lineCurr->isInline = _G.inLine;
209     lineCurr->isDebug = _G.debugLine;
210     va_end (ap);
211 }
212
213 /*-----------------------------------------------------------------*/
214 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
215 /*-----------------------------------------------------------------*/
216 static regs *
217 getFreePtr (iCode * ic, asmop ** aopp, bool result)
218 {
219   bool r0iu, r1iu;
220   bool r0ou, r1ou;
221
222   /* the logic: if r0 & r1 used in the instruction
223      then we are in trouble otherwise */
224
225   /* first check if r0 & r1 are used by this
226      instruction, in which case we are in trouble */
227   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
228   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
229   if (r0iu && r1iu) {
230       goto endOfWorld;
231     }
232
233   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
234   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
235
236   /* if no usage of r0 then return it */
237   if (!r0iu && !r0ou)
238     {
239       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
240       (*aopp)->type = AOP_R0;
241
242       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
243     }
244
245   /* if no usage of r1 then return it */
246   if (!r1iu && !r1ou)
247     {
248       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
249       (*aopp)->type = AOP_R1;
250
251       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
252     }
253
254   /* now we know they both have usage */
255   /* if r0 not used in this instruction */
256   if (!r0iu)
257     {
258       /* push it if not already pushed */
259       if (!_G.r0Pushed)
260         {
261           emitcode ("push", "%s",
262                     ds390_regWithIdx (R0_IDX)->dname);
263           _G.r0Pushed++;
264         }
265
266       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
267       (*aopp)->type = AOP_R0;
268
269       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
270     }
271
272   /* if r1 not used then */
273
274   if (!r1iu)
275     {
276       /* push it if not already pushed */
277       if (!_G.r1Pushed)
278         {
279           emitcode ("push", "%s",
280                     ds390_regWithIdx (R1_IDX)->dname);
281           _G.r1Pushed++;
282         }
283
284       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
285       (*aopp)->type = AOP_R1;
286       return ds390_regWithIdx (R1_IDX);
287     }
288
289 endOfWorld:
290   /* I said end of world but not quite end of world yet */
291   /* if this is a result then we can push it on the stack */
292   if (result)
293     {
294       (*aopp)->type = AOP_STK;
295       return NULL;
296     }
297
298   /* other wise this is true end of the world */
299   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300           "getFreePtr should never reach here");
301   exit (1);
302     
303   return NULL; // notreached, but makes compiler happy.
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp                                  */
308 /*-----------------------------------------------------------------*/
309 static asmop *
310 newAsmop (short type)
311 {
312   asmop *aop;
313
314   aop = Safe_calloc (1, sizeof (asmop));
315   aop->type = type;
316   return aop;
317 }
318
319 static int _currentDPS;         /* Current processor DPS. */
320 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
321 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
322
323 /*-----------------------------------------------------------------*/
324 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
325 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
326 /* alternate DPTR (DPL1/DPH1/DPX1).          */
327 /*-----------------------------------------------------------------*/
328 static void
329 genSetDPTR (int n)
330 {
331
332   /* If we are doing lazy evaluation, simply note the desired
333    * change, but don't emit any code yet.
334    */
335   if (_lazyDPS)
336     {
337       _desiredDPS = n;
338       return;
339     }
340
341   if (!n)
342     {
343       emitcode ("mov", "dps,#0");
344     }
345   else
346     {
347       TR_DPTR("#1");
348       emitcode ("mov", "dps,#1");
349     }
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
354 /*                   */
355 /* Any code that operates on DPTR (NB: not on the individual     */
356 /* components, like DPH) *must* call _flushLazyDPS() before using  */
357 /* DPTR within a lazy DPS evaluation block.        */
358 /*                   */
359 /* Note that aopPut and aopGet already contain the proper calls to */
360 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
361 /* DPS evaluation block.             */
362 /*                   */
363 /* Also, _flushLazyDPS must be called before any flow control      */
364 /* operations that could potentially branch out of the block.    */
365 /*                         */
366 /* Lazy DPS evaluation is simply an optimization (though an      */
367 /* important one), so if in doubt, leave it out.       */
368 /*-----------------------------------------------------------------*/
369 static void
370 _startLazyDPSEvaluation (void)
371 {
372   _currentDPS = 0;
373   _desiredDPS = 0;
374 #ifdef BETTER_LITERAL_SHIFT  
375   _lazyDPS++;
376 #else
377   _lazyDPS = 1;
378 #endif  
379 }
380
381 /*-----------------------------------------------------------------*/
382 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
383 /* desired one. Call before using DPTR within a lazy DPS evaluation */
384 /* block.                */
385 /*-----------------------------------------------------------------*/
386 static void
387 _flushLazyDPS (void)
388 {
389   if (!_lazyDPS)
390     {
391       /* nothing to do. */
392       return;
393     }
394
395   if (_desiredDPS != _currentDPS)
396     {
397       if (_desiredDPS)
398         {
399           emitcode ("inc", "dps");
400         }
401       else
402         {
403           emitcode ("dec", "dps");
404         }
405       _currentDPS = _desiredDPS;
406     }
407 }
408
409 /*-----------------------------------------------------------------*/
410 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
411 /*                   */
412 /* Forces us back to the safe state (standard DPTR selected).    */
413 /*-----------------------------------------------------------------*/
414 static void
415 _endLazyDPSEvaluation (void)
416 {
417 #ifdef BETTER_LITERAL_SHIFT  
418   _lazyDPS--;
419 #else
420   _lazyDPS = 0;
421 #endif    
422   if (!_lazyDPS)
423   {
424     if (_currentDPS)
425     {
426       genSetDPTR (0);
427       _flushLazyDPS ();
428     }
429     _currentDPS = 0;
430     _desiredDPS = 0;
431   }
432 }
433
434
435
436 /*-----------------------------------------------------------------*/
437 /* pointerCode - returns the code for a pointer type               */
438 /*-----------------------------------------------------------------*/
439 static int
440 pointerCode (sym_link * etype)
441 {
442
443   return PTR_TYPE (SPEC_OCLS (etype));
444
445 }
446
447 /*-----------------------------------------------------------------*/
448 /* aopForSym - for a true symbol                                   */
449 /*-----------------------------------------------------------------*/
450 static asmop *
451 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
452 {
453   asmop *aop;
454   memmap *space = SPEC_OCLS (sym->etype);
455
456   /* if already has one */
457   if (sym->aop)
458     return sym->aop;
459
460   /* assign depending on the storage class */
461   /* if it is on the stack or indirectly addressable */
462   /* space we need to assign either r0 or r1 to it   */
463   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
464     {
465       sym->aop = aop = newAsmop (0);
466       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
467       aop->size = getSize (sym->type);
468
469       /* now assign the address of the variable to
470          the pointer register */
471       if (aop->type != AOP_STK)
472         {
473
474           if (sym->onStack)
475             {
476               if (_G.accInUse)
477                 emitcode ("push", "acc");
478
479               if (_G.bInUse)
480                 emitcode ("push", "b");
481
482               emitcode ("mov", "a,_bp");
483               emitcode ("add", "a,#!constbyte",
484                         ((sym->stack < 0) ?
485                          ((char) (sym->stack - _G.nRegsSaved)) :
486                          ((char) sym->stack)) & 0xff);
487               emitcode ("mov", "%s,a",
488                         aop->aopu.aop_ptr->name);
489
490               if (_G.bInUse)
491                 emitcode ("pop", "b");
492
493               if (_G.accInUse)
494                 emitcode ("pop", "acc");
495             }
496           else
497             emitcode ("mov", "%s,#%s",
498                       aop->aopu.aop_ptr->name,
499                       sym->rname);
500           aop->paged = space->paged;
501         }
502       else
503         aop->aopu.aop_stk = sym->stack;
504       return aop;
505     }
506
507   if (sym->onStack && options.stack10bit)
508     {
509         short stack_val = -((sym->stack < 0) ?
510                             ((short) (sym->stack - _G.nRegsSaved)) :
511                             ((short) sym->stack)) ;
512         if (useDP2 && _G.dptr1InUse) {
513             emitcode ("push","dpl1");
514             emitcode ("push","dph1");
515             emitcode ("push","dpx1");
516         } else if (_G.dptrInUse ) {
517             emitcode ("push","dpl");
518             emitcode ("push","dph");
519             emitcode ("push","dpx");
520         }
521       /* It's on the 10 bit stack, which is located in
522        * far data space.
523        */           
524         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
525             if (useDP2) {
526                 if (options.model == MODEL_FLAT24)
527                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
528                 TR_DPTR("#2");
529                 emitcode ("mov", "dph1,_bpx+1");
530                 emitcode ("mov", "dpl1,_bpx");
531                 emitcode ("mov","dps,#1");
532             } else {
533                 if (options.model == MODEL_FLAT24)
534                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
535                 emitcode ("mov", "dph,_bpx+1");
536                 emitcode ("mov", "dpl,_bpx");
537             }
538             stack_val = -stack_val;
539             while (stack_val--) {
540                 emitcode ("inc","dptr");
541             }
542             if (useDP2) {
543                 emitcode("mov","dps,#0");
544             }
545         }  else {
546             if (_G.accInUse)
547                 emitcode ("push", "acc");
548             
549             if (_G.bInUse)
550                 emitcode ("push", "b");
551         
552             emitcode ("mov", "a,_bpx");
553             emitcode ("clr","c");
554             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555             emitcode ("mov","b,a");
556             emitcode ("mov","a,_bpx+1");
557             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
558             if (useDP2) {
559                 if (options.model == MODEL_FLAT24)
560                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
561                 TR_DPTR("#2");
562                 emitcode ("mov", "dph1,a");
563                 emitcode ("mov", "dpl1,b");
564             } else {
565                 if (options.model == MODEL_FLAT24)
566                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
567                 emitcode ("mov", "dph,a");
568                 emitcode ("mov", "dpl,b");
569             }
570             
571             if (_G.bInUse)
572                 emitcode ("pop", "b");
573             
574             if (_G.accInUse)
575                 emitcode ("pop", "acc");
576         }
577         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
578         aop->size = getSize (sym->type);
579         return aop;
580     }
581
582   /* if in bit space */
583   if (IN_BITSPACE (space))
584     {
585       sym->aop = aop = newAsmop (AOP_CRY);
586       aop->aopu.aop_dir = sym->rname;
587       aop->size = getSize (sym->type);
588       return aop;
589     }
590   /* if it is in direct space */
591   if (IN_DIRSPACE (space))
592     {
593       sym->aop = aop = newAsmop (AOP_DIR);
594       aop->aopu.aop_dir = sym->rname;
595       aop->size = getSize (sym->type);
596       return aop;
597     }
598
599   /* special case for a function */
600   if (IS_FUNC (sym->type))
601     {
602       sym->aop = aop = newAsmop (AOP_IMMD);
603       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
604       aop->size = FPTRSIZE;
605       return aop;
606     }
607   
608   /* only remaining is far space */
609   /* in which case DPTR gets the address */
610   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
611   if (useDP2)
612     {
613       genSetDPTR (1);
614       _flushLazyDPS ();
615       emitcode ("mov", "dptr,#%s", sym->rname);
616       genSetDPTR (0);
617     }
618   else
619     {
620       emitcode ("mov", "dptr,#%s", sym->rname);
621     }
622   aop->size = getSize (sym->type);
623
624   /* if it is in code space */
625   if (IN_CODESPACE (space))
626     aop->code = 1;
627
628   return aop;
629 }
630
631 /*-----------------------------------------------------------------*/
632 /* aopForRemat - rematerialzes an object                           */
633 /*-----------------------------------------------------------------*/
634 static asmop *
635 aopForRemat (symbol * sym)
636 {
637   iCode *ic = sym->rematiCode;
638   asmop *aop = newAsmop (AOP_IMMD);
639   int ptr_type =0;
640   int val = 0;
641
642   for (;;)
643     {
644       if (ic->op == '+')
645         val += (int) operandLitValue (IC_RIGHT (ic));
646       else if (ic->op == '-')
647         val -= (int) operandLitValue (IC_RIGHT (ic));
648       else if (IS_CAST_ICODE(ic)) {
649               sym_link *from_type = operandType(IC_RIGHT(ic));
650               aop->aopu.aop_immd.from_cast_remat = 1;
651               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
652               ptr_type = DCL_TYPE(from_type);
653               if (ptr_type == IPOINTER) {
654                 // bug #481053
655                 ptr_type = POINTER;
656               }
657               continue ;
658       } else break;
659       
660       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
661     }
662
663   if (val)
664   {
665       SNPRINTF (buffer, sizeof(buffer),
666                 "(%s %c 0x%04x)",
667                 OP_SYMBOL (IC_LEFT (ic))->rname,
668                 val >= 0 ? '+' : '-',
669                 abs (val) & 0xffff);
670   }
671   else 
672   {
673       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
674       {
675           SNPRINTF(buffer, sizeof(buffer), 
676                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
677       }
678       else
679       {
680           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
681       }
682   }
683
684   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
685   /* set immd2 field if required */
686   if (aop->aopu.aop_immd.from_cast_remat) 
687   {
688       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
689       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
690   }
691
692   return aop;
693 }
694
695 /*-----------------------------------------------------------------*/
696 /* aopHasRegs - returns true if aop has regs between from-to       */
697 /*-----------------------------------------------------------------*/
698 static int aopHasRegs(asmop *aop, int from, int to)
699 {
700     int size =0;
701
702     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
703
704     for (; size < aop->size ; size++) {
705         int reg;
706         for (reg = from ; reg <= to ; reg++)
707             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
708     }
709     return 0;
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* regsInCommon - two operands have some registers in common       */
714 /*-----------------------------------------------------------------*/
715 static bool
716 regsInCommon (operand * op1, operand * op2)
717 {
718   symbol *sym1, *sym2;
719   int i;
720
721   /* if they have registers in common */
722   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
723     return FALSE;
724
725   sym1 = OP_SYMBOL (op1);
726   sym2 = OP_SYMBOL (op2);
727
728   if (sym1->nRegs == 0 || sym2->nRegs == 0)
729     return FALSE;
730
731   for (i = 0; i < sym1->nRegs; i++)
732     {
733       int j;
734       if (!sym1->regs[i])
735         continue;
736
737       for (j = 0; j < sym2->nRegs; j++)
738         {
739           if (!sym2->regs[j])
740             continue;
741
742           if (sym2->regs[j] == sym1->regs[i])
743             return TRUE;
744         }
745     }
746
747   return FALSE;
748 }
749
750 /*-----------------------------------------------------------------*/
751 /* operandsEqu - equivalent                                        */
752 /*-----------------------------------------------------------------*/
753 static bool
754 operandsEqu (operand * op1, operand * op2)
755 {
756   symbol *sym1, *sym2;
757
758   /* if they not symbols */
759   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
760     return FALSE;
761
762   sym1 = OP_SYMBOL (op1);
763   sym2 = OP_SYMBOL (op2);
764
765   /* if both are itemps & one is spilt
766      and the other is not then false */
767   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
768       sym1->isspilt != sym2->isspilt)
769     return FALSE;
770
771   /* if they are the same */
772   if (sym1 == sym2)
773     return TRUE;
774
775   if (strcmp (sym1->rname, sym2->rname) == 0)
776     return TRUE;
777
778
779   /* if left is a tmp & right is not */
780   if (IS_ITEMP (op1) &&
781       !IS_ITEMP (op2) &&
782       sym1->isspilt &&
783       (sym1->usl.spillLoc == sym2))
784     return TRUE;
785
786   if (IS_ITEMP (op2) &&
787       !IS_ITEMP (op1) &&
788       sym2->isspilt &&
789       sym1->level > 0 &&
790       (sym2->usl.spillLoc == sym1))
791     return TRUE;
792
793   return FALSE;
794 }
795
796 /*-----------------------------------------------------------------*/
797 /* sameRegs - two asmops have the same registers                   */
798 /*-----------------------------------------------------------------*/
799 static bool
800 sameRegs (asmop * aop1, asmop * aop2)
801 {
802   int i;
803
804   if (aop1 == aop2)
805     {
806       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
807         {
808           return FALSE;
809         }
810       return TRUE;
811     }
812
813   if (aop1->type != AOP_REG ||
814       aop2->type != AOP_REG)
815     return FALSE;
816
817   if (aop1->size != aop2->size)
818     return FALSE;
819
820   for (i = 0; i < aop1->size; i++)
821     if (aop1->aopu.aop_reg[i] !=
822         aop2->aopu.aop_reg[i])
823       return FALSE;
824
825   return TRUE;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* aopOp - allocates an asmop for an operand  :                    */
830 /*-----------------------------------------------------------------*/
831 static void
832 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
833 {
834   asmop *aop;
835   symbol *sym;
836   int i;
837
838   if (!op)
839     return;
840
841   /* if this a literal */
842   if (IS_OP_LITERAL (op))
843     {
844       op->aop = aop = newAsmop (AOP_LIT);
845       aop->aopu.aop_lit = op->operand.valOperand;
846       aop->size = getSize (operandType (op));
847       return;
848     }
849
850   /* if already has a asmop then continue */
851   if (op->aop)
852     return;
853
854   /* if the underlying symbol has a aop */
855   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
856     {
857       op->aop = OP_SYMBOL (op)->aop;
858       return;
859     }
860
861   /* if this is a true symbol */
862   if (IS_TRUE_SYMOP (op))
863     {
864       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
865       return;
866     }
867
868   /* this is a temporary : this has
869      only four choices :
870      a) register
871      b) spillocation
872      c) rematerialize
873      d) conditional
874      e) can be a return use only */
875
876   sym = OP_SYMBOL (op);
877
878
879   /* if the type is a conditional */
880   if (sym->regType == REG_CND)
881     {
882       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
883       aop->size = 0;
884       return;
885     }
886
887   /* if it is spilt then two situations
888      a) is rematerialize
889      b) has a spill location */
890   if (sym->isspilt || sym->nRegs == 0)
891     {
892
893       /* rematerialize it NOW */
894       if (sym->remat)
895         {
896           sym->aop = op->aop = aop =
897             aopForRemat (sym);
898           aop->size = getSize (sym->type);
899           return;
900         }
901
902       if (sym->accuse)
903         {
904           int i;
905           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
906           aop->size = getSize (sym->type);
907           for (i = 0; i < 2; i++)
908             aop->aopu.aop_str[i] = accUse[i];
909           return;
910         }
911
912       if (sym->ruonly)
913         {
914           int i;
915
916           if (useDP2)
917             {
918               /* a AOP_STR uses DPTR, but DPTR is already in use;
919                * we're just hosed.
920                */
921                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
922             }
923
924           aop = op->aop = sym->aop = newAsmop (AOP_STR);
925           aop->size = getSize (sym->type);
926           for (i = 0; i < (int) fReturnSizeDS390; i++)
927             aop->aopu.aop_str[i] = fReturn[i];
928           return;
929         }
930       
931       if (sym->dptr) { /* has been allocated to a DPTRn */
932           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
933           aop->size = getSize (sym->type);
934           aop->aopu.dptr = sym->dptr;
935           return ;
936       }
937       /* else spill location  */
938       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
939           /* force a new aop if sizes differ */
940           sym->usl.spillLoc->aop = NULL;
941       }
942       sym->aop = op->aop = aop =
943         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
944       aop->size = getSize (sym->type);
945       return;
946     }
947
948   /* must be in a register */
949   sym->aop = op->aop = aop = newAsmop (AOP_REG);
950   aop->size = sym->nRegs;
951   for (i = 0; i < sym->nRegs; i++)
952     aop->aopu.aop_reg[i] = sym->regs[i];
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* freeAsmop - free up the asmop given to an operand               */
957 /*----------------------------------------------------------------*/
958 static void
959 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
960 {
961   asmop *aop;
962
963   if (!op)
964     aop = aaop;
965   else
966     aop = op->aop;
967
968   if (!aop)
969     return;
970
971   if (aop->freed)
972     goto dealloc;
973
974   aop->freed = 1;
975
976   /* depending on the asmop type only three cases need work AOP_RO
977      , AOP_R1 && AOP_STK */
978   switch (aop->type)
979     {
980     case AOP_R0:
981       if (_G.r0Pushed)
982         {
983           if (pop)
984             {
985               emitcode ("pop", "ar0");
986               _G.r0Pushed--;
987             }
988         }
989       bitVectUnSetBit (ic->rUsed, R0_IDX);
990       break;
991
992     case AOP_R1:
993       if (_G.r1Pushed)
994         {
995           if (pop)
996             {
997               emitcode ("pop", "ar1");
998               _G.r1Pushed--;
999             }
1000         }
1001       bitVectUnSetBit (ic->rUsed, R1_IDX);
1002       break;
1003
1004     case AOP_STK:
1005       {
1006         int sz = aop->size;
1007         int stk = aop->aopu.aop_stk + aop->size;
1008         bitVectUnSetBit (ic->rUsed, R0_IDX);
1009         bitVectUnSetBit (ic->rUsed, R1_IDX);
1010
1011         getFreePtr (ic, &aop, FALSE);
1012
1013         if (options.stack10bit)
1014           {
1015             /* I'm not sure what to do here yet... */
1016             /* #STUB */
1017             fprintf (stderr,
1018                      "*** Warning: probably generating bad code for "
1019                      "10 bit stack mode.\n");
1020           }
1021
1022         if (stk)
1023           {
1024             emitcode ("mov", "a,_bp");
1025             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1026             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1027           }
1028         else
1029           {
1030             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1031           }
1032
1033         while (sz--)
1034           {
1035             emitcode ("pop", "acc");
1036             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1037             if (!sz)
1038               break;
1039             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1040           }
1041         op->aop = aop;
1042         freeAsmop (op, NULL, ic, TRUE);
1043         if (_G.r0Pushed)
1044           {
1045             emitcode ("pop", "ar0");
1046             _G.r0Pushed--;
1047           }
1048
1049         if (_G.r1Pushed)
1050           {
1051             emitcode ("pop", "ar1");
1052             _G.r1Pushed--;
1053           }
1054       }
1055     case AOP_DPTR2:
1056         if (_G.dptr1InUse) {
1057             emitcode ("pop","dpx1");
1058             emitcode ("pop","dph1");
1059             emitcode ("pop","dpl1");
1060         }
1061         break;
1062     case AOP_DPTR:
1063         if (_G.dptrInUse) {
1064             emitcode ("pop","dpx");
1065             emitcode ("pop","dph");
1066             emitcode ("pop","dpl");
1067         }
1068         break;
1069     }
1070 dealloc:
1071   /* all other cases just dealloc */
1072   if (op)
1073     {
1074       op->aop = NULL;
1075       if (IS_SYMOP (op))
1076         {
1077           OP_SYMBOL (op)->aop = NULL;
1078           /* if the symbol has a spill */
1079           if (SPIL_LOC (op))
1080             SPIL_LOC (op)->aop = NULL;
1081         }
1082     }
1083 }
1084
1085 #define DEFAULT_ACC_WARNING 0
1086 static int saveAccWarn = DEFAULT_ACC_WARNING;
1087
1088 /*-------------------------------------------------------------------*/
1089 /* aopGet - for fetching value of the aop                            */
1090 /*                                                                   */
1091 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1092 /* in the accumulator. Set it to the name of a free register         */
1093 /* if acc must be preserved; the register will be used to preserve   */
1094 /* acc temporarily and to return the result byte.                    */
1095 /*-------------------------------------------------------------------*/
1096
1097 static char *
1098 aopGet (asmop *aop,
1099         int   offset,
1100         bool  bit16,
1101         bool  dname,
1102         char  *saveAcc)
1103 {
1104   /* offset is greater than
1105      size then zero */
1106   if (offset > (aop->size - 1) &&
1107       aop->type != AOP_LIT)
1108     return zero;
1109
1110   /* depending on type */
1111   switch (aop->type)
1112     {
1113
1114     case AOP_R0:
1115     case AOP_R1:
1116       /* if we need to increment it */
1117       while (offset > aop->coff)
1118         {
1119           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1120           aop->coff++;
1121         }
1122
1123       while (offset < aop->coff)
1124         {
1125           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126           aop->coff--;
1127         }
1128
1129       aop->coff = offset;
1130       if (aop->paged)
1131         {
1132           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1133           return (dname ? "acc" : "a");
1134         }
1135       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1136       return Safe_strdup(buffer);       
1137
1138     case AOP_DPTRn:
1139         assert(offset <= 3);
1140         return dptrn[aop->aopu.dptr][offset];
1141
1142     case AOP_DPTR:
1143     case AOP_DPTR2:
1144
1145       if (aop->type == AOP_DPTR2)
1146         {
1147           genSetDPTR (1);
1148         }
1149         
1150       if (saveAcc)
1151         {
1152             TR_AP("#1");
1153             if (aop->type != AOP_DPTR2)
1154             {
1155                 if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1156                 emitcode(";", "spanky: saveAcc for DPTR");
1157             }
1158             
1159             emitcode ("xch", "a, %s", saveAcc);
1160         }
1161
1162       _flushLazyDPS ();
1163
1164       while (offset > aop->coff)
1165         {
1166           emitcode ("inc", "dptr");
1167           aop->coff++;
1168         }
1169
1170       while (offset < aop->coff)
1171         {
1172           emitcode ("lcall", "__decdptr");
1173           aop->coff--;
1174         }
1175
1176       aop->coff = offset;
1177       if (aop->code)
1178         {
1179           emitcode ("clr", "a");
1180           emitcode ("movc", "a,@a+dptr");
1181         }
1182       else
1183         {
1184           emitcode ("movx", "a,@dptr");
1185         }
1186
1187       if (aop->type == AOP_DPTR2)
1188         {
1189           genSetDPTR (0);
1190         }
1191         
1192         if (saveAcc)
1193         {
1194        TR_AP("#2");
1195               emitcode ("xch", "a, %s", saveAcc);
1196               if (strcmp(saveAcc, "_ap"))
1197               {
1198                   emitcode(";", "spiffy: non _ap return from aopGet.");
1199               }
1200                   
1201               return saveAcc;
1202         }
1203       return (dname ? "acc" : "a");
1204
1205     case AOP_IMMD:
1206       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1207       {
1208           SNPRINTF(buffer, sizeof(buffer), 
1209                    "%s",aop->aopu.aop_immd.aop_immd2);
1210       } 
1211       else if (bit16)
1212       {
1213          SNPRINTF(buffer, sizeof(buffer), 
1214                   "#%s", aop->aopu.aop_immd.aop_immd1);
1215       }
1216       else if (offset) 
1217       {
1218           switch (offset) {
1219           case 1:
1220               tsprintf(buffer, sizeof(buffer),
1221                        "#!his",aop->aopu.aop_immd.aop_immd1);
1222               break;
1223           case 2:
1224               tsprintf(buffer, sizeof(buffer), 
1225                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1226               break;
1227           case 3:
1228               tsprintf(buffer, sizeof(buffer),
1229                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1230               break;
1231           default: /* should not need this (just in case) */
1232               SNPRINTF (buffer, sizeof(buffer), 
1233                         "#(%s >> %d)",
1234                        aop->aopu.aop_immd.aop_immd1,
1235                        offset * 8);
1236           }
1237       }
1238       else
1239       {
1240         SNPRINTF (buffer, sizeof(buffer), 
1241                   "#%s", aop->aopu.aop_immd.aop_immd1);
1242       }
1243       return Safe_strdup(buffer);       
1244
1245     case AOP_DIR:
1246       if (offset)
1247       {
1248         SNPRINTF (buffer, sizeof(buffer),
1249                   "(%s + %d)",
1250                  aop->aopu.aop_dir,
1251                  offset);
1252       }
1253       else
1254       {
1255         SNPRINTF(buffer, sizeof(buffer), 
1256                  "%s", aop->aopu.aop_dir);
1257       }
1258
1259       return Safe_strdup(buffer);
1260
1261     case AOP_REG:
1262       if (dname)
1263         return aop->aopu.aop_reg[offset]->dname;
1264       else
1265         return aop->aopu.aop_reg[offset]->name;
1266
1267     case AOP_CRY:
1268       emitcode ("clr", "a");
1269       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1270       emitcode ("rlc", "a");
1271       return (dname ? "acc" : "a");
1272
1273     case AOP_ACC:
1274       if (!offset && dname)
1275         return "acc";
1276       return aop->aopu.aop_str[offset];
1277
1278     case AOP_LIT:
1279       return aopLiteral (aop->aopu.aop_lit, offset);
1280
1281     case AOP_STR:
1282       aop->coff = offset;
1283       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1284           dname)
1285         return "acc";
1286
1287       return aop->aopu.aop_str[offset];
1288
1289     }
1290
1291   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1292           "aopget got unsupported aop->type");
1293   exit (1);
1294     
1295   return NULL;  // not reached, but makes compiler happy.
1296 }
1297 /*-----------------------------------------------------------------*/
1298 /* aopPut - puts a string for a aop                                */
1299 /*-----------------------------------------------------------------*/
1300 static void
1301 aopPut (asmop * aop, char *s, int offset)
1302 {
1303   if (aop->size && offset > (aop->size - 1))
1304     {
1305       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306               "aopPut got offset > aop->size");
1307       exit (1);
1308     }
1309
1310   /* will assign value to value */
1311   /* depending on where it is ofcourse */
1312   switch (aop->type)
1313     {
1314     case AOP_DIR:
1315         if (offset)
1316         {
1317             SNPRINTF (buffer, sizeof(buffer),
1318                       "(%s + %d)",
1319                       aop->aopu.aop_dir, offset);
1320         }
1321         else
1322         {
1323             SNPRINTF (buffer, sizeof(buffer), 
1324                      "%s", aop->aopu.aop_dir);
1325         }
1326         
1327
1328         if (strcmp (buffer, s))
1329         {
1330             emitcode ("mov", "%s,%s", buffer, s);
1331         }
1332       break;
1333
1334     case AOP_REG:
1335       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1336           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1337         {
1338           if (*s == '@' ||
1339               strcmp (s, "r0") == 0 ||
1340               strcmp (s, "r1") == 0 ||
1341               strcmp (s, "r2") == 0 ||
1342               strcmp (s, "r3") == 0 ||
1343               strcmp (s, "r4") == 0 ||
1344               strcmp (s, "r5") == 0 ||
1345               strcmp (s, "r6") == 0 ||
1346               strcmp (s, "r7") == 0)
1347             {
1348                 emitcode ("mov", "%s,%s",
1349                           aop->aopu.aop_reg[offset]->dname, s);
1350             }
1351             else
1352             {
1353                 emitcode ("mov", "%s,%s",
1354                           aop->aopu.aop_reg[offset]->name, s);
1355             }
1356         }
1357       break;
1358
1359     case AOP_DPTRn:
1360         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1361         break;
1362
1363     case AOP_DPTR:
1364     case AOP_DPTR2:
1365
1366       if (aop->type == AOP_DPTR2)
1367         {
1368           genSetDPTR (1);
1369         }
1370       _flushLazyDPS ();
1371
1372       if (aop->code)
1373         {
1374           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375                   "aopPut writting to code space");
1376           exit (1);
1377         }
1378
1379       while (offset > aop->coff)
1380         {
1381           aop->coff++;
1382           emitcode ("inc", "dptr");
1383         }
1384
1385       while (offset < aop->coff)
1386         {
1387           aop->coff--;
1388           emitcode ("lcall", "__decdptr");
1389         }
1390
1391       aop->coff = offset;
1392
1393       /* if not in accumulater */
1394       MOVA (s);
1395
1396       emitcode ("movx", "@dptr,a");
1397
1398       if (aop->type == AOP_DPTR2)
1399         {
1400           genSetDPTR (0);
1401         }
1402       break;
1403
1404     case AOP_R0:
1405     case AOP_R1:
1406       while (offset > aop->coff)
1407         {
1408           aop->coff++;
1409           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1410         }
1411       while (offset < aop->coff)
1412         {
1413           aop->coff--;
1414           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1415         }
1416       aop->coff = offset;
1417
1418       if (aop->paged)
1419         {
1420           MOVA (s);
1421           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1422
1423         }
1424       else if (*s == '@')
1425         {
1426           MOVA (s);
1427           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1428         }
1429       else if (strcmp (s, "r0") == 0 ||
1430                strcmp (s, "r1") == 0 ||
1431                strcmp (s, "r2") == 0 ||
1432                strcmp (s, "r3") == 0 ||
1433                strcmp (s, "r4") == 0 ||
1434                strcmp (s, "r5") == 0 ||
1435                strcmp (s, "r6") == 0 ||
1436                strcmp (s, "r7") == 0)
1437         {
1438           char buff[10];
1439           SNPRINTF(buff, sizeof(buff), 
1440                    "a%s", s);
1441           emitcode ("mov", "@%s,%s",
1442                     aop->aopu.aop_ptr->name, buff);
1443         }
1444         else
1445         {
1446             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1447         }
1448       break;
1449
1450     case AOP_STK:
1451       if (strcmp (s, "a") == 0)
1452         emitcode ("push", "acc");
1453       else
1454         if (*s=='@') {
1455           MOVA(s);
1456           emitcode ("push", "acc");
1457         } else {
1458           emitcode ("push", s);
1459         }
1460
1461       break;
1462
1463     case AOP_CRY:
1464       /* if bit variable */
1465       if (!aop->aopu.aop_dir)
1466         {
1467           emitcode ("clr", "a");
1468           emitcode ("rlc", "a");
1469         }
1470       else
1471         {
1472           if (s == zero)
1473             emitcode ("clr", "%s", aop->aopu.aop_dir);
1474           else if (s == one)
1475             emitcode ("setb", "%s", aop->aopu.aop_dir);
1476           else if (!strcmp (s, "c"))
1477             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1478           else
1479             {
1480               if (strcmp (s, "a"))
1481                 {
1482                   MOVA (s);
1483                 }
1484               {
1485                 /* set C, if a >= 1 */
1486                 emitcode ("add", "a,#!constbyte",0xff);
1487                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1488               }
1489             }
1490         }
1491       break;
1492
1493     case AOP_STR:
1494       aop->coff = offset;
1495       if (strcmp (aop->aopu.aop_str[offset], s))
1496         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1497       break;
1498
1499     case AOP_ACC:
1500       aop->coff = offset;
1501       if (!offset && (strcmp (s, "acc") == 0))
1502         break;
1503
1504       if (strcmp (aop->aopu.aop_str[offset], s))
1505         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1506       break;
1507
1508     default:
1509       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1510               "aopPut got unsupported aop->type");
1511       exit (1);
1512     }
1513
1514 }
1515
1516
1517 /*--------------------------------------------------------------------*/
1518 /* reAdjustPreg - points a register back to where it should (coff==0) */
1519 /*--------------------------------------------------------------------*/
1520 static void
1521 reAdjustPreg (asmop * aop)
1522 {
1523   if ((aop->coff==0) || (aop->size <= 1)) {
1524     return;
1525   }
1526
1527   switch (aop->type)
1528     {
1529     case AOP_R0:
1530     case AOP_R1:
1531       while (aop->coff--)
1532         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1533       break;
1534     case AOP_DPTR:
1535     case AOP_DPTR2:
1536       if (aop->type == AOP_DPTR2)
1537         {
1538           genSetDPTR (1);
1539           _flushLazyDPS ();
1540         }
1541       while (aop->coff--)
1542         {
1543           emitcode ("lcall", "__decdptr");
1544         }
1545
1546       if (aop->type == AOP_DPTR2)
1547         {
1548           genSetDPTR (0);
1549         }
1550       break;
1551
1552     }
1553   aop->coff=0;
1554 }
1555
1556 #define AOP(op) op->aop
1557 #define AOP_TYPE(op) AOP(op)->type
1558 #define AOP_SIZE(op) AOP(op)->size
1559 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1560                        AOP_TYPE(x) == AOP_R0))
1561
1562 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1563                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1564                          AOP(x)->paged))
1565
1566 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1567                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1568                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1569 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1570 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1571 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1572
1573 // The following two macros can be used even if the aop has not yet been aopOp'd.
1574 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1575 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1576
1577 /* Workaround for DS80C390 bug: div ab may return bogus results
1578  * if A is accessed in instruction immediately before the div.
1579  *
1580  * Will be fixed in B4 rev of processor, Dallas claims.
1581  */
1582
1583 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1584     if (!AOP_NEEDSACC(RIGHT))         \
1585     {               \
1586       /* We can load A first, then B, since     \
1587        * B (the RIGHT operand) won't clobber A,   \
1588        * thus avoiding touching A right before the div. \
1589        */             \
1590       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1591       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1592       MOVA(L);            \
1593       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1594       MOVB(L); \
1595     }               \
1596     else              \
1597     {               \
1598       /* Just stuff in a nop after loading A. */    \
1599       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1600       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1601       MOVA(L);            \
1602       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1603     }
1604
1605 /*-----------------------------------------------------------------*/
1606 /* genNotFloat - generates not for float operations              */
1607 /*-----------------------------------------------------------------*/
1608 static void
1609 genNotFloat (operand * op, operand * res)
1610 {
1611   int size, offset;
1612   char *l;
1613   symbol *tlbl;
1614
1615   D (emitcode (";", "genNotFloat "););
1616
1617   /* we will put 127 in the first byte of
1618      the result */
1619   aopPut (AOP (res), "#127", 0);
1620   size = AOP_SIZE (op) - 1;
1621   offset = 1;
1622
1623   _startLazyDPSEvaluation ();
1624   l = aopGet (op->aop, offset++, FALSE, FALSE, NULL);
1625   MOVA (l);
1626
1627   while (size--)
1628     {
1629       emitcode ("orl", "a,%s",
1630                 aopGet (op->aop,
1631                         offset++, FALSE, FALSE,
1632                         DP2_RESULT_REG));
1633     }
1634   _endLazyDPSEvaluation ();
1635
1636   tlbl = newiTempLabel (NULL);
1637   aopPut (res->aop, one, 1);
1638   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1639   aopPut (res->aop, zero, 1);
1640   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1641
1642   size = res->aop->size - 2;
1643   offset = 2;
1644   /* put zeros in the rest */
1645   while (size--)
1646     aopPut (res->aop, zero, offset++);
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* opIsGptr: returns non-zero if the passed operand is       */
1651 /* a generic pointer type.             */
1652 /*-----------------------------------------------------------------*/
1653 static int
1654 opIsGptr (operand * op)
1655 {
1656   sym_link *type = operandType (op);
1657
1658   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1659     {
1660       return 1;
1661     }
1662   return 0;
1663 }
1664
1665 /*-----------------------------------------------------------------*/
1666 /* getDataSize - get the operand data size                         */
1667 /*-----------------------------------------------------------------*/
1668 static int
1669 getDataSize (operand * op)
1670 {
1671   int size;
1672   size = AOP_SIZE (op);
1673   if (size == GPTRSIZE)
1674     {
1675       sym_link *type = operandType (op);
1676       if (IS_GENPTR (type))
1677         {
1678           /* generic pointer; arithmetic operations
1679            * should ignore the high byte (pointer type).
1680            */
1681           size--;
1682         }
1683     }
1684   return size;
1685 }
1686
1687 /*-----------------------------------------------------------------*/
1688 /* outAcc - output Acc                                             */
1689 /*-----------------------------------------------------------------*/
1690 static void
1691 outAcc (operand * result)
1692 {
1693   int size, offset;
1694   size = getDataSize (result);
1695   if (size)
1696     {
1697       aopPut (AOP (result), "a", 0);
1698       size--;
1699       offset = 1;
1700       /* unsigned or positive */
1701       while (size--)
1702         {
1703           aopPut (AOP (result), zero, offset++);
1704         }
1705     }
1706 }
1707
1708 /*-----------------------------------------------------------------*/
1709 /* outBitC - output a bit C                                        */
1710 /*-----------------------------------------------------------------*/
1711 static void
1712 outBitC (operand * result)
1713 {
1714   /* if the result is bit */
1715   if (AOP_TYPE (result) == AOP_CRY)
1716     {
1717       aopPut (AOP (result), "c", 0);
1718     }
1719   else
1720     {
1721       emitcode ("clr", "a");
1722       emitcode ("rlc", "a");
1723       outAcc (result);
1724     }
1725 }
1726
1727 /*-----------------------------------------------------------------*/
1728 /* toBoolean - emit code for orl a,operator(sizeop)                */
1729 /*-----------------------------------------------------------------*/
1730 static void
1731 toBoolean (operand * oper)
1732 {
1733   int   size = AOP_SIZE (oper) - 1;
1734   int   offset = 1;
1735   bool usedB = FALSE;
1736
1737   /* The generic part of a generic pointer should
1738    * not participate in it's truth value.
1739    *
1740    * i.e. 0x10000000 is zero.
1741    */
1742   if (opIsGptr (oper))
1743     {
1744       D (emitcode (";", "toBoolean: generic ptr special case."););
1745       size--;
1746     }
1747
1748   _startLazyDPSEvaluation ();
1749   if (AOP_NEEDSACC (oper) && size)
1750     {
1751       usedB = TRUE;
1752       if (_G.bInUse)
1753       {
1754           emitcode ("push", "b");
1755       }
1756       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1757     }
1758   else
1759     {
1760       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1761     }
1762     
1763   while (size--)
1764     {
1765       if (usedB)
1766         {
1767           emitcode ("orl", "b,%s",
1768                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1769         }
1770       else
1771         {
1772           emitcode ("orl", "a,%s",
1773                     aopGet (AOP (oper), offset++, FALSE, FALSE, DP2_RESULT_REG));
1774         }
1775     }
1776   _endLazyDPSEvaluation ();
1777
1778   if (usedB)
1779     {
1780       emitcode ("mov", "a,b");
1781       if (_G.bInUse)
1782       {
1783           emitcode ("pop", "b");
1784       }
1785         
1786     }
1787 }
1788
1789
1790 /*-----------------------------------------------------------------*/
1791 /* genNot - generate code for ! operation                          */
1792 /*-----------------------------------------------------------------*/
1793 static void
1794 genNot (iCode * ic)
1795 {
1796   symbol *tlbl;
1797   sym_link *optype = operandType (IC_LEFT (ic));
1798
1799   D (emitcode (";", "genNot "););
1800
1801   /* assign asmOps to operand & result */
1802   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1803   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1804
1805   /* if in bit space then a special case */
1806   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1807     {
1808       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1809       emitcode ("cpl", "c");
1810       outBitC (IC_RESULT (ic));
1811       goto release;
1812     }
1813
1814   /* if type float then do float */
1815   if (IS_FLOAT (optype))
1816     {
1817       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1818       goto release;
1819     }
1820
1821   toBoolean (IC_LEFT (ic));
1822
1823   tlbl = newiTempLabel (NULL);
1824   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1825   emitcode ("", "!tlabeldef", tlbl->key + 100);
1826   outBitC (IC_RESULT (ic));
1827
1828 release:
1829   /* release the aops */
1830   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1831   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1832 }
1833
1834
1835 /*-----------------------------------------------------------------*/
1836 /* genCpl - generate code for complement                           */
1837 /*-----------------------------------------------------------------*/
1838 static void
1839 genCpl (iCode * ic)
1840 {
1841   int offset = 0;
1842   int size;
1843   symbol *tlbl;
1844
1845   D (emitcode (";", "genCpl "););
1846
1847
1848   /* assign asmOps to operand & result */
1849   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1850   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1851
1852   /* special case if in bit space */
1853   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1854     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1855       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1856       emitcode ("cpl", "c");
1857       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1858       goto release;
1859     }
1860     tlbl=newiTempLabel(NULL);
1861     emitcode ("cjne", "%s,#0x01,%05d$", 
1862               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1863     emitcode ("", "%05d$:", tlbl->key+100);
1864     outBitC (IC_RESULT(ic));
1865     goto release;
1866   }
1867
1868   size = AOP_SIZE (IC_RESULT (ic));
1869   _startLazyDPSEvaluation ();
1870   while (size--)
1871     {
1872       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1873       emitcode ("cpl", "a");
1874       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1875     }
1876   _endLazyDPSEvaluation ();
1877
1878
1879 release:
1880   /* release the aops */
1881   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1882   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1883 }
1884
1885 /*-----------------------------------------------------------------*/
1886 /* genUminusFloat - unary minus for floating points                */
1887 /*-----------------------------------------------------------------*/
1888 static void
1889 genUminusFloat (operand * op, operand * result)
1890 {
1891   int size, offset = 0;
1892     
1893   D(emitcode (";", "genUminusFloat"););
1894   
1895   /* for this we just copy and then flip the bit */
1896     
1897   _startLazyDPSEvaluation ();
1898   size = AOP_SIZE (op) - 1;
1899
1900   while (size--)
1901   {
1902       aopPut (AOP (result),
1903               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1904               offset);
1905       offset++;
1906     }
1907   
1908   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1909
1910   emitcode ("cpl", "acc.7");
1911   aopPut (AOP (result), "a", offset);    
1912   _endLazyDPSEvaluation ();
1913 }
1914
1915 /*-----------------------------------------------------------------*/
1916 /* genUminus - unary minus code generation                         */
1917 /*-----------------------------------------------------------------*/
1918 static void
1919 genUminus (iCode * ic)
1920 {
1921   int offset, size;
1922   sym_link *optype;
1923
1924   D (emitcode (";", "genUminus "););
1925
1926   /* assign asmops */
1927   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1928   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1929
1930   /* if both in bit space then special
1931      case */
1932   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1933       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1934     {
1935
1936       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1937       emitcode ("cpl", "c");
1938       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1939       goto release;
1940     }
1941
1942   optype = operandType (IC_LEFT (ic));
1943
1944   /* if float then do float stuff */
1945   if (IS_FLOAT (optype))
1946     {
1947       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1948       goto release;
1949     }
1950
1951   /* otherwise subtract from zero */
1952   size = AOP_SIZE (IC_LEFT (ic));
1953   offset = 0;
1954   _startLazyDPSEvaluation ();
1955   while (size--)
1956     {
1957       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1958       if (!strcmp (l, "a"))
1959         {
1960           if (offset == 0)
1961             SETC;
1962           emitcode ("cpl", "a");
1963           emitcode ("addc", "a,#0");
1964         }
1965       else
1966         {
1967           if (offset == 0)
1968             CLRC;
1969           emitcode ("clr", "a");
1970           emitcode ("subb", "a,%s", l);
1971         }
1972       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1973     }
1974   _endLazyDPSEvaluation ();
1975
1976   /* if any remaining bytes in the result */
1977   /* we just need to propagate the sign   */
1978   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1979     {
1980       emitcode ("rlc", "a");
1981       emitcode ("subb", "a,acc");
1982       while (size--)
1983         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1984     }
1985
1986 release:
1987   /* release the aops */
1988   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1989   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1990 }
1991
1992 /*-----------------------------------------------------------------*/
1993 /* savermask - saves registers in the mask                         */
1994 /*-----------------------------------------------------------------*/
1995 static void savermask(bitVect *rs_mask)
1996 {
1997     int i;
1998     if (options.useXstack) {
1999         if (bitVectBitValue (rs_mask, R0_IDX))
2000             emitcode ("mov", "b,r0");
2001         emitcode ("mov", "r0,%s", spname);
2002         for (i = 0; i < ds390_nRegs; i++) {
2003             if (bitVectBitValue (rs_mask, i)) {
2004                 if (i == R0_IDX)
2005                     emitcode ("mov", "a,b");
2006                 else
2007                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2008                 emitcode ("movx", "@r0,a");
2009                 emitcode ("inc", "r0");
2010             }
2011         }
2012         emitcode ("mov", "%s,r0", spname);
2013         if (bitVectBitValue (rs_mask, R0_IDX))
2014             emitcode ("mov", "r0,b");
2015     } else {
2016         for (i = 0; i < ds390_nRegs; i++) {
2017             if (bitVectBitValue (rs_mask, i))
2018                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2019         }
2020     }
2021 }
2022
2023 /*-----------------------------------------------------------------*/
2024 /* saveRegisters - will look for a call and save the registers     */
2025 /*-----------------------------------------------------------------*/
2026 static void
2027 saveRegisters (iCode * lic)
2028 {
2029   iCode *ic;
2030   bitVect *rsave;
2031
2032   /* look for call */
2033   for (ic = lic; ic; ic = ic->next)
2034     if (ic->op == CALL || ic->op == PCALL)
2035       break;
2036
2037   if (!ic)
2038     {
2039       fprintf (stderr, "found parameter push with no function call\n");
2040       return;
2041     }
2042
2043   /* if the registers have been saved already then
2044      do nothing */
2045   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2046
2047   /* special case if DPTR alive across a function call then must save it 
2048      even though callee saves */
2049   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2050       int i;
2051       rsave = newBitVect(ic->rMask->size);
2052       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2053           if (bitVectBitValue(ic->rMask,i))
2054               rsave = bitVectSetBit(rsave,i);
2055       }
2056       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2057   } else {
2058     /* safe the registers in use at this time but skip the
2059        ones for the result */
2060     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2061                            ds390_rUmaskForOp (IC_RESULT(ic)));
2062   }
2063   ic->regsSaved = 1;
2064   savermask(rsave);
2065 }
2066
2067 /*-----------------------------------------------------------------*/
2068 /* usavermask - restore registers with mask                        */
2069 /*-----------------------------------------------------------------*/
2070 static void unsavermask(bitVect *rs_mask)
2071 {
2072     int i;
2073     if (options.useXstack) {
2074         emitcode ("mov", "r0,%s", spname);
2075         for (i = ds390_nRegs; i >= 0; i--) {
2076             if (bitVectBitValue (rs_mask, i)) {
2077                 emitcode ("dec", "r0");
2078                 emitcode ("movx", "a,@r0");
2079                 if (i == R0_IDX)
2080                     emitcode ("mov", "b,a");
2081                 else
2082                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2083             }       
2084         }
2085         emitcode ("mov", "%s,r0", spname);
2086         if (bitVectBitValue (rs_mask, R0_IDX))
2087             emitcode ("mov", "r0,b");
2088     } else {
2089         for (i = ds390_nRegs; i >= 0; i--) {
2090             if (bitVectBitValue (rs_mask, i))
2091                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2092         }
2093     }
2094 }
2095
2096 /*-----------------------------------------------------------------*/
2097 /* unsaveRegisters - pop the pushed registers                      */
2098 /*-----------------------------------------------------------------*/
2099 static void
2100 unsaveRegisters (iCode * ic)
2101 {
2102   bitVect *rsave;
2103
2104   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2105       int i;
2106       rsave = newBitVect(ic->rMask->size);
2107       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2108           if (bitVectBitValue(ic->rMask,i))
2109               rsave = bitVectSetBit(rsave,i);
2110       }
2111       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2112   } else {
2113     /* restore the registers in use at this time but skip the
2114        ones for the result */
2115     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2116                            ds390_rUmaskForOp (IC_RESULT(ic)));
2117   }
2118   unsavermask(rsave);
2119 }
2120
2121
2122 /*-----------------------------------------------------------------*/
2123 /* pushSide -                */
2124 /*-----------------------------------------------------------------*/
2125 static void
2126 pushSide (operand * oper, int size)
2127 {
2128   int offset = 0;
2129   _startLazyDPSEvaluation ();
2130   while (size--)
2131     {
2132       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2133       if (AOP_TYPE (oper) != AOP_REG &&
2134           AOP_TYPE (oper) != AOP_DIR &&
2135           strcmp (l, "a"))
2136         {
2137           emitcode ("mov", "a,%s", l);
2138           emitcode ("push", "acc");
2139         }
2140       else
2141         emitcode ("push", "%s", l);
2142     }
2143   _endLazyDPSEvaluation ();
2144 }
2145
2146 /*-----------------------------------------------------------------*/
2147 /* assignResultValue -               */
2148 /*-----------------------------------------------------------------*/
2149 static void
2150 assignResultValue (operand * oper)
2151 {
2152   int offset = 0;
2153   int size = AOP_SIZE (oper);
2154
2155   _startLazyDPSEvaluation ();
2156   while (size--)
2157     {
2158       aopPut (AOP (oper), fReturn[offset], offset);
2159       offset++;
2160     }
2161   _endLazyDPSEvaluation ();
2162 }
2163
2164
2165 /*-----------------------------------------------------------------*/
2166 /* genXpush - pushes onto the external stack                       */
2167 /*-----------------------------------------------------------------*/
2168 static void
2169 genXpush (iCode * ic)
2170 {
2171   asmop *aop = newAsmop (0);
2172   regs *r;
2173   int size, offset = 0;
2174
2175   D (emitcode (";", "genXpush ");
2176     );
2177
2178   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2179   r = getFreePtr (ic, &aop, FALSE);
2180
2181
2182   emitcode ("mov", "%s,_spx", r->name);
2183
2184   size = AOP_SIZE (IC_LEFT (ic));
2185   _startLazyDPSEvaluation ();
2186   while (size--)
2187     {
2188
2189       MOVA (aopGet (AOP (IC_LEFT (ic)),
2190                         offset++, FALSE, FALSE, NULL));
2191       emitcode ("movx", "@%s,a", r->name);
2192       emitcode ("inc", "%s", r->name);
2193
2194     }
2195   _endLazyDPSEvaluation ();
2196
2197
2198   emitcode ("mov", "_spx,%s", r->name);
2199
2200   freeAsmop (NULL, aop, ic, TRUE);
2201   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2202 }
2203
2204 /*-----------------------------------------------------------------*/
2205 /* genIpush - generate code for pushing this gets a little complex  */
2206 /*-----------------------------------------------------------------*/
2207 static void
2208 genIpush (iCode * ic)
2209 {
2210   int size, offset = 0;
2211   char *l;
2212
2213   D (emitcode (";", "genIpush ");
2214     );
2215
2216   /* if this is not a parm push : ie. it is spill push
2217      and spill push is always done on the local stack */
2218   if (!ic->parmPush)
2219     {
2220
2221       /* and the item is spilt then do nothing */
2222       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2223         return;
2224
2225       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226       size = AOP_SIZE (IC_LEFT (ic));
2227       /* push it on the stack */
2228       _startLazyDPSEvaluation ();
2229       while (size--)
2230         {
2231           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2232           if (*l == '#')
2233             {
2234               MOVA (l);
2235               l = "acc";
2236             }
2237           emitcode ("push", "%s", l);
2238         }
2239       _endLazyDPSEvaluation ();
2240       return;
2241     }
2242
2243   /* this is a paramter push: in this case we call
2244      the routine to find the call and save those
2245      registers that need to be saved */
2246   saveRegisters (ic);
2247
2248   /* if use external stack then call the external
2249      stack pushing routine */
2250   if (options.useXstack)
2251     {
2252       genXpush (ic);
2253       return;
2254     }
2255
2256   /* then do the push */
2257   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2258
2259   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2260   size = AOP_SIZE (IC_LEFT (ic));
2261
2262   _startLazyDPSEvaluation ();
2263   while (size--)
2264     {
2265       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2266       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2267           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2268           strcmp (l, "acc"))
2269         {
2270           emitcode ("mov", "a,%s", l);
2271           emitcode ("push", "acc");
2272         }
2273       else
2274         {
2275             emitcode ("push", "%s", l);
2276         }
2277     }
2278   _endLazyDPSEvaluation ();
2279
2280   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2281 }
2282
2283 /*-----------------------------------------------------------------*/
2284 /* genIpop - recover the registers: can happen only for spilling   */
2285 /*-----------------------------------------------------------------*/
2286 static void
2287 genIpop (iCode * ic)
2288 {
2289   int size, offset;
2290
2291   D (emitcode (";", "genIpop ");
2292     );
2293
2294
2295   /* if the temp was not pushed then */
2296   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2297     return;
2298
2299   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2300   size = AOP_SIZE (IC_LEFT (ic));
2301   offset = (size - 1);
2302   _startLazyDPSEvaluation ();
2303   while (size--)
2304     {
2305       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2306                                      FALSE, TRUE, NULL));
2307     }
2308   _endLazyDPSEvaluation ();
2309
2310   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2311 }
2312
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRBank - restores the resgister bank from stack            */
2315 /*-----------------------------------------------------------------*/
2316 static void
2317 unsaveRBank (int bank, iCode * ic, bool popPsw)
2318 {
2319   int i;
2320   asmop *aop = NULL;
2321   regs *r = NULL;
2322
2323   if (options.useXstack)
2324   {
2325       if (!ic)
2326       {
2327           /* Assume r0 is available for use. */
2328           r = ds390_regWithIdx (R0_IDX);;          
2329       } 
2330       else
2331       {
2332           aop = newAsmop (0);
2333           r = getFreePtr (ic, &aop, FALSE);
2334       }
2335       emitcode ("mov", "%s,_spx", r->name);      
2336   }
2337   
2338   if (popPsw)
2339     {
2340       if (options.useXstack)
2341       {
2342           emitcode ("movx", "a,@%s", r->name);
2343           emitcode ("mov", "psw,a");
2344           emitcode ("dec", "%s", r->name);
2345         }
2346       else
2347       {
2348         emitcode ("pop", "psw");
2349       }
2350     }
2351
2352   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2353     {
2354       if (options.useXstack)
2355         {
2356           emitcode ("movx", "a,@%s", r->name);
2357           emitcode ("mov", "(%s+%d),a",
2358                     regs390[i].base, 8 * bank + regs390[i].offset);
2359           emitcode ("dec", "%s", r->name);
2360
2361         }
2362       else
2363         emitcode ("pop", "(%s+%d)",
2364                   regs390[i].base, 8 * bank + regs390[i].offset);
2365     }
2366
2367   if (options.useXstack)
2368     {
2369       emitcode ("mov", "_spx,%s", r->name);
2370     }
2371     
2372   if (aop)
2373   {
2374       freeAsmop (NULL, aop, ic, TRUE);  
2375   }    
2376 }
2377
2378 /*-----------------------------------------------------------------*/
2379 /* saveRBank - saves an entire register bank on the stack          */
2380 /*-----------------------------------------------------------------*/
2381 static void
2382 saveRBank (int bank, iCode * ic, bool pushPsw)
2383 {
2384   int i;
2385   asmop *aop = NULL;
2386   regs *r = NULL;
2387
2388   if (options.useXstack)
2389     {
2390         if (!ic)
2391         {
2392           /* Assume r0 is available for use. */
2393                   r = ds390_regWithIdx (R0_IDX);;
2394         }
2395         else
2396         {
2397           aop = newAsmop (0);
2398           r = getFreePtr (ic, &aop, FALSE);
2399         }
2400         emitcode ("mov", "%s,_spx", r->name);    
2401     }
2402
2403   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2404     {
2405       if (options.useXstack)
2406         {
2407           emitcode ("inc", "%s", r->name);
2408           emitcode ("mov", "a,(%s+%d)",
2409                     regs390[i].base, 8 * bank + regs390[i].offset);
2410           emitcode ("movx", "@%s,a", r->name);
2411         }
2412       else
2413         emitcode ("push", "(%s+%d)",
2414                   regs390[i].base, 8 * bank + regs390[i].offset);
2415     }
2416
2417   if (pushPsw)
2418     {
2419       if (options.useXstack)
2420         {
2421           emitcode ("mov", "a,psw");
2422           emitcode ("movx", "@%s,a", r->name);
2423           emitcode ("inc", "%s", r->name);
2424           emitcode ("mov", "_spx,%s", r->name);
2425         }
2426       else
2427       {
2428         emitcode ("push", "psw");
2429       }
2430
2431       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2432     }
2433   
2434   if (aop)
2435   {
2436        freeAsmop (NULL, aop, ic, TRUE);
2437   }    
2438     
2439   if (ic)
2440   {  
2441       ic->bankSaved = 1;
2442   }
2443 }
2444
2445 /*-----------------------------------------------------------------*/
2446 /* genSend - gen code for SEND                                     */
2447 /*-----------------------------------------------------------------*/
2448 static void genSend(set *sendSet)
2449 {
2450     iCode *sic;
2451     int sendCount = 0 ;
2452     static int rb1_count = 0;
2453
2454     for (sic = setFirstItem (sendSet); sic;
2455          sic = setNextItem (sendSet)) {     
2456         int size, offset = 0;
2457         
2458         size=getSize(operandType(IC_LEFT(sic)));
2459         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2460         if (sendCount == 0) { /* first parameter */
2461             // we know that dpl(hxb) is the result, so
2462             rb1_count = 0 ;
2463             _startLazyDPSEvaluation ();
2464             if (size>1) {
2465                 aopOp (IC_LEFT (sic), sic, FALSE, 
2466                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2467             } else {
2468                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2469             }
2470             while (size--) {
2471                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2472                                   FALSE, FALSE, NULL);
2473                 if (strcmp (l, fReturn[offset])) {
2474                     emitcode ("mov", "%s,%s",
2475                               fReturn[offset],
2476                               l);
2477                 }
2478                 offset++;
2479             }
2480             _endLazyDPSEvaluation ();
2481             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2482             rb1_count =0;
2483         } else { /* if more parameter in registers */
2484             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2485             while (size--) {
2486                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2487                                                                 FALSE, FALSE, NULL));
2488             }
2489             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2490         }
2491         sendCount++;
2492     }
2493 }
2494
2495 /*-----------------------------------------------------------------*/
2496 /* genCall - generates a call statement                            */
2497 /*-----------------------------------------------------------------*/
2498 static void
2499 genCall (iCode * ic)
2500 {
2501   sym_link *dtype;
2502   bool restoreBank = FALSE;
2503   bool swapBanks = FALSE;
2504
2505   D (emitcode (";", "genCall "););
2506
2507   /* if we are calling a not _naked function that is not using
2508      the same register bank then we need to save the
2509      destination registers on the stack */
2510   dtype = operandType (IC_LEFT (ic));
2511   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2512       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2513       IFFUNC_ISISR (currFunc->type))
2514   {
2515       if (!ic->bankSaved) 
2516       {
2517            /* This is unexpected; the bank should have been saved in
2518             * genFunction.
2519             */
2520            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2521            restoreBank = TRUE;
2522       }
2523       swapBanks = TRUE;
2524   }
2525   
2526     /* if caller saves & we have not saved then */
2527     if (!ic->regsSaved)
2528       saveRegisters (ic);
2529   
2530   /* if send set is not empty the assign */
2531   /* We've saved all the registers we care about;
2532   * therefore, we may clobber any register not used
2533   * in the calling convention (i.e. anything not in
2534   * fReturn.
2535   */
2536   if (_G.sendSet)
2537     {
2538         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2539             genSend(reverseSet(_G.sendSet));
2540         } else {
2541             genSend(_G.sendSet);
2542         }
2543       _G.sendSet = NULL;
2544     }  
2545     
2546   if (swapBanks)
2547   {
2548         emitcode ("mov", "psw,#!constbyte", 
2549            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2550   }
2551
2552   /* make the call */
2553   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2554                             OP_SYMBOL (IC_LEFT (ic))->rname :
2555                             OP_SYMBOL (IC_LEFT (ic))->name));
2556
2557   if (swapBanks)
2558   {
2559        emitcode ("mov", "psw,#!constbyte", 
2560           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2561   }
2562
2563   /* if we need assign a result value */
2564   if ((IS_ITEMP (IC_RESULT (ic)) &&
2565        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2566         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2567         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2568       IS_TRUE_SYMOP (IC_RESULT (ic)))
2569     {
2570       if (isOperandInFarSpace (IC_RESULT (ic))
2571           && getSize (operandType (IC_RESULT (ic))) <= 2)
2572         {
2573           int size = getSize (operandType (IC_RESULT (ic)));
2574
2575           /* Special case for 1 or 2 byte return in far space. */
2576           MOVA (fReturn[0]);
2577           if (size > 1)
2578             {
2579               emitcode ("mov", "b,%s", fReturn[1]);
2580             }
2581
2582           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2583           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2584
2585           if (size > 1)
2586             {
2587               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2588             }
2589           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2590         }
2591       else
2592         {
2593           _G.accInUse++;
2594           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2595           _G.accInUse--;
2596
2597           assignResultValue (IC_RESULT (ic));
2598
2599           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2600         }
2601     }
2602
2603   /* adjust the stack for parameters if
2604      required */
2605   if (ic->parmBytes) {
2606       int i;
2607       if (options.stack10bit) {
2608           if (ic->parmBytes <= 10) {
2609               emitcode(";","stack adjustment for parms");
2610               for (i=0; i < ic->parmBytes ; i++) {
2611                   emitcode("pop","acc");
2612               }
2613           } else {            
2614               PROTECT_SP;
2615               emitcode ("clr","c");
2616               emitcode ("mov","a,sp");
2617               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2618               emitcode ("mov","sp,a");
2619               emitcode ("mov","a,esp");
2620               emitcode ("anl","a,#3");
2621               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2622               emitcode ("mov","esp,a");   
2623               UNPROTECT_SP;
2624           }
2625       } else {
2626           if (ic->parmBytes > 3) {
2627               emitcode ("mov", "a,%s", spname);
2628               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2629               emitcode ("mov", "%s,a", spname);
2630           } else
2631               for (i = 0; i < ic->parmBytes; i++)
2632                   emitcode ("dec", "%s", spname);
2633       }
2634   }
2635
2636   /* if we hade saved some registers then unsave them */
2637   if (ic->regsSaved)
2638     unsaveRegisters (ic);
2639
2640   /* if register bank was saved then pop them */
2641   if (restoreBank)
2642     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2643 }
2644
2645 /*-----------------------------------------------------------------*/
2646 /* genPcall - generates a call by pointer statement                */
2647 /*-----------------------------------------------------------------*/
2648 static void
2649 genPcall (iCode * ic)
2650 {
2651   sym_link *dtype;
2652   symbol *rlbl = newiTempLabel (NULL);
2653   bool restoreBank=FALSE;
2654
2655   D (emitcode (";", "genPcall ");
2656     );
2657
2658
2659   /* if caller saves & we have not saved then */
2660   if (!ic->regsSaved)
2661     saveRegisters (ic);
2662
2663   /* if we are calling a function that is not using
2664      the same register bank then we need to save the
2665      destination registers on the stack */
2666   dtype = operandType (IC_LEFT (ic));
2667   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2668       IFFUNC_ISISR (currFunc->type) &&
2669       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2670     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2671     restoreBank=TRUE;
2672   }
2673
2674   /* push the return address on to the stack */
2675   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2676   emitcode ("push", "acc");
2677   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2678   emitcode ("push", "acc");
2679
2680   if (options.model == MODEL_FLAT24)
2681     {
2682       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2683       emitcode ("push", "acc");
2684     }
2685
2686   /* now push the calling address */
2687   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2688
2689   pushSide (IC_LEFT (ic), FPTRSIZE);
2690
2691   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2692
2693   /* if send set is not empty the assign */
2694   if (_G.sendSet)
2695     {
2696         genSend(reverseSet(_G.sendSet));
2697         _G.sendSet = NULL;
2698     }
2699
2700   emitcode ("ret", "");
2701   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2702
2703
2704   /* if we need assign a result value */
2705   if ((IS_ITEMP (IC_RESULT (ic)) &&
2706        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2707         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2708       IS_TRUE_SYMOP (IC_RESULT (ic)))
2709     {
2710
2711       _G.accInUse++;
2712       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2713       _G.accInUse--;
2714
2715       assignResultValue (IC_RESULT (ic));
2716
2717       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2718     }
2719
2720   /* adjust the stack for parameters if
2721      required */
2722   if (ic->parmBytes)
2723     {
2724       int i;
2725       if (options.stack10bit) {
2726           if (ic->parmBytes <= 10) {
2727               emitcode(";","stack adjustment for parms");
2728               for (i=0; i < ic->parmBytes ; i++) {
2729                   emitcode("pop","acc");
2730               }
2731           } else {            
2732               PROTECT_SP;
2733               emitcode ("clr","c");
2734               emitcode ("mov","a,sp");
2735               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2736               emitcode ("mov","sp,a");
2737               emitcode ("mov","a,esp");
2738               emitcode ("anl","a,#3");
2739               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2740               emitcode ("mov","esp,a");   
2741               UNPROTECT_SP;
2742           }
2743       } else {
2744           if (ic->parmBytes > 3) {
2745               emitcode ("mov", "a,%s", spname);
2746               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2747               emitcode ("mov", "%s,a", spname);
2748           }
2749           else
2750               for (i = 0; i < ic->parmBytes; i++)
2751                   emitcode ("dec", "%s", spname);
2752           
2753       }
2754     }
2755   /* if register bank was saved then unsave them */
2756   if (restoreBank)
2757     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2758   
2759   /* if we hade saved some registers then
2760      unsave them */
2761   if (ic->regsSaved)
2762     unsaveRegisters (ic);
2763
2764 }
2765
2766 /*-----------------------------------------------------------------*/
2767 /* resultRemat - result  is rematerializable                       */
2768 /*-----------------------------------------------------------------*/
2769 static int
2770 resultRemat (iCode * ic)
2771 {
2772   if (SKIP_IC (ic) || ic->op == IFX)
2773     return 0;
2774
2775   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2776     {
2777       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2778       if (sym->remat && !POINTER_SET (ic))
2779         return 1;
2780     }
2781
2782   return 0;
2783 }
2784
2785 #if defined(__BORLANDC__) || defined(_MSC_VER)
2786 #define STRCASECMP stricmp
2787 #else
2788 #define STRCASECMP strcasecmp
2789 #endif
2790
2791 /*-----------------------------------------------------------------*/
2792 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2793 /*-----------------------------------------------------------------*/
2794 static bool
2795 inExcludeList (char *s)
2796 {
2797   int i = 0;
2798
2799   if (options.excludeRegs[i] &&
2800       STRCASECMP (options.excludeRegs[i], "none") == 0)
2801     return FALSE;
2802
2803   for (i = 0; options.excludeRegs[i]; i++)
2804     {
2805       if (options.excludeRegs[i] &&
2806           STRCASECMP (s, options.excludeRegs[i]) == 0)
2807         return TRUE;
2808     }
2809   return FALSE;
2810 }
2811
2812 /*-----------------------------------------------------------------*/
2813 /* genFunction - generated code for function entry                 */
2814 /*-----------------------------------------------------------------*/
2815 static void
2816 genFunction (iCode * ic)
2817 {
2818   symbol *sym;
2819   sym_link *ftype;
2820   bool   switchedPSW = FALSE;
2821
2822   D (emitcode (";", "genFunction "););
2823
2824   _G.nRegsSaved = 0;
2825   /* create the function header */
2826   emitcode (";", "-----------------------------------------");
2827   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2828   emitcode (";", "-----------------------------------------");
2829
2830   emitcode ("", "%s:", sym->rname);
2831   ftype = operandType (IC_LEFT (ic));
2832
2833   if (IFFUNC_ISNAKED(ftype))
2834   {
2835       emitcode(";", "naked function: no prologue.");
2836       return;
2837   }
2838   
2839   if (options.stack_probe) 
2840       emitcode ("lcall","__stack_probe");
2841   /* if critical function then turn interrupts off */
2842   if (IFFUNC_ISCRITICAL (ftype))
2843     emitcode ("clr", "ea");
2844
2845   /* here we need to generate the equates for the
2846      register bank if required */
2847   if (FUNC_REGBANK (ftype) != rbank)
2848     {
2849       int i;
2850
2851       rbank = FUNC_REGBANK (ftype);
2852       for (i = 0; i < ds390_nRegs; i++)
2853         {
2854           if (regs390[i].print) {
2855               if (strcmp (regs390[i].base, "0") == 0)
2856                   emitcode ("", "%s !equ !constbyte",
2857                             regs390[i].dname,
2858                             8 * rbank + regs390[i].offset);
2859               else
2860                   emitcode ("", "%s !equ %s + !constbyte",
2861                             regs390[i].dname,
2862                             regs390[i].base,
2863                             8 * rbank + regs390[i].offset);
2864           }
2865         }
2866     }
2867
2868   /* if this is an interrupt service routine then
2869      save acc, b, dpl, dph  */
2870   if (IFFUNC_ISISR (sym->type))
2871       { /* is ISR */
2872       if (!inExcludeList ("acc"))
2873         emitcode ("push", "acc");
2874       if (!inExcludeList ("b"))
2875         emitcode ("push", "b");
2876       if (!inExcludeList ("dpl"))
2877         emitcode ("push", "dpl");
2878       if (!inExcludeList ("dph"))
2879         emitcode ("push", "dph");
2880       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2881         {
2882           emitcode ("push", "dpx");
2883           /* Make sure we're using standard DPTR */
2884           emitcode ("push", "dps");
2885           emitcode ("mov", "dps,#0");
2886           if (options.stack10bit)
2887             {
2888               /* This ISR could conceivably use DPTR2. Better save it. */
2889               emitcode ("push", "dpl1");
2890               emitcode ("push", "dph1");
2891               emitcode ("push", "dpx1");
2892               emitcode ("push",  DP2_RESULT_REG);
2893             }
2894         }
2895       /* if this isr has no bank i.e. is going to
2896          run with bank 0 , then we need to save more
2897          registers :-) */
2898       if (!FUNC_REGBANK (sym->type))
2899         {
2900             int i;
2901
2902           /* if this function does not call any other
2903              function then we can be economical and
2904              save only those registers that are used */
2905           if (!IFFUNC_HASFCALL(sym->type))
2906             {
2907
2908               /* if any registers used */
2909               if (sym->regsUsed)
2910                 {
2911                   /* save the registers used */
2912                   for (i = 0; i < sym->regsUsed->size; i++)
2913                     {
2914                       if (bitVectBitValue (sym->regsUsed, i) ||
2915                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2916                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2917                     }
2918                 }
2919
2920             }
2921           else
2922             {
2923               /* this function has  a function call cannot
2924                  determines register usage so we will have to push the
2925                  entire bank */
2926               saveRBank (0, ic, FALSE);
2927               if (options.parms_in_bank1) {
2928                   for (i=0; i < 8 ; i++ ) {
2929                       emitcode ("push","%s",rb1regs[i]);
2930                   }
2931               }
2932             }
2933         }
2934         else
2935         {
2936             /* This ISR uses a non-zero bank.
2937              *
2938              * We assume that the bank is available for our
2939              * exclusive use.
2940              *
2941              * However, if this ISR calls a function which uses some
2942              * other bank, we must save that bank entirely.
2943              */
2944             unsigned long banksToSave = 0;
2945             
2946             if (IFFUNC_HASFCALL(sym->type))
2947             {
2948
2949 #define MAX_REGISTER_BANKS 4
2950
2951                 iCode *i;
2952                 int ix;
2953
2954                 for (i = ic; i; i = i->next)
2955                 {
2956                     if (i->op == ENDFUNCTION)
2957                     {
2958                         /* we got to the end OK. */
2959                         break;
2960                     }
2961                     
2962                     if (i->op == CALL)
2963                     {
2964                         sym_link *dtype;
2965                         
2966                         dtype = operandType (IC_LEFT(i));
2967                         if (dtype 
2968                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2969                         {
2970                              /* Mark this bank for saving. */
2971                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2972                              {
2973                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2974                              }
2975                              else
2976                              {
2977                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2978                              }
2979                              
2980                              /* And note that we don't need to do it in 
2981                               * genCall.
2982                               */
2983                              i->bankSaved = 1;
2984                         }
2985                     }
2986                     if (i->op == PCALL)
2987                     {
2988                         /* This is a mess; we have no idea what
2989                          * register bank the called function might
2990                          * use.
2991                          *
2992                          * The only thing I can think of to do is
2993                          * throw a warning and hope.
2994                          */
2995                         werror(W_FUNCPTR_IN_USING_ISR);   
2996                     }
2997                 }
2998
2999                 if (banksToSave && options.useXstack)
3000                 {
3001                     /* Since we aren't passing it an ic, 
3002                      * saveRBank will assume r0 is available to abuse.
3003                      *
3004                      * So switch to our (trashable) bank now, so
3005                      * the caller's R0 isn't trashed.
3006                      */
3007                     emitcode ("push", "psw");
3008                     emitcode ("mov", "psw,#!constbyte", 
3009                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3010                     switchedPSW = TRUE;
3011                 }
3012                 
3013                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3014                 {
3015                      if (banksToSave & (1 << ix))
3016                      {
3017                          saveRBank(ix, NULL, FALSE);
3018                      }
3019                 }
3020             }
3021             // jwk: this needs a closer look
3022             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3023         }
3024     }
3025   else
3026     {
3027       /* if callee-save to be used for this function
3028          then save the registers being used in this function */
3029       if (IFFUNC_CALLEESAVES(sym->type))
3030         {
3031           int i;
3032
3033           /* if any registers used */
3034           if (sym->regsUsed)
3035             {
3036               /* save the registers used */
3037               for (i = 0; i < sym->regsUsed->size; i++)
3038                 {
3039                   if (bitVectBitValue (sym->regsUsed, i) ||
3040                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3041                     {
3042                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3043                       _G.nRegsSaved++;
3044                     }
3045                 }
3046             }
3047         }
3048     }
3049
3050   /* set the register bank to the desired value */
3051   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3052    && !switchedPSW)
3053     {
3054       emitcode ("push", "psw");
3055       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3056     }
3057
3058   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3059        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3060       if (options.stack10bit) {
3061           emitcode ("push","_bpx");
3062           emitcode ("push","_bpx+1");
3063           emitcode ("mov","_bpx,%s",spname);
3064           emitcode ("mov","_bpx+1,esp");
3065           emitcode ("anl","_bpx+1,#3");
3066       } else {
3067           if (options.useXstack) {
3068               emitcode ("mov", "r0,%s", spname);
3069               emitcode ("mov", "a,_bp");
3070               emitcode ("movx", "@r0,a");
3071               emitcode ("inc", "%s", spname);
3072           } else {
3073               /* set up the stack */
3074               emitcode ("push", "_bp"); /* save the callers stack  */
3075           }
3076           emitcode ("mov", "_bp,%s", spname);
3077       }
3078   }
3079
3080   /* adjust the stack for the function */
3081   if (sym->stack) {
3082       int i = sym->stack;
3083       if (options.stack10bit) {
3084           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3085           assert (sym->recvSize <= 4);
3086           if (sym->stack <= 8) {
3087               while (i--) emitcode ("push","acc");
3088           } else {
3089               PROTECT_SP;
3090               emitcode ("mov","a,sp");
3091               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3092               emitcode ("mov","sp,a");
3093               emitcode ("mov","a,esp");
3094               emitcode ("anl","a,#3");
3095               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3096               emitcode ("mov","esp,a");
3097               UNPROTECT_SP;
3098           }
3099       } else {
3100           if (i > 256)
3101               werror (W_STACK_OVERFLOW, sym->name);
3102           
3103           if (i > 3 && sym->recvSize < 4) {
3104               
3105               emitcode ("mov", "a,sp");
3106               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3107               emitcode ("mov", "sp,a");
3108               
3109           } else
3110               while (i--)
3111                   emitcode ("inc", "sp");
3112       }
3113   }
3114
3115   if (sym->xstack)
3116     {
3117
3118       emitcode ("mov", "a,_spx");
3119       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3120       emitcode ("mov", "_spx,a");
3121     }
3122
3123 }
3124
3125 /*-----------------------------------------------------------------*/
3126 /* genEndFunction - generates epilogue for functions               */
3127 /*-----------------------------------------------------------------*/
3128 static void
3129 genEndFunction (iCode * ic)
3130 {
3131   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3132
3133   D (emitcode (";", "genEndFunction "););
3134
3135   if (IFFUNC_ISNAKED(sym->type))
3136   {
3137       emitcode(";", "naked function: no epilogue.");
3138       return;
3139   }
3140
3141   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3142        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3143
3144       if (options.stack10bit) {
3145           PROTECT_SP;     
3146           emitcode ("mov", "sp,_bpx", spname);
3147           emitcode ("mov", "esp,_bpx+1", spname);
3148           UNPROTECT_SP;
3149       } else {
3150           emitcode ("mov", "%s,_bp", spname);
3151       }
3152   }
3153
3154   /* if use external stack but some variables were
3155      added to the local stack then decrement the
3156      local stack */
3157   if (options.useXstack && sym->stack) {
3158       emitcode ("mov", "a,sp");
3159       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3160       emitcode ("mov", "sp,a");
3161   }
3162
3163
3164   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3165        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3166
3167       if (options.useXstack) {
3168           emitcode ("mov", "r0,%s", spname);
3169           emitcode ("movx", "a,@r0");
3170           emitcode ("mov", "_bp,a");
3171           emitcode ("dec", "%s", spname);
3172       } else {
3173           if (options.stack10bit) {
3174               emitcode ("pop", "_bpx+1");
3175               emitcode ("pop", "_bpx");
3176           } else {
3177               emitcode ("pop", "_bp");
3178           }
3179       }
3180   }
3181
3182   /* restore the register bank  */
3183   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3184   {
3185     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3186      || !options.useXstack)
3187     {
3188         /* Special case of ISR using non-zero bank with useXstack
3189          * is handled below.
3190          */
3191         emitcode ("pop", "psw");
3192     }
3193   } 
3194
3195   if (IFFUNC_ISISR (sym->type))
3196       { /* is ISR */  
3197
3198       /* now we need to restore the registers */
3199       /* if this isr has no bank i.e. is going to
3200          run with bank 0 , then we need to save more
3201          registers :-) */
3202       if (!FUNC_REGBANK (sym->type))
3203         {
3204             int i;
3205           /* if this function does not call any other
3206              function then we can be economical and
3207              save only those registers that are used */
3208           if (!IFFUNC_HASFCALL(sym->type))
3209             {
3210
3211               /* if any registers used */
3212               if (sym->regsUsed)
3213                 {
3214                   /* save the registers used */
3215                   for (i = sym->regsUsed->size; i >= 0; i--)
3216                     {
3217                       if (bitVectBitValue (sym->regsUsed, i) ||
3218                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3219                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3220                     }
3221                 }
3222
3223             }
3224           else
3225             {
3226               /* this function has  a function call cannot
3227                  determines register usage so we will have to pop the
3228                  entire bank */
3229               if (options.parms_in_bank1) {
3230                   for (i = 7 ; i >= 0 ; i-- ) {
3231                       emitcode ("pop","%s",rb1regs[i]);
3232                   }
3233               }
3234               unsaveRBank (0, ic, FALSE);
3235             }
3236         }
3237         else
3238         {
3239             /* This ISR uses a non-zero bank.
3240              *
3241              * Restore any register banks saved by genFunction
3242              * in reverse order.
3243              */
3244           // jwk: this needs a closer look
3245             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3246             int ix;
3247           
3248             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3249             {
3250                 if (savedBanks & (1 << ix))
3251                 {
3252                     unsaveRBank(ix, NULL, FALSE);
3253                 }
3254             }
3255             
3256             if (options.useXstack)
3257             {
3258                 /* Restore bank AFTER calling unsaveRBank,
3259                  * since it can trash r0.
3260                  */
3261                 emitcode ("pop", "psw");
3262             }
3263         }
3264
3265       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3266         {
3267           if (options.stack10bit)
3268             {
3269               emitcode ("pop", DP2_RESULT_REG);
3270               emitcode ("pop", "dpx1");
3271               emitcode ("pop", "dph1");
3272               emitcode ("pop", "dpl1");
3273             }
3274           emitcode ("pop", "dps");
3275           emitcode ("pop", "dpx");
3276         }
3277       if (!inExcludeList ("dph"))
3278         emitcode ("pop", "dph");
3279       if (!inExcludeList ("dpl"))
3280         emitcode ("pop", "dpl");
3281       if (!inExcludeList ("b"))
3282         emitcode ("pop", "b");
3283       if (!inExcludeList ("acc"))
3284         emitcode ("pop", "acc");
3285
3286       if (IFFUNC_ISCRITICAL (sym->type))
3287         emitcode ("setb", "ea");
3288
3289       /* if debug then send end of function */
3290       if (options.debug && currFunc) {
3291           _G.debugLine = 1;
3292           emitcode ("", "C$%s$%d$%d$%d ==.",
3293                     FileBaseName (ic->filename), currFunc->lastLine,
3294                     ic->level, ic->block);
3295           if (IS_STATIC (currFunc->etype))
3296             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3297           else
3298             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3299           _G.debugLine = 0;
3300         }
3301
3302       emitcode ("reti", "");
3303     }
3304   else
3305     {
3306       if (IFFUNC_ISCRITICAL (sym->type))
3307         emitcode ("setb", "ea");
3308
3309       if (IFFUNC_CALLEESAVES(sym->type))
3310         {
3311           int i;
3312
3313           /* if any registers used */
3314           if (sym->regsUsed)
3315             {
3316               /* save the registers used */
3317               for (i = sym->regsUsed->size; i >= 0; i--)
3318                 {
3319                   if (bitVectBitValue (sym->regsUsed, i) ||
3320                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3321                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3322                 }
3323             }
3324
3325         }
3326
3327       /* if debug then send end of function */
3328       if (options.debug && currFunc)
3329         {
3330           _G.debugLine = 1;
3331           emitcode ("", "C$%s$%d$%d$%d ==.",
3332                     FileBaseName (ic->filename), currFunc->lastLine,
3333                     ic->level, ic->block);
3334           if (IS_STATIC (currFunc->etype))
3335             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3336           else
3337             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3338           _G.debugLine = 0;
3339         }
3340
3341       emitcode ("ret", "");
3342     }
3343
3344 }
3345
3346 /*-----------------------------------------------------------------*/
3347 /* genJavaNativeRet - generate code for return JavaNative          */
3348 /*-----------------------------------------------------------------*/
3349 static void genJavaNativeRet(iCode *ic)
3350 {
3351     int i, size;
3352
3353     aopOp (IC_LEFT (ic), ic, FALSE, 
3354            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3355     size = AOP_SIZE (IC_LEFT (ic));
3356
3357     assert (size <= 4);
3358
3359     /* it is assigned to GPR0-R3 then push them */
3360     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3361         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3362         for (i = 0 ; i < size ; i++ ) {
3363             emitcode ("push","%s",
3364                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3365         }
3366         for (i = (size-1) ; i >= 0 ; i--) {
3367             emitcode ("pop","a%s",javaRet[i]);
3368         }
3369     } else {
3370         for (i = 0 ; i < size ; i++) 
3371             emitcode ("mov","%s,%s",javaRet[i],
3372                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3373     }
3374     for (i = size ; i < 4 ; i++ )
3375             emitcode ("mov","%s,#0",javaRet[i]);
3376     return;
3377 }
3378
3379 /*-----------------------------------------------------------------*/
3380 /* genRet - generate code for return statement                     */
3381 /*-----------------------------------------------------------------*/
3382 static void
3383 genRet (iCode * ic)
3384 {
3385   int size, offset = 0, pushed = 0;
3386
3387   D (emitcode (";", "genRet "););
3388
3389   /* if we have no return value then
3390      just generate the "ret" */
3391   if (!IC_LEFT (ic))
3392     goto jumpret;
3393
3394   /* if this is a JavaNative function then return 
3395      value in different register */
3396   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3397       genJavaNativeRet(ic);
3398       goto jumpret;
3399   }
3400   /* we have something to return then
3401      move the return value into place */
3402   aopOp (IC_LEFT (ic), ic, FALSE, 
3403          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3404   size = AOP_SIZE (IC_LEFT (ic));
3405
3406   _startLazyDPSEvaluation ();
3407   while (size--)
3408     {
3409       char *l;
3410       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3411         {
3412           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3413                       FALSE, TRUE, NULL);
3414           emitcode ("push", "%s", l);
3415           pushed++;
3416         }
3417       else
3418         {
3419           /* Since A is the last element of fReturn,
3420            * is is OK to clobber it in the aopGet.
3421            */
3422           l = aopGet (AOP (IC_LEFT (ic)), offset,
3423                       FALSE, FALSE, NULL);
3424           if (strcmp (fReturn[offset], l))
3425             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3426         }
3427     }
3428   _endLazyDPSEvaluation ();
3429
3430   if (pushed)
3431     {
3432       while (pushed)
3433         {
3434           pushed--;
3435           if (strcmp (fReturn[pushed], "a"))
3436             emitcode ("pop", fReturn[pushed]);
3437           else
3438             emitcode ("pop", "acc");
3439         }
3440     }
3441   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3442
3443 jumpret:
3444   /* generate a jump to the return label
3445      if the next is not the return statement */
3446   if (!(ic->next && ic->next->op == LABEL &&
3447         IC_LABEL (ic->next) == returnLabel))
3448
3449     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3450
3451 }
3452
3453 /*-----------------------------------------------------------------*/
3454 /* genLabel - generates a label                                    */
3455 /*-----------------------------------------------------------------*/
3456 static void
3457 genLabel (iCode * ic)
3458 {
3459   /* special case never generate */
3460   if (IC_LABEL (ic) == entryLabel)
3461     return;
3462
3463   D (emitcode (";", "genLabel ");
3464     );
3465
3466   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3467 }
3468
3469 /*-----------------------------------------------------------------*/
3470 /* genGoto - generates a ljmp                                      */
3471 /*-----------------------------------------------------------------*/
3472 static void
3473 genGoto (iCode * ic)
3474 {
3475   D (emitcode (";", "genGoto ");
3476     );
3477   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* findLabelBackwards: walks back through the iCode chain looking  */
3482 /* for the given label. Returns number of iCode instructions     */
3483 /* between that label and given ic.          */
3484 /* Returns zero if label not found.          */
3485 /*-----------------------------------------------------------------*/
3486 static int
3487 findLabelBackwards (iCode * ic, int key)
3488 {
3489   int count = 0;
3490
3491   while (ic->prev)
3492     {
3493       ic = ic->prev;
3494       count++;
3495
3496       /* If we have any pushes or pops, we cannot predict the distance.
3497          I don't like this at all, this should be dealt with in the 
3498          back-end */
3499       if (ic->op == IPUSH || ic->op == IPOP) {
3500         return 0;
3501       }
3502
3503       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3504         {
3505           /* printf("findLabelBackwards = %d\n", count); */
3506           return count;
3507         }
3508     }
3509
3510   return 0;
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* genPlusIncr :- does addition with increment if possible         */
3515 /*-----------------------------------------------------------------*/
3516 static bool
3517 genPlusIncr (iCode * ic)
3518 {
3519   unsigned int icount;
3520   unsigned int size = getDataSize (IC_RESULT (ic));
3521
3522   /* will try to generate an increment */
3523   /* if the right side is not a literal
3524      we cannot */
3525   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3526     return FALSE;
3527
3528   /* if the literal value of the right hand side
3529      is greater than 4 then it is not worth it */
3530   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3531     return FALSE;
3532
3533   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3534       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3535       while (icount--) {
3536           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3537       }
3538       return TRUE;
3539   }
3540   /* if increment 16 bits in register */
3541   if (
3542        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3543        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3544        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3545        (size > 1) &&
3546        (icount == 1))
3547     {
3548       symbol  *tlbl;
3549       int     emitTlbl;
3550       int     labelRange;
3551       char    *l;
3552
3553       /* If the next instruction is a goto and the goto target
3554        * is <= 5 instructions previous to this, we can generate
3555        * jumps straight to that target.
3556        */
3557       if (ic->next && ic->next->op == GOTO
3558           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3559           && labelRange <= 5)
3560         {
3561           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3562           tlbl = IC_LABEL (ic->next);
3563           emitTlbl = 0;
3564         }
3565       else
3566         {
3567           tlbl = newiTempLabel (NULL);
3568           emitTlbl = 1;
3569         }
3570         
3571       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3572       emitcode ("inc", "%s", l);
3573       
3574       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3575           IS_AOP_PREG (IC_RESULT (ic)))
3576       {   
3577         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3578       }
3579       else
3580       {
3581           emitcode ("clr", "a");
3582           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3583       }
3584
3585       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3586       emitcode ("inc", "%s", l);
3587       if (size > 2)
3588         {
3589             if (!strcmp(l, "acc"))
3590             {
3591                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3592             }
3593             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3594                      IS_AOP_PREG (IC_RESULT (ic)))
3595             {
3596                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3597             }
3598             else
3599             {
3600                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3601             }
3602
3603             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3604             emitcode ("inc", "%s", l);
3605         }
3606       if (size > 3)
3607         {
3608             if (!strcmp(l, "acc"))
3609             {
3610                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3611             }
3612             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3613                      IS_AOP_PREG (IC_RESULT (ic)))
3614             {
3615                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3616             }
3617             else
3618             {
3619                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3620             }
3621
3622             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3623             emitcode ("inc", "%s", l);  }
3624
3625       if (emitTlbl)
3626         {
3627           emitcode ("", "!tlabeldef", tlbl->key + 100);
3628         }
3629       return TRUE;
3630     }
3631
3632   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3633       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3634       options.model == MODEL_FLAT24 ) {
3635
3636       switch (size) {
3637       case 3:
3638           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3639       case 2:
3640           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3641       case 1:
3642           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3643           break;
3644       }
3645       while (icount--) emitcode ("inc","dptr");      
3646       return TRUE;
3647   }
3648
3649   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3650       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3651       icount <= 5 ) {
3652       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3653       while (icount--) emitcode ("inc","dptr");
3654       emitcode ("mov","dps,#0");
3655       return TRUE;
3656   }
3657
3658   /* if the sizes are greater than 1 then we cannot */
3659   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3660       AOP_SIZE (IC_LEFT (ic)) > 1)
3661     return FALSE;
3662
3663   /* we can if the aops of the left & result match or
3664      if they are in registers and the registers are the
3665      same */
3666   if (
3667        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3668        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3669        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3670     {
3671
3672       if (icount > 3)
3673         {
3674           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3675           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3676           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3677         }
3678       else
3679         {
3680
3681           _startLazyDPSEvaluation ();
3682           while (icount--)
3683             {
3684               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3685             }
3686           _endLazyDPSEvaluation ();
3687         }
3688
3689       return TRUE;
3690     }
3691
3692   return FALSE;
3693 }
3694
3695 /*-----------------------------------------------------------------*/
3696 /* outBitAcc - output a bit in acc                                 */
3697 /*-----------------------------------------------------------------*/
3698 static void
3699 outBitAcc (operand * result)
3700 {
3701   symbol *tlbl = newiTempLabel (NULL);
3702   /* if the result is a bit */
3703   if (AOP_TYPE (result) == AOP_CRY)
3704     {
3705       aopPut (AOP (result), "a", 0);
3706     }
3707   else
3708     {
3709       emitcode ("jz", "!tlabel", tlbl->key + 100);
3710       emitcode ("mov", "a,%s", one);
3711       emitcode ("", "!tlabeldef", tlbl->key + 100);
3712       outAcc (result);
3713     }
3714 }
3715
3716 /*-----------------------------------------------------------------*/
3717 /* genPlusBits - generates code for addition of two bits           */
3718 /*-----------------------------------------------------------------*/
3719 static void
3720 genPlusBits (iCode * ic)
3721 {
3722   D (emitcode (";", "genPlusBits "););
3723     
3724   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3725     {
3726       symbol *lbl = newiTempLabel (NULL);
3727       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3728       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3729       emitcode ("cpl", "c");
3730       emitcode ("", "!tlabeldef", (lbl->key + 100));
3731       outBitC (IC_RESULT (ic));
3732     }
3733   else
3734     {
3735       emitcode ("clr", "a");
3736       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3737       emitcode ("rlc", "a");
3738       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3739       emitcode ("addc", "a,#0");
3740       outAcc (IC_RESULT (ic));
3741     }
3742 }
3743
3744 static void
3745 adjustArithmeticResult (iCode * ic)
3746 {
3747   if (opIsGptr (IC_RESULT (ic)) &&
3748       opIsGptr (IC_LEFT (ic)) &&
3749       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3750     {
3751       aopPut (AOP (IC_RESULT (ic)),
3752               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3753               GPTRSIZE - 1);
3754     }
3755
3756   if (opIsGptr (IC_RESULT (ic)) &&
3757       opIsGptr (IC_RIGHT (ic)) &&
3758       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3759     {
3760       aopPut (AOP (IC_RESULT (ic)),
3761             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3762               GPTRSIZE - 1);
3763     }
3764
3765   if (opIsGptr (IC_RESULT (ic)) &&
3766       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3767       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3768       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3769       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3770     {
3771       char buff[5];
3772       SNPRINTF (buff, sizeof(buff), 
3773                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3774       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3775     }
3776 }
3777
3778 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3779 // generates the result if possible. If result is generated, returns TRUE; otherwise
3780 // returns false and caller must deal with fact that result isn't aopOp'd.
3781 bool aopOp3(iCode * ic)
3782 {
3783     bool dp1InUse, dp2InUse;
3784     bool useDp2;
3785     
3786     // First, generate the right opcode. DPTR may be used if neither left nor result are
3787     // of type AOP_STR.
3788     
3789 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3790 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3791 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3792 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3793 //      );
3794 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3795 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3796 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3797 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3798 //      );      
3799
3800     
3801     // Right uses DPTR unless left or result is an AOP_STR.
3802     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3803     
3804     // if the right used DPTR, left MUST use DPTR2.
3805     // if the right used DPTR2, left MUST use DPTR.
3806     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3807     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3808     // enabling us to assign DPTR to result.
3809      
3810     if (AOP_USESDPTR(IC_RIGHT(ic)))
3811     {
3812         useDp2 = TRUE;
3813     }
3814     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3815     {
3816         useDp2 = FALSE;
3817     }
3818     else
3819     {
3820         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3821         {
3822             useDp2 = TRUE;
3823         }
3824         else
3825         {
3826             useDp2 = FALSE;
3827         }
3828     }
3829
3830     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3831     
3832     // We've op'd the left & right. So, if left or right are the same operand as result, 
3833     // we know aopOp will succeed, and we can just do it & bail.
3834     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3835         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3836     {
3837 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3838         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3839         return TRUE;
3840     }
3841     
3842     // Note which dptrs are currently in use.
3843     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3844     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3845     
3846     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3847     // generate it.
3848     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3849     {
3850         return FALSE;
3851     }
3852     
3853     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3854     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3855     {
3856         return FALSE;
3857     }
3858     
3859     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3860     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3861     {
3862         return FALSE;
3863     }
3864
3865     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3866
3867     // Some sanity checking...
3868     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3869     {
3870         fprintf(stderr,
3871                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3872                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3873         emitcode(";", ">>> unexpected DPTR here.");
3874     }
3875     
3876     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3877     {
3878         fprintf(stderr,
3879                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3880                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3881         emitcode(";", ">>> unexpected DPTR2 here.");
3882     }    
3883     
3884     return TRUE;
3885 }
3886
3887 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3888 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3889 // will be set TRUE. The caller must then handle the case specially, noting
3890 // that the IC_RESULT operand is not aopOp'd.
3891 // 
3892 #define AOP_OP_3_NOFATAL(ic, rc) \
3893             do { rc = !aopOp3(ic); } while (0)
3894
3895 // aopOp the left & right operands of an ic.
3896 #define AOP_OP_2(ic) \
3897     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3898     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3899
3900 // convienience macro.
3901 #define AOP_SET_LOCALS(ic) \
3902     left = IC_LEFT(ic); \
3903     right = IC_RIGHT(ic); \
3904     result = IC_RESULT(ic);
3905
3906
3907 // Given an integer value of pushedSize bytes on the stack,
3908 // adjust it to be resultSize bytes, either by discarding
3909 // the most significant bytes or by zero-padding.
3910 //
3911 // On exit from this macro, pushedSize will have been adjusted to
3912 // equal resultSize, and ACC may be trashed.
3913 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3914       /* If the pushed data is bigger than the result,          \
3915        * simply discard unused bytes. Icky, but works.          \
3916        */                                                       \
3917       while (pushedSize > resultSize)                           \
3918       {                                                         \
3919           D (emitcode (";", "discarding unused result byte."););\
3920           emitcode ("pop", "acc");                              \
3921           pushedSize--;                                         \
3922       }                                                         \
3923       if (pushedSize < resultSize)                              \
3924       {                                                         \
3925           emitcode ("clr", "a");                                \
3926           /* Conversly, we haven't pushed enough here.          \
3927            * just zero-pad, and all is well.                    \
3928            */                                                   \
3929           while (pushedSize < resultSize)                       \
3930           {                                                     \
3931               emitcode("push", "acc");                          \
3932               pushedSize++;                                     \
3933           }                                                     \
3934       }                                                         \
3935       assert(pushedSize == resultSize);
3936
3937 /*-----------------------------------------------------------------*/
3938 /* genPlus - generates code for addition                           */
3939 /*-----------------------------------------------------------------*/
3940 static void
3941 genPlus (iCode * ic)
3942 {
3943   int size, offset = 0;
3944   bool pushResult;
3945   int rSize;
3946
3947   D (emitcode (";", "genPlus "););
3948
3949   /* special cases :- */
3950   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3951       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3952       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3953       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3954       if (size <= 9) {
3955           while (size--) emitcode ("inc","dptr");
3956       } else {
3957           emitcode ("mov","a,dpl");
3958           emitcode ("add","a,#!constbyte",size & 0xff);
3959           emitcode ("mov","dpl,a");
3960           emitcode ("mov","a,dph");
3961           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3962           emitcode ("mov","dph,a");
3963           emitcode ("mov","a,dpx");
3964           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3965           emitcode ("mov","dpx,a");
3966       }
3967       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3968       return ;
3969   }
3970   if ( IS_SYMOP(IC_LEFT(ic)) && 
3971        OP_SYMBOL(IC_LEFT(ic))->remat &&
3972        isOperandInFarSpace(IC_RIGHT(ic))) {
3973       operand *op = IC_RIGHT(ic);
3974       IC_RIGHT(ic) = IC_LEFT(ic);
3975       IC_LEFT(ic) = op;
3976   }
3977                 
3978   AOP_OP_3_NOFATAL (ic, pushResult);
3979     
3980   if (pushResult)
3981     {
3982       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3983     }
3984
3985   if (!pushResult)
3986     {
3987       /* if literal, literal on the right or
3988          if left requires ACC or right is already
3989          in ACC */
3990       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3991        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3992           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3993         {
3994           operand *t = IC_RIGHT (ic);
3995           IC_RIGHT (ic) = IC_LEFT (ic);
3996           IC_LEFT (ic) = t;
3997           emitcode (";", "Swapped plus args.");
3998         }
3999
4000       /* if both left & right are in bit
4001          space */
4002       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4003           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4004         {
4005           genPlusBits (ic);
4006           goto release;
4007         }
4008
4009       /* if left in bit space & right literal */
4010       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4011           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4012         {
4013           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4014           /* if result in bit space */
4015           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4016             {
4017               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4018                 emitcode ("cpl", "c");
4019               outBitC (IC_RESULT (ic));
4020             }
4021           else
4022             {
4023               size = getDataSize (IC_RESULT (ic));
4024               _startLazyDPSEvaluation ();
4025               while (size--)
4026                 {
4027                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4028                   emitcode ("addc", "a,#0");
4029                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4030                 }
4031               _endLazyDPSEvaluation ();
4032             }
4033           goto release;
4034         }
4035
4036       /* if I can do an increment instead
4037          of add then GOOD for ME */
4038       if (genPlusIncr (ic) == TRUE)
4039         {
4040           emitcode (";", "did genPlusIncr");
4041           goto release;
4042         }
4043
4044     }
4045   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4046
4047   _startLazyDPSEvaluation ();
4048   while (size--)
4049     {
4050       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4051         {
4052           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4053           if (offset == 0)
4054             emitcode ("add", "a,%s",
4055                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4056           else
4057             emitcode ("addc", "a,%s",
4058                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, DP2_RESULT_REG));
4059         }
4060       else
4061         {
4062           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4063           {
4064               /* right is going to use ACC or we would have taken the
4065                * above branch.
4066                */
4067               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4068        TR_AP("#3");
4069               D(emitcode(";", "+ AOP_ACC special case."););
4070               emitcode("xch", "a, %s", DP2_RESULT_REG);
4071           }
4072           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4073           if (offset == 0)
4074           {
4075             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4076             {
4077          TR_AP("#4");
4078                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4079             }
4080             else
4081             {
4082                 emitcode ("add", "a,%s",
4083                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4084                                   DP2_RESULT_REG));
4085             }
4086           }
4087           else
4088           {
4089             emitcode ("addc", "a,%s",
4090                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4091                           DP2_RESULT_REG));
4092           }
4093         }
4094       if (!pushResult)
4095         {
4096           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4097         }
4098       else
4099         {
4100           emitcode ("push", "acc");
4101         }
4102       offset++;
4103     }
4104   _endLazyDPSEvaluation ();
4105
4106   if (pushResult)
4107     {
4108       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4109
4110       size = getDataSize (IC_LEFT (ic));
4111       rSize = getDataSize (IC_RESULT (ic));
4112
4113       ADJUST_PUSHED_RESULT(size, rSize);
4114
4115       _startLazyDPSEvaluation ();
4116       while (size--)
4117         {
4118           emitcode ("pop", "acc");
4119           aopPut (AOP (IC_RESULT (ic)), "a", size);
4120         }
4121       _endLazyDPSEvaluation ();
4122     }
4123
4124   adjustArithmeticResult (ic);
4125
4126 release:
4127   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4130 }
4131
4132 /*-----------------------------------------------------------------*/
4133 /* genMinusDec :- does subtraction with deccrement if possible     */
4134 /*-----------------------------------------------------------------*/
4135 static bool
4136 genMinusDec (iCode * ic)
4137 {
4138   unsigned int icount;
4139   unsigned int size = getDataSize (IC_RESULT (ic));
4140
4141   /* will try to generate an increment */
4142   /* if the right side is not a literal
4143      we cannot */
4144   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4145     return FALSE;
4146
4147   /* if the literal value of the right hand side
4148      is greater than 4 then it is not worth it */
4149   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4150     return FALSE;
4151
4152   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4153       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4154       while (icount--) {
4155           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4156       }
4157       return TRUE;
4158   }
4159   /* if decrement 16 bits in register */
4160   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4161       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4162       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4163       (size > 1) &&
4164       (icount == 1))
4165     {
4166       symbol *tlbl;
4167       int    emitTlbl;
4168       int    labelRange;
4169       char   *l;
4170
4171       /* If the next instruction is a goto and the goto target
4172          * is <= 5 instructions previous to this, we can generate
4173          * jumps straight to that target.
4174        */
4175       if (ic->next && ic->next->op == GOTO
4176           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4177           && labelRange <= 5)
4178         {
4179           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4180           tlbl = IC_LABEL (ic->next);
4181           emitTlbl = 0;
4182         }
4183       else
4184         {
4185           tlbl = newiTempLabel (NULL);
4186           emitTlbl = 1;
4187         }
4188
4189       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4190       emitcode ("dec", "%s", l);
4191  
4192       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4193           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4194           IS_AOP_PREG (IC_RESULT (ic)))
4195       {     
4196           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4197       }
4198       else
4199       {
4200           emitcode ("mov", "a,#!constbyte",0xff);
4201           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4202       }
4203       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, NULL, NULL);
4204       emitcode ("dec", "%s", l);
4205       if (size > 2)
4206         {
4207             if (!strcmp(l, "acc"))
4208             {
4209                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4210             }
4211             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4212                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4213                      IS_AOP_PREG (IC_RESULT (ic)))
4214             {       
4215                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4216             }
4217             else
4218             {
4219                 emitcode ("mov", "a,#!constbyte",0xff);
4220                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4221             }
4222             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, NULL, NULL);
4223             emitcode ("dec", "%s", l);
4224         }
4225       if (size > 3)
4226         {
4227             if (!strcmp(l, "acc"))
4228             {
4229                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4230             }
4231             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4232                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4233                      IS_AOP_PREG (IC_RESULT (ic)))
4234             {       
4235                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4236             }
4237             else
4238             {
4239                 emitcode ("mov", "a,#!constbyte",0xff);
4240                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4241             }       
4242             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, NULL, NULL);
4243             emitcode ("dec", "%s", l);
4244         }
4245       if (emitTlbl)
4246         {
4247           emitcode ("", "!tlabeldef", tlbl->key + 100);
4248         }
4249       return TRUE;
4250     }
4251
4252   /* if the sizes are greater than 1 then we cannot */
4253   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4254       AOP_SIZE (IC_LEFT (ic)) > 1)
4255     return FALSE;
4256
4257   /* we can if the aops of the left & result match or
4258      if they are in registers and the registers are the
4259      same */
4260   if (
4261        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4262        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4263        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4264     {
4265
4266       _startLazyDPSEvaluation ();
4267       while (icount--)
4268         {
4269           emitcode ("dec", "%s",
4270                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4271         }
4272       _endLazyDPSEvaluation ();
4273
4274       return TRUE;
4275     }
4276
4277   return FALSE;
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* addSign - complete with sign                                    */
4282 /*-----------------------------------------------------------------*/
4283 static void
4284 addSign (operand * result, int offset, int sign)
4285 {
4286   int size = (getDataSize (result) - offset);
4287   if (size > 0)
4288     {
4289       _startLazyDPSEvaluation();
4290       if (sign)
4291         {
4292           emitcode ("rlc", "a");
4293           emitcode ("subb", "a,acc");
4294           while (size--)
4295           {
4296             aopPut (AOP (result), "a", offset++);
4297           }
4298         }
4299       else
4300       {
4301         while (size--)
4302         {
4303           aopPut (AOP (result), zero, offset++);
4304         }
4305       }
4306       _endLazyDPSEvaluation();
4307     }
4308 }
4309
4310 /*-----------------------------------------------------------------*/
4311 /* genMinusBits - generates code for subtraction  of two bits      */
4312 /*-----------------------------------------------------------------*/
4313 static void
4314 genMinusBits (iCode * ic)
4315 {
4316   symbol *lbl = newiTempLabel (NULL);
4317
4318   D (emitcode (";", "genMinusBits "););
4319
4320   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4321     {
4322       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4323       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4324       emitcode ("cpl", "c");
4325       emitcode ("", "!tlabeldef", (lbl->key + 100));
4326       outBitC (IC_RESULT (ic));
4327     }
4328   else
4329     {
4330       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4331       emitcode ("subb", "a,acc");
4332       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4333       emitcode ("inc", "a");
4334       emitcode ("", "!tlabeldef", (lbl->key + 100));
4335       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4336       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4337     }
4338 }
4339
4340 /*-----------------------------------------------------------------*/
4341 /* genMinus - generates code for subtraction                       */
4342 /*-----------------------------------------------------------------*/
4343 static void
4344 genMinus (iCode * ic)
4345 {
4346     int size, offset = 0;
4347     int rSize;
4348     long lit = 0L;
4349     bool pushResult;
4350
4351     D (emitcode (";", "genMinus "););
4352
4353     AOP_OP_3_NOFATAL(ic, pushResult);   
4354
4355     if (!pushResult)
4356     {
4357       /* special cases :- */
4358       /* if both left & right are in bit space */
4359       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4360           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4361         {
4362           genMinusBits (ic);
4363           goto release;
4364         }
4365
4366       /* if I can do an decrement instead
4367          of subtract then GOOD for ME */
4368       if (genMinusDec (ic) == TRUE)
4369         goto release;
4370
4371     }
4372
4373   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4374
4375   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4376     {
4377       CLRC;
4378     }
4379   else
4380     {
4381       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4382       lit = -lit;
4383     }
4384
4385
4386   /* if literal, add a,#-lit, else normal subb */
4387   _startLazyDPSEvaluation ();
4388   while (size--) {
4389       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4390           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4391               emitcode ("mov","b,%s",
4392                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4393               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4394               emitcode ("subb","a,b");
4395           } else {
4396               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4397               emitcode ("subb", "a,%s",
4398                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4399                                 DP2_RESULT_REG));
4400           }
4401       } else {
4402           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4403           /* first add without previous c */
4404           if (!offset) {
4405               if (!size && lit==-1) {
4406                   emitcode ("dec", "a");
4407               } else {
4408                   emitcode ("add", "a,#!constbyte",
4409                             (unsigned int) (lit & 0x0FFL));
4410               }
4411           } else {
4412               emitcode ("addc", "a,#!constbyte",
4413                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4414           }
4415       }
4416       
4417       if (pushResult) {
4418           emitcode ("push", "acc");
4419       } else {
4420           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4421       }
4422       offset++;
4423   }
4424   _endLazyDPSEvaluation ();
4425   
4426   if (pushResult)
4427     {
4428       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4429
4430       size = getDataSize (IC_LEFT (ic));
4431       rSize = getDataSize (IC_RESULT (ic));
4432
4433       ADJUST_PUSHED_RESULT(size, rSize);
4434
4435       _startLazyDPSEvaluation ();
4436       while (size--)
4437         {
4438           emitcode ("pop", "acc");
4439           aopPut (AOP (IC_RESULT (ic)), "a", size);
4440         }
4441       _endLazyDPSEvaluation ();
4442     }
4443
4444   adjustArithmeticResult (ic);
4445
4446 release:
4447   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4448   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4449   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4450 }
4451
4452
4453 /*-----------------------------------------------------------------*/
4454 /* genMultbits :- multiplication of bits                           */
4455 /*-----------------------------------------------------------------*/
4456 static void
4457 genMultbits (operand * left,
4458              operand * right,
4459              operand * result,
4460              iCode   * ic)
4461 {
4462   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4463   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4464   aopOp(result, ic, TRUE, FALSE);
4465   outBitC (result);
4466 }
4467
4468
4469 /*-----------------------------------------------------------------*/
4470 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4471 /*-----------------------------------------------------------------*/
4472 static void
4473 genMultOneByte (operand * left,
4474                 operand * right,
4475                 operand * result,
4476                 iCode   * ic)
4477 {
4478   sym_link *opetype = operandType (result);
4479   symbol *lbl;
4480
4481
4482   /* (if two literals: the value is computed before) */
4483   /* if one literal, literal on the right */
4484   if (AOP_TYPE (left) == AOP_LIT)
4485     {
4486       operand *t = right;
4487       right = left;
4488       left = t;
4489       emitcode (";", "swapped left and right");
4490     }
4491
4492   if (SPEC_USIGN(opetype)
4493       // ignore the sign of left and right, what else can we do?
4494       || (SPEC_USIGN(operandType(left)) && 
4495           SPEC_USIGN(operandType(right)))) {
4496     // just an unsigned 8*8=8/16 multiply
4497     //emitcode (";","unsigned");
4498     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4499     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4500     emitcode ("mul", "ab");
4501    
4502     _G.accInUse++; _G.bInUse++;
4503     aopOp(result, ic, TRUE, FALSE);
4504       
4505       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4506       {
4507           // this should never happen
4508           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4509                    AOP_SIZE(result), __FILE__, lineno);
4510           exit (1);
4511       }      
4512       
4513     aopPut (AOP (result), "a", 0);
4514     _G.accInUse--; _G.bInUse--;
4515     if (AOP_SIZE(result)==2) 
4516     {
4517       aopPut (AOP (result), "b", 1);
4518     }
4519     return;
4520   }
4521
4522   // we have to do a signed multiply
4523
4524   emitcode (";", "signed");
4525   emitcode ("clr", "F0"); // reset sign flag
4526   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4527
4528   lbl=newiTempLabel(NULL);
4529   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4530   // left side is negative, 8-bit two's complement, this fails for -128
4531   emitcode ("setb", "F0"); // set sign flag
4532   emitcode ("cpl", "a");
4533   emitcode ("inc", "a");
4534
4535   emitcode ("", "!tlabeldef", lbl->key+100);
4536
4537   /* if literal */
4538   if (AOP_TYPE(right)==AOP_LIT) {
4539     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4540     /* AND literal negative */
4541     if ((int) val < 0) {
4542       emitcode ("cpl", "F0"); // complement sign flag
4543       emitcode ("mov", "b,#!constbyte", -val);
4544     } else {
4545       emitcode ("mov", "b,#!constbyte", val);
4546     }
4547   } else {
4548     lbl=newiTempLabel(NULL);
4549     emitcode ("mov", "b,a");
4550     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4551     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4552     // right side is negative, 8-bit two's complement
4553     emitcode ("cpl", "F0"); // complement sign flag
4554     emitcode ("cpl", "a");
4555     emitcode ("inc", "a");
4556     emitcode ("", "!tlabeldef", lbl->key+100);
4557   }
4558   emitcode ("mul", "ab");
4559     
4560   _G.accInUse++;_G.bInUse++;
4561   aopOp(result, ic, TRUE, FALSE);
4562     
4563   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4564   {
4565     // this should never happen
4566       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4567                AOP_SIZE(result), __FILE__, lineno);
4568       exit (1);
4569   }    
4570     
4571   lbl=newiTempLabel(NULL);
4572   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4573   // only ONE op was negative, we have to do a 8/16-bit two's complement
4574   emitcode ("cpl", "a"); // lsb
4575   if (AOP_SIZE(result)==1) {
4576     emitcode ("inc", "a");
4577   } else {
4578     emitcode ("add", "a,#1");
4579     emitcode ("xch", "a,b");
4580     emitcode ("cpl", "a"); // msb
4581     emitcode ("addc", "a,#0");
4582     emitcode ("xch", "a,b");
4583   }
4584
4585   emitcode ("", "!tlabeldef", lbl->key+100);
4586   aopPut (AOP (result), "a", 0);
4587   _G.accInUse--;_G.bInUse--;
4588   if (AOP_SIZE(result)==2) {
4589     aopPut (AOP (result), "b", 1);
4590   }
4591 }
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4595 /*-----------------------------------------------------------------*/
4596 static void genMultTwoByte (operand *left, operand *right, 
4597                             operand *result, iCode *ic)
4598 {
4599         sym_link *retype = getSpec(operandType(right));
4600         sym_link *letype = getSpec(operandType(left));
4601         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4602         symbol *lbl;
4603
4604         if (AOP_TYPE (left) == AOP_LIT) {
4605                 operand *t = right;
4606                 right = left;
4607                 left = t;
4608         }
4609         /* save EA bit in F1 */
4610         lbl = newiTempLabel(NULL);
4611         emitcode ("setb","F1");
4612         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4613         emitcode ("clr","F1");
4614         emitcode("","!tlabeldef",lbl->key+100);
4615
4616         /* load up MB with right */
4617         if (!umult) {
4618                 emitcode("clr","F0");
4619                 if (AOP_TYPE(right) == AOP_LIT) {
4620                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4621                         if (val < 0) {
4622                                 emitcode("setb","F0");
4623                                 val = -val;
4624                         }
4625                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4626                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4627                 } else {
4628                         lbl = newiTempLabel(NULL);
4629                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4630                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4631                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4632                         emitcode ("xch", "a,b");
4633                         emitcode ("cpl","a");
4634                         emitcode ("add", "a,#1");
4635                         emitcode ("xch", "a,b");
4636                         emitcode ("cpl", "a"); // msb
4637                         emitcode ("addc", "a,#0");
4638                         emitcode ("setb","F0");
4639                         emitcode ("","!tlabeldef",lbl->key+100);
4640                         emitcode ("mov","mb,b");
4641                         emitcode ("mov","mb,a");
4642                 }
4643         } else {
4644                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4645                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4646         }
4647         /* load up MA with left */
4648         if (!umult) {
4649                 lbl = newiTempLabel(NULL);
4650                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4651                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4652                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4653                 emitcode ("xch", "a,b");
4654                 emitcode ("cpl","a");
4655                 emitcode ("add", "a,#1");
4656                 emitcode ("xch", "a,b");
4657                 emitcode ("cpl", "a"); // msb
4658                 emitcode ("addc","a,#0");
4659                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660                 emitcode ("setb","F0");
4661                 emitcode ("","!tlabeldef",lbl->key+100);
4662                 emitcode ("mov","ma,b");
4663                 emitcode ("mov","ma,a");
4664         } else {
4665                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4666                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4667         }
4668         /* wait for multiplication to finish */
4669         lbl = newiTempLabel(NULL);
4670         emitcode("","!tlabeldef", lbl->key+100);
4671         emitcode("mov","a,mcnt1");
4672         emitcode("anl","a,#!constbyte",0x80);
4673         emitcode("jnz","!tlabel",lbl->key+100);
4674         
4675         freeAsmop (left, NULL, ic, TRUE);
4676         freeAsmop (right, NULL, ic,TRUE);
4677         aopOp(result, ic, TRUE, FALSE);
4678
4679         /* if unsigned then simple */   
4680         if (umult) {
4681                 emitcode ("mov","a,ma");
4682                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4683                 emitcode ("mov","a,ma");
4684                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4685                 aopPut(AOP(result),"ma",1);
4686                 aopPut(AOP(result),"ma",0);
4687         } else {
4688                 emitcode("push","ma");
4689                 emitcode("push","ma");
4690                 emitcode("push","ma");
4691                 MOVA("ma");
4692                 /* negate result if needed */
4693                 lbl = newiTempLabel(NULL);      
4694                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4695                 emitcode("cpl","a");
4696                 emitcode("add","a,#1");
4697                 emitcode("","!tlabeldef", lbl->key+100);
4698                 if (AOP_TYPE(result) == AOP_ACC)
4699                 {
4700                     D(emitcode(";", "ACC special case."););
4701                     /* We know result is the only live aop, and 
4702                      * it's obviously not a DPTR2, so AP is available.
4703                      */
4704                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4705                 }
4706                 else
4707                 {
4708                     aopPut(AOP(result),"a",0);
4709                 }
4710             
4711                 emitcode("pop","acc");
4712                 lbl = newiTempLabel(NULL);      
4713                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4714                 emitcode("cpl","a");
4715                 emitcode("addc","a,#0");
4716                 emitcode("","!tlabeldef", lbl->key+100);
4717                 aopPut(AOP(result),"a",1);
4718                 emitcode("pop","acc");
4719                 if (AOP_SIZE(result) >= 3) {
4720                         lbl = newiTempLabel(NULL);      
4721                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4722                         emitcode("cpl","a");
4723                         emitcode("addc","a,#0");                        
4724                         emitcode("","!tlabeldef", lbl->key+100);
4725                         aopPut(AOP(result),"a",2);
4726                 }
4727                 emitcode("pop","acc");
4728                 if (AOP_SIZE(result) >= 4) {
4729                         lbl = newiTempLabel(NULL);      
4730                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4731                         emitcode("cpl","a");
4732                         emitcode("addc","a,#0");                        
4733                         emitcode("","!tlabeldef", lbl->key+100);
4734                         aopPut(AOP(result),"a",3);
4735                 }
4736                 if (AOP_TYPE(result) == AOP_ACC)
4737                 {
4738                     /* We stashed the result away above. */
4739                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4740                 }           
4741                 
4742         }
4743         freeAsmop (result, NULL, ic, TRUE);
4744
4745         /* restore EA bit in F1 */
4746         lbl = newiTempLabel(NULL);
4747         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4748         emitcode ("setb","EA");
4749         emitcode("","!tlabeldef",lbl->key+100);
4750         return ;
4751 }
4752
4753 /*-----------------------------------------------------------------*/
4754 /* genMult - generates code for multiplication                     */
4755 /*-----------------------------------------------------------------*/
4756 static void
4757 genMult (iCode * ic)
4758 {
4759   operand *left = IC_LEFT (ic);
4760   operand *right = IC_RIGHT (ic);
4761   operand *result = IC_RESULT (ic);
4762
4763   D (emitcode (";", "genMult "););
4764
4765   /* assign the amsops */
4766   AOP_OP_2 (ic);
4767
4768   /* special cases first */
4769   /* both are bits */
4770   if (AOP_TYPE (left) == AOP_CRY &&
4771       AOP_TYPE (right) == AOP_CRY)
4772     {
4773       genMultbits (left, right, result, ic);
4774       goto release;
4775     }
4776
4777   /* if both are of size == 1 */
4778   if (AOP_SIZE (left) == 1 &&
4779       AOP_SIZE (right) == 1)
4780     {
4781       genMultOneByte (left, right, result, ic);
4782       goto release;
4783     }
4784
4785   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4786           /* use the ds390 ARITHMETIC accel UNIT */
4787           genMultTwoByte (left, right, result, ic);
4788           return ;
4789   }
4790   /* should have been converted to function call */
4791   assert (0);
4792
4793 release:
4794   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4795   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796   freeAsmop (result, NULL, ic, TRUE);
4797 }
4798
4799 /*-----------------------------------------------------------------*/
4800 /* genDivbits :- division of bits                                  */
4801 /*-----------------------------------------------------------------*/
4802 static void
4803 genDivbits (operand * left,
4804             operand * right,
4805             operand * result,
4806             iCode   * ic)
4807 {
4808
4809   char *l;
4810
4811   /* the result must be bit */
4812   LOAD_AB_FOR_DIV (left, right, l);
4813   emitcode ("div", "ab");
4814   emitcode ("rrc", "a");
4815   aopOp(result, ic, TRUE, FALSE);
4816     
4817   aopPut (AOP (result), "c", 0);
4818 }
4819
4820 /*-----------------------------------------------------------------*/
4821 /* genDivOneByte : 8 bit division                                  */
4822 /*-----------------------------------------------------------------*/
4823 static void
4824 genDivOneByte (operand * left,
4825                operand * right,
4826                operand * result,
4827                iCode   * ic)
4828 {
4829   sym_link *opetype = operandType (result);
4830   char *l;
4831   symbol *lbl;
4832   int size, offset;
4833
4834   offset = 1;
4835   /* signed or unsigned */
4836   if (SPEC_USIGN (opetype))
4837     {
4838         /* unsigned is easy */
4839         LOAD_AB_FOR_DIV (left, right, l);
4840         emitcode ("div", "ab");
4841
4842         _G.accInUse++;
4843         aopOp(result, ic, TRUE, FALSE);
4844         aopPut (AOP (result), "a", 0);
4845         _G.accInUse--;
4846
4847         size = AOP_SIZE (result) - 1;
4848         
4849         while (size--)
4850         {
4851             aopPut (AOP (result), zero, offset++);
4852         }
4853       return;
4854     }
4855
4856   /* signed is a little bit more difficult */
4857
4858   /* save the signs of the operands */
4859   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4860   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4861   emitcode ("push", "acc");     /* save it on the stack */
4862
4863   /* now sign adjust for both left & right */
4864   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4865   lbl = newiTempLabel (NULL);
4866   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4867   emitcode ("cpl", "a");
4868   emitcode ("inc", "a");
4869   emitcode ("", "!tlabeldef", (lbl->key + 100));
4870   emitcode ("mov", "b,a");
4871
4872   /* sign adjust left side */
4873   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4874
4875   lbl = newiTempLabel (NULL);
4876   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4877   emitcode ("cpl", "a");
4878   emitcode ("inc", "a");
4879   emitcode ("", "!tlabeldef", (lbl->key + 100));
4880
4881   /* now the division */
4882   emitcode ("nop", "; workaround for DS80C390 div bug.");
4883   emitcode ("div", "ab");
4884   /* we are interested in the lower order
4885      only */
4886   emitcode ("mov", "b,a");
4887   lbl = newiTempLabel (NULL);
4888   emitcode ("pop", "acc");
4889   /* if there was an over flow we don't
4890      adjust the sign of the result */
4891   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4892   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4893   CLRC;
4894   emitcode ("clr", "a");
4895   emitcode ("subb", "a,b");
4896   emitcode ("mov", "b,a");
4897   emitcode ("", "!tlabeldef", (lbl->key + 100));
4898
4899   /* now we are done */
4900   _G.accInUse++;     _G.bInUse++;
4901     aopOp(result, ic, TRUE, FALSE);
4902     
4903     aopPut (AOP (result), "b", 0);
4904     
4905     size = AOP_SIZE (result) - 1;
4906     
4907     if (size > 0)
4908     {
4909       emitcode ("mov", "c,b.7");
4910       emitcode ("subb", "a,acc");
4911     }
4912     while (size--)
4913     {
4914         aopPut (AOP (result), "a", offset++);
4915     }
4916     _G.accInUse--;     _G.bInUse--;
4917
4918 }
4919
4920 /*-----------------------------------------------------------------*/
4921 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4922 /*-----------------------------------------------------------------*/
4923 static void genDivTwoByte (operand *left, operand *right, 
4924                             operand *result, iCode *ic)
4925 {
4926         sym_link *retype = getSpec(operandType(right));
4927         sym_link *letype = getSpec(operandType(left));
4928         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4929         symbol *lbl;
4930
4931         /* save EA bit in F1 */
4932         lbl = newiTempLabel(NULL);
4933         emitcode ("setb","F1");
4934         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4935         emitcode ("clr","F1");
4936         emitcode("","!tlabeldef",lbl->key+100);
4937
4938         /* load up MA with left */
4939         if (!umult) {
4940                 emitcode("clr","F0");
4941                 lbl = newiTempLabel(NULL);
4942                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4943                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4944                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4945                 emitcode ("xch", "a,b");
4946                 emitcode ("cpl","a");
4947                 emitcode ("add", "a,#1");
4948                 emitcode ("xch", "a,b");
4949                 emitcode ("cpl", "a"); // msb
4950                 emitcode ("addc","a,#0");
4951                 emitcode ("setb","F0");
4952                 emitcode ("","!tlabeldef",lbl->key+100);
4953                 emitcode ("mov","ma,b");
4954                 emitcode ("mov","ma,a");
4955         } else {
4956                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4957                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4958         }
4959
4960         /* load up MB with right */
4961         if (!umult) {
4962                 if (AOP_TYPE(right) == AOP_LIT) {
4963                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4964                         if (val < 0) {
4965                                 lbl = newiTempLabel(NULL);
4966                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4967                                 emitcode("setb","F0");
4968                                 emitcode ("","!tlabeldef",lbl->key+100);
4969                                 val = -val;
4970                         } 
4971                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4972                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4973                 } else {
4974                         lbl = newiTempLabel(NULL);
4975                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4976                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4977                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4978                         emitcode ("xch", "a,b");
4979                         emitcode ("cpl","a");
4980                         emitcode ("add", "a,#1");
4981                         emitcode ("xch", "a,b");
4982                         emitcode ("cpl", "a"); // msb
4983                         emitcode ("addc", "a,#0");
4984                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4985                         emitcode ("setb","F0");
4986                         emitcode ("","!tlabeldef",lbl->key+100);
4987                         emitcode ("mov","mb,b");
4988                         emitcode ("mov","mb,a");
4989                 }
4990         } else {
4991                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4992                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4993         }
4994
4995         /* wait for multiplication to finish */
4996         lbl = newiTempLabel(NULL);
4997         emitcode("","!tlabeldef", lbl->key+100);
4998         emitcode("mov","a,mcnt1");
4999         emitcode("anl","a,#!constbyte",0x80);
5000         emitcode("jnz","!tlabel",lbl->key+100);
5001         
5002         freeAsmop (left, NULL, ic, TRUE);
5003         freeAsmop (right, NULL, ic,TRUE);
5004         aopOp(result, ic, TRUE, FALSE);
5005
5006         /* if unsigned then simple */   
5007         if (umult) {
5008                 aopPut(AOP(result),"ma",1);
5009                 aopPut(AOP(result),"ma",0);
5010         } else {
5011                 emitcode("push","ma");
5012                 MOVA("ma");
5013                 /* negate result if needed */
5014                 lbl = newiTempLabel(NULL);      
5015                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5016                 emitcode("cpl","a");
5017                 emitcode("add","a,#1");
5018                 emitcode("","!tlabeldef", lbl->key+100);
5019                 aopPut(AOP(result),"a",0);
5020                 emitcode("pop","acc");
5021                 lbl = newiTempLabel(NULL);      
5022                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5023                 emitcode("cpl","a");
5024                 emitcode("addc","a,#0");
5025                 emitcode("","!tlabeldef", lbl->key+100);
5026                 aopPut(AOP(result),"a",1);
5027         }
5028         freeAsmop (result, NULL, ic, TRUE);
5029         /* restore EA bit in F1 */
5030         lbl = newiTempLabel(NULL);
5031         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5032         emitcode ("setb","EA");
5033         emitcode("","!tlabeldef",lbl->key+100);
5034         return ;
5035 }
5036
5037 /*-----------------------------------------------------------------*/
5038 /* genDiv - generates code for division                            */
5039 /*-----------------------------------------------------------------*/
5040 static void
5041 genDiv (iCode * ic)
5042 {
5043   operand *left = IC_LEFT (ic);
5044   operand *right = IC_RIGHT (ic);
5045   operand *result = IC_RESULT (ic);
5046
5047   D (emitcode (";", "genDiv "););
5048
5049   /* assign the amsops */
5050   AOP_OP_2 (ic);
5051
5052   /* special cases first */
5053   /* both are bits */
5054   if (AOP_TYPE (left) == AOP_CRY &&
5055       AOP_TYPE (right) == AOP_CRY)
5056     {
5057       genDivbits (left, right, result, ic);
5058       goto release;
5059     }
5060
5061   /* if both are of size == 1 */
5062   if (AOP_SIZE (left) == 1 &&
5063       AOP_SIZE (right) == 1)
5064     {
5065       genDivOneByte (left, right, result, ic);
5066       goto release;
5067     }
5068
5069   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5070           /* use the ds390 ARITHMETIC accel UNIT */
5071           genDivTwoByte (left, right, result, ic);
5072           return ;
5073   }
5074   /* should have been converted to function call */
5075   assert (0);
5076 release:
5077   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5078   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079   freeAsmop (result, NULL, ic, TRUE);
5080 }
5081
5082 /*-----------------------------------------------------------------*/
5083 /* genModbits :- modulus of bits                                   */
5084 /*-----------------------------------------------------------------*/
5085 static void
5086 genModbits (operand * left,
5087             operand * right,
5088             operand * result,
5089             iCode   * ic)
5090 {
5091
5092   char *l;
5093
5094   /* the result must be bit */
5095   LOAD_AB_FOR_DIV (left, right, l);
5096   emitcode ("div", "ab");
5097   emitcode ("mov", "a,b");
5098   emitcode ("rrc", "a");
5099   aopOp(result, ic, TRUE, FALSE);
5100   aopPut (AOP (result), "c", 0);
5101 }
5102
5103 /*-----------------------------------------------------------------*/
5104 /* genModOneByte : 8 bit modulus                                   */
5105 /*-----------------------------------------------------------------*/
5106 static void
5107 genModOneByte (operand * left,
5108                operand * right,
5109                operand * result,
5110                iCode   * ic)
5111 {
5112   sym_link *opetype = operandType (result);
5113   char *l;
5114   symbol *lbl;
5115
5116   /* signed or unsigned */
5117   if (SPEC_USIGN (opetype))
5118     {
5119       /* unsigned is easy */
5120       LOAD_AB_FOR_DIV (left, right, l);
5121       emitcode ("div", "ab");
5122       aopOp(result, ic, TRUE, FALSE);   
5123       aopPut (AOP (result), "b", 0);
5124       return;
5125     }
5126
5127   /* signed is a little bit more difficult */
5128
5129   /* save the signs of the operands */
5130   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5131
5132   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5133   emitcode ("push", "acc");     /* save it on the stack */
5134
5135   /* now sign adjust for both left & right */
5136   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5137
5138   lbl = newiTempLabel (NULL);
5139   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5140   emitcode ("cpl", "a");
5141   emitcode ("inc", "a");
5142   emitcode ("", "!tlabeldef", (lbl->key + 100));
5143   emitcode ("mov", "b,a");
5144
5145   /* sign adjust left side */
5146   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5147
5148   lbl = newiTempLabel (NULL);
5149   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5150   emitcode ("cpl", "a");
5151   emitcode ("inc", "a");
5152   emitcode ("", "!tlabeldef", (lbl->key + 100));
5153
5154   /* now the multiplication */
5155   emitcode ("nop", "; workaround for DS80C390 div bug.");
5156   emitcode ("div", "ab");
5157   /* we are interested in the lower order
5158      only */
5159   lbl = newiTempLabel (NULL);
5160   emitcode ("pop", "acc");
5161   /* if there was an over flow we don't
5162      adjust the sign of the result */
5163   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5164   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5165   CLRC;
5166   emitcode ("clr", "a");
5167   emitcode ("subb", "a,b");
5168   emitcode ("mov", "b,a");
5169   emitcode ("", "!tlabeldef", (lbl->key + 100));
5170   
5171   _G.bInUse++;
5172   /* now we are done */
5173   aopOp(result, ic, TRUE, FALSE);    
5174   aopPut (AOP (result), "b", 0);
5175   _G.bInUse--;
5176
5177 }
5178
5179 /*-----------------------------------------------------------------*/
5180 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5181 /*-----------------------------------------------------------------*/
5182 static void genModTwoByte (operand *left, operand *right, 
5183                             operand *result, iCode *ic)
5184 {
5185         sym_link *retype = getSpec(operandType(right));
5186         sym_link *letype = getSpec(operandType(left));
5187         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5188         symbol *lbl;
5189
5190         /* load up MA with left */
5191         /* save EA bit in F1 */
5192         lbl = newiTempLabel(NULL);
5193         emitcode ("setb","F1");
5194         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5195         emitcode ("clr","F1");
5196         emitcode("","!tlabeldef",lbl->key+100);
5197
5198         if (!umult) {
5199                 lbl = newiTempLabel(NULL);
5200                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5201                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5202                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5203                 emitcode ("xch", "a,b");
5204                 emitcode ("cpl","a");
5205                 emitcode ("add", "a,#1");
5206                 emitcode ("xch", "a,b");
5207                 emitcode ("cpl", "a"); // msb
5208                 emitcode ("addc","a,#0");
5209                 emitcode ("","!tlabeldef",lbl->key+100);
5210                 emitcode ("mov","ma,b");
5211                 emitcode ("mov","ma,a");
5212         } else {
5213                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5214                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5215         }
5216
5217         /* load up MB with right */
5218         if (!umult) {
5219                 if (AOP_TYPE(right) == AOP_LIT) {
5220                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5221                         if (val < 0) {
5222                                 val = -val;
5223                         } 
5224                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5225                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5226                 } else {
5227                         lbl = newiTempLabel(NULL);
5228                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5229                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5230                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5231                         emitcode ("xch", "a,b");
5232                         emitcode ("cpl","a");
5233                         emitcode ("add", "a,#1");
5234                         emitcode ("xch", "a,b");
5235                         emitcode ("cpl", "a"); // msb
5236                         emitcode ("addc", "a,#0");
5237                         emitcode ("","!tlabeldef",lbl->key+100);
5238                         emitcode ("mov","mb,b");
5239                         emitcode ("mov","mb,a");
5240                 }
5241         } else {
5242                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5243                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5244         }
5245
5246         /* wait for multiplication to finish */
5247         lbl = newiTempLabel(NULL);
5248         emitcode("","!tlabeldef", lbl->key+100);
5249         emitcode("mov","a,mcnt1");
5250         emitcode("anl","a,#!constbyte",0x80);
5251         emitcode("jnz","!tlabel",lbl->key+100);
5252         
5253         freeAsmop (left, NULL, ic, TRUE);
5254         freeAsmop (right, NULL, ic,TRUE);
5255         aopOp(result, ic, TRUE, FALSE);
5256
5257         aopPut(AOP(result),"mb",1);
5258         aopPut(AOP(result),"mb",0);
5259         freeAsmop (result, NULL, ic, TRUE);
5260
5261         /* restore EA bit in F1 */
5262         lbl = newiTempLabel(NULL);
5263         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5264         emitcode ("setb","EA");
5265         emitcode("","!tlabeldef",lbl->key+100);
5266         return ;
5267 }
5268
5269 /*-----------------------------------------------------------------*/
5270 /* genMod - generates code for division                            */
5271 /*-----------------------------------------------------------------*/
5272 static void
5273 genMod (iCode * ic)
5274 {
5275   operand *left = IC_LEFT (ic);
5276   operand *right = IC_RIGHT (ic);
5277   operand *result = IC_RESULT (ic);
5278
5279   D (emitcode (";", "genMod "); );
5280
5281   /* assign the amsops */
5282   AOP_OP_2 (ic);
5283
5284   /* special cases first */
5285   /* both are bits */
5286   if (AOP_TYPE (left) == AOP_CRY &&
5287       AOP_TYPE (right) == AOP_CRY)
5288     {
5289       genModbits (left, right, result, ic);
5290       goto release;
5291     }
5292
5293   /* if both are of size == 1 */
5294   if (AOP_SIZE (left) == 1 &&
5295       AOP_SIZE (right) == 1)
5296     {
5297       genModOneByte (left, right, result, ic);
5298       goto release;
5299     }
5300
5301   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5302           /* use the ds390 ARITHMETIC accel UNIT */
5303           genModTwoByte (left, right, result, ic);
5304           return ;
5305   }
5306
5307   /* should have been converted to function call */
5308   assert (0);
5309
5310 release:
5311   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5312   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313   freeAsmop (result, NULL, ic, TRUE);
5314 }
5315
5316 /*-----------------------------------------------------------------*/
5317 /* genIfxJump :- will create a jump depending on the ifx           */
5318 /*-----------------------------------------------------------------*/
5319 static void
5320 genIfxJump (iCode * ic, char *jval)
5321 {
5322   symbol *jlbl;
5323   symbol *tlbl = newiTempLabel (NULL);
5324   char *inst;
5325
5326   D (emitcode (";", "genIfxJump"););
5327
5328   /* if true label then we jump if condition
5329      supplied is true */
5330   if (IC_TRUE (ic))
5331     {
5332       jlbl = IC_TRUE (ic);
5333       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5334                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5335     }
5336   else
5337     {
5338       /* false label is present */
5339       jlbl = IC_FALSE (ic);
5340       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5341                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5342     }
5343   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5344     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5345   else
5346     emitcode (inst, "!tlabel", tlbl->key + 100);
5347   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5348   emitcode ("", "!tlabeldef", tlbl->key + 100);
5349
5350   /* mark the icode as generated */
5351   ic->generated = 1;
5352 }
5353
5354 /*-----------------------------------------------------------------*/
5355 /* genCmp :- greater or less than comparison                       */
5356 /*-----------------------------------------------------------------*/
5357 static void
5358 genCmp (operand * left, operand * right,
5359         iCode * ic, iCode * ifx, int sign)
5360 {
5361   int size, offset = 0;
5362   unsigned long lit = 0L;
5363   operand *result;
5364
5365   D (emitcode (";", "genCmp"););
5366
5367   result = IC_RESULT (ic);
5368
5369   /* if left & right are bit variables */
5370   if (AOP_TYPE (left) == AOP_CRY &&
5371       AOP_TYPE (right) == AOP_CRY)
5372     {
5373       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5374       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5375     }
5376   else
5377     {
5378       /* subtract right from left if at the
5379          end the carry flag is set then we know that
5380          left is greater than right */
5381       size = max (AOP_SIZE (left), AOP_SIZE (right));
5382
5383       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5384       if ((size == 1) && !sign 
5385           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5386         {
5387           symbol *lbl = newiTempLabel (NULL);
5388           emitcode ("cjne", "%s,%s,!tlabel",
5389                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5390                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5391                     lbl->key + 100);
5392           emitcode ("", "!tlabeldef", lbl->key + 100);
5393         }
5394       else
5395         {
5396           if (AOP_TYPE (right) == AOP_LIT)
5397             {
5398               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5399               /* optimize if(x < 0) or if(x >= 0) */
5400               if (lit == 0L)
5401                 {
5402                   if (!sign)
5403                     {
5404                       CLRC;
5405                     }
5406                   else
5407                     {
5408                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5409
5410                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5412
5413                       aopOp (result, ic, FALSE, FALSE);
5414
5415                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5416                         {
5417                           freeAsmop (result, NULL, ic, TRUE);
5418                           genIfxJump (ifx, "acc.7");
5419                           return;
5420                         }
5421                       else
5422                         {
5423                           emitcode ("rlc", "a");
5424                         }
5425                       goto release_freedLR;
5426                     }
5427                   goto release;
5428                 }
5429             }
5430           CLRC;
5431           while (size--)
5432             {
5433               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5434               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5435               // emitcode (";", "genCmp #2");
5436               if (sign && (size == 0))
5437                 {
5438                   // emitcode (";", "genCmp #3");
5439                   emitcode ("xrl", "a,#!constbyte",0x80);
5440                   if (AOP_TYPE (right) == AOP_LIT)
5441                     {
5442                       unsigned long lit = (unsigned long)
5443                       floatFromVal (AOP (right)->aopu.aop_lit);
5444                       // emitcode (";", "genCmp #3.1");
5445                       emitcode ("subb", "a,#!constbyte",
5446                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5447                     }
5448                   else
5449                     {
5450                       // emitcode (";", "genCmp #3.2");
5451                       saveAccWarn = 0;  
5452                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5453                       saveAccWarn = DEFAULT_ACC_WARNING;
5454                       emitcode ("xrl", "b,#!constbyte",0x80);
5455                       emitcode ("subb", "a,b");
5456                     }
5457                 }
5458               else
5459                 {
5460                   const char *s;
5461
5462                   // emitcode (";", "genCmp #4");
5463                   saveAccWarn = 0;
5464                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5465                   saveAccWarn = DEFAULT_ACC_WARNING;
5466
5467                   emitcode ("subb", "a,%s", s);
5468                 }
5469             }
5470         }
5471     }
5472
5473 release:
5474 /* Don't need the left & right operands any more; do need the result. */
5475   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477
5478   aopOp (result, ic, FALSE, FALSE);
5479
5480 release_freedLR:
5481
5482   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5483     {
5484       outBitC (result);
5485     }
5486   else
5487     {
5488       /* if the result is used in the next
5489          ifx conditional branch then generate
5490          code a little differently */
5491       if (ifx)
5492         {
5493           genIfxJump (ifx, "c");
5494         }
5495       else
5496         {
5497           outBitC (result);
5498         }
5499       /* leave the result in acc */
5500     }
5501   freeAsmop (result, NULL, ic, TRUE);
5502 }
5503
5504 /*-----------------------------------------------------------------*/
5505 /* genCmpGt :- greater than comparison                             */
5506 /*-----------------------------------------------------------------*/
5507 static void
5508 genCmpGt (iCode * ic, iCode * ifx)
5509 {
5510   operand *left, *right;
5511   sym_link *letype, *retype;
5512   int sign;
5513
5514   D (emitcode (";", "genCmpGt ");
5515     );
5516
5517   left = IC_LEFT (ic);
5518   right = IC_RIGHT (ic);
5519
5520   letype = getSpec (operandType (left));
5521   retype = getSpec (operandType (right));
5522   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5523
5524   /* assign the left & right amsops */
5525   AOP_OP_2 (ic);
5526
5527   genCmp (right, left, ic, ifx, sign);
5528 }
5529
5530 /*-----------------------------------------------------------------*/
5531 /* genCmpLt - less than comparisons                                */
5532 /*-----------------------------------------------------------------*/
5533 static void
5534 genCmpLt (iCode * ic, iCode * ifx)
5535 {
5536   operand *left, *right;
5537   sym_link *letype, *retype;
5538   int sign;
5539
5540   D (emitcode (";", "genCmpLt "););
5541
5542   left = IC_LEFT (ic);
5543   right = IC_RIGHT (ic);
5544
5545   letype = getSpec (operandType (left));
5546   retype = getSpec (operandType (right));
5547   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5548
5549   /* assign the left & right amsops */
5550   AOP_OP_2 (ic);
5551
5552   genCmp (left, right, ic, ifx, sign);
5553 }
5554
5555 /*-----------------------------------------------------------------*/
5556 /* gencjneshort - compare and jump if not equal                    */
5557 /*-----------------------------------------------------------------*/
5558 static void
5559 gencjneshort (operand * left, operand * right, symbol * lbl)
5560 {
5561   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5562   int offset = 0;
5563   unsigned long lit = 0L;
5564
5565   D (emitcode (";", "gencjneshort");
5566     );
5567
5568   /* if the left side is a literal or
5569      if the right is in a pointer register and left
5570      is not */
5571   if ((AOP_TYPE (left) == AOP_LIT) ||
5572       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5573     {
5574       operand *t = right;
5575       right = left;
5576       left = t;
5577     }
5578
5579   if (AOP_TYPE (right) == AOP_LIT)
5580     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5581
5582   if (opIsGptr (left) || opIsGptr (right))
5583     {
5584       /* We are comparing a generic pointer to something.
5585        * Exclude the generic type byte from the comparison.
5586        */
5587       size--;
5588       D (emitcode (";", "cjneshort: generic ptr special case."););
5589     }
5590
5591
5592   /* if the right side is a literal then anything goes */
5593   if (AOP_TYPE (right) == AOP_LIT &&
5594       AOP_TYPE (left) != AOP_DIR)
5595     {
5596       while (size--)
5597         {
5598           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5599           emitcode ("cjne", "a,%s,!tlabel",
5600                     aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG),
5601                     lbl->key + 100);
5602           offset++;
5603         }
5604     }
5605
5606   /* if the right side is in a register or in direct space or
5607      if the left is a pointer register & right is not */
5608   else if (AOP_TYPE (right) == AOP_REG ||
5609            AOP_TYPE (right) == AOP_DIR ||
5610            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5611            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5612     {
5613       while (size--)
5614         {
5615           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5616           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5617               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5618             emitcode ("jnz", "!tlabel", lbl->key + 100);
5619           else
5620             emitcode ("cjne", "a,%s,!tlabel",
5621                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5622                       lbl->key + 100);
5623           offset++;
5624         }
5625     }
5626   else
5627     {
5628       /* right is a pointer reg need both a & b */
5629       while (size--)
5630         {
5631           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5632           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5633           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5634           offset++;
5635         }
5636     }
5637 }
5638
5639 /*-----------------------------------------------------------------*/
5640 /* gencjne - compare and jump if not equal                         */
5641 /*-----------------------------------------------------------------*/
5642 static void
5643 gencjne (operand * left, operand * right, symbol * lbl)
5644 {
5645   symbol *tlbl = newiTempLabel (NULL);
5646
5647   D (emitcode (";", "gencjne");
5648     );
5649
5650   gencjneshort (left, right, lbl);
5651
5652   emitcode ("mov", "a,%s", one);
5653   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5654   emitcode ("", "!tlabeldef", lbl->key + 100);
5655   emitcode ("clr", "a");
5656   emitcode ("", "!tlabeldef", tlbl->key + 100);
5657 }
5658
5659 /*-----------------------------------------------------------------*/
5660 /* genCmpEq - generates code for equal to                          */
5661 /*-----------------------------------------------------------------*/
5662 static void
5663 genCmpEq (iCode * ic, iCode * ifx)
5664 {
5665   operand *left, *right, *result;
5666
5667   D (emitcode (";", "genCmpEq ");
5668     );
5669
5670   AOP_OP_2 (ic);
5671   AOP_SET_LOCALS (ic);
5672
5673   /* if literal, literal on the right or
5674      if the right is in a pointer register and left
5675      is not */
5676   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5677       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5678     {
5679       operand *t = IC_RIGHT (ic);
5680       IC_RIGHT (ic) = IC_LEFT (ic);
5681       IC_LEFT (ic) = t;
5682     }
5683
5684   if (ifx &&                    /* !AOP_SIZE(result) */
5685       OP_SYMBOL (result) &&
5686       OP_SYMBOL (result)->regType == REG_CND)
5687     {
5688       symbol *tlbl;
5689       /* if they are both bit variables */
5690       if (AOP_TYPE (left) == AOP_CRY &&
5691           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5692         {
5693           if (AOP_TYPE (right) == AOP_LIT)
5694             {
5695               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5696               if (lit == 0L)
5697                 {
5698                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5699                   emitcode ("cpl", "c");
5700                 }
5701               else if (lit == 1L)
5702                 {
5703                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5704                 }
5705               else
5706                 {
5707                   emitcode ("clr", "c");
5708                 }
5709               /* AOP_TYPE(right) == AOP_CRY */
5710             }
5711           else
5712             {
5713               symbol *lbl = newiTempLabel (NULL);
5714               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5715               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5716               emitcode ("cpl", "c");
5717               emitcode ("", "!tlabeldef", (lbl->key + 100));
5718             }
5719           /* if true label then we jump if condition
5720              supplied is true */
5721           tlbl = newiTempLabel (NULL);
5722           if (IC_TRUE (ifx))
5723             {
5724               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5725               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5726             }
5727           else
5728             {
5729               emitcode ("jc", "!tlabel", tlbl->key + 100);
5730               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5731             }
5732           emitcode ("", "!tlabeldef", tlbl->key + 100);
5733         }
5734       else
5735         {
5736           tlbl = newiTempLabel (NULL);
5737           gencjneshort (left, right, tlbl);
5738           if (IC_TRUE (ifx))
5739             {
5740               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5741               emitcode ("", "!tlabeldef", tlbl->key + 100);
5742             }
5743           else
5744             {
5745               symbol *lbl = newiTempLabel (NULL);
5746               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5747               emitcode ("", "!tlabeldef", tlbl->key + 100);
5748               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5749               emitcode ("", "!tlabeldef", lbl->key + 100);
5750             }
5751         }
5752       /* mark the icode as generated */
5753       ifx->generated = 1;
5754
5755       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5756       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5757       return;
5758     }
5759
5760   /* if they are both bit variables */
5761   if (AOP_TYPE (left) == AOP_CRY &&
5762       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5763     {
5764       if (AOP_TYPE (right) == AOP_LIT)
5765         {
5766           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5767           if (lit == 0L)
5768             {
5769               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5770               emitcode ("cpl", "c");
5771             }
5772           else if (lit == 1L)
5773             {
5774               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5775             }
5776           else
5777             {
5778               emitcode ("clr", "c");
5779             }
5780           /* AOP_TYPE(right) == AOP_CRY */
5781         }
5782       else
5783         {
5784           symbol *lbl = newiTempLabel (NULL);
5785           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5786           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5787           emitcode ("cpl", "c");
5788           emitcode ("", "!tlabeldef", (lbl->key + 100));
5789         }
5790
5791       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5792       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5793
5794       aopOp (result, ic, TRUE, FALSE);
5795
5796       /* c = 1 if egal */
5797       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5798         {
5799           outBitC (result);
5800           goto release;
5801         }
5802       if (ifx)
5803         {
5804           genIfxJump (ifx, "c");
5805           goto release;
5806         }
5807       /* if the result is used in an arithmetic operation
5808          then put the result in place */
5809       outBitC (result);
5810     }
5811   else
5812     {
5813       gencjne (left, right, newiTempLabel (NULL));
5814
5815       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817
5818       aopOp (result, ic, TRUE, FALSE);
5819
5820       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5821         {
5822           aopPut (AOP (result), "a", 0);
5823           goto release;
5824         }
5825       if (ifx)
5826         {
5827           genIfxJump (ifx, "a");
5828           goto release;
5829         }
5830       /* if the result is used in an arithmetic operation
5831          then put the result in place */
5832       if (AOP_TYPE (result) != AOP_CRY)
5833         outAcc (result);
5834       /* leave the result in acc */
5835     }
5836
5837 release:
5838   freeAsmop (result, NULL, ic, TRUE);
5839 }
5840
5841 /*-----------------------------------------------------------------*/
5842 /* ifxForOp - returns the icode containing the ifx for operand     */
5843 /*-----------------------------------------------------------------*/
5844 static iCode *
5845 ifxForOp (operand * op, iCode * ic)
5846 {
5847   /* if true symbol then needs to be assigned */
5848   if (IS_TRUE_SYMOP (op))
5849     return NULL;
5850
5851   /* if this has register type condition and
5852      the next instruction is ifx with the same operand
5853      and live to of the operand is upto the ifx only then */
5854   if (ic->next &&
5855       ic->next->op == IFX &&
5856       IC_COND (ic->next)->key == op->key &&
5857       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5858     return ic->next;
5859
5860   return NULL;
5861 }
5862 /*-----------------------------------------------------------------*/
5863 /* hasInc - operand is incremented before any other use            */
5864 /*-----------------------------------------------------------------*/
5865 static iCode *
5866 hasInc (operand *op, iCode *ic, int osize)
5867 {
5868   sym_link *type = operandType(op);
5869   sym_link *retype = getSpec (type);
5870   iCode *lic = ic->next;
5871   int isize ;
5872   
5873   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5874   if (!IS_SYMOP(op)) return NULL;
5875
5876   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5877   if (IS_AGGREGATE(type->next)) return NULL;
5878   if (osize != (isize = getSize(type->next))) return NULL;
5879
5880   while (lic) {
5881       /* if operand of the form op = op + <sizeof *op> */
5882       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5883           isOperandEqual(IC_RESULT(lic),op) && 
5884           isOperandLiteral(IC_RIGHT(lic)) &&
5885           operandLitValue(IC_RIGHT(lic)) == isize) {
5886           return lic;
5887       }
5888       /* if the operand used or deffed */
5889       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5890           return NULL;
5891       }
5892       /* if GOTO or IFX */
5893       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5894       lic = lic->next;
5895   }
5896   return NULL;
5897 }
5898
5899 /*-----------------------------------------------------------------*/
5900 /* genAndOp - for && operation                                     */
5901 /*-----------------------------------------------------------------*/
5902 static void
5903 genAndOp (iCode * ic)
5904 {
5905   operand *left, *right, *result;
5906   symbol *tlbl;
5907
5908   D (emitcode (";", "genAndOp "););
5909
5910   /* note here that && operations that are in an
5911      if statement are taken away by backPatchLabels
5912      only those used in arthmetic operations remain */
5913   AOP_OP_2 (ic);
5914   AOP_SET_LOCALS (ic);
5915
5916   /* if both are bit variables */
5917   if (AOP_TYPE (left) == AOP_CRY &&
5918       AOP_TYPE (right) == AOP_CRY)
5919     {
5920       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5921       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5922       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5923       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5924   
5925       aopOp (result,ic,FALSE, FALSE);
5926       outBitC (result);
5927     }
5928   else
5929     {
5930       tlbl = newiTempLabel (NULL);
5931       toBoolean (left);
5932       emitcode ("jz", "!tlabel", tlbl->key + 100);
5933       toBoolean (right);
5934       emitcode ("", "!tlabeldef", tlbl->key + 100);
5935       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937   
5938       aopOp (result,ic,FALSE, FALSE);
5939       outBitAcc (result);
5940     }
5941     freeAsmop (result, NULL, ic, TRUE);
5942 }
5943
5944
5945 /*-----------------------------------------------------------------*/
5946 /* genOrOp - for || operation                                      */
5947 /*-----------------------------------------------------------------*/
5948 static void
5949 genOrOp (iCode * ic)
5950 {
5951   operand *left, *right, *result;
5952   symbol *tlbl;
5953
5954   D (emitcode (";", "genOrOp "););
5955
5956   /* note here that || operations that are in an
5957      if statement are taken away by backPatchLabels
5958      only those used in arthmetic operations remain */
5959   AOP_OP_2 (ic);
5960   AOP_SET_LOCALS (ic);
5961
5962   /* if both are bit variables */
5963   if (AOP_TYPE (left) == AOP_CRY &&
5964       AOP_TYPE (right) == AOP_CRY)
5965     {
5966       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5967       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5968       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5969       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970   
5971       aopOp (result,ic,FALSE, FALSE);
5972       
5973       outBitC (result);
5974     }
5975   else
5976     {
5977       tlbl = newiTempLabel (NULL);
5978       toBoolean (left);
5979       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5980       toBoolean (right);
5981       emitcode ("", "!tlabeldef", tlbl->key + 100);
5982       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984   
5985       aopOp (result,ic,FALSE, FALSE);
5986       
5987       outBitAcc (result);
5988     }
5989
5990   freeAsmop (result, NULL, ic, TRUE);
5991 }
5992
5993 /*-----------------------------------------------------------------*/
5994 /* isLiteralBit - test if lit == 2^n                               */
5995 /*-----------------------------------------------------------------*/
5996 static int
5997 isLiteralBit (unsigned long lit)
5998 {
5999   unsigned long pw[32] =
6000   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6001    0x100L, 0x200L, 0x400L, 0x800L,
6002    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6003    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6004    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6005    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6006    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6007   int idx;
6008
6009   for (idx = 0; idx < 32; idx++)
6010     if (lit == pw[idx])
6011       return idx + 1;
6012   return 0;
6013 }
6014
6015 /*-----------------------------------------------------------------*/
6016 /* continueIfTrue -                                                */
6017 /*-----------------------------------------------------------------*/
6018 static void
6019 continueIfTrue (iCode * ic)
6020 {
6021   if (IC_TRUE (ic))
6022     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6023   ic->generated = 1;
6024 }
6025
6026 /*-----------------------------------------------------------------*/
6027 /* jmpIfTrue -                                                     */
6028 /*-----------------------------------------------------------------*/
6029 static void
6030 jumpIfTrue (iCode * ic)
6031 {
6032   if (!IC_TRUE (ic))
6033     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6034   ic->generated = 1;
6035 }
6036
6037 /*-----------------------------------------------------------------*/
6038 /* jmpTrueOrFalse -                                                */
6039 /*-----------------------------------------------------------------*/
6040 static void
6041 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6042 {
6043   // ugly but optimized by peephole
6044   if (IC_TRUE (ic))
6045     {
6046       symbol *nlbl = newiTempLabel (NULL);
6047       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6048       emitcode ("", "!tlabeldef", tlbl->key + 100);
6049       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6050       emitcode ("", "!tlabeldef", nlbl->key + 100);
6051     }
6052   else
6053     {
6054       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6055       emitcode ("", "!tlabeldef", tlbl->key + 100);
6056     }
6057   ic->generated = 1;
6058 }
6059
6060 // Generate code to perform a bit-wise logic operation
6061 // on two operands in far space (assumed to already have been 
6062 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6063 // in far space. This requires pushing the result on the stack
6064 // then popping it into the result.
6065 static void
6066 genFarFarLogicOp(iCode *ic, char *logicOp)
6067 {
6068       int size, resultSize, compSize;
6069       int offset = 0;
6070       
6071       TR_AP("#5");
6072       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6073       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6074                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6075       
6076       _startLazyDPSEvaluation();
6077       for (size = compSize; (size--); offset++)
6078       {
6079           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6080           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6081           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6082           
6083           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6084           emitcode ("push", "acc");
6085       }
6086       _endLazyDPSEvaluation();
6087      
6088       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6089       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6090       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6091      
6092       resultSize = AOP_SIZE(IC_RESULT(ic));
6093
6094       ADJUST_PUSHED_RESULT(compSize, resultSize);
6095
6096       _startLazyDPSEvaluation();
6097       while (compSize--)
6098       {
6099           emitcode ("pop", "acc");
6100           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6101       }
6102       _endLazyDPSEvaluation();
6103       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6104 }
6105
6106
6107 /*-----------------------------------------------------------------*/
6108 /* genAnd  - code for and                                          */
6109 /*-----------------------------------------------------------------*/
6110 static void
6111 genAnd (iCode * ic, iCode * ifx)
6112 {
6113   operand *left, *right, *result;
6114   int size, offset = 0;
6115   unsigned long lit = 0L;
6116   int bytelit;
6117   char buff[10];
6118   bool pushResult;
6119
6120   D (emitcode (";", "genAnd "););
6121
6122   AOP_OP_3_NOFATAL (ic, pushResult);
6123   AOP_SET_LOCALS (ic);
6124
6125   if (pushResult)
6126   {
6127       genFarFarLogicOp(ic, "anl");
6128       return;
6129   }  
6130
6131 #ifdef DEBUG_TYPE
6132   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6133             AOP_TYPE (result),
6134             AOP_TYPE (left), AOP_TYPE (right));
6135   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6136             AOP_SIZE (result),
6137             AOP_SIZE (left), AOP_SIZE (right));
6138 #endif
6139
6140   /* if left is a literal & right is not then exchange them */
6141   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6142 #ifdef LOGIC_OPS_BROKEN      
6143     ||  AOP_NEEDSACC (left)
6144 #endif
6145     )
6146     {
6147       operand *tmp = right;
6148       right = left;
6149       left = tmp;
6150     }
6151
6152   /* if result = right then exchange them */
6153   if (sameRegs (AOP (result), AOP (right)))
6154     {
6155       operand *tmp = right;
6156       right = left;
6157       left = tmp;
6158     }
6159
6160   /* if right is bit then exchange them */
6161   if (AOP_TYPE (right) == AOP_CRY &&
6162       AOP_TYPE (left) != AOP_CRY)
6163     {
6164       operand *tmp = right;
6165       right = left;
6166       left = tmp;
6167     }
6168   if (AOP_TYPE (right) == AOP_LIT)
6169     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6170
6171   size = AOP_SIZE (result);
6172
6173   // if(bit & yy)
6174   // result = bit & yy;
6175   if (AOP_TYPE (left) == AOP_CRY)
6176     {
6177       // c = bit & literal;
6178       if (AOP_TYPE (right) == AOP_LIT)
6179         {
6180           if (lit & 1)
6181             {
6182               if (size && sameRegs (AOP (result), AOP (left)))
6183                 // no change
6184                 goto release;
6185               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6186             }
6187           else
6188             {
6189               // bit(result) = 0;
6190               if (size && (AOP_TYPE (result) == AOP_CRY))
6191                 {
6192                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6193                   goto release;
6194                 }
6195               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6196                 {
6197                   jumpIfTrue (ifx);
6198                   goto release;
6199                 }
6200               emitcode ("clr", "c");
6201             }
6202         }
6203       else
6204         {
6205           if (AOP_TYPE (right) == AOP_CRY)
6206             {
6207               // c = bit & bit;
6208               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6209               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6210             }
6211           else
6212             {
6213               // c = bit & val;
6214               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6215               // c = lsb
6216               emitcode ("rrc", "a");
6217               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6218             }
6219         }
6220       // bit = c
6221       // val = c
6222       if (size)
6223         outBitC (result);
6224       // if(bit & ...)
6225       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6226         genIfxJump (ifx, "c");
6227       goto release;
6228     }
6229
6230   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6231   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6232   if ((AOP_TYPE (right) == AOP_LIT) &&
6233       (AOP_TYPE (result) == AOP_CRY) &&
6234       (AOP_TYPE (left) != AOP_CRY))
6235     {
6236       int posbit = isLiteralBit (lit);
6237       /* left &  2^n */
6238       if (posbit)
6239         {
6240           posbit--;
6241           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6242           // bit = left & 2^n
6243           if (size)
6244             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6245           // if(left &  2^n)
6246           else
6247             {
6248               if (ifx)
6249                 {
6250                   SNPRINTF (buff, sizeof(buff), 
6251                             "acc.%d", posbit & 0x07);
6252                   genIfxJump (ifx, buff);
6253                 }
6254               else 
6255                   {
6256                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6257                   }
6258               goto release;
6259             }
6260         }
6261       else
6262         {
6263           symbol *tlbl = newiTempLabel (NULL);
6264           int sizel = AOP_SIZE (left);
6265           if (size)
6266             emitcode ("setb", "c");
6267           while (sizel--)
6268             {
6269               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6270                 {
6271                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6272                   // byte ==  2^n ?
6273                   if ((posbit = isLiteralBit (bytelit)) != 0)
6274                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6275                   else
6276                     {
6277                       if (bytelit != 0x0FFL)
6278                         emitcode ("anl", "a,%s",
6279                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6280                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6281                     }
6282                 }
6283               offset++;
6284             }
6285           // bit = left & literal
6286           if (size)
6287             {
6288               emitcode ("clr", "c");
6289               emitcode ("", "!tlabeldef", tlbl->key + 100);
6290             }
6291           // if(left & literal)
6292           else
6293             {
6294               if (ifx)
6295                 jmpTrueOrFalse (ifx, tlbl);
6296               goto release;
6297             }
6298         }
6299       outBitC (result);
6300       goto release;
6301     }
6302
6303   /* if left is same as result */
6304   if (sameRegs (AOP (result), AOP (left)))
6305     {
6306       for (; size--; offset++)
6307         {
6308           if (AOP_TYPE (right) == AOP_LIT)
6309             {
6310               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6311                 continue;
6312               else if (bytelit == 0)
6313                 aopPut (AOP (result), zero, offset);
6314               else if (IS_AOP_PREG (result))
6315                 {
6316                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6317                   emitcode ("anl", "a,%s",
6318                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6319                   aopPut (AOP (result), "a", offset);
6320                 }
6321               else
6322                 emitcode ("anl", "%s,%s",
6323                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6324                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6325             }
6326           else
6327             {
6328               if (AOP_TYPE (left) == AOP_ACC)
6329                 emitcode ("anl", "a,%s",
6330                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6331               else
6332                 {
6333                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6334                   if (IS_AOP_PREG (result))
6335                     {
6336                       emitcode ("anl", "a,%s",
6337                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6338                       aopPut (AOP (result), "a", offset);
6339                     }
6340                   else
6341                     emitcode ("anl", "%s,a",
6342                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6343                 }
6344             }
6345         }
6346     }
6347   else
6348     {
6349       // left & result in different registers
6350       if (AOP_TYPE (result) == AOP_CRY)
6351         {
6352           // result = bit
6353           // if(size), result in bit
6354           // if(!size && ifx), conditional oper: if(left & right)
6355           symbol *tlbl = newiTempLabel (NULL);
6356           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6357           if (size)
6358             emitcode ("setb", "c");
6359           while (sizer--)
6360             {
6361               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6362                 emitcode ("anl", "a,%s",
6363                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6364               } else {
6365                 if (AOP_TYPE(left)==AOP_ACC) {
6366                   emitcode("mov", "b,a");
6367                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6368                   emitcode("anl", "a,b");
6369                 }else {
6370                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6371                   emitcode ("anl", "a,%s",
6372                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6373                 }
6374               }
6375               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6376               offset++;
6377             }
6378           if (size)
6379             {
6380               CLRC;
6381               emitcode ("", "!tlabeldef", tlbl->key + 100);
6382               outBitC (result);
6383             }
6384           else if (ifx)
6385             jmpTrueOrFalse (ifx, tlbl);
6386         }
6387       else
6388         {
6389           for (; (size--); offset++)
6390             {
6391               // normal case
6392               // result = left & right
6393               if (AOP_TYPE (right) == AOP_LIT)
6394                 {
6395                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6396                     {
6397                       aopPut (AOP (result),
6398                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6399                               offset);
6400                       continue;
6401                     }
6402                   else if (bytelit == 0)
6403                     {
6404                       aopPut (AOP (result), zero, offset);
6405                       continue;
6406                     }
6407                   D (emitcode (";", "better literal AND."););
6408                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6409                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6410                                                     FALSE, FALSE, DP2_RESULT_REG));
6411
6412                 }
6413               else
6414                 {
6415                   // faster than result <- left, anl result,right
6416                   // and better if result is SFR
6417                   if (AOP_TYPE (left) == AOP_ACC)
6418                     {
6419                       emitcode ("anl", "a,%s", 
6420                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6421                     }
6422                   else
6423                     {
6424                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6425                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6426                       {
6427                           emitcode("mov", "b,a");
6428                           rOp = "b";
6429                       }
6430                         
6431                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6432                       emitcode ("anl", "a,%s", rOp);
6433                     }                   
6434                 }
6435               aopPut (AOP (result), "a", offset);
6436             }
6437         }
6438     }
6439
6440 release:
6441   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6442   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443   freeAsmop (result, NULL, ic, TRUE);
6444 }
6445
6446
6447 /*-----------------------------------------------------------------*/
6448 /* genOr  - code for or                                            */
6449 /*-----------------------------------------------------------------*/
6450 static void
6451 genOr (iCode * ic, iCode * ifx)
6452 {
6453   operand *left, *right, *result;
6454   int size, offset = 0;
6455   unsigned long lit = 0L;
6456   bool     pushResult;
6457
6458   D (emitcode (";", "genOr "););
6459
6460   AOP_OP_3_NOFATAL (ic, pushResult);
6461   AOP_SET_LOCALS (ic);
6462
6463   if (pushResult)
6464   {
6465       genFarFarLogicOp(ic, "orl");
6466       return;
6467   }
6468
6469
6470 #ifdef DEBUG_TYPE
6471   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6472             AOP_TYPE (result),
6473             AOP_TYPE (left), AOP_TYPE (right));
6474   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6475             AOP_SIZE (result),
6476             AOP_SIZE (left), AOP_SIZE (right));
6477 #endif
6478
6479   /* if left is a literal & right is not then exchange them */
6480   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6481 #ifdef LOGIC_OPS_BROKEN
6482    || AOP_NEEDSACC (left) // I think this is a net loss now.
6483 #endif      
6484       )
6485     {
6486       operand *tmp = right;
6487       right = left;
6488       left = tmp;
6489     }
6490
6491   /* if result = right then exchange them */
6492   if (sameRegs (AOP (result), AOP (right)))
6493     {
6494       operand *tmp = right;
6495       right = left;
6496       left = tmp;
6497     }
6498
6499   /* if right is bit then exchange them */
6500   if (AOP_TYPE (right) == AOP_CRY &&
6501       AOP_TYPE (left) != AOP_CRY)
6502     {
6503       operand *tmp = right;
6504       right = left;
6505       left = tmp;
6506     }
6507   if (AOP_TYPE (right) == AOP_LIT)
6508     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6509
6510   size = AOP_SIZE (result);
6511
6512   // if(bit | yy)
6513   // xx = bit | yy;
6514   if (AOP_TYPE (left) == AOP_CRY)
6515     {
6516       if (AOP_TYPE (right) == AOP_LIT)
6517         {
6518           // c = bit & literal;
6519           if (lit)
6520             {
6521               // lit != 0 => result = 1
6522               if (AOP_TYPE (result) == AOP_CRY)
6523                 {
6524                   if (size)
6525                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6526                   else if (ifx)
6527                     continueIfTrue (ifx);
6528                   goto release;
6529                 }
6530               emitcode ("setb", "c");
6531             }
6532           else
6533             {
6534               // lit == 0 => result = left
6535               if (size && sameRegs (AOP (result), AOP (left)))
6536                 goto release;
6537               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6538             }
6539         }
6540       else
6541         {
6542           if (AOP_TYPE (right) == AOP_CRY)
6543             {
6544               // c = bit | bit;
6545               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6546               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6547             }
6548           else
6549             {
6550               // c = bit | val;
6551               symbol *tlbl = newiTempLabel (NULL);
6552               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6553                 emitcode ("setb", "c");
6554               emitcode ("jb", "%s,!tlabel",
6555                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6556               toBoolean (right);
6557               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6558               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6559                 {
6560                   jmpTrueOrFalse (ifx, tlbl);
6561                   goto release;
6562                 }
6563               else
6564                 {
6565                   CLRC;
6566                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6567                 }
6568             }
6569         }
6570       // bit = c
6571       // val = c
6572       if (size)
6573         outBitC (result);
6574       // if(bit | ...)
6575       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6576            genIfxJump (ifx, "c");
6577       goto release;
6578     }
6579
6580   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6581   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6582   if ((AOP_TYPE (right) == AOP_LIT) &&
6583       (AOP_TYPE (result) == AOP_CRY) &&
6584       (AOP_TYPE (left) != AOP_CRY))
6585     {
6586       if (lit)
6587         {
6588           // result = 1
6589           if (size)
6590             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6591           else
6592             continueIfTrue (ifx);
6593           goto release;
6594         }
6595       else
6596         {
6597           // lit = 0, result = boolean(left)
6598           if (size)
6599             emitcode ("setb", "c");
6600           toBoolean (right);
6601           if (size)
6602             {
6603               symbol *tlbl = newiTempLabel (NULL);
6604               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6605               CLRC;
6606               emitcode ("", "!tlabeldef", tlbl->key + 100);
6607             }
6608           else
6609             {
6610               genIfxJump (ifx, "a");
6611               goto release;
6612             }
6613         }
6614       outBitC (result);
6615       goto release;
6616     }
6617
6618   /* if left is same as result */
6619   if (sameRegs (AOP (result), AOP (left)))
6620     {
6621       for (; size--; offset++)
6622         {
6623           if (AOP_TYPE (right) == AOP_LIT)
6624             {
6625               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6626                 {
6627                   continue;
6628                 }
6629               else
6630                 {
6631                   if (IS_AOP_PREG (left))
6632                     {
6633                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6634                       emitcode ("orl", "a,%s",
6635                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6636                       aopPut (AOP (result), "a", offset);
6637                     }
6638                   else
6639                     {
6640                       emitcode ("orl", "%s,%s",
6641                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6642                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6643                     }
6644                 }
6645             }
6646           else
6647             {
6648               if (AOP_TYPE (left) == AOP_ACC)
6649                 {
6650                   emitcode ("orl", "a,%s",
6651                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6652                 }
6653               else
6654                 {
6655                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6656                   if (IS_AOP_PREG (left))
6657                     {
6658                       emitcode ("orl", "a,%s", 
6659                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6660                       aopPut (AOP (result), "a", offset);
6661                     }
6662                   else
6663                     {
6664                       emitcode ("orl", "%s,a",
6665                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6666                     }
6667                 }
6668             }
6669         }
6670     }
6671   else
6672     {
6673       // left & result in different registers
6674       if (AOP_TYPE (result) == AOP_CRY)
6675         {
6676           // result = bit
6677           // if(size), result in bit
6678           // if(!size && ifx), conditional oper: if(left | right)
6679           symbol *tlbl = newiTempLabel (NULL);
6680           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6681           if (size)
6682             emitcode ("setb", "c");
6683           while (sizer--)
6684             {
6685               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6686                 emitcode ("orl", "a,%s",
6687                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6688               } else {
6689                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6690                 emitcode ("orl", "a,%s",
6691                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6692               }
6693               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6694               offset++;
6695             }
6696           if (size)
6697             {
6698               CLRC;
6699               emitcode ("", "!tlabeldef", tlbl->key + 100);
6700               outBitC (result);
6701             }
6702           else if (ifx)
6703             jmpTrueOrFalse (ifx, tlbl);
6704         }
6705       else
6706         {
6707             _startLazyDPSEvaluation();
6708           for (; (size--); offset++)
6709             {
6710               // normal case
6711               // result = left & right
6712               if (AOP_TYPE (right) == AOP_LIT)
6713                 {
6714                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6715                     {
6716                       aopPut (AOP (result),
6717                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6718                               offset);
6719                       continue;
6720                     }
6721                   D (emitcode (";", "better literal OR."););
6722                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6723                   emitcode ("orl", "a, %s",
6724                             aopGet (AOP (right), offset,
6725                                     FALSE, FALSE, DP2_RESULT_REG));
6726
6727                 }
6728               else
6729                 {
6730                   // faster than result <- left, anl result,right
6731                   // and better if result is SFR
6732                   if (AOP_TYPE (left) == AOP_ACC)
6733                     {
6734                       emitcode ("orl", "a,%s",
6735                                 aopGet (AOP (right), offset,
6736                                         FALSE, FALSE, DP2_RESULT_REG));
6737                     }
6738                   else
6739                     {
6740                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6741                         
6742                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6743                       {
6744                           emitcode("mov", "b,a");
6745                           rOp = "b";
6746                       }
6747                         
6748                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6749                       emitcode ("orl", "a,%s", rOp);
6750                     }
6751                 }
6752               aopPut (AOP (result), "a", offset);
6753             }
6754             _endLazyDPSEvaluation();
6755         }
6756     }
6757
6758 release:
6759   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6760   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761   freeAsmop (result, NULL, ic, TRUE);
6762 }
6763
6764 /*-----------------------------------------------------------------*/
6765 /* genXor - code for xclusive or                                   */
6766 /*-----------------------------------------------------------------*/
6767 static void
6768 genXor (iCode * ic, iCode * ifx)
6769 {
6770   operand *left, *right, *result;
6771   int size, offset = 0;
6772   unsigned long lit = 0L;
6773   bool pushResult;
6774
6775   D (emitcode (";", "genXor "););
6776
6777   AOP_OP_3_NOFATAL (ic, pushResult);
6778   AOP_SET_LOCALS (ic);
6779
6780   if (pushResult)
6781   {
6782       genFarFarLogicOp(ic, "xrl");
6783       return;
6784   }  
6785
6786 #ifdef DEBUG_TYPE
6787   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6788             AOP_TYPE (result),
6789             AOP_TYPE (left), AOP_TYPE (right));
6790   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6791             AOP_SIZE (result),
6792             AOP_SIZE (left), AOP_SIZE (right));
6793 #endif
6794
6795   /* if left is a literal & right is not ||
6796      if left needs acc & right does not */
6797   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6798 #ifdef LOGIC_OPS_BROKEN      
6799       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6800 #endif
6801      )
6802     {
6803       operand *tmp = right;
6804       right = left;
6805       left = tmp;
6806     }
6807
6808   /* if result = right then exchange them */
6809   if (sameRegs (AOP (result), AOP (right)))
6810     {
6811       operand *tmp = right;
6812       right = left;
6813       left = tmp;
6814     }
6815
6816   /* if right is bit then exchange them */
6817   if (AOP_TYPE (right) == AOP_CRY &&
6818       AOP_TYPE (left) != AOP_CRY)
6819     {
6820       operand *tmp = right;
6821       right = left;
6822       left = tmp;
6823     }
6824   if (AOP_TYPE (right) == AOP_LIT)
6825     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6826
6827   size = AOP_SIZE (result);
6828
6829   // if(bit ^ yy)
6830   // xx = bit ^ yy;
6831   if (AOP_TYPE (left) == AOP_CRY)
6832     {
6833       if (AOP_TYPE (right) == AOP_LIT)
6834         {
6835           // c = bit & literal;
6836           if (lit >> 1)
6837             {
6838               // lit>>1  != 0 => result = 1
6839               if (AOP_TYPE (result) == AOP_CRY)
6840                 {
6841                   if (size)
6842                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6843                   else if (ifx)
6844                     continueIfTrue (ifx);
6845                   goto release;
6846                 }
6847               emitcode ("setb", "c");
6848             }
6849           else
6850             {
6851               // lit == (0 or 1)
6852               if (lit == 0)
6853                 {
6854                   // lit == 0, result = left
6855                   if (size && sameRegs (AOP (result), AOP (left)))
6856                     goto release;
6857                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6858                 }
6859               else
6860                 {
6861                   // lit == 1, result = not(left)
6862                   if (size && sameRegs (AOP (result), AOP (left)))
6863                     {
6864                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6865                       goto release;
6866                     }
6867                   else
6868                     {
6869                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6870                       emitcode ("cpl", "c");
6871                     }
6872                 }
6873             }
6874
6875         }
6876       else
6877         {
6878           // right != literal
6879           symbol *tlbl = newiTempLabel (NULL);
6880           if (AOP_TYPE (right) == AOP_CRY)
6881             {
6882               // c = bit ^ bit;
6883               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6884             }
6885           else
6886             {
6887               int sizer = AOP_SIZE (right);
6888               // c = bit ^ val
6889               // if val>>1 != 0, result = 1
6890               emitcode ("setb", "c");
6891               while (sizer)
6892                 {
6893                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6894                   if (sizer == 1)
6895                     // test the msb of the lsb
6896                     emitcode ("anl", "a,#!constbyte",0xfe);
6897                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6898                   sizer--;
6899                 }
6900               // val = (0,1)
6901               emitcode ("rrc", "a");
6902             }
6903           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6904           emitcode ("cpl", "c");
6905           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6906         }
6907       // bit = c
6908       // val = c
6909       if (size)
6910         outBitC (result);
6911       // if(bit | ...)
6912       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6913         genIfxJump (ifx, "c");
6914       goto release;
6915     }
6916
6917   if (sameRegs (AOP (result), AOP (left)))
6918     {
6919       /* if left is same as result */
6920       for (; size--; offset++)
6921         {
6922           if (AOP_TYPE (right) == AOP_LIT)
6923             {
6924               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6925                 continue;
6926               else if (IS_AOP_PREG (left))
6927                 {
6928                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6929                   emitcode ("xrl", "a,%s",
6930                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6931                   aopPut (AOP (result), "a", offset);
6932                 }
6933               else
6934                 emitcode ("xrl", "%s,%s",
6935                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6936                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6937             }
6938           else
6939             {
6940               if (AOP_TYPE (left) == AOP_ACC)
6941                 emitcode ("xrl", "a,%s",
6942                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6943               else
6944                 {
6945                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6946                   if (IS_AOP_PREG (left))
6947                     {
6948                       emitcode ("xrl", "a,%s",
6949                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6950                       aopPut (AOP (result), "a", offset);
6951                     }
6952                   else
6953                     emitcode ("xrl", "%s,a",
6954                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6955                 }
6956             }
6957         }
6958     }
6959   else
6960     {
6961       // left & result in different registers
6962       if (AOP_TYPE (result) == AOP_CRY)
6963         {
6964           // result = bit
6965           // if(size), result in bit
6966           // if(!size && ifx), conditional oper: if(left ^ right)
6967           symbol *tlbl = newiTempLabel (NULL);
6968           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6969                   
6970           if (size)
6971             emitcode ("setb", "c");
6972           while (sizer--)
6973             {
6974               if ((AOP_TYPE (right) == AOP_LIT) &&
6975                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6976                 {
6977                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6978                 }
6979               else
6980                 {
6981                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6982                     emitcode ("xrl", "a,%s",
6983                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6984                   } else {
6985                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6986                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6987                       {
6988                           emitcode("mov", "b,a");
6989                           rOp = "b";
6990                       }
6991                         
6992                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6993                       emitcode ("xrl", "a,%s", rOp);                  
6994                   }
6995                 }
6996               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6997               offset++;
6998             }
6999           if (size)
7000             {
7001               CLRC;
7002               emitcode ("", "!tlabeldef", tlbl->key + 100);
7003               outBitC (result);
7004             }
7005           else if (ifx)
7006             jmpTrueOrFalse (ifx, tlbl);
7007         }
7008       else
7009         {
7010         for (; (size--); offset++)
7011           {
7012             // normal case
7013             // result = left & right
7014             if (AOP_TYPE (right) == AOP_LIT)
7015               {
7016                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7017                   {
7018                     aopPut (AOP (result),
7019                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7020                             offset);
7021                     continue;
7022                   }
7023                 D (emitcode (";", "better literal XOR."););
7024                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7025                 emitcode ("xrl", "a, %s",
7026                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7027               }
7028             else
7029               {
7030                 // faster than result <- left, anl result,right
7031                 // and better if result is SFR
7032                 if (AOP_TYPE (left) == AOP_ACC)
7033                   {
7034                     emitcode ("xrl", "a,%s",
7035                               aopGet (AOP (right), offset,
7036                                       FALSE, FALSE, DP2_RESULT_REG));
7037                   }
7038                 else
7039                   {
7040                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7041                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7042                       {
7043                           emitcode("mov", "b,a");
7044                           rOp = "b";
7045                       }
7046                         
7047                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7048                       emitcode ("xrl", "a,%s", rOp);
7049                   }
7050               }
7051             aopPut (AOP (result), "a", offset);
7052           }
7053         }
7054         
7055     }
7056
7057 release:
7058   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7059   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7060   freeAsmop (result, NULL, ic, TRUE);
7061 }
7062
7063 /*-----------------------------------------------------------------*/
7064 /* genInline - write the inline code out                           */
7065 /*-----------------------------------------------------------------*/
7066 static void
7067 genInline (iCode * ic)
7068 {
7069   char *buffer, *bp, *bp1;
7070
7071   D (emitcode (";", "genInline "); );
7072
7073   _G.inLine += (!options.asmpeep);
7074
7075   buffer = Safe_strdup(IC_INLINE(ic));
7076   bp = buffer;
7077   bp1 = buffer;
7078
7079   /* emit each line as a code */
7080   while (*bp)
7081     {
7082       if (*bp == '\n')
7083         {
7084           *bp++ = '\0';
7085           emitcode (bp1, "");
7086           bp1 = bp;
7087         }
7088       else
7089         {
7090           if (*bp == ':')
7091             {
7092               bp++;
7093               *bp = '\0';
7094               bp++;
7095               emitcode (bp1, "");
7096               bp1 = bp;
7097             }
7098           else
7099             bp++;
7100         }
7101     }
7102   if (bp1 != bp)
7103     emitcode (bp1, "");
7104   /*     emitcode("",buffer); */
7105   _G.inLine -= (!options.asmpeep);
7106 }
7107
7108 /*-----------------------------------------------------------------*/
7109 /* genRRC - rotate right with carry                                */
7110 /*-----------------------------------------------------------------*/
7111 static void
7112 genRRC (iCode * ic)
7113 {
7114   operand *left, *result;
7115   int     size, offset;
7116
7117   D (emitcode (";", "genRRC "););
7118
7119   /* rotate right with carry */
7120   left = IC_LEFT (ic);
7121   result = IC_RESULT (ic);
7122   aopOp (left, ic, FALSE, FALSE);
7123   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7124
7125   /* move it to the result */
7126   size = AOP_SIZE (result);
7127   offset = size - 1;
7128   CLRC;
7129
7130   _startLazyDPSEvaluation ();
7131   while (size--)
7132     {
7133       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7134       emitcode ("rrc", "a");
7135       if (AOP_SIZE (result) > 1)
7136         aopPut (AOP (result), "a", offset--);
7137     }
7138   _endLazyDPSEvaluation ();
7139
7140   /* now we need to put the carry into the
7141      highest order byte of the result */
7142   if (AOP_SIZE (result) > 1)
7143     {
7144       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7145     }
7146   emitcode ("mov", "acc.7,c");
7147   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7148   freeAsmop (left, NULL, ic, TRUE);
7149   freeAsmop (result, NULL, ic, TRUE);
7150 }
7151
7152 /*-----------------------------------------------------------------*/
7153 /* genRLC - generate code for rotate left with carry               */
7154 /*-----------------------------------------------------------------*/
7155 static void
7156 genRLC (iCode * ic)
7157 {
7158   operand *left, *result;
7159   int size, offset;
7160   char *l;
7161
7162   D (emitcode (";", "genRLC "););
7163
7164   /* rotate right with carry */
7165   left = IC_LEFT (ic);
7166   result = IC_RESULT (ic);
7167   aopOp (left, ic, FALSE, FALSE);
7168   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7169
7170   /* move it to the result */
7171   size = AOP_SIZE (result);
7172   offset = 0;
7173   if (size--)
7174     {
7175       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7176       MOVA (l);
7177       emitcode ("add", "a,acc");
7178       if (AOP_SIZE (result) > 1)
7179         {
7180           aopPut (AOP (result), "a", offset++);
7181         }
7182
7183       _startLazyDPSEvaluation ();
7184       while (size--)
7185         {
7186           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7187           MOVA (l);
7188           emitcode ("rlc", "a");
7189           if (AOP_SIZE (result) > 1)
7190             aopPut (AOP (result), "a", offset++);
7191         }
7192       _endLazyDPSEvaluation ();
7193     }
7194   /* now we need to put the carry into the
7195      highest order byte of the result */
7196   if (AOP_SIZE (result) > 1)
7197     {
7198       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7199       MOVA (l);
7200     }
7201   emitcode ("mov", "acc.0,c");
7202   aopPut (AOP (result), "a", 0);
7203   freeAsmop (left, NULL, ic, TRUE);
7204   freeAsmop (result, NULL, ic, TRUE);
7205 }
7206
7207 /*-----------------------------------------------------------------*/
7208 /* genGetHbit - generates code get highest order bit               */
7209 /*-----------------------------------------------------------------*/
7210 static void
7211 genGetHbit (iCode * ic)
7212 {
7213   operand *left, *result;
7214   left = IC_LEFT (ic);
7215   result = IC_RESULT (ic);
7216   aopOp (left, ic, FALSE, FALSE);
7217   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7218
7219   D (emitcode (";", "genGetHbit "););
7220
7221   /* get the highest order byte into a */
7222   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7223   if (AOP_TYPE (result) == AOP_CRY)
7224     {
7225       emitcode ("rlc", "a");
7226       outBitC (result);
7227     }
7228   else
7229     {
7230       emitcode ("rl", "a");
7231       emitcode ("anl", "a,#1");
7232       outAcc (result);
7233     }
7234
7235
7236   freeAsmop (left, NULL, ic, TRUE);
7237   freeAsmop (result, NULL, ic, TRUE);
7238 }
7239
7240 /*-----------------------------------------------------------------*/
7241 /* AccRol - rotate left accumulator by known count                 */
7242 /*-----------------------------------------------------------------*/
7243 static void
7244 AccRol (int shCount)
7245 {
7246   shCount &= 0x0007;            // shCount : 0..7
7247
7248   switch (shCount)
7249     {
7250     case 0:
7251       break;
7252     case 1:
7253       emitcode ("rl", "a");
7254       break;
7255     case 2:
7256       emitcode ("rl", "a");
7257       emitcode ("rl", "a");
7258       break;
7259     case 3:
7260       emitcode ("swap", "a");
7261       emitcode ("rr", "a");
7262       break;
7263     case 4:
7264       emitcode ("swap", "a");
7265       break;
7266     case 5:
7267       emitcode ("swap", "a");
7268       emitcode ("rl", "a");
7269       break;
7270     case 6:
7271       emitcode ("rr", "a");
7272       emitcode ("rr", "a");
7273       break;
7274     case 7:
7275       emitcode ("rr", "a");
7276       break;
7277     }
7278 }
7279
7280 /*-----------------------------------------------------------------*/
7281 /* AccLsh - left shift accumulator by known count                  */
7282 /*-----------------------------------------------------------------*/
7283 static void
7284 AccLsh (int shCount)
7285 {
7286   if (shCount != 0)
7287     {
7288       if (shCount == 1)
7289         emitcode ("add", "a,acc");
7290       else if (shCount == 2)
7291         {
7292           emitcode ("add", "a,acc");
7293           emitcode ("add", "a,acc");
7294         }
7295       else
7296         {
7297           /* rotate left accumulator */
7298           AccRol (shCount);
7299           /* and kill the lower order bits */
7300           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7301         }
7302     }
7303 }
7304
7305 /*-----------------------------------------------------------------*/
7306 /* AccRsh - right shift accumulator by known count                 */
7307 /*-----------------------------------------------------------------*/
7308 static void
7309 AccRsh (int shCount)
7310 {
7311   if (shCount != 0)
7312     {
7313       if (shCount == 1)
7314         {
7315           CLRC;
7316           emitcode ("rrc", "a");
7317         }
7318       else
7319         {
7320           /* rotate right accumulator */
7321           AccRol (8 - shCount);
7322           /* and kill the higher order bits */
7323           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7324         }
7325     }
7326 }
7327
7328 #ifdef BETTER_LITERAL_SHIFT
7329 /*-----------------------------------------------------------------*/
7330 /* AccSRsh - signed right shift accumulator by known count                 */
7331 /*-----------------------------------------------------------------*/
7332 static void
7333 AccSRsh (int shCount)
7334 {
7335   symbol *tlbl;
7336   if (shCount != 0)
7337     {
7338       if (shCount == 1)
7339         {
7340           emitcode ("mov", "c,acc.7");
7341           emitcode ("rrc", "a");
7342         }
7343       else if (shCount == 2)
7344         {
7345           emitcode ("mov", "c,acc.7");
7346           emitcode ("rrc", "a");
7347           emitcode ("mov", "c,acc.7");
7348           emitcode ("rrc", "a");
7349         }
7350       else
7351         {
7352           tlbl = newiTempLabel (NULL);
7353           /* rotate right accumulator */
7354           AccRol (8 - shCount);
7355           /* and kill the higher order bits */
7356           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7357           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7358           emitcode ("orl", "a,#!constbyte",
7359                     (unsigned char) ~SRMask[shCount]);
7360           emitcode ("", "!tlabeldef", tlbl->key + 100);
7361         }
7362     }
7363 }
7364 #endif
7365
7366 #ifdef BETTER_LITERAL_SHIFT
7367 /*-----------------------------------------------------------------*/
7368 /* shiftR1Left2Result - shift right one byte from left to result   */
7369 /*-----------------------------------------------------------------*/
7370 static void
7371 shiftR1Left2Result (operand * left, int offl,
7372                     operand * result, int offr,
7373                     int shCount, int sign)
7374 {
7375   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7376   /* shift right accumulator */
7377   if (sign)
7378     AccSRsh (shCount);
7379   else
7380     AccRsh (shCount);
7381   aopPut (AOP (result), "a", offr);
7382 }
7383 #endif
7384
7385 #ifdef BETTER_LITERAL_SHIFT
7386 /*-----------------------------------------------------------------*/
7387 /* shiftL1Left2Result - shift left one byte from left to result    */
7388 /*-----------------------------------------------------------------*/
7389 static void
7390 shiftL1Left2Result (operand * left, int offl,
7391                     operand * result, int offr, int shCount)
7392 {
7393   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7394   /* shift left accumulator */
7395   AccLsh (shCount);
7396   aopPut (AOP (result), "a", offr);
7397 }
7398 #endif
7399
7400 #ifdef BETTER_LITERAL_SHIFT
7401 /*-----------------------------------------------------------------*/
7402 /* movLeft2Result - move byte from left to result                  */
7403 /*-----------------------------------------------------------------*/
7404 static void
7405 movLeft2Result (operand * left, int offl,
7406                 operand * result, int offr, int sign)
7407 {
7408   char *l;
7409   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7410   {
7411       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7412
7413       if (*l == '@' && (IS_AOP_PREG (result)))
7414       {
7415           emitcode ("mov", "a,%s", l);
7416           aopPut (AOP (result), "a", offr);
7417       }
7418       else
7419       {
7420           if (!sign)
7421           {
7422             aopPut (AOP (result), l, offr);
7423           }
7424           else
7425             {
7426               /* MSB sign in acc.7 ! */
7427               if (getDataSize (left) == offl + 1)
7428                 {
7429                   emitcode ("mov", "a,%s", l);
7430                   aopPut (AOP (result), "a", offr);
7431                 }
7432             }
7433       }
7434   }
7435 }
7436 #endif
7437
7438 #ifdef BETTER_LITERAL_SHIFT
7439 /*-----------------------------------------------------------------*/
7440 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7441 /*-----------------------------------------------------------------*/
7442 static void
7443 AccAXRrl1 (char *x)
7444 {
7445   emitcode ("rrc", "a");
7446   emitcode ("xch", "a,%s", x);
7447   emitcode ("rrc", "a");
7448   emitcode ("xch", "a,%s", x);
7449 }
7450 #endif
7451
7452 #ifdef BETTER_LITERAL_SHIFT
7453 //REMOVE ME!!!
7454 /*-----------------------------------------------------------------*/
7455 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7456 /*-----------------------------------------------------------------*/
7457 static void
7458 AccAXLrl1 (char *x)
7459 {
7460   emitcode ("xch", "a,%s", x);
7461   emitcode ("rlc", "a");
7462   emitcode ("xch", "a,%s", x);
7463   emitcode ("rlc", "a");
7464 }
7465 #endif
7466
7467 #ifdef BETTER_LITERAL_SHIFT
7468 /*-----------------------------------------------------------------*/
7469 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7470 /*-----------------------------------------------------------------*/
7471 static void
7472 AccAXLsh1 (char *x)
7473 {
7474   emitcode ("xch", "a,%s", x);
7475   emitcode ("add", "a,acc");
7476   emitcode ("xch", "a,%s", x);
7477   emitcode ("rlc", "a");
7478 }
7479 #endif
7480
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7484 /*-----------------------------------------------------------------*/
7485 static void
7486 AccAXLsh (char *x, int shCount)
7487 {
7488   switch (shCount)
7489     {
7490     case 0:
7491       break;
7492     case 1:
7493       AccAXLsh1 (x);
7494       break;
7495     case 2:
7496       AccAXLsh1 (x);
7497       AccAXLsh1 (x);
7498       break;
7499     case 3:
7500     case 4:
7501     case 5:                     // AAAAABBB:CCCCCDDD
7502
7503       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7504
7505       emitcode ("anl", "a,#!constbyte",
7506                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7507
7508       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7509
7510       AccRol (shCount);         // DDDCCCCC:BBB00000
7511
7512       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7513
7514       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7515
7516       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7517
7518       emitcode ("anl", "a,#!constbyte",
7519                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7520
7521       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7522
7523       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7524
7525       break;
7526     case 6:                     // AAAAAABB:CCCCCCDD
7527       emitcode ("anl", "a,#!constbyte",
7528                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7529       emitcode ("mov", "c,acc.0");      // c = B
7530       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7531 #if 0
7532       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7533       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7534 #else
7535       emitcode("rrc","a"); 
7536       emitcode("xch","a,%s", x); 
7537       emitcode("rrc","a"); 
7538       emitcode("mov","c,acc.0"); //<< get correct bit 
7539       emitcode("xch","a,%s", x); 
7540
7541       emitcode("rrc","a"); 
7542       emitcode("xch","a,%s", x); 
7543       emitcode("rrc","a"); 
7544       emitcode("xch","a,%s", x); 
7545 #endif
7546       break;
7547     case 7:                     // a:x <<= 7
7548
7549       emitcode ("anl", "a,#!constbyte",
7550                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7551
7552       emitcode ("mov", "c,acc.0");      // c = B
7553
7554       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7555
7556       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7557
7558       break;
7559     default:
7560       break;
7561     }
7562 }
7563 #endif
7564
7565 #ifdef BETTER_LITERAL_SHIFT
7566 //REMOVE ME!!!
7567 /*-----------------------------------------------------------------*/
7568 /* AccAXRsh - right shift a:x known count (0..7)                   */
7569 /*-----------------------------------------------------------------*/
7570 static void
7571 AccAXRsh (char *x, int shCount)
7572 {
7573   switch (shCount)
7574     {
7575     case 0:
7576       break;
7577     case 1:
7578       CLRC;
7579       AccAXRrl1 (x);            // 0->a:x
7580
7581       break;
7582     case 2:
7583       CLRC;
7584       AccAXRrl1 (x);            // 0->a:x
7585
7586       CLRC;
7587       AccAXRrl1 (x);            // 0->a:x
7588
7589       break;
7590     case 3:
7591     case 4:
7592     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7593
7594       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7595
7596       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7597
7598       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7599
7600       emitcode ("anl", "a,#!constbyte",
7601                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7602
7603       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7604
7605       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7606
7607       emitcode ("anl", "a,#!constbyte",
7608                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7609
7610       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7611
7612       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7613
7614       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7615
7616       break;
7617     case 6:                     // AABBBBBB:CCDDDDDD
7618
7619       emitcode ("mov", "c,acc.7");
7620       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7621
7622       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7623
7624       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7625
7626       emitcode ("anl", "a,#!constbyte",
7627                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7628
7629       break;
7630     case 7:                     // ABBBBBBB:CDDDDDDD
7631
7632       emitcode ("mov", "c,acc.7");      // c = A
7633
7634       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7635
7636       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7637
7638       emitcode ("anl", "a,#!constbyte",
7639                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7640
7641       break;
7642     default:
7643       break;
7644     }
7645 }
7646 #endif
7647
7648 #ifdef BETTER_LITERAL_SHIFT
7649 /*-----------------------------------------------------------------*/
7650 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7651 /*-----------------------------------------------------------------*/
7652 static void
7653 AccAXRshS (char *x, int shCount)
7654 {
7655   symbol *tlbl;
7656   switch (shCount)
7657     {
7658     case 0:
7659       break;
7660     case 1:
7661       emitcode ("mov", "c,acc.7");
7662       AccAXRrl1 (x);            // s->a:x
7663
7664       break;
7665     case 2:
7666       emitcode ("mov", "c,acc.7");
7667       AccAXRrl1 (x);            // s->a:x
7668
7669       emitcode ("mov", "c,acc.7");
7670       AccAXRrl1 (x);            // s->a:x
7671
7672       break;
7673     case 3:
7674     case 4:
7675     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7676
7677       tlbl = newiTempLabel (NULL);
7678       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7679
7680       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7681
7682       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7683
7684       emitcode ("anl", "a,#!constbyte",
7685                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7686
7687       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7688
7689       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7690
7691       emitcode ("anl", "a,#!constbyte",
7692                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7693
7694       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7695
7696       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7697
7698       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7699
7700       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7701       emitcode ("orl", "a,#!constbyte",
7702                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7703
7704       emitcode ("", "!tlabeldef", tlbl->key + 100);
7705       break;                    // SSSSAAAA:BBBCCCCC
7706
7707     case 6:                     // AABBBBBB:CCDDDDDD
7708
7709       tlbl = newiTempLabel (NULL);
7710       emitcode ("mov", "c,acc.7");
7711       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7712
7713       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7714
7715       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7716
7717       emitcode ("anl", "a,#!constbyte",
7718                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7719
7720       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7721       emitcode ("orl", "a,#!constbyte",
7722                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7723
7724       emitcode ("", "!tlabeldef", tlbl->key + 100);
7725       break;
7726     case 7:                     // ABBBBBBB:CDDDDDDD
7727
7728       tlbl = newiTempLabel (NULL);
7729       emitcode ("mov", "c,acc.7");      // c = A
7730
7731       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7732
7733       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7734
7735       emitcode ("anl", "a,#!constbyte",
7736                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7737
7738       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7739       emitcode ("orl", "a,#!constbyte",
7740                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7741
7742       emitcode ("", "!tlabeldef", tlbl->key + 100);
7743       break;
7744     default:
7745       break;
7746     }
7747 }
7748 #endif
7749
7750 #ifdef BETTER_LITERAL_SHIFT
7751 static void
7752 _loadLeftIntoAx(char    **lsb, 
7753                 operand *left, 
7754                 operand *result,
7755                 int     offl,
7756                 int     offr)
7757 {
7758   // Get the initial value from left into a pair of registers.
7759   // MSB must be in A, LSB can be any register.
7760   //
7761   // If the result is held in registers, it is an optimization
7762   // if the LSB can be held in the register which will hold the,
7763   // result LSB since this saves us from having to copy it into
7764   // the result following AccAXLsh.
7765   //
7766   // If the result is addressed indirectly, this is not a gain.
7767   if (AOP_NEEDSACC(result))
7768   {
7769        char *leftByte;
7770        
7771        _startLazyDPSEvaluation();
7772       if (AOP_TYPE(left) == AOP_DPTR2)
7773        {
7774            // Get MSB in A.
7775            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7776            // get LSB in DP2_RESULT_REG.
7777            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7778            assert(!strcmp(leftByte, DP2_RESULT_REG));
7779        }
7780        else
7781        {
7782            // get LSB into DP2_RESULT_REG
7783            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7784            if (strcmp(leftByte, DP2_RESULT_REG))
7785            {
7786                TR_AP("#7");
7787                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7788            }
7789            // And MSB in A.
7790            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7791            assert(strcmp(leftByte, DP2_RESULT_REG));
7792            MOVA(leftByte);
7793        }
7794        _endLazyDPSEvaluation();
7795        *lsb = DP2_RESULT_REG;
7796   }
7797   else
7798   {
7799       if (sameRegs (AOP (result), AOP (left)) &&
7800         ((offl + MSB16) == offr))
7801       {
7802           /* don't crash result[offr] */
7803           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7804           emitcode ("xch", "a,%s", 
7805                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7806       }
7807       else
7808       {
7809           movLeft2Result (left, offl, result, offr, 0);
7810           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7811       }
7812       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7813       assert(strcmp(*lsb,"a"));      
7814   }
7815 }
7816
7817 static void
7818 _storeAxResults(char    *lsb,
7819                 operand *result,
7820                 int     offr)
7821 {
7822   _startLazyDPSEvaluation();
7823   if (AOP_NEEDSACC(result))
7824   {
7825       /* We have to explicitly update the result LSB.
7826        */
7827       emitcode("xch","a,%s", lsb);
7828       aopPut(AOP(result), "a", offr);
7829       emitcode("mov","a,%s", lsb);
7830   }
7831   if (getDataSize (result) > 1)
7832   {
7833       aopPut (AOP (result), "a", offr + MSB16);
7834   }
7835   _endLazyDPSEvaluation();
7836 }
7837
7838 /*-----------------------------------------------------------------*/
7839 /* shiftL2Left2Result - shift left two bytes from left to result   */
7840 /*-----------------------------------------------------------------*/
7841 static void
7842 shiftL2Left2Result (operand * left, int offl,
7843                     operand * result, int offr, int shCount)
7844 {
7845   char *lsb;
7846
7847   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7848   
7849   AccAXLsh (lsb, shCount);
7850   
7851   _storeAxResults(lsb, result, offr);
7852 }
7853 #endif
7854
7855 #ifdef BETTER_LITERAL_SHIFT
7856 /*-----------------------------------------------------------------*/
7857 /* shiftR2Left2Result - shift right two bytes from left to result  */
7858 /*-----------------------------------------------------------------*/
7859 static void
7860 shiftR2Left2Result (operand * left, int offl,
7861                     operand * result, int offr,
7862                     int shCount, int sign)
7863 {
7864   char *lsb;
7865   
7866   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7867   
7868   /* a:x >> shCount (x = lsb(result)) */
7869   if (sign)
7870   {
7871      AccAXRshS(lsb, shCount);
7872   }
7873   else
7874   {
7875     AccAXRsh(lsb, shCount);
7876   }
7877   
7878   _storeAxResults(lsb, result, offr);
7879 }
7880 #endif
7881
7882 #if 0
7883 //REMOVE ME!!!
7884 /*-----------------------------------------------------------------*/
7885 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7886 /*-----------------------------------------------------------------*/
7887 static void
7888 shiftLLeftOrResult (operand * left, int offl,
7889                     operand * result, int offr, int shCount)
7890 {
7891   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7892   /* shift left accumulator */
7893   AccLsh (shCount);
7894   /* or with result */
7895   emitcode ("orl", "a,%s",
7896             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7897   /* back to result */
7898   aopPut (AOP (result), "a", offr);
7899 }
7900 #endif
7901
7902 #if 0
7903 //REMOVE ME!!!
7904 /*-----------------------------------------------------------------*/
7905 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7906 /*-----------------------------------------------------------------*/
7907 static void
7908 shiftRLeftOrResult (operand * left, int offl,
7909                     operand * result, int offr, int shCount)
7910 {
7911   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7912   /* shift right accumulator */
7913   AccRsh (shCount);
7914   /* or with result */
7915   emitcode ("orl", "a,%s",
7916             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7917   /* back to result */
7918   aopPut (AOP (result), "a", offr);
7919 }
7920 #endif
7921
7922 #ifdef BETTER_LITERAL_SHIFT
7923 /*-----------------------------------------------------------------*/
7924 /* genlshOne - left shift a one byte quantity by known count       */
7925 /*-----------------------------------------------------------------*/
7926 static void
7927 genlshOne (operand * result, operand * left, int shCount)
7928 {
7929   D (emitcode (";", "genlshOne "););
7930   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7931 }
7932 #endif
7933
7934 #ifdef BETTER_LITERAL_SHIFT
7935 /*-----------------------------------------------------------------*/
7936 /* genlshTwo - left shift two bytes by known amount != 0           */
7937 /*-----------------------------------------------------------------*/
7938 static void
7939 genlshTwo (operand * result, operand * left, int shCount)
7940 {
7941   int size;
7942
7943   D (emitcode (";", "genlshTwo "););
7944
7945   size = getDataSize (result);
7946
7947   /* if shCount >= 8 */
7948   if (shCount >= 8)
7949   {
7950       shCount -= 8;
7951
7952       _startLazyDPSEvaluation();
7953
7954       if (size > 1)
7955         {
7956           if (shCount)
7957           {
7958             _endLazyDPSEvaluation();
7959             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7960             aopPut (AOP (result), zero, LSB);       
7961           }
7962           else
7963           {
7964             movLeft2Result (left, LSB, result, MSB16, 0);
7965             aopPut (AOP (result), zero, LSB);
7966             _endLazyDPSEvaluation();
7967           }
7968         }
7969         else
7970         {
7971           aopPut (AOP (result), zero, LSB);
7972           _endLazyDPSEvaluation();
7973         }
7974   }
7975
7976   /*  1 <= shCount <= 7 */
7977   else
7978     {
7979       if (size == 1)
7980       {
7981         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7982       }
7983       else
7984       {
7985         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7986       }
7987     }
7988 }
7989 #endif
7990
7991 #if 0
7992 //REMOVE ME!!!
7993 /*-----------------------------------------------------------------*/
7994 /* shiftLLong - shift left one long from left to result            */
7995 /* offl = LSB or MSB16                                             */
7996 /*-----------------------------------------------------------------*/
7997 static void
7998 shiftLLong (operand * left, operand * result, int offr)
7999 {
8000   char *l;
8001   int size = AOP_SIZE (result);
8002
8003   if (size >= LSB + offr)
8004     {
8005       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8006       MOVA (l);
8007       emitcode ("add", "a,acc");
8008       if (sameRegs (AOP (left), AOP (result)) &&
8009           size >= MSB16 + offr && offr != LSB)
8010         emitcode ("xch", "a,%s",
8011                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8012       else
8013         aopPut (AOP (result), "a", LSB + offr);
8014     }
8015
8016   if (size >= MSB16 + offr)
8017     {
8018       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8019         {
8020           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8021         }
8022       emitcode ("rlc", "a");
8023       if (sameRegs (AOP (left), AOP (result)) &&
8024           size >= MSB24 + offr && offr != LSB)
8025         emitcode ("xch", "a,%s",
8026                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8027       else
8028         aopPut (AOP (result), "a", MSB16 + offr);
8029     }
8030
8031   if (size >= MSB24 + offr)
8032     {
8033       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8034         {
8035           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8036         }
8037       emitcode ("rlc", "a");
8038       if (sameRegs (AOP (left), AOP (result)) &&
8039           size >= MSB32 + offr && offr != LSB)
8040         emitcode ("xch", "a,%s",
8041                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8042       else
8043         aopPut (AOP (result), "a", MSB24 + offr);
8044     }
8045
8046   if (size > MSB32 + offr)
8047     {
8048       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8049         {
8050           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8051         }
8052       emitcode ("rlc", "a");
8053       aopPut (AOP (result), "a", MSB32 + offr);
8054     }
8055   if (offr != LSB)
8056     aopPut (AOP (result), zero, LSB);
8057 }
8058 #endif
8059
8060 #if 0
8061 //REMOVE ME!!!
8062 /*-----------------------------------------------------------------*/
8063 /* genlshFour - shift four byte by a known amount != 0             */
8064 /*-----------------------------------------------------------------*/
8065 static void
8066 genlshFour (operand * result, operand * left, int shCount)
8067 {
8068   int size;
8069
8070   D (emitcode (";", "genlshFour ");
8071     );
8072
8073   size = AOP_SIZE (result);
8074
8075   /* if shifting more that 3 bytes */
8076   if (shCount >= 24)
8077     {
8078       shCount -= 24;
8079       if (shCount)
8080         /* lowest order of left goes to the highest
8081            order of the destination */
8082         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8083       else
8084         movLeft2Result (left, LSB, result, MSB32, 0);
8085       aopPut (AOP (result), zero, LSB);
8086       aopPut (AOP (result), zero, MSB16);
8087       aopPut (AOP (result), zero, MSB24);
8088       return;
8089     }
8090
8091   /* more than two bytes */
8092   else if (shCount >= 16)
8093     {
8094       /* lower order two bytes goes to higher order two bytes */
8095       shCount -= 16;
8096       /* if some more remaining */
8097       if (shCount)
8098         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8099       else
8100         {
8101           movLeft2Result (left, MSB16, result, MSB32, 0);
8102           movLeft2Result (left, LSB, result, MSB24, 0);
8103         }
8104       aopPut (AOP (result), zero, MSB16);
8105       aopPut (AOP (result), zero, LSB);
8106       return;
8107     }
8108
8109   /* if more than 1 byte */
8110   else if (shCount >= 8)
8111     {
8112       /* lower order three bytes goes to higher order  three bytes */
8113       shCount -= 8;
8114       if (size == 2)
8115         {
8116           if (shCount)
8117             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8118           else
8119             movLeft2Result (left, LSB, result, MSB16, 0);
8120         }
8121       else
8122         {                       /* size = 4 */
8123           if (shCount == 0)
8124             {
8125               movLeft2Result (left, MSB24, result, MSB32, 0);
8126               movLeft2Result (left, MSB16, result, MSB24, 0);
8127               movLeft2Result (left, LSB, result, MSB16, 0);
8128               aopPut (AOP (result), zero, LSB);
8129             }
8130           else if (shCount == 1)
8131             shiftLLong (left, result, MSB16);
8132           else
8133             {
8134               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8135               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8136               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8137               aopPut (AOP (result), zero, LSB);
8138             }
8139         }
8140     }
8141
8142   /* 1 <= shCount <= 7 */
8143   else if (shCount <= 2)
8144     {
8145       shiftLLong (left, result, LSB);
8146       if (shCount == 2)
8147         shiftLLong (result, result, LSB);
8148     }
8149   /* 3 <= shCount <= 7, optimize */
8150   else
8151     {
8152       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8153       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8154       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8155     }
8156 }
8157 #endif
8158
8159 #ifdef BETTER_LITERAL_SHIFT
8160 /*-----------------------------------------------------------------*/
8161 /* genLeftShiftLiteral - left shifting by known count              */
8162 /*-----------------------------------------------------------------*/
8163 static bool
8164 genLeftShiftLiteral (operand * left,
8165                      operand * right,
8166                      operand * result,
8167                      iCode * ic)
8168 {
8169   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8170   int size;
8171
8172   size = getSize (operandType (result));
8173
8174   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8175
8176   /* We only handle certain easy cases so far. */
8177   if ((shCount != 0)
8178    && (shCount < (size * 8))
8179    && (size != 1)
8180    && (size != 2))
8181   {
8182       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8183       return FALSE;
8184   }
8185
8186   freeAsmop (right, NULL, ic, TRUE);
8187
8188   aopOp(left, ic, FALSE, FALSE);
8189   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8190
8191 #if 0 // debug spew
8192   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8193   {
8194         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8195         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8196         {
8197            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8198         }
8199   }
8200   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8201   {
8202         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8203         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8204         {
8205            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8206         }       
8207   }  
8208 #endif
8209   
8210 #if VIEW_SIZE
8211   emitcode ("; shift left ", "result %d, left %d", size,
8212             AOP_SIZE (left));
8213 #endif
8214
8215   /* I suppose that the left size >= result size */
8216   if (shCount == 0)
8217   {
8218         _startLazyDPSEvaluation();
8219         while (size--)
8220         {
8221           movLeft2Result (left, size, result, size, 0);
8222         }
8223         _endLazyDPSEvaluation();
8224   }
8225   else if (shCount >= (size * 8))
8226   {
8227     _startLazyDPSEvaluation();
8228     while (size--)
8229     {
8230       aopPut (AOP (result), zero, size);
8231     }
8232     _endLazyDPSEvaluation();
8233   }
8234   else
8235   {
8236       switch (size)
8237         {
8238         case 1:
8239           genlshOne (result, left, shCount);
8240           break;
8241
8242         case 2:
8243           genlshTwo (result, left, shCount);
8244           break;
8245 #if 0
8246         case 4:
8247           genlshFour (result, left, shCount);
8248           break;
8249 #endif
8250         default:
8251           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8252           break;
8253         }
8254     }
8255   freeAsmop (left, NULL, ic, TRUE);
8256   freeAsmop (result, NULL, ic, TRUE);
8257   return TRUE;
8258 }
8259 #endif
8260
8261 /*-----------------------------------------------------------------*/
8262 /* genLeftShift - generates code for left shifting                 */
8263 /*-----------------------------------------------------------------*/
8264 static void
8265 genLeftShift (iCode * ic)
8266 {
8267   operand *left, *right, *result;
8268   int size, offset;
8269   char *l;
8270   symbol *tlbl, *tlbl1;
8271
8272   D (emitcode (";", "genLeftShift "););
8273
8274   right = IC_RIGHT (ic);
8275   left = IC_LEFT (ic);
8276   result = IC_RESULT (ic);
8277
8278   aopOp (right, ic, FALSE, FALSE);
8279
8280
8281 #ifdef BETTER_LITERAL_SHIFT
8282   /* if the shift count is known then do it
8283      as efficiently as possible */
8284   if (AOP_TYPE (right) == AOP_LIT)
8285     {
8286       if (genLeftShiftLiteral (left, right, result, ic))
8287       {
8288         return;
8289       }
8290     }
8291 #endif
8292
8293   /* shift count is unknown then we have to form
8294      a loop get the loop count in B : Note: we take
8295      only the lower order byte since shifting
8296      more that 32 bits make no sense anyway, ( the
8297      largest size of an object can be only 32 bits ) */
8298
8299   if (AOP_TYPE (right) == AOP_LIT)
8300   {
8301       /* Really should be handled by genLeftShiftLiteral,
8302        * but since I'm too lazy to fix that today, at least we can make
8303        * some small improvement.
8304        */
8305        emitcode("mov", "b,#!constbyte",
8306                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8307   }
8308   else
8309   {
8310       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8311       emitcode ("inc", "b");
8312   }
8313   freeAsmop (right, NULL, ic, TRUE);
8314   aopOp (left, ic, FALSE, FALSE);
8315   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8316
8317   /* now move the left to the result if they are not the
8318      same */
8319   if (!sameRegs (AOP (left), AOP (result)) &&
8320       AOP_SIZE (result) > 1)
8321     {
8322
8323       size = AOP_SIZE (result);
8324       offset = 0;
8325       _startLazyDPSEvaluation ();
8326       while (size--)
8327         {
8328           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8329           if (*l == '@' && (IS_AOP_PREG (result)))
8330             {
8331
8332               emitcode ("mov", "a,%s", l);
8333               aopPut (AOP (result), "a", offset);
8334             }
8335           else
8336             aopPut (AOP (result), l, offset);
8337           offset++;
8338         }
8339       _endLazyDPSEvaluation ();
8340     }
8341
8342   tlbl = newiTempLabel (NULL);
8343   size = AOP_SIZE (result);
8344   offset = 0;
8345   tlbl1 = newiTempLabel (NULL);
8346
8347   /* if it is only one byte then */
8348   if (size == 1)
8349     {
8350       symbol *tlbl1 = newiTempLabel (NULL);
8351
8352       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8353       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8354       emitcode ("", "!tlabeldef", tlbl->key + 100);
8355       emitcode ("add", "a,acc");
8356       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8357       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8358       aopPut (AOP (result), "a", 0);
8359       goto release;
8360     }
8361
8362   reAdjustPreg (AOP (result));
8363
8364   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8365   emitcode ("", "!tlabeldef", tlbl->key + 100);
8366   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8367   emitcode ("add", "a,acc");
8368   aopPut (AOP (result), "a", offset++);
8369   _startLazyDPSEvaluation ();
8370   while (--size)
8371     {
8372       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8373       emitcode ("rlc", "a");
8374       aopPut (AOP (result), "a", offset++);
8375     }
8376   _endLazyDPSEvaluation ();
8377   reAdjustPreg (AOP (result));
8378
8379   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8380   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8381 release:
8382   freeAsmop (left, NULL, ic, TRUE);
8383   freeAsmop (result, NULL, ic, TRUE);
8384 }
8385
8386 #ifdef BETTER_LITERAL_SHIFT
8387 /*-----------------------------------------------------------------*/
8388 /* genrshOne - right shift a one byte quantity by known count      */
8389 /*-----------------------------------------------------------------*/
8390 static void
8391 genrshOne (operand * result, operand * left,
8392            int shCount, int sign)
8393 {
8394   D (emitcode (";", "genrshOne"););
8395   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8396 }
8397 #endif
8398
8399 #ifdef BETTER_LITERAL_SHIFT
8400 /*-----------------------------------------------------------------*/
8401 /* genrshTwo - right shift two bytes by known amount != 0          */
8402 /*-----------------------------------------------------------------*/
8403 static void
8404 genrshTwo (operand * result, operand * left,
8405            int shCount, int sign)
8406 {
8407   D (emitcode (";", "genrshTwo"););
8408
8409   /* if shCount >= 8 */
8410   if (shCount >= 8)
8411     {
8412       shCount -= 8;
8413       _startLazyDPSEvaluation();
8414       if (shCount)
8415       {
8416         shiftR1Left2Result (left, MSB16, result, LSB,
8417                             shCount, sign);
8418       }                     
8419       else
8420       {
8421         movLeft2Result (left, MSB16, result, LSB, sign);
8422       }
8423       addSign (result, MSB16, sign);
8424       _endLazyDPSEvaluation();
8425     }
8426
8427   /*  1 <= shCount <= 7 */
8428   else
8429   {
8430     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8431   }
8432 }
8433 #endif
8434
8435 #if 0
8436 //REMOVE ME!!!
8437 /*-----------------------------------------------------------------*/
8438 /* shiftRLong - shift right one long from left to result           */
8439 /* offl = LSB or MSB16                                             */
8440 /*-----------------------------------------------------------------*/
8441 static void
8442 shiftRLong (operand * left, int offl,
8443             operand * result, int sign)
8444 {
8445   int isSameRegs=sameRegs(AOP(left),AOP(result));
8446
8447   if (isSameRegs && offl>1) {
8448     // we are in big trouble, but this shouldn't happen
8449     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8450   }
8451
8452   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8453   
8454   if (offl==MSB16) {
8455     // shift is > 8
8456     if (sign) {
8457       emitcode ("rlc", "a");
8458       emitcode ("subb", "a,acc");
8459       emitcode ("xch", "a,%s",
8460                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8461     } else {
8462       aopPut (AOP(result), zero, MSB32);
8463     }
8464   }
8465
8466   if (!sign) {
8467     emitcode ("clr", "c");
8468   } else {
8469     emitcode ("mov", "c,acc.7");
8470   }
8471
8472   emitcode ("rrc", "a");
8473
8474   if (isSameRegs && offl==MSB16) {
8475     emitcode ("xch",
8476               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8477   } else {
8478     aopPut (AOP (result), "a", MSB32);
8479     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8480   }
8481
8482   emitcode ("rrc", "a");
8483   if (isSameRegs && offl==1) {
8484     emitcode ("xch", "a,%s",
8485               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8486   } else {
8487     aopPut (AOP (result), "a", MSB24);
8488     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8489   }
8490   emitcode ("rrc", "a");
8491   aopPut (AOP (result), "a", MSB16 - offl);
8492
8493   if (offl == LSB)
8494     {
8495       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8496       emitcode ("rrc", "a");
8497       aopPut (AOP (result), "a", LSB);
8498     }
8499 }
8500 #endif
8501
8502 #if 0
8503 //REMOVE ME!!!
8504 /*-----------------------------------------------------------------*/
8505 /* genrshFour - shift four byte by a known amount != 0             */
8506 /*-----------------------------------------------------------------*/
8507 static void
8508 genrshFour (operand * result, operand * left,
8509             int shCount, int sign)
8510 {
8511   D (emitcode (";", "genrshFour");
8512     );
8513
8514   /* if shifting more that 3 bytes */
8515   if (shCount >= 24)
8516     {
8517       shCount -= 24;
8518       if (shCount)
8519         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8520       else
8521         movLeft2Result (left, MSB32, result, LSB, sign);
8522       addSign (result, MSB16, sign);
8523     }
8524   else if (shCount >= 16)
8525     {
8526       shCount -= 16;
8527       if (shCount)
8528         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8529       else
8530         {
8531           movLeft2Result (left, MSB24, result, LSB, 0);
8532           movLeft2Result (left, MSB32, result, MSB16, sign);
8533         }
8534       addSign (result, MSB24, sign);
8535     }
8536   else if (shCount >= 8)
8537     {
8538       shCount -= 8;
8539       if (shCount == 1)
8540         shiftRLong (left, MSB16, result, sign);
8541       else if (shCount == 0)
8542         {
8543           movLeft2Result (left, MSB16, result, LSB, 0);
8544           movLeft2Result (left, MSB24, result, MSB16, 0);
8545           movLeft2Result (left, MSB32, result, MSB24, sign);
8546           addSign (result, MSB32, sign);
8547         }
8548       else
8549         {
8550           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8551           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8552           /* the last shift is signed */
8553           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8554           addSign (result, MSB32, sign);
8555         }
8556     }
8557   else
8558     {                           /* 1 <= shCount <= 7 */
8559       if (shCount <= 2)
8560         {
8561           shiftRLong (left, LSB, result, sign);
8562           if (shCount == 2)
8563             shiftRLong (result, LSB, result, sign);
8564         }
8565       else
8566         {
8567           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8568           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8569           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8570         }
8571     }
8572 }
8573 #endif
8574
8575 #ifdef BETTER_LITERAL_SHIFT
8576 /*-----------------------------------------------------------------*/
8577 /* genRightShiftLiteral - right shifting by known count            */
8578 /*-----------------------------------------------------------------*/
8579 static bool
8580 genRightShiftLiteral (operand * left,
8581                       operand * right,
8582                       operand * result,
8583                       iCode * ic,
8584                       int sign)
8585 {
8586   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8587   int size;
8588
8589   size = getSize (operandType (result));
8590
8591   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8592
8593   /* We only handle certain easy cases so far. */
8594   if ((shCount != 0)
8595    && (shCount < (size * 8))
8596    && (size != 1)
8597    && (size != 2))
8598   {
8599       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8600       return FALSE;
8601   }
8602
8603   freeAsmop (right, NULL, ic, TRUE);
8604
8605   aopOp (left, ic, FALSE, FALSE);
8606   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8607
8608 #if VIEW_SIZE
8609   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8610             AOP_SIZE (left));
8611 #endif
8612
8613   /* test the LEFT size !!! */
8614
8615   /* I suppose that the left size >= result size */
8616   if (shCount == 0)
8617   {
8618       size = getDataSize (result);
8619       _startLazyDPSEvaluation();
8620       while (size--)
8621       {
8622         movLeft2Result (left, size, result, size, 0);
8623       }
8624       _endLazyDPSEvaluation();
8625   }
8626   else if (shCount >= (size * 8))
8627     {
8628       if (sign)
8629       {
8630         /* get sign in acc.7 */
8631         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8632       }
8633       addSign (result, LSB, sign);
8634     }
8635   else
8636     {
8637       switch (size)
8638         {
8639         case 1:
8640           genrshOne (result, left, shCount, sign);
8641           break;
8642
8643         case 2:
8644           genrshTwo (result, left, shCount, sign);
8645           break;
8646 #if 0
8647         case 4:
8648           genrshFour (result, left, shCount, sign);
8649           break;
8650 #endif    
8651         default:
8652           break;
8653         }
8654     }
8655   freeAsmop (left, NULL, ic, TRUE);
8656   freeAsmop (result, NULL, ic, TRUE);
8657   
8658   return TRUE;
8659 }
8660 #endif
8661
8662 /*-----------------------------------------------------------------*/
8663 /* genSignedRightShift - right shift of signed number              */
8664 /*-----------------------------------------------------------------*/
8665 static void
8666 genSignedRightShift (iCode * ic)
8667 {
8668   operand *right, *left, *result;
8669   int size, offset;
8670   char *l;
8671   symbol *tlbl, *tlbl1;
8672
8673   D (emitcode (";", "genSignedRightShift "););
8674
8675   /* we do it the hard way put the shift count in b
8676      and loop thru preserving the sign */
8677
8678   right = IC_RIGHT (ic);
8679   left = IC_LEFT (ic);
8680   result = IC_RESULT (ic);
8681
8682   aopOp (right, ic, FALSE, FALSE);
8683
8684 #ifdef BETTER_LITERAL_SHIFT
8685   if (AOP_TYPE (right) == AOP_LIT)
8686     {
8687       if (genRightShiftLiteral (left, right, result, ic, 1))
8688       {
8689         return;
8690       }
8691     }
8692 #endif
8693   /* shift count is unknown then we have to form
8694      a loop get the loop count in B : Note: we take
8695      only the lower order byte since shifting
8696      more that 32 bits make no sense anyway, ( the
8697      largest size of an object can be only 32 bits ) */
8698
8699   if (AOP_TYPE (right) == AOP_LIT)
8700   {
8701       /* Really should be handled by genRightShiftLiteral,
8702        * but since I'm too lazy to fix that today, at least we can make
8703        * some small improvement.
8704        */
8705        emitcode("mov", "b,#!constbyte",
8706                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8707   }
8708   else
8709   {
8710         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8711         emitcode ("inc", "b");
8712   }
8713   freeAsmop (right, NULL, ic, TRUE);
8714   aopOp (left, ic, FALSE, FALSE);
8715   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8716
8717   /* now move the left to the result if they are not the
8718      same */
8719   if (!sameRegs (AOP (left), AOP (result)) &&
8720       AOP_SIZE (result) > 1)
8721     {
8722
8723       size = AOP_SIZE (result);
8724       offset = 0;
8725       _startLazyDPSEvaluation ();
8726       while (size--)
8727         {
8728           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8729           if (*l == '@' && IS_AOP_PREG (result))
8730             {
8731
8732               emitcode ("mov", "a,%s", l);
8733               aopPut (AOP (result), "a", offset);
8734             }
8735           else
8736             aopPut (AOP (result), l, offset);
8737           offset++;
8738         }
8739       _endLazyDPSEvaluation ();
8740     }
8741
8742   /* mov the highest order bit to OVR */
8743   tlbl = newiTempLabel (NULL);
8744   tlbl1 = newiTempLabel (NULL);
8745
8746   size = AOP_SIZE (result);
8747   offset = size - 1;
8748   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8749   emitcode ("rlc", "a");
8750   emitcode ("mov", "ov,c");
8751   /* if it is only one byte then */
8752   if (size == 1)
8753     {
8754       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8755       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8756       emitcode ("", "!tlabeldef", tlbl->key + 100);
8757       emitcode ("mov", "c,ov");
8758       emitcode ("rrc", "a");
8759       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8760       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8761       aopPut (AOP (result), "a", 0);
8762       goto release;
8763     }
8764
8765   reAdjustPreg (AOP (result));
8766   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8767   emitcode ("", "!tlabeldef", tlbl->key + 100);
8768   emitcode ("mov", "c,ov");
8769   _startLazyDPSEvaluation ();
8770   while (size--)
8771     {
8772       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8773       emitcode ("rrc", "a");
8774       aopPut (AOP (result), "a", offset--);
8775     }
8776   _endLazyDPSEvaluation ();
8777   reAdjustPreg (AOP (result));
8778   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8779   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8780
8781 release:
8782   freeAsmop (left, NULL, ic, TRUE);
8783   freeAsmop (result, NULL, ic, TRUE);
8784 }
8785
8786 /*-----------------------------------------------------------------*/
8787 /* genRightShift - generate code for right shifting                */
8788 /*-----------------------------------------------------------------*/
8789 static void
8790 genRightShift (iCode * ic)
8791 {
8792   operand *right, *left, *result;
8793   sym_link *retype;
8794   int size, offset;
8795   char *l;
8796   symbol *tlbl, *tlbl1;
8797
8798   D (emitcode (";", "genRightShift "););
8799
8800   /* if signed then we do it the hard way preserve the
8801      sign bit moving it inwards */
8802   retype = getSpec (operandType (IC_RESULT (ic)));
8803
8804   if (!SPEC_USIGN (retype))
8805     {
8806       genSignedRightShift (ic);
8807       return;
8808     }
8809
8810   /* signed & unsigned types are treated the same : i.e. the
8811      signed is NOT propagated inwards : quoting from the
8812      ANSI - standard : "for E1 >> E2, is equivalent to division
8813      by 2**E2 if unsigned or if it has a non-negative value,
8814      otherwise the result is implementation defined ", MY definition
8815      is that the sign does not get propagated */
8816
8817   right = IC_RIGHT (ic);
8818   left = IC_LEFT (ic);
8819   result = IC_RESULT (ic);
8820
8821   aopOp (right, ic, FALSE, FALSE);
8822
8823 #ifdef BETTER_LITERAL_SHIFT
8824   /* if the shift count is known then do it
8825      as efficiently as possible */
8826   if (AOP_TYPE (right) == AOP_LIT)
8827     {
8828       if (genRightShiftLiteral (left, right, result, ic, 0))
8829       {
8830         return;
8831       }
8832     }
8833 #endif
8834
8835   /* shift count is unknown then we have to form
8836      a loop get the loop count in B : Note: we take
8837      only the lower order byte since shifting
8838      more that 32 bits make no sense anyway, ( the
8839      largest size of an object can be only 32 bits ) */
8840   
8841   if (AOP_TYPE (right) == AOP_LIT)
8842   {
8843       /* Really should be handled by genRightShiftLiteral,
8844        * but since I'm too lazy to fix that today, at least we can make
8845        * some small improvement.
8846        */
8847        emitcode("mov", "b,#!constbyte",
8848                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8849   }
8850   else
8851   {
8852       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8853       emitcode ("inc", "b");
8854   }
8855   freeAsmop (right, NULL, ic, TRUE);
8856   aopOp (left, ic, FALSE, FALSE);
8857   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8858
8859   /* now move the left to the result if they are not the
8860      same */
8861   if (!sameRegs (AOP (left), AOP (result)) &&
8862       AOP_SIZE (result) > 1)
8863     {
8864
8865       size = AOP_SIZE (result);
8866       offset = 0;
8867       _startLazyDPSEvaluation ();
8868       while (size--)
8869         {
8870           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8871           if (*l == '@' && IS_AOP_PREG (result))
8872             {
8873
8874               emitcode ("mov", "a,%s", l);
8875               aopPut (AOP (result), "a", offset);
8876             }
8877           else
8878             aopPut (AOP (result), l, offset);
8879           offset++;
8880         }
8881       _endLazyDPSEvaluation ();
8882     }
8883
8884   tlbl = newiTempLabel (NULL);
8885   tlbl1 = newiTempLabel (NULL);
8886   size = AOP_SIZE (result);
8887   offset = size - 1;
8888
8889   /* if it is only one byte then */
8890   if (size == 1)
8891     {
8892       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8893       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8894       emitcode ("", "!tlabeldef", tlbl->key + 100);
8895       CLRC;
8896       emitcode ("rrc", "a");
8897       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8898       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8899       aopPut (AOP (result), "a", 0);
8900       goto release;
8901     }
8902
8903   reAdjustPreg (AOP (result));
8904   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8905   emitcode ("", "!tlabeldef", tlbl->key + 100);
8906   CLRC;
8907   _startLazyDPSEvaluation ();
8908   while (size--)
8909     {
8910       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8911       emitcode ("rrc", "a");
8912       aopPut (AOP (result), "a", offset--);
8913     }
8914   _endLazyDPSEvaluation ();
8915   reAdjustPreg (AOP (result));
8916
8917   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8918   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8919
8920 release:
8921   freeAsmop (left, NULL, ic, TRUE);
8922   freeAsmop (result, NULL, ic, TRUE);
8923 }
8924
8925 /*-----------------------------------------------------------------*/
8926 /* genUnpackBits - generates code for unpacking bits               */
8927 /*-----------------------------------------------------------------*/
8928 static void
8929 genUnpackBits (operand * result, char *rname, int ptype)
8930 {
8931   int shCnt;
8932   int rlen;
8933   sym_link *etype;
8934   int offset = 0;
8935
8936   D (emitcode (";", "genUnpackBits "););
8937
8938   etype = getSpec (operandType (result));
8939
8940   /* read the first byte  */
8941   switch (ptype)
8942     {
8943
8944     case POINTER:
8945     case IPOINTER:
8946       emitcode ("mov", "a,@%s", rname);
8947       break;
8948
8949     case PPOINTER:
8950       emitcode ("movx", "a,@%s", rname);
8951       break;
8952
8953     case FPOINTER:
8954       emitcode ("movx", "a,@dptr");
8955       break;
8956
8957     case CPOINTER:
8958       emitcode ("clr", "a");
8959       emitcode ("movc", "a,@a+dptr");
8960       break;
8961
8962     case GPOINTER:
8963       emitcode ("lcall", "__gptrget");
8964       break;
8965     }
8966
8967   /* if we have bitdisplacement then it fits   */
8968   /* into this byte completely or if length is */
8969   /* less than a byte                          */
8970   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8971     {
8972
8973       /* shift right acc */
8974       AccRsh (shCnt);
8975
8976       emitcode ("anl", "a,#!constbyte",
8977                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8978       aopPut (AOP (result), "a", offset);
8979       return;
8980     }
8981
8982   /* bit field did not fit in a byte  */
8983   rlen = SPEC_BLEN (etype) - 8;
8984   aopPut (AOP (result), "a", offset++);
8985
8986   while (1)
8987     {
8988
8989       switch (ptype)
8990         {
8991         case POINTER:
8992         case IPOINTER:
8993           emitcode ("inc", "%s", rname);
8994           emitcode ("mov", "a,@%s", rname);
8995           break;
8996
8997         case PPOINTER:
8998           emitcode ("inc", "%s", rname);
8999           emitcode ("movx", "a,@%s", rname);
9000           break;
9001
9002         case FPOINTER:
9003           emitcode ("inc", "dptr");
9004           emitcode ("movx", "a,@dptr");
9005           break;
9006
9007         case CPOINTER:
9008           emitcode ("clr", "a");
9009           emitcode ("inc", "dptr");
9010           emitcode ("movc", "a,@a+dptr");
9011           break;
9012
9013         case GPOINTER:
9014           emitcode ("inc", "dptr");
9015           emitcode ("lcall", "__gptrget");
9016           break;
9017         }
9018
9019       rlen -= 8;
9020       /* if we are done */
9021       if (rlen < 8)
9022         break;
9023
9024       aopPut (AOP (result), "a", offset++);
9025
9026     }
9027
9028   if (rlen)
9029     {
9030       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9031       aopPut (AOP (result), "a", offset);
9032     }
9033
9034   return;
9035 }
9036
9037
9038 /*-----------------------------------------------------------------*/
9039 /* genDataPointerGet - generates code when ptr offset is known     */
9040 /*-----------------------------------------------------------------*/
9041 static void
9042 genDataPointerGet (operand * left,
9043                    operand * result,
9044                    iCode * ic)
9045 {
9046   char *l;
9047   char buff[256];
9048   int size, offset = 0;
9049   aopOp (result, ic, TRUE, FALSE);
9050
9051   /* get the string representation of the name */
9052   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9053   size = AOP_SIZE (result);
9054   _startLazyDPSEvaluation ();
9055   while (size--)
9056     {
9057         if (offset)
9058         {
9059             SNPRINTF (buff, sizeof(buff), 
9060                       "(%s + %d)", l + 1, offset);
9061         }
9062         else
9063         {
9064             SNPRINTF (buff, sizeof(buff), 
9065                       "%s", l + 1);
9066         }
9067       aopPut (AOP (result), buff, offset++);
9068     }
9069   _endLazyDPSEvaluation ();
9070
9071   freeAsmop (left, NULL, ic, TRUE);
9072   freeAsmop (result, NULL, ic, TRUE);
9073 }
9074
9075 /*-----------------------------------------------------------------*/
9076 /* genNearPointerGet - emitcode for near pointer fetch             */
9077 /*-----------------------------------------------------------------*/
9078 static void
9079 genNearPointerGet (operand * left,
9080                    operand * result,
9081                    iCode * ic,
9082                    iCode *pi)
9083 {
9084   asmop *aop = NULL;
9085   regs *preg;
9086   char *rname;
9087   sym_link *rtype, *retype, *letype;
9088   sym_link *ltype = operandType (left);
9089   char buff[80];
9090
9091   rtype = operandType (result);
9092   retype = getSpec (rtype);
9093   letype = getSpec (ltype);
9094
9095   aopOp (left, ic, FALSE, FALSE);
9096
9097   /* if left is rematerialisable and
9098      result is not bit variable type and
9099      the left is pointer to data space i.e
9100      lower 128 bytes of space */
9101   if (AOP_TYPE (left) == AOP_IMMD &&
9102       !IS_BITVAR (retype) &&
9103       !IS_BITVAR (letype) &&
9104       DCL_TYPE (ltype) == POINTER)
9105     {
9106       genDataPointerGet (left, result, ic);
9107       return;
9108     }
9109
9110   /* if the value is already in a pointer register
9111      then don't need anything more */
9112   if (!AOP_INPREG (AOP (left)))
9113     {
9114       /* otherwise get a free pointer register */
9115       aop = newAsmop (0);
9116       preg = getFreePtr (ic, &aop, FALSE);
9117       emitcode ("mov", "%s,%s",
9118                 preg->name,
9119                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9120       rname = preg->name;
9121     }
9122   else
9123     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9124
9125   freeAsmop (left, NULL, ic, TRUE);
9126   aopOp (result, ic, FALSE, FALSE);
9127
9128   /* if bitfield then unpack the bits */
9129   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9130     genUnpackBits (result, rname, POINTER);
9131   else
9132     {
9133       /* we have can just get the values */
9134       int size = AOP_SIZE (result);
9135       int offset = 0;
9136
9137       while (size--)
9138         {
9139           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9140             {
9141
9142               emitcode ("mov", "a,@%s", rname);
9143               aopPut (AOP (result), "a", offset);
9144             }
9145           else
9146             {
9147               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9148               aopPut (AOP (result), buff, offset);
9149             }
9150           offset++;
9151           if (size || pi)
9152             {
9153                 emitcode ("inc", "%s", rname);
9154             }
9155         }
9156     }
9157
9158   /* now some housekeeping stuff */
9159   if (aop)
9160     {
9161       /* we had to allocate for this iCode */
9162       if (pi) { /* post increment present */
9163         aopPut(AOP ( left ),rname,0);
9164       }
9165       freeAsmop (NULL, aop, ic, TRUE);
9166     }
9167   else
9168     {
9169       /* we did not allocate which means left
9170          already in a pointer register, then
9171          if size > 0 && this could be used again
9172          we have to point it back to where it
9173          belongs */
9174       if (AOP_SIZE (result) > 1 &&
9175           !OP_SYMBOL (left)->remat &&
9176           (OP_SYMBOL (left)->liveTo > ic->seq ||
9177            ic->depth) &&
9178           !pi)
9179         {
9180           int size = AOP_SIZE (result) - 1;
9181           while (size--)
9182             emitcode ("dec", "%s", rname);
9183         }
9184     }
9185
9186   /* done */
9187   freeAsmop (result, NULL, ic, TRUE);
9188   if (pi) pi->generated = 1;
9189 }
9190
9191 /*-----------------------------------------------------------------*/
9192 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9193 /*-----------------------------------------------------------------*/
9194 static void
9195 genPagedPointerGet (operand * left,
9196                     operand * result,
9197                     iCode * ic,
9198                     iCode * pi)
9199 {
9200   asmop *aop = NULL;
9201   regs *preg;
9202   char *rname;
9203   sym_link *rtype, *retype, *letype;
9204
9205   rtype = operandType (result);
9206   retype = getSpec (rtype);
9207   letype = getSpec (operandType (left));
9208   aopOp (left, ic, FALSE, FALSE);
9209
9210   /* if the value is already in a pointer register
9211      then don't need anything more */
9212   if (!AOP_INPREG (AOP (left)))
9213     {
9214       /* otherwise get a free pointer register */
9215       aop = newAsmop (0);
9216       preg = getFreePtr (ic, &aop, FALSE);
9217       emitcode ("mov", "%s,%s",
9218                 preg->name,
9219                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9220       rname = preg->name;
9221     }
9222   else
9223     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9224
9225   freeAsmop (left, NULL, ic, TRUE);
9226   aopOp (result, ic, FALSE, FALSE);
9227
9228   /* if bitfield then unpack the bits */
9229   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9230     genUnpackBits (result, rname, PPOINTER);
9231   else
9232     {
9233       /* we have can just get the values */
9234       int size = AOP_SIZE (result);
9235       int offset = 0;
9236
9237       while (size--)
9238         {
9239
9240           emitcode ("movx", "a,@%s", rname);
9241           aopPut (AOP (result), "a", offset);
9242
9243           offset++;
9244
9245           if (size || pi)
9246             emitcode ("inc", "%s", rname);
9247         }
9248     }
9249
9250   /* now some housekeeping stuff */
9251   if (aop)
9252     {
9253       /* we had to allocate for this iCode */
9254       if (pi) aopPut ( AOP (left), rname, 0);
9255       freeAsmop (NULL, aop, ic, TRUE);
9256     }
9257   else
9258     {
9259       /* we did not allocate which means left
9260          already in a pointer register, then
9261          if size > 0 && this could be used again
9262          we have to point it back to where it
9263          belongs */
9264       if (AOP_SIZE (result) > 1 &&
9265           !OP_SYMBOL (left)->remat &&
9266           (OP_SYMBOL (left)->liveTo > ic->seq ||
9267            ic->depth) &&
9268           !pi)
9269         {
9270           int size = AOP_SIZE (result) - 1;
9271           while (size--)
9272             emitcode ("dec", "%s", rname);
9273         }
9274     }
9275
9276   /* done */
9277   freeAsmop (result, NULL, ic, TRUE);
9278   if (pi) pi->generated = 1;
9279 }
9280
9281 /*-----------------------------------------------------------------*/
9282 /* genFarPointerGet - gget value from far space                    */
9283 /*-----------------------------------------------------------------*/
9284 static void
9285 genFarPointerGet (operand * left,
9286                   operand * result, iCode * ic, iCode *pi)
9287 {
9288     int size, offset, dopi=1;
9289   sym_link *retype = getSpec (operandType (result));
9290   sym_link *letype = getSpec (operandType (left));
9291   D (emitcode (";", "genFarPointerGet"););
9292
9293   aopOp (left, ic, FALSE, FALSE);
9294
9295   /* if the operand is already in dptr
9296      then we do nothing else we move the value to dptr */
9297   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9298     {
9299       /* if this is remateriazable */
9300       if (AOP_TYPE (left) == AOP_IMMD)
9301         {
9302           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9303         }
9304       else
9305         {
9306           /* we need to get it byte by byte */
9307           _startLazyDPSEvaluation ();
9308           if (AOP_TYPE (left) != AOP_DPTR)
9309             {
9310               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9311               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9312               if (options.model == MODEL_FLAT24)
9313                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9314             }
9315           else
9316             {
9317               /* We need to generate a load to DPTR indirect through DPTR. */
9318               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9319                 );
9320               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9321               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9322               if (options.model == MODEL_FLAT24)
9323                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9324               emitcode ("pop", "dph");
9325               emitcode ("pop", "dpl");
9326               dopi =0;
9327             }
9328           _endLazyDPSEvaluation ();
9329         }
9330     }
9331   /* so dptr know contains the address */
9332   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9333
9334   /* if bit then unpack */
9335   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9336       if (AOP_INDPTRn(left)) {
9337           genSetDPTR(AOP(left)->aopu.dptr);
9338       }
9339       genUnpackBits (result, "dptr", FPOINTER);
9340       if (AOP_INDPTRn(left)) {
9341           genSetDPTR(0);
9342       }
9343   } else
9344     {
9345       size = AOP_SIZE (result);
9346       offset = 0;
9347
9348       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9349           while (size--) {
9350               genSetDPTR(AOP(left)->aopu.dptr);
9351               emitcode ("movx", "a,@dptr");
9352               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9353                   emitcode ("inc", "dptr");
9354               genSetDPTR (0);
9355               aopPut (AOP (result), "a", offset++);
9356           }
9357       } else {
9358           _startLazyDPSEvaluation ();
9359           while (size--) {
9360               if (AOP_INDPTRn(left)) {
9361                   genSetDPTR(AOP(left)->aopu.dptr);
9362               } else {
9363                   genSetDPTR (0);
9364               }
9365               _flushLazyDPS ();
9366               
9367               emitcode ("movx", "a,@dptr");
9368               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9369                   emitcode ("inc", "dptr");
9370               
9371               aopPut (AOP (result), "a", offset++);
9372           }
9373           _endLazyDPSEvaluation ();
9374       }
9375     }
9376   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9377       if (!AOP_INDPTRn(left)) {
9378           aopPut ( AOP (left), "dpl", 0);
9379           aopPut ( AOP (left), "dph", 1);
9380           if (options.model == MODEL_FLAT24)
9381               aopPut ( AOP (left), "dpx", 2);
9382       }
9383     pi->generated = 1;
9384   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9385              AOP_SIZE(result) > 1 &&
9386              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9387       
9388       size = AOP_SIZE (result) - 1;
9389       if (AOP_INDPTRn(left)) {
9390           genSetDPTR(AOP(left)->aopu.dptr);
9391       }
9392       while (size--) emitcode ("lcall","__decdptr");
9393       if (AOP_INDPTRn(left)) {
9394           genSetDPTR(0);
9395       }
9396   }
9397
9398   freeAsmop (left, NULL, ic, TRUE);
9399   freeAsmop (result, NULL, ic, TRUE);
9400 }
9401
9402 /*-----------------------------------------------------------------*/
9403 /* genCodePointerGet - get value from code space                  */
9404 /*-----------------------------------------------------------------*/
9405 static void
9406 genCodePointerGet (operand * left,
9407                     operand * result, iCode * ic, iCode *pi)
9408 {
9409   int size, offset, dopi=1;
9410   sym_link *retype = getSpec (operandType (result));
9411
9412   aopOp (left, ic, FALSE, FALSE);
9413
9414   /* if the operand is already in dptr
9415      then we do nothing else we move the value to dptr */
9416   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9417     {
9418       /* if this is remateriazable */
9419       if (AOP_TYPE (left) == AOP_IMMD)
9420         {
9421           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9422         }
9423       else
9424         {                       /* we need to get it byte by byte */
9425           _startLazyDPSEvaluation ();
9426           if (AOP_TYPE (left) != AOP_DPTR)
9427             {
9428               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9429               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9430               if (options.model == MODEL_FLAT24)
9431                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9432             }
9433           else
9434             {
9435               /* We need to generate a load to DPTR indirect through DPTR. */
9436               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9437                 );
9438               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9439               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9440               if (options.model == MODEL_FLAT24)
9441                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9442               emitcode ("pop", "dph");
9443               emitcode ("pop", "dpl");
9444               dopi=0;
9445             }
9446           _endLazyDPSEvaluation ();
9447         }
9448     }
9449   /* so dptr know contains the address */
9450   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9451
9452   /* if bit then unpack */
9453   if (IS_BITVAR (retype)) {
9454       if (AOP_INDPTRn(left)) {
9455           genSetDPTR(AOP(left)->aopu.dptr);
9456       }
9457       genUnpackBits (result, "dptr", CPOINTER);
9458       if (AOP_INDPTRn(left)) {
9459           genSetDPTR(0);
9460       }
9461   } else
9462     {
9463       size = AOP_SIZE (result);
9464       offset = 0;
9465       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9466           while (size--) {
9467               genSetDPTR(AOP(left)->aopu.dptr);
9468               emitcode ("clr", "a");
9469               emitcode ("movc", "a,@a+dptr");
9470               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9471                   emitcode ("inc", "dptr");
9472               genSetDPTR (0);
9473               aopPut (AOP (result), "a", offset++);
9474           }
9475       } else {
9476           _startLazyDPSEvaluation ();
9477           while (size--)
9478               {
9479                   if (AOP_INDPTRn(left)) {
9480                       genSetDPTR(AOP(left)->aopu.dptr);
9481                   } else {
9482                       genSetDPTR (0);
9483                   }
9484                   _flushLazyDPS ();
9485                   
9486                   emitcode ("clr", "a");
9487                   emitcode ("movc", "a,@a+dptr");
9488                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9489                       emitcode ("inc", "dptr");
9490                   aopPut (AOP (result), "a", offset++);
9491               }
9492           _endLazyDPSEvaluation ();
9493       }
9494     }
9495   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9496       if (!AOP_INDPTRn(left)) {
9497           aopPut ( AOP (left), "dpl", 0);
9498           aopPut ( AOP (left), "dph", 1);
9499           if (options.model == MODEL_FLAT24)
9500               aopPut ( AOP (left), "dpx", 2);
9501       }
9502       pi->generated = 1;
9503   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9504              AOP_SIZE(result) > 1 &&
9505              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9506       
9507       size = AOP_SIZE (result) - 1;
9508       if (AOP_INDPTRn(left)) {
9509           genSetDPTR(AOP(left)->aopu.dptr);
9510       }
9511       while (size--) emitcode ("lcall","__decdptr");
9512       if (AOP_INDPTRn(left)) {
9513           genSetDPTR(0);
9514       }
9515   }
9516   
9517   freeAsmop (left, NULL, ic, TRUE);
9518   freeAsmop (result, NULL, ic, TRUE);
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genGenPointerGet - gget value from generic pointer space        */
9523 /*-----------------------------------------------------------------*/
9524 static void
9525 genGenPointerGet (operand * left,
9526                   operand * result, iCode * ic, iCode * pi)
9527 {
9528   int size, offset;
9529   sym_link *retype = getSpec (operandType (result));
9530   sym_link *letype = getSpec (operandType (left));
9531
9532   D (emitcode (";", "genGenPointerGet "); );
9533
9534   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9535
9536   /* if the operand is already in dptr
9537      then we do nothing else we move the value to dptr */
9538   if (AOP_TYPE (left) != AOP_STR)
9539     {
9540       /* if this is remateriazable */
9541       if (AOP_TYPE (left) == AOP_IMMD)
9542         {
9543           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9544           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9545             {
9546                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9547             }
9548             else
9549             {
9550                 emitcode ("mov", "b,#%d", pointerCode (retype));
9551             }
9552         }
9553       else
9554         {                       /* we need to get it byte by byte */
9555             _startLazyDPSEvaluation ();
9556             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9557             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9558             if (options.model == MODEL_FLAT24) {
9559                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9560                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9561             } else {
9562                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9563             }
9564             _endLazyDPSEvaluation ();
9565         }
9566     }
9567
9568   /* so dptr-b now contains the address */
9569   _G.bInUse++;
9570   aopOp (result, ic, FALSE, TRUE);
9571   _G.bInUse--;
9572
9573   /* if bit then unpack */
9574   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9575   {
9576     genUnpackBits (result, "dptr", GPOINTER);
9577   }
9578   else
9579     {
9580         size = AOP_SIZE (result);
9581         offset = 0;
9582
9583         while (size--)
9584         {
9585             if (size)
9586             {
9587                 // Get two bytes at a time, results in _AP & A.
9588                 // dptr will be incremented ONCE by __gptrgetWord.
9589                 //
9590                 // Note: any change here must be coordinated
9591                 // with the implementation of __gptrgetWord
9592                 // in device/lib/_gptrget.c
9593                 emitcode ("lcall", "__gptrgetWord");
9594                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9595                 aopPut (AOP (result), "a", offset++);
9596                 size--;
9597             }
9598             else
9599             {
9600                 // Only one byte to get.
9601                 emitcode ("lcall", "__gptrget");
9602                 aopPut (AOP (result), "a", offset++);
9603             }
9604             
9605             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9606             {
9607                 emitcode ("inc", "dptr");
9608             }
9609         }
9610     }
9611
9612   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9613     aopPut ( AOP (left), "dpl", 0);
9614     aopPut ( AOP (left), "dph", 1);
9615     if (options.model == MODEL_FLAT24) {
9616         aopPut ( AOP (left), "dpx", 2);
9617         aopPut ( AOP (left), "b", 3);   
9618     } else  aopPut ( AOP (left), "b", 2);       
9619     pi->generated = 1;
9620   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9621              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9622       
9623       size = AOP_SIZE (result) - 1;
9624       while (size--) emitcode ("lcall","__decdptr");
9625   }
9626
9627   freeAsmop (left, NULL, ic, TRUE);
9628   freeAsmop (result, NULL, ic, TRUE);
9629 }
9630
9631 /*-----------------------------------------------------------------*/
9632 /* genPointerGet - generate code for pointer get                   */
9633 /*-----------------------------------------------------------------*/
9634 static void
9635 genPointerGet (iCode * ic, iCode *pi)
9636 {
9637   operand *left, *result;
9638   sym_link *type, *etype;
9639   int p_type;
9640
9641   D (emitcode (";", "genPointerGet ");
9642     );
9643
9644   left = IC_LEFT (ic);
9645   result = IC_RESULT (ic);
9646
9647   /* depending on the type of pointer we need to
9648      move it to the correct pointer register */
9649   type = operandType (left);
9650   etype = getSpec (type);
9651   /* if left is of type of pointer then it is simple */
9652   if (IS_PTR (type) && !IS_FUNC (type->next))
9653     p_type = DCL_TYPE (type);
9654   else
9655     {
9656       /* we have to go by the storage class */
9657       p_type = PTR_TYPE (SPEC_OCLS (etype));
9658     }
9659   /* special case when cast remat */
9660   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9661       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9662           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9663           type = operandType (left);
9664           p_type = DCL_TYPE (type);
9665   }
9666   /* now that we have the pointer type we assign
9667      the pointer values */
9668   switch (p_type)
9669     {
9670
9671     case POINTER:
9672     case IPOINTER:
9673       genNearPointerGet (left, result, ic, pi);
9674       break;
9675
9676     case PPOINTER:
9677       genPagedPointerGet (left, result, ic, pi);
9678       break;
9679
9680     case FPOINTER:
9681       genFarPointerGet (left, result, ic, pi);
9682       break;
9683
9684     case CPOINTER:
9685       genCodePointerGet (left, result, ic, pi);
9686       break;
9687
9688     case GPOINTER:
9689       genGenPointerGet (left, result, ic, pi);
9690       break;
9691     }
9692
9693 }
9694
9695 /*-----------------------------------------------------------------*/
9696 /* genPackBits - generates code for packed bit storage             */
9697 /*-----------------------------------------------------------------*/
9698 static void
9699 genPackBits (sym_link * etype,
9700              operand * right,
9701              char *rname, int p_type)
9702 {
9703   int offset = 0;
9704   int rLen;
9705   int blen, bstr;
9706   char *l;
9707
9708   blen = SPEC_BLEN (etype);
9709   bstr = SPEC_BSTR (etype);
9710
9711   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9712
9713   /* if the bit lenth is less than or    */
9714   /* it exactly fits a byte then         */
9715   if (SPEC_BLEN (etype) <= 8)
9716     {
9717       /* shift left acc */
9718       AccLsh (SPEC_BSTR (etype));
9719
9720       if (SPEC_BLEN (etype) < 8)
9721         {                       /* if smaller than a byte */
9722
9723
9724           switch (p_type)
9725             {
9726             case POINTER:
9727               emitcode ("mov", "b,a");
9728               emitcode ("mov", "a,@%s", rname);
9729               break;
9730
9731             case FPOINTER:
9732               emitcode ("mov", "b,a");
9733               emitcode ("movx", "a,@dptr");
9734               break;
9735
9736             case GPOINTER:
9737               emitcode ("push", "b");
9738               emitcode ("push", "acc");
9739               emitcode ("lcall", "__gptrget");
9740               emitcode ("pop", "b");
9741               break;
9742             }
9743
9744           emitcode ("anl", "a,#!constbyte", (unsigned char)
9745                     ((unsigned char) (0xFF << (blen + bstr)) |
9746                      (unsigned char) (0xFF >> (8 - bstr))));
9747           emitcode ("orl", "a,b");
9748           if (p_type == GPOINTER)
9749             emitcode ("pop", "b");
9750         }
9751     }
9752
9753   switch (p_type)
9754     {
9755     case POINTER:
9756       emitcode ("mov", "@%s,a", rname);
9757       break;
9758
9759     case FPOINTER:
9760       emitcode ("movx", "@dptr,a");
9761       break;
9762
9763     case GPOINTER:
9764       emitcode ("lcall", "__gptrput");
9765       break;
9766     }
9767
9768   /* if we r done */
9769   if (SPEC_BLEN (etype) <= 8)
9770     return;
9771
9772   emitcode ("inc", "%s", rname);
9773   rLen = SPEC_BLEN (etype);
9774
9775   /* now generate for lengths greater than one byte */
9776   while (1)
9777     {
9778
9779       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9780
9781       rLen -= 8;
9782       if (rLen < 8)
9783         break;
9784
9785       switch (p_type)
9786         {
9787         case POINTER:
9788           if (*l == '@')
9789             {
9790               MOVA (l);
9791               emitcode ("mov", "@%s,a", rname);
9792             }
9793           else
9794             emitcode ("mov", "@%s,%s", rname, l);
9795           break;
9796
9797         case FPOINTER:
9798           MOVA (l);
9799           emitcode ("movx", "@dptr,a");
9800           break;
9801
9802         case GPOINTER:
9803           MOVA (l);
9804           emitcode ("lcall", "__gptrput");
9805           break;
9806         }
9807       emitcode ("inc", "%s", rname);
9808     }
9809
9810   MOVA (l);
9811
9812   /* last last was not complete */
9813   if (rLen)
9814     {
9815       /* save the byte & read byte */
9816       switch (p_type)
9817         {
9818         case POINTER:
9819           emitcode ("mov", "b,a");
9820           emitcode ("mov", "a,@%s", rname);
9821           break;
9822
9823         case FPOINTER:
9824           emitcode ("mov", "b,a");
9825           emitcode ("movx", "a,@dptr");
9826           break;
9827
9828         case GPOINTER:
9829           emitcode ("push", "b");
9830           emitcode ("push", "acc");
9831           emitcode ("lcall", "__gptrget");
9832           emitcode ("pop", "b");
9833           break;
9834         }
9835
9836       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9837       emitcode ("orl", "a,b");
9838     }
9839
9840   if (p_type == GPOINTER)
9841     emitcode ("pop", "b");
9842
9843   switch (p_type)
9844     {
9845
9846     case POINTER:
9847       emitcode ("mov", "@%s,a", rname);
9848       break;
9849
9850     case FPOINTER:
9851       emitcode ("movx", "@dptr,a");
9852       break;
9853
9854     case GPOINTER:
9855       emitcode ("lcall", "__gptrput");
9856       break;
9857     }
9858 }
9859 /*-----------------------------------------------------------------*/
9860 /* genDataPointerSet - remat pointer to data space                 */
9861 /*-----------------------------------------------------------------*/
9862 static void
9863 genDataPointerSet (operand * right,
9864                    operand * result,
9865                    iCode * ic)
9866 {
9867   int size, offset = 0;
9868   char *l, buff[256];
9869
9870   aopOp (right, ic, FALSE, FALSE);
9871
9872   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9873   size = AOP_SIZE (right);
9874   while (size--)
9875     {
9876       if (offset)
9877         {
9878             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9879         }
9880       else
9881         {
9882             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9883         }
9884         
9885       emitcode ("mov", "%s,%s", buff,
9886                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9887     }
9888
9889   freeAsmop (right, NULL, ic, TRUE);
9890   freeAsmop (result, NULL, ic, TRUE);
9891 }
9892
9893 /*-----------------------------------------------------------------*/
9894 /* genNearPointerSet - emitcode for near pointer put                */
9895 /*-----------------------------------------------------------------*/
9896 static void
9897 genNearPointerSet (operand * right,
9898                    operand * result,
9899                    iCode * ic,
9900                    iCode * pi)
9901 {
9902   asmop *aop = NULL;
9903   char *rname, *l;
9904   sym_link *retype, *letype;
9905   sym_link *ptype = operandType (result);
9906
9907   retype = getSpec (operandType (right));
9908   letype = getSpec (ptype);
9909
9910   aopOp (result, ic, FALSE, FALSE);
9911
9912   /* if the result is rematerializable &
9913      in data space & not a bit variable */
9914   if (AOP_TYPE (result) == AOP_IMMD &&
9915       DCL_TYPE (ptype) == POINTER &&
9916       !IS_BITVAR (retype) &&
9917       !IS_BITVAR (letype))
9918     {
9919       genDataPointerSet (right, result, ic);
9920       return;
9921     }
9922
9923   /* if the value is already in a pointer register
9924      then don't need anything more */
9925   if (!AOP_INPREG (AOP (result)))
9926     {
9927       /* otherwise get a free pointer register */
9928       regs *preg;
9929         
9930       aop = newAsmop (0);
9931       preg = getFreePtr (ic, &aop, FALSE);
9932       emitcode ("mov", "%s,%s",
9933                 preg->name,
9934                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9935       rname = preg->name;
9936     }
9937   else
9938     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9939
9940   aopOp (right, ic, FALSE, FALSE);
9941
9942   /* if bitfield then unpack the bits */
9943   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9944     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9945   else
9946     {
9947       /* we have can just get the values */
9948       int size = AOP_SIZE (right);
9949       int offset = 0;
9950
9951       while (size--)
9952         {
9953           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9954           if (*l == '@')
9955             {
9956               MOVA (l);
9957               emitcode ("mov", "@%s,a", rname);
9958             }
9959           else
9960             emitcode ("mov", "@%s,%s", rname, l);
9961           if (size || pi)
9962             emitcode ("inc", "%s", rname);
9963           offset++;
9964         }
9965     }
9966
9967   /* now some housekeeping stuff */
9968   if (aop)
9969     {
9970       /* we had to allocate for this iCode */
9971       if (pi) aopPut (AOP (result),rname,0);
9972       freeAsmop (NULL, aop, ic, TRUE);
9973     }
9974   else
9975     {
9976       /* we did not allocate which means left
9977          already in a pointer register, then
9978          if size > 0 && this could be used again
9979          we have to point it back to where it
9980          belongs */
9981       if (AOP_SIZE (right) > 1 &&
9982           !OP_SYMBOL (result)->remat &&
9983           (OP_SYMBOL (result)->liveTo > ic->seq ||
9984            ic->depth) &&
9985           !pi)
9986         {
9987           int size = AOP_SIZE (right) - 1;
9988           while (size--)
9989             emitcode ("dec", "%s", rname);
9990         }
9991     }
9992
9993   /* done */
9994   if (pi) pi->generated = 1;
9995   freeAsmop (result, NULL, ic, TRUE);
9996   freeAsmop (right, NULL, ic, TRUE);
9997
9998
9999 }
10000
10001 /*-----------------------------------------------------------------*/
10002 /* genPagedPointerSet - emitcode for Paged pointer put             */
10003 /*-----------------------------------------------------------------*/
10004 static void
10005 genPagedPointerSet (operand * right,
10006                     operand * result,
10007                     iCode * ic,
10008                     iCode *pi)
10009 {
10010   asmop *aop = NULL;
10011   char *rname;
10012   sym_link *retype, *letype;
10013
10014   retype = getSpec (operandType (right));
10015   letype = getSpec (operandType (result));
10016
10017   aopOp (result, ic, FALSE, FALSE);
10018
10019   /* if the value is already in a pointer register
10020      then don't need anything more */
10021   if (!AOP_INPREG (AOP (result)))
10022     {
10023       /* otherwise get a free pointer register */
10024       regs *preg;
10025         
10026       aop = newAsmop (0);
10027       preg = getFreePtr (ic, &aop, FALSE);
10028       emitcode ("mov", "%s,%s",
10029                 preg->name,
10030                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10031       rname = preg->name;
10032     }
10033   else
10034     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10035
10036   aopOp (right, ic, FALSE, FALSE);
10037
10038   /* if bitfield then unpack the bits */
10039   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10040     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10041   else
10042     {
10043       /* we have can just get the values */
10044       int size = AOP_SIZE (right);
10045       int offset = 0;
10046
10047       while (size--)
10048         {
10049           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10050
10051           emitcode ("movx", "@%s,a", rname);
10052
10053           if (size || pi)
10054             emitcode ("inc", "%s", rname);
10055
10056           offset++;
10057         }
10058     }
10059
10060   /* now some housekeeping stuff */
10061   if (aop)
10062     {
10063       if (pi) aopPut (AOP (result),rname,0);
10064       /* we had to allocate for this iCode */
10065       freeAsmop (NULL, aop, ic, TRUE);
10066     }
10067   else
10068     {
10069       /* we did not allocate which means left
10070          already in a pointer register, then
10071          if size > 0 && this could be used again
10072          we have to point it back to where it
10073          belongs */
10074       if (AOP_SIZE (right) > 1 &&
10075           !OP_SYMBOL (result)->remat &&
10076           (OP_SYMBOL (result)->liveTo > ic->seq ||
10077            ic->depth) &&
10078           !pi)
10079         {
10080           int size = AOP_SIZE (right) - 1;
10081           while (size--)
10082             emitcode ("dec", "%s", rname);
10083         }
10084     }
10085
10086   /* done */
10087   if (pi) pi->generated = 1;
10088   freeAsmop (result, NULL, ic, TRUE);
10089   freeAsmop (right, NULL, ic, TRUE);
10090
10091
10092 }
10093
10094 /*-----------------------------------------------------------------*/
10095 /* genFarPointerSet - set value from far space                     */
10096 /*-----------------------------------------------------------------*/
10097 static void
10098 genFarPointerSet (operand * right,
10099                   operand * result, iCode * ic, iCode *pi)
10100 {
10101   int size, offset, dopi=1;
10102   sym_link *retype = getSpec (operandType (right));
10103   sym_link *letype = getSpec (operandType (result));
10104
10105   aopOp (result, ic, FALSE, FALSE);
10106
10107   /* if the operand is already in dptr
10108      then we do nothing else we move the value to dptr */
10109   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10110     {
10111       /* if this is remateriazable */
10112       if (AOP_TYPE (result) == AOP_IMMD)
10113         emitcode ("mov", "dptr,%s", 
10114                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10115       else
10116         {
10117           /* we need to get it byte by byte */
10118           _startLazyDPSEvaluation ();
10119           if (AOP_TYPE (result) != AOP_DPTR)
10120             {
10121               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10122               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10123               if (options.model == MODEL_FLAT24)
10124                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10125             }
10126           else
10127             {
10128               /* We need to generate a load to DPTR indirect through DPTR. */
10129               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10130                 
10131               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10132               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10133               if (options.model == MODEL_FLAT24)
10134                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10135               emitcode ("pop", "dph");
10136               emitcode ("pop", "dpl");
10137               dopi=0;
10138             }
10139           _endLazyDPSEvaluation ();
10140         }
10141     }
10142   /* so dptr know contains the address */
10143   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10144
10145   /* if bit then unpack */
10146   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10147       if (AOP_INDPTRn(result)) {
10148           genSetDPTR(AOP(result)->aopu.dptr);
10149       }
10150       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10151       if (AOP_INDPTRn(result)) {
10152           genSetDPTR(0);
10153       }
10154   } else {
10155       size = AOP_SIZE (right);
10156       offset = 0;
10157       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10158           while (size--) {
10159               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10160               
10161               genSetDPTR(AOP(result)->aopu.dptr);
10162               emitcode ("movx", "@dptr,a");
10163               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10164                   emitcode ("inc", "dptr");
10165               genSetDPTR (0);
10166           }
10167       } else {
10168           _startLazyDPSEvaluation ();
10169           while (size--) {
10170               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10171               
10172               if (AOP_INDPTRn(result)) {
10173                   genSetDPTR(AOP(result)->aopu.dptr);
10174               } else {
10175                   genSetDPTR (0);
10176               }
10177               _flushLazyDPS ();
10178               
10179               emitcode ("movx", "@dptr,a");
10180               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10181                   emitcode ("inc", "dptr");
10182           }
10183           _endLazyDPSEvaluation ();
10184       }
10185   }
10186   
10187   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10188       if (!AOP_INDPTRn(result)) {
10189           aopPut (AOP(result),"dpl",0);
10190           aopPut (AOP(result),"dph",1);
10191           if (options.model == MODEL_FLAT24)
10192               aopPut (AOP(result),"dpx",2);
10193       }
10194       pi->generated=1;
10195   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10196              AOP_SIZE(right) > 1 &&
10197              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10198       
10199       size = AOP_SIZE (right) - 1;
10200       if (AOP_INDPTRn(result)) {
10201           genSetDPTR(AOP(result)->aopu.dptr);
10202       } 
10203       while (size--) emitcode ("lcall","__decdptr");
10204       if (AOP_INDPTRn(result)) {
10205           genSetDPTR(0);
10206       }
10207   }
10208   freeAsmop (result, NULL, ic, TRUE);
10209   freeAsmop (right, NULL, ic, TRUE);
10210 }
10211
10212 /*-----------------------------------------------------------------*/
10213 /* genGenPointerSet - set value from generic pointer space         */
10214 /*-----------------------------------------------------------------*/
10215 static void
10216 genGenPointerSet (operand * right,
10217                   operand * result, iCode * ic, iCode *pi)
10218 {
10219   int size, offset;
10220   sym_link *retype = getSpec (operandType (right));
10221   sym_link *letype = getSpec (operandType (result));
10222
10223   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10224
10225   /* if the operand is already in dptr
10226      then we do nothing else we move the value to dptr */
10227   if (AOP_TYPE (result) != AOP_STR)
10228     {
10229       _startLazyDPSEvaluation ();
10230       /* if this is remateriazable */
10231       if (AOP_TYPE (result) == AOP_IMMD)
10232         {
10233           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10234           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10235           {
10236               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10237           }
10238           else
10239           {
10240               emitcode ("mov", 
10241                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10242           }
10243         }
10244       else
10245         {                       /* we need to get it byte by byte */
10246           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10247           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10248           if (options.model == MODEL_FLAT24) {
10249             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10250             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10251           } else {
10252             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10253           }
10254         }
10255       _endLazyDPSEvaluation ();
10256     }
10257   /* so dptr know contains the address */
10258   aopOp (right, ic, FALSE, TRUE);
10259
10260   /* if bit then unpack */
10261   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10262     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10263   else
10264     {
10265       size = AOP_SIZE (right);
10266       offset = 0;
10267
10268       _startLazyDPSEvaluation ();
10269       while (size--)
10270         {
10271           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10272
10273           genSetDPTR (0);
10274           _flushLazyDPS ();
10275
10276           emitcode ("lcall", "__gptrput");
10277           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10278             emitcode ("inc", "dptr");
10279         }
10280       _endLazyDPSEvaluation ();
10281     }
10282
10283   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10284       aopPut (AOP(result),"dpl",0);
10285       aopPut (AOP(result),"dph",1);
10286       if (options.model == MODEL_FLAT24) {
10287           aopPut (AOP(result),"dpx",2);
10288           aopPut (AOP(result),"b",3);
10289       } else {
10290           aopPut (AOP(result),"b",2);
10291       }
10292       pi->generated=1;
10293   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10294              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10295       
10296       size = AOP_SIZE (right) - 1;
10297       while (size--) emitcode ("lcall","__decdptr");
10298   }
10299   freeAsmop (result, NULL, ic, TRUE);
10300   freeAsmop (right, NULL, ic, TRUE);
10301 }
10302
10303 /*-----------------------------------------------------------------*/
10304 /* genPointerSet - stores the value into a pointer location        */
10305 /*-----------------------------------------------------------------*/
10306 static void
10307 genPointerSet (iCode * ic, iCode *pi)
10308 {
10309   operand *right, *result;
10310   sym_link *type, *etype;
10311   int p_type;
10312
10313   D (emitcode (";", "genPointerSet "););
10314
10315   right = IC_RIGHT (ic);
10316   result = IC_RESULT (ic);
10317
10318   /* depending on the type of pointer we need to
10319      move it to the correct pointer register */
10320   type = operandType (result);
10321   etype = getSpec (type);
10322   /* if left is of type of pointer then it is simple */
10323   if (IS_PTR (type) && !IS_FUNC (type->next))
10324     {
10325       p_type = DCL_TYPE (type);
10326     }
10327   else
10328     {
10329       /* we have to go by the storage class */
10330       p_type = PTR_TYPE (SPEC_OCLS (etype));
10331     }
10332   /* special case when cast remat */
10333   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10334       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10335           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10336           type = operandType (result);
10337           p_type = DCL_TYPE (type);
10338   }
10339
10340   /* now that we have the pointer type we assign
10341      the pointer values */
10342   switch (p_type)
10343     {
10344
10345     case POINTER:
10346     case IPOINTER:
10347       genNearPointerSet (right, result, ic, pi);
10348       break;
10349
10350     case PPOINTER:
10351       genPagedPointerSet (right, result, ic, pi);
10352       break;
10353
10354     case FPOINTER:
10355       genFarPointerSet (right, result, ic, pi);
10356       break;
10357
10358     case GPOINTER:
10359       genGenPointerSet (right, result, ic, pi);
10360       break;
10361
10362     default:
10363       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10364               "genPointerSet: illegal pointer type");
10365     }
10366
10367 }
10368
10369 /*-----------------------------------------------------------------*/
10370 /* genIfx - generate code for Ifx statement                        */
10371 /*-----------------------------------------------------------------*/
10372 static void
10373 genIfx (iCode * ic, iCode * popIc)
10374 {
10375   operand *cond = IC_COND (ic);
10376   int isbit = 0;
10377
10378   D (emitcode (";", "genIfx "););
10379
10380   aopOp (cond, ic, FALSE, FALSE);
10381
10382   /* get the value into acc */
10383   if (AOP_TYPE (cond) != AOP_CRY)
10384     {
10385         toBoolean (cond);
10386     }
10387   else
10388     {
10389         isbit = 1;
10390     }
10391     
10392   /* the result is now in the accumulator */
10393   freeAsmop (cond, NULL, ic, TRUE);
10394
10395   /* if there was something to be popped then do it */
10396   if (popIc)
10397     genIpop (popIc);
10398
10399   /* if the condition is  a bit variable */
10400   if (isbit && IS_ITEMP (cond) &&
10401       SPIL_LOC (cond))
10402     {
10403         genIfxJump (ic, SPIL_LOC (cond)->rname);
10404     }
10405   else if (isbit && !IS_ITEMP (cond))
10406     {
10407         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10408     }
10409   else
10410     {
10411         genIfxJump (ic, "a");
10412     }
10413
10414   ic->generated = 1;
10415 }
10416
10417 /*-----------------------------------------------------------------*/
10418 /* genAddrOf - generates code for address of                       */
10419 /*-----------------------------------------------------------------*/
10420 static void
10421 genAddrOf (iCode * ic)
10422 {
10423   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10424   int size, offset;
10425
10426   D (emitcode (";", "genAddrOf ");
10427     );
10428
10429   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10430
10431   /* if the operand is on the stack then we
10432      need to get the stack offset of this
10433      variable */
10434   if (sym->onStack) {
10435       
10436       /* if 10 bit stack */
10437       if (options.stack10bit) {
10438           char buff[10];
10439           tsprintf(buff, sizeof(buff), 
10440                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10441           /* if it has an offset then we need to compute it */
10442 /*        emitcode ("subb", "a,#!constbyte", */
10443 /*                  -((sym->stack < 0) ? */
10444 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10445 /*                    ((short) sym->stack)) & 0xff); */
10446 /*        emitcode ("mov","b,a"); */
10447 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10448 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10449 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10450           if (sym->stack) {
10451               emitcode ("mov", "a,_bpx");
10452               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10453                                              ((char) (sym->stack - _G.nRegsSaved)) :
10454                                              ((char) sym->stack )) & 0xff);
10455               emitcode ("mov", "b,a");
10456               emitcode ("mov", "a,_bpx+1");
10457               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10458                                               ((short) (sym->stack - _G.nRegsSaved)) :
10459                                               ((short) sym->stack )) >> 8) & 0xff);
10460               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10461               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10462               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10463           } else {
10464               /* we can just move _bp */
10465               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10466               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10467               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10468           }       
10469       } else {
10470           /* if it has an offset then we need to compute it */
10471           if (sym->stack) {
10472               emitcode ("mov", "a,_bp");
10473               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10474               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10475           } else {
10476               /* we can just move _bp */
10477               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10478           }
10479           /* fill the result with zero */
10480           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10481           
10482           
10483           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10484               fprintf (stderr,
10485                        "*** warning: pointer to stack var truncated.\n");
10486           }
10487
10488           offset = 1;
10489           while (size--) {
10490               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10491           }      
10492       }
10493       goto release;
10494   }
10495
10496   /* object not on stack then we need the name */
10497   size = AOP_SIZE (IC_RESULT (ic));
10498   offset = 0;
10499
10500   while (size--)
10501     {
10502       char s[SDCC_NAME_MAX];
10503       if (offset) {
10504           switch (offset) {
10505           case 1:
10506               tsprintf(s, sizeof(s), "!his",sym->rname);
10507               break;
10508           case 2:
10509               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10510               break;
10511           case 3:
10512               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10513               break;
10514           default: /* should not need this (just in case) */
10515               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10516                        sym->rname,
10517                        offset * 8);
10518           }
10519       } 
10520       else
10521       {
10522           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10523       }
10524         
10525       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10526     }
10527
10528 release:
10529   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10530
10531 }
10532
10533 /*-----------------------------------------------------------------*/
10534 /* genArrayInit - generates code for address of                       */
10535 /*-----------------------------------------------------------------*/
10536 static void
10537 genArrayInit (iCode * ic)
10538 {
10539     literalList *iLoop;
10540     int         ix, count;
10541     int         elementSize = 0, eIndex;
10542     unsigned    val, lastVal;
10543     sym_link    *type;
10544     operand     *left=IC_LEFT(ic);
10545     
10546     D (emitcode (";", "genArrayInit "););
10547
10548     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10549     
10550     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10551     {
10552         // Load immediate value into DPTR.
10553         emitcode("mov", "dptr, %s",
10554              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10555     }
10556     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10557     {
10558 #if 0
10559       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10560               "Unexpected operand to genArrayInit.\n");
10561       exit(1);
10562 #else
10563       // a regression because of SDCCcse.c:1.52
10564       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10565       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10566       if (options.model == MODEL_FLAT24)
10567         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10568 #endif
10569     }
10570     
10571     type = operandType(IC_LEFT(ic));
10572     
10573     if (type && type->next)
10574     {
10575         elementSize = getSize(type->next);
10576     }
10577     else
10578     {
10579         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10580                                 "can't determine element size in genArrayInit.\n");
10581         exit(1);
10582     }
10583     
10584     iLoop = IC_ARRAYILIST(ic);
10585     lastVal = 0xffff;
10586     
10587     while (iLoop)
10588     {
10589         bool firstpass = TRUE;
10590         
10591         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10592                  iLoop->count, (int)iLoop->literalValue, elementSize);
10593         
10594         ix = iLoop->count;
10595         
10596         while (ix)
10597         {
10598             symbol *tlbl = NULL;
10599             
10600             count = ix > 256 ? 256 : ix;
10601             
10602             if (count > 1)
10603             {
10604                 tlbl = newiTempLabel (NULL);
10605                 if (firstpass || (count & 0xff))
10606                 {
10607                     emitcode("mov", "b, #!constbyte", count & 0xff);
10608                 }
10609                 
10610                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10611             }
10612             
10613             firstpass = FALSE;
10614                 
10615             for (eIndex = 0; eIndex < elementSize; eIndex++)
10616             {
10617                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10618                 if (val != lastVal)
10619                 {
10620                     emitcode("mov", "a, #!constbyte", val);
10621                     lastVal = val;
10622                 }
10623                 
10624                 emitcode("movx", "@dptr, a");
10625                 emitcode("inc", "dptr");
10626             }
10627             
10628             if (count > 1)
10629             {
10630                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10631             }
10632             
10633             ix -= count;
10634         }
10635         
10636         iLoop = iLoop->next;
10637     }
10638     
10639     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10640 }
10641
10642 /*-----------------------------------------------------------------*/
10643 /* genFarFarAssign - assignment when both are in far space         */
10644 /*-----------------------------------------------------------------*/
10645 static void
10646 genFarFarAssign (operand * result, operand * right, iCode * ic)
10647 {
10648   int size = AOP_SIZE (right);
10649   int offset = 0;
10650   symbol *rSym = NULL;
10651
10652   if (size == 1)
10653   {
10654       /* quick & easy case. */
10655       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10656       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10657       freeAsmop (right, NULL, ic, FALSE);
10658       /* now assign DPTR to result */
10659       _G.accInUse++;
10660       aopOp(result, ic, FALSE, FALSE);
10661       _G.accInUse--;
10662       aopPut(AOP(result), "a", 0);
10663       freeAsmop(result, NULL, ic, FALSE);
10664       return;
10665   }
10666   
10667   /* See if we've got an underlying symbol to abuse. */
10668   if (IS_SYMOP(result) && OP_SYMBOL(result))
10669   {
10670       if (IS_TRUE_SYMOP(result))
10671       {
10672           rSym = OP_SYMBOL(result);
10673       }
10674       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10675       {
10676           rSym = OP_SYMBOL(result)->usl.spillLoc;
10677       }
10678   }
10679              
10680   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10681   {
10682       /* We can use the '390 auto-toggle feature to good effect here. */
10683       
10684       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10685       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10686       emitcode ("mov", "dptr,#%s", rSym->rname); 
10687       /* DP2 = result, DP1 = right, DP1 is current. */
10688       while (size)
10689       {
10690           emitcode("movx", "a,@dptr");
10691           emitcode("movx", "@dptr,a");
10692           if (--size)
10693           {
10694                emitcode("inc", "dptr");
10695                emitcode("inc", "dptr");
10696           }
10697       }
10698       emitcode("mov", "dps,#0");
10699       freeAsmop (right, NULL, ic, FALSE);
10700 #if 0
10701 some alternative code for processors without auto-toggle
10702 no time to test now, so later well put in...kpb
10703         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10704         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10705         emitcode ("mov", "dptr,#%s", rSym->rname); 
10706         /* DP2 = result, DP1 = right, DP1 is current. */
10707         while (size)
10708         {
10709           --size;
10710           emitcode("movx", "a,@dptr");
10711           if (size)
10712             emitcode("inc", "dptr");
10713           emitcode("inc", "dps");
10714           emitcode("movx", "@dptr,a");
10715           if (size)
10716             emitcode("inc", "dptr");
10717           emitcode("inc", "dps");
10718         }
10719         emitcode("mov", "dps,#0");
10720         freeAsmop (right, NULL, ic, FALSE);
10721 #endif
10722   }
10723   else
10724   {
10725       D (emitcode (";", "genFarFarAssign"););
10726       aopOp (result, ic, TRUE, TRUE);
10727
10728       _startLazyDPSEvaluation ();
10729       
10730       while (size--)
10731         {
10732           aopPut (AOP (result),
10733                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10734           offset++;
10735         }
10736       _endLazyDPSEvaluation ();
10737       freeAsmop (result, NULL, ic, FALSE);
10738       freeAsmop (right, NULL, ic, FALSE);
10739   }
10740 }
10741
10742 /*-----------------------------------------------------------------*/
10743 /* genAssign - generate code for assignment                        */
10744 /*-----------------------------------------------------------------*/
10745 static void
10746 genAssign (iCode * ic)
10747 {
10748   operand *result, *right;
10749   int size, offset;
10750   unsigned long lit = 0L;
10751
10752   D (emitcode (";", "genAssign ");
10753     );
10754
10755   result = IC_RESULT (ic);
10756   right = IC_RIGHT (ic);
10757
10758   /* if they are the same */
10759   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10760     return;
10761
10762   aopOp (right, ic, FALSE, FALSE);
10763
10764   emitcode (";", "genAssign: resultIsFar = %s",
10765             isOperandInFarSpace (result) ?
10766             "TRUE" : "FALSE");
10767
10768   /* special case both in far space */
10769   if ((AOP_TYPE (right) == AOP_DPTR ||
10770        AOP_TYPE (right) == AOP_DPTR2) &&
10771   /* IS_TRUE_SYMOP(result)       && */
10772       isOperandInFarSpace (result))
10773     {
10774       genFarFarAssign (result, right, ic);
10775       return;
10776     }
10777
10778   aopOp (result, ic, TRUE, FALSE);
10779
10780   /* if they are the same registers */
10781   if (sameRegs (AOP (right), AOP (result)))
10782     goto release;
10783
10784   /* if the result is a bit */
10785   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10786     {
10787       /* if the right size is a literal then
10788          we know what the value is */
10789       if (AOP_TYPE (right) == AOP_LIT)
10790         {
10791           if (((int) operandLitValue (right)))
10792             aopPut (AOP (result), one, 0);
10793           else
10794             aopPut (AOP (result), zero, 0);
10795           goto release;
10796         }
10797
10798       /* the right is also a bit variable */
10799       if (AOP_TYPE (right) == AOP_CRY)
10800         {
10801           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10802           aopPut (AOP (result), "c", 0);
10803           goto release;
10804         }
10805
10806       /* we need to or */
10807       toBoolean (right);
10808       aopPut (AOP (result), "a", 0);
10809       goto release;
10810     }
10811
10812   /* bit variables done */
10813   /* general case */
10814   size = AOP_SIZE (result);
10815   offset = 0;
10816   if (AOP_TYPE (right) == AOP_LIT)
10817     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10818
10819   if ((size > 1) &&
10820       (AOP_TYPE (result) != AOP_REG) &&
10821       (AOP_TYPE (right) == AOP_LIT) &&
10822       !IS_FLOAT (operandType (right)))
10823     {
10824       _startLazyDPSEvaluation ();
10825       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10826         {
10827           aopPut (AOP (result),
10828                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10829                   offset);
10830           offset++;
10831           size--;
10832         }
10833       /* And now fill the rest with zeros. */
10834       if (size)
10835         {
10836           emitcode ("clr", "a");
10837         }
10838       while (size--)
10839         {
10840           aopPut (AOP (result), "a", offset++);
10841         }
10842       _endLazyDPSEvaluation ();
10843     }
10844   else
10845     {
10846       _startLazyDPSEvaluation ();
10847       while (size--)
10848         {
10849           aopPut (AOP (result),
10850                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10851                   offset);
10852           offset++;
10853         }
10854       _endLazyDPSEvaluation ();
10855     }
10856
10857 release:
10858   freeAsmop (right, NULL, ic, FALSE);
10859   freeAsmop (result, NULL, ic, TRUE);
10860 }
10861
10862 /*-----------------------------------------------------------------*/
10863 /* genJumpTab - generates code for jump table                      */
10864 /*-----------------------------------------------------------------*/
10865 static void
10866 genJumpTab (iCode * ic)
10867 {
10868   symbol *jtab;
10869   char *l;
10870
10871   D (emitcode (";", "genJumpTab ");
10872     );
10873
10874   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10875   /* get the condition into accumulator */
10876   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10877   MOVA (l);
10878   /* multiply by four! */
10879   emitcode ("add", "a,acc");
10880   emitcode ("add", "a,acc");
10881   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10882
10883   jtab = newiTempLabel (NULL);
10884   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10885   emitcode ("jmp", "@a+dptr");
10886   emitcode ("", "!tlabeldef", jtab->key + 100);
10887   /* now generate the jump labels */
10888   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10889        jtab = setNextItem (IC_JTLABELS (ic)))
10890     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10891
10892 }
10893
10894 /*-----------------------------------------------------------------*/
10895 /* genCast - gen code for casting                                  */
10896 /*-----------------------------------------------------------------*/
10897 static void
10898 genCast (iCode * ic)
10899 {
10900   operand *result = IC_RESULT (ic);
10901   sym_link *ctype = operandType (IC_LEFT (ic));
10902   sym_link *rtype = operandType (IC_RIGHT (ic));
10903   operand *right = IC_RIGHT (ic);
10904   int size, offset;
10905
10906   D (emitcode (";", "genCast "););
10907
10908   /* if they are equivalent then do nothing */
10909   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10910     return;
10911
10912   aopOp (right, ic, FALSE, FALSE);
10913   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10914
10915   /* if the result is a bit */
10916   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10917   if (IS_BITVAR(OP_SYMBOL(result)->type))
10918     {
10919       /* if the right size is a literal then
10920          we know what the value is */
10921       if (AOP_TYPE (right) == AOP_LIT)
10922         {
10923           if (((int) operandLitValue (right)))
10924             aopPut (AOP (result), one, 0);
10925           else
10926             aopPut (AOP (result), zero, 0);
10927
10928           goto release;
10929         }
10930
10931       /* the right is also a bit variable */
10932       if (AOP_TYPE (right) == AOP_CRY)
10933         {
10934           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10935           aopPut (AOP (result), "c", 0);
10936           goto release;
10937         }
10938
10939       /* we need to or */
10940       toBoolean (right);
10941       aopPut (AOP (result), "a", 0);
10942       goto release;
10943     }
10944
10945   /* if they are the same size : or less */
10946   if (AOP_SIZE (result) <= AOP_SIZE (right))
10947     {
10948
10949       /* if they are in the same place */
10950       if (sameRegs (AOP (right), AOP (result)))
10951         goto release;
10952
10953       /* if they in different places then copy */
10954       size = AOP_SIZE (result);
10955       offset = 0;
10956       _startLazyDPSEvaluation ();
10957       while (size--)
10958         {
10959           aopPut (AOP (result),
10960                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10961                   offset);
10962           offset++;
10963         }
10964       _endLazyDPSEvaluation ();
10965       goto release;
10966     }
10967
10968
10969   /* if the result is of type pointer */
10970   if (IS_PTR (ctype))
10971     {
10972
10973       int p_type;
10974       sym_link *type = operandType (right);
10975
10976       /* pointer to generic pointer */
10977       if (IS_GENPTR (ctype))
10978         {
10979           if (IS_PTR (type))
10980             {
10981               p_type = DCL_TYPE (type);
10982             }
10983           else
10984             {
10985 #if OLD_CAST_BEHAVIOR
10986               /* KV: we are converting a non-pointer type to
10987                * a generic pointer. This (ifdef'd out) code
10988                * says that the resulting generic pointer
10989                * should have the same class as the storage
10990                * location of the non-pointer variable.
10991                *
10992                * For example, converting an int (which happens
10993                * to be stored in DATA space) to a pointer results
10994                * in a DATA generic pointer; if the original int
10995                * in XDATA space, so will be the resulting pointer.
10996                *
10997                * I don't like that behavior, and thus this change:
10998                * all such conversions will be forced to XDATA and
10999                * throw a warning. If you want some non-XDATA
11000                * type, or you want to suppress the warning, you
11001                * must go through an intermediate cast, like so:
11002                *
11003                * char _generic *gp = (char _xdata *)(intVar);
11004                */
11005               sym_link *etype = getSpec (type);
11006
11007               /* we have to go by the storage class */
11008               if (SPEC_OCLS (etype) != generic)
11009                 {
11010                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11011                 }
11012               else
11013 #endif
11014                 {
11015                   /* Converting unknown class (i.e. register variable)
11016                    * to generic pointer. This is not good, but
11017                    * we'll make a guess (and throw a warning).
11018                    */
11019                   p_type = FPOINTER;
11020                   werror (W_INT_TO_GEN_PTR_CAST);
11021                 }
11022             }
11023
11024           /* the first two bytes are known */
11025           size = GPTRSIZE - 1;
11026           offset = 0;
11027           _startLazyDPSEvaluation ();
11028           while (size--)
11029             {
11030               aopPut (AOP (result),
11031                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11032                       offset);
11033               offset++;
11034             }
11035           _endLazyDPSEvaluation ();
11036
11037           /* the last byte depending on type */
11038             {
11039                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11040                 char gpValStr[10];
11041             
11042                 if (gpVal == -1)
11043                 {
11044                     // pointerTypeToGPByte will have bitched.
11045                     exit(1);
11046                 }
11047             
11048                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11049                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11050             }
11051           goto release;
11052         }
11053
11054       /* just copy the pointers */
11055       size = AOP_SIZE (result);
11056       offset = 0;
11057       _startLazyDPSEvaluation ();
11058       while (size--)
11059         {
11060           aopPut (AOP (result),
11061                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11062                   offset);
11063           offset++;
11064         }
11065       _endLazyDPSEvaluation ();
11066       goto release;
11067     }
11068
11069   /* so we now know that the size of destination is greater
11070      than the size of the source */
11071   /* we move to result for the size of source */
11072   size = AOP_SIZE (right);
11073   offset = 0;
11074   _startLazyDPSEvaluation ();
11075   while (size--)
11076     {
11077       aopPut (AOP (result),
11078               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11079               offset);
11080       offset++;
11081     }
11082   _endLazyDPSEvaluation ();
11083
11084   /* now depending on the sign of the source && destination */
11085   size = AOP_SIZE (result) - AOP_SIZE (right);
11086   /* if unsigned or not an integral type */
11087   /* also, if the source is a bit, we don't need to sign extend, because
11088    * it can't possibly have set the sign bit.
11089    */
11090   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11091     {
11092       while (size--)
11093         {
11094           aopPut (AOP (result), zero, offset++);
11095         }
11096     }
11097   else
11098     {
11099       /* we need to extend the sign :{ */
11100       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11101                         FALSE, FALSE, NULL));
11102       emitcode ("rlc", "a");
11103       emitcode ("subb", "a,acc");
11104       while (size--)
11105         aopPut (AOP (result), "a", offset++);
11106     }
11107
11108   /* we are done hurray !!!! */
11109
11110 release:
11111   freeAsmop (right, NULL, ic, TRUE);
11112   freeAsmop (result, NULL, ic, TRUE);
11113
11114 }
11115
11116 /*-----------------------------------------------------------------*/
11117 /* genDjnz - generate decrement & jump if not zero instrucion      */
11118 /*-----------------------------------------------------------------*/
11119 static int
11120 genDjnz (iCode * ic, iCode * ifx)
11121 {
11122   symbol *lbl, *lbl1;
11123   if (!ifx)
11124     return 0;
11125
11126   /* if the if condition has a false label
11127      then we cannot save */
11128   if (IC_FALSE (ifx))
11129     return 0;
11130
11131   /* if the minus is not of the form
11132      a = a - 1 */
11133   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11134       !IS_OP_LITERAL (IC_RIGHT (ic)))
11135     return 0;
11136
11137   if (operandLitValue (IC_RIGHT (ic)) != 1)
11138     return 0;
11139
11140   /* if the size of this greater than one then no
11141      saving */
11142   if (getSize (operandType (IC_RESULT (ic))) > 1)
11143     return 0;
11144
11145   /* otherwise we can save BIG */
11146   D(emitcode(";", "genDjnz"););
11147
11148   lbl = newiTempLabel (NULL);
11149   lbl1 = newiTempLabel (NULL);
11150
11151   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11152
11153   if (AOP_NEEDSACC(IC_RESULT(ic)))
11154   {
11155       /* If the result is accessed indirectly via
11156        * the accumulator, we must explicitly write
11157        * it back after the decrement.
11158        */
11159       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11160       
11161       if (strcmp(rByte, "a"))
11162       {
11163            /* Something is hopelessly wrong */
11164            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11165                    __FILE__, __LINE__);
11166            /* We can just give up; the generated code will be inefficient,
11167             * but what the hey.
11168             */
11169            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11170            return 0;
11171       }
11172       emitcode ("dec", "%s", rByte);
11173       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11174       emitcode ("jnz", "!tlabel", lbl->key + 100);
11175   }
11176   else if (IS_AOP_PREG (IC_RESULT (ic)))
11177     {
11178       emitcode ("dec", "%s",
11179                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11180       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11181       emitcode ("jnz", "!tlabel", lbl->key + 100);
11182     }
11183   else
11184     {
11185       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11186                 lbl->key + 100);
11187     }
11188   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11189   emitcode ("", "!tlabeldef", lbl->key + 100);
11190   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11191   emitcode ("", "!tlabeldef", lbl1->key + 100);
11192
11193   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11194   ifx->generated = 1;
11195   return 1;
11196 }
11197
11198 /*-----------------------------------------------------------------*/
11199 /* genReceive - generate code for a receive iCode                  */
11200 /*-----------------------------------------------------------------*/
11201 static void
11202 genReceive (iCode * ic)
11203 {
11204
11205     int size = getSize (operandType (IC_RESULT (ic)));
11206     int offset = 0;
11207     int rb1off ;
11208     
11209     D (emitcode (";", "genReceive ");
11210        );
11211
11212   if (ic->argreg == 1) { /* first parameter */
11213       if (isOperandInFarSpace (IC_RESULT (ic)) &&
11214           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11215            IS_TRUE_SYMOP (IC_RESULT (ic))))
11216           {
11217               offset = fReturnSizeDS390 - size;
11218               while (size--)
11219                   {
11220                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11221                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11222                       offset++;
11223                   }
11224               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11225               size = AOP_SIZE (IC_RESULT (ic));
11226               offset = 0;
11227               while (size--)
11228                   {
11229                       emitcode ("pop", "acc");
11230                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11231                   }
11232               
11233           } else {
11234               _G.accInUse++;
11235               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11236               _G.accInUse--;
11237               assignResultValue (IC_RESULT (ic));
11238           }
11239   } else { /* second receive onwards */
11240       /* this gets a little tricky since unused recevies will be
11241          eliminated, we have saved the reg in the type field . and
11242          we use that to figure out which register to use */
11243       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11244       rb1off = ic->argreg;
11245       while (size--) {
11246           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11247       }
11248       
11249   }
11250   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11251 }
11252
11253 /*-----------------------------------------------------------------*/
11254 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11255 /*-----------------------------------------------------------------*/
11256 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11257 {
11258     operand *from , *to , *count;
11259     symbol *lbl;
11260     bitVect *rsave;
11261     int i;
11262
11263     /* we know it has to be 3 parameters */
11264     assert (nparms == 3);
11265     
11266     rsave = newBitVect(16);
11267     /* save DPTR if it needs to be saved */
11268     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11269             if (bitVectBitValue(ic->rMask,i))
11270                     rsave = bitVectSetBit(rsave,i);
11271     }
11272     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11273                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11274     savermask(rsave);
11275     
11276     to = parms[0];
11277     from = parms[1];
11278     count = parms[2];
11279
11280     aopOp (from, ic->next, FALSE, FALSE);
11281
11282     /* get from into DPTR1 */
11283     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11284     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11285     if (options.model == MODEL_FLAT24) {
11286         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11287     }
11288
11289     freeAsmop (from, NULL, ic, FALSE);
11290     aopOp (to, ic, FALSE, FALSE);
11291     /* get "to" into DPTR */
11292     /* if the operand is already in dptr
11293        then we do nothing else we move the value to dptr */
11294     if (AOP_TYPE (to) != AOP_STR) {
11295         /* if already in DPTR then we need to push */
11296         if (AOP_TYPE(to) == AOP_DPTR) {
11297             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11298             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11299             if (options.model == MODEL_FLAT24)
11300                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11301             emitcode ("pop", "dph");
11302             emitcode ("pop", "dpl");        
11303         } else {
11304             _startLazyDPSEvaluation ();
11305             /* if this is remateriazable */
11306             if (AOP_TYPE (to) == AOP_IMMD) {
11307                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11308             } else {                    /* we need to get it byte by byte */
11309                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11310                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11311                 if (options.model == MODEL_FLAT24) {
11312                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11313                 }
11314             }
11315             _endLazyDPSEvaluation ();
11316         }
11317     }
11318     freeAsmop (to, NULL, ic, FALSE);
11319     _G.dptrInUse = _G.dptr1InUse = 1;
11320     aopOp (count, ic->next->next, FALSE,FALSE);
11321     lbl =newiTempLabel(NULL);
11322
11323     /* now for the actual copy */
11324     if (AOP_TYPE(count) == AOP_LIT && 
11325         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11326         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11327         if (fromc) {
11328             emitcode ("lcall","__bi_memcpyc2x_s");
11329         } else {
11330             emitcode ("lcall","__bi_memcpyx2x_s");
11331         }
11332         freeAsmop (count, NULL, ic, FALSE);
11333     } else {
11334         symbol *lbl1 = newiTempLabel(NULL);
11335         
11336         emitcode (";"," Auto increment but no djnz");
11337         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11338         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11339         freeAsmop (count, NULL, ic, FALSE);
11340         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11341         emitcode ("","!tlabeldef",lbl->key+100);
11342         if (fromc) {
11343             emitcode ("clr","a");
11344             emitcode ("movc", "a,@a+dptr");
11345         } else 
11346             emitcode ("movx", "a,@dptr");
11347         emitcode ("movx", "@dptr,a");
11348         emitcode ("inc", "dptr");
11349         emitcode ("inc", "dptr");
11350         emitcode ("mov","a,b");
11351         emitcode ("orl","a,_ap");
11352         emitcode ("jz","!tlabel",lbl1->key+100);
11353         emitcode ("mov","a,_ap");
11354         emitcode ("add","a,#!constbyte",0xFF);
11355         emitcode ("mov","_ap,a");
11356         emitcode ("mov","a,b");
11357         emitcode ("addc","a,#!constbyte",0xFF);
11358         emitcode ("mov","b,a");
11359         emitcode ("sjmp","!tlabel",lbl->key+100);
11360         emitcode ("","!tlabeldef",lbl1->key+100);
11361     }
11362     emitcode ("mov", "dps,#0"); 
11363     _G.dptrInUse = _G.dptr1InUse = 0;
11364     unsavermask(rsave);
11365
11366 }
11367
11368 /*-----------------------------------------------------------------*/
11369 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11370 /*-----------------------------------------------------------------*/
11371 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11372 {
11373     operand *from , *to , *count;
11374     symbol *lbl,*lbl2;
11375     bitVect *rsave;
11376     int i;
11377
11378     /* we know it has to be 3 parameters */
11379     assert (nparms == 3);
11380     
11381     rsave = newBitVect(16);
11382     /* save DPTR if it needs to be saved */
11383     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11384             if (bitVectBitValue(ic->rMask,i))
11385                     rsave = bitVectSetBit(rsave,i);
11386     }
11387     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11388                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11389     savermask(rsave);
11390     
11391     to = parms[0];
11392     from = parms[1];
11393     count = parms[2];
11394
11395     aopOp (from, ic->next, FALSE, FALSE);
11396
11397     /* get from into DPTR1 */
11398     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11399     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11400     if (options.model == MODEL_FLAT24) {
11401         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11402     }
11403
11404     freeAsmop (from, NULL, ic, FALSE);
11405     aopOp (to, ic, FALSE, FALSE);
11406     /* get "to" into DPTR */
11407     /* if the operand is already in dptr
11408        then we do nothing else we move the value to dptr */
11409     if (AOP_TYPE (to) != AOP_STR) {
11410         /* if already in DPTR then we need to push */
11411         if (AOP_TYPE(to) == AOP_DPTR) {
11412             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11413             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11414             if (options.model == MODEL_FLAT24)
11415                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11416             emitcode ("pop", "dph");
11417             emitcode ("pop", "dpl");        
11418         } else {
11419             _startLazyDPSEvaluation ();
11420             /* if this is remateriazable */
11421             if (AOP_TYPE (to) == AOP_IMMD) {
11422                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11423             } else {                    /* we need to get it byte by byte */
11424                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11425                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11426                 if (options.model == MODEL_FLAT24) {
11427                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11428                 }
11429             }
11430             _endLazyDPSEvaluation ();
11431         }
11432     }
11433     freeAsmop (to, NULL, ic, FALSE);
11434     _G.dptrInUse = _G.dptr1InUse = 1;
11435     aopOp (count, ic->next->next, FALSE,FALSE);
11436     lbl =newiTempLabel(NULL);
11437     lbl2 =newiTempLabel(NULL);
11438
11439     /* now for the actual compare */
11440     if (AOP_TYPE(count) == AOP_LIT && 
11441         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11442         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11443         if (fromc)
11444             emitcode("lcall","__bi_memcmpc2x_s");
11445         else
11446             emitcode("lcall","__bi_memcmpx2x_s");
11447         freeAsmop (count, NULL, ic, FALSE);
11448         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11449         aopPut(AOP(IC_RESULT(ic)),"a",0);
11450         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11451     } else {
11452         symbol *lbl1 = newiTempLabel(NULL);
11453
11454         emitcode("push","ar0");         
11455         emitcode (";"," Auto increment but no djnz");
11456         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11457         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11458         freeAsmop (count, NULL, ic, FALSE);
11459         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11460         emitcode ("","!tlabeldef",lbl->key+100);
11461         if (fromc) {
11462             emitcode ("clr","a");
11463             emitcode ("movc", "a,@a+dptr");
11464         } else 
11465             emitcode ("movx", "a,@dptr");
11466         emitcode ("mov","r0,a");
11467         emitcode ("movx", "a,@dptr");
11468         emitcode ("clr","c");
11469         emitcode ("subb","a,r0");
11470         emitcode ("jnz","!tlabel",lbl2->key+100);
11471         emitcode ("inc", "dptr");
11472         emitcode ("inc", "dptr");
11473         emitcode ("mov","a,b");
11474         emitcode ("orl","a,_ap");
11475         emitcode ("jz","!tlabel",lbl1->key+100);
11476         emitcode ("mov","a,_ap");
11477         emitcode ("add","a,#!constbyte",0xFF);
11478         emitcode ("mov","_ap,a");
11479         emitcode ("mov","a,b");
11480         emitcode ("addc","a,#!constbyte",0xFF);
11481         emitcode ("mov","b,a");
11482         emitcode ("sjmp","!tlabel",lbl->key+100);
11483         emitcode ("","!tlabeldef",lbl1->key+100);
11484         emitcode ("clr","a");
11485         emitcode ("","!tlabeldef",lbl2->key+100);
11486         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11487         aopPut(AOP(IC_RESULT(ic)),"a",0);
11488         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11489         emitcode("pop","ar0");
11490         emitcode ("mov", "dps,#0");      
11491     }
11492     _G.dptrInUse = _G.dptr1InUse = 0;
11493     unsavermask(rsave);
11494
11495 }
11496
11497 /*-----------------------------------------------------------------*/
11498 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11499 /* port, first parameter output area second parameter pointer to   */
11500 /* port third parameter count                                      */
11501 /*-----------------------------------------------------------------*/
11502 static void genInp( iCode *ic, int nparms, operand **parms)
11503 {
11504     operand *from , *to , *count;
11505     symbol *lbl;
11506     bitVect *rsave;
11507     int i;
11508
11509     /* we know it has to be 3 parameters */
11510     assert (nparms == 3);
11511     
11512     rsave = newBitVect(16);
11513     /* save DPTR if it needs to be saved */
11514     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11515             if (bitVectBitValue(ic->rMask,i))
11516                     rsave = bitVectSetBit(rsave,i);
11517     }
11518     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11519                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11520     savermask(rsave);
11521     
11522     to = parms[0];
11523     from = parms[1];
11524     count = parms[2];
11525
11526     aopOp (from, ic->next, FALSE, FALSE);
11527
11528     /* get from into DPTR1 */
11529     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11530     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11531     if (options.model == MODEL_FLAT24) {
11532         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11533     }
11534
11535     freeAsmop (from, NULL, ic, FALSE);
11536     aopOp (to, ic, FALSE, FALSE);
11537     /* get "to" into DPTR */
11538     /* if the operand is already in dptr
11539        then we do nothing else we move the value to dptr */
11540     if (AOP_TYPE (to) != AOP_STR) {
11541         /* if already in DPTR then we need to push */
11542         if (AOP_TYPE(to) == AOP_DPTR) {
11543             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11544             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11545             if (options.model == MODEL_FLAT24)
11546                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11547             emitcode ("pop", "dph");
11548             emitcode ("pop", "dpl");        
11549         } else {
11550             _startLazyDPSEvaluation ();
11551             /* if this is remateriazable */
11552             if (AOP_TYPE (to) == AOP_IMMD) {
11553                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11554             } else {                    /* we need to get it byte by byte */
11555                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11556                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11557                 if (options.model == MODEL_FLAT24) {
11558                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11559                 }
11560             }
11561             _endLazyDPSEvaluation ();
11562         }
11563     }
11564     freeAsmop (to, NULL, ic, FALSE);
11565
11566     _G.dptrInUse = _G.dptr1InUse = 1;
11567     aopOp (count, ic->next->next, FALSE,FALSE);
11568     lbl =newiTempLabel(NULL);
11569
11570     /* now for the actual copy */
11571     if (AOP_TYPE(count) == AOP_LIT && 
11572         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11573         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11574         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11575         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11576         freeAsmop (count, NULL, ic, FALSE);
11577         emitcode ("","!tlabeldef",lbl->key+100);
11578         emitcode ("movx", "a,@dptr");   /* read data from port */
11579         emitcode ("dec","dps");         /* switch to DPTR */
11580         emitcode ("movx", "@dptr,a");   /* save into location */
11581         emitcode ("inc", "dptr");       /* point to next area */
11582         emitcode ("inc","dps");         /* switch to DPTR2 */
11583         emitcode ("djnz","b,!tlabel",lbl->key+100);
11584     } else {
11585         symbol *lbl1 = newiTempLabel(NULL);
11586         
11587         emitcode (";"," Auto increment but no djnz");
11588         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11589         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11590         freeAsmop (count, NULL, ic, FALSE);
11591         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11592         emitcode ("","!tlabeldef",lbl->key+100);
11593         emitcode ("movx", "a,@dptr");
11594         emitcode ("dec","dps");         /* switch to DPTR */
11595         emitcode ("movx", "@dptr,a");
11596         emitcode ("inc", "dptr");
11597         emitcode ("inc","dps");         /* switch to DPTR2 */
11598 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11599 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11600         emitcode ("mov","a,b");
11601         emitcode ("orl","a,_ap");
11602         emitcode ("jz","!tlabel",lbl1->key+100);
11603         emitcode ("mov","a,_ap");
11604         emitcode ("add","a,#!constbyte",0xFF);
11605         emitcode ("mov","_ap,a");
11606         emitcode ("mov","a,b");
11607         emitcode ("addc","a,#!constbyte",0xFF);
11608         emitcode ("mov","b,a");
11609         emitcode ("sjmp","!tlabel",lbl->key+100);
11610         emitcode ("","!tlabeldef",lbl1->key+100);
11611     }
11612     emitcode ("mov", "dps,#0"); 
11613     _G.dptrInUse = _G.dptr1InUse = 0;
11614     unsavermask(rsave);
11615
11616 }
11617
11618 /*-----------------------------------------------------------------*/
11619 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11620 /* port, first parameter output area second parameter pointer to   */
11621 /* port third parameter count                                      */
11622 /*-----------------------------------------------------------------*/
11623 static void genOutp( iCode *ic, int nparms, operand **parms)
11624 {
11625     operand *from , *to , *count;
11626     symbol *lbl;
11627     bitVect *rsave;
11628     int i;
11629
11630     /* we know it has to be 3 parameters */
11631     assert (nparms == 3);
11632     
11633     rsave = newBitVect(16);
11634     /* save DPTR if it needs to be saved */
11635     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11636             if (bitVectBitValue(ic->rMask,i))
11637                     rsave = bitVectSetBit(rsave,i);
11638     }
11639     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11640                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11641     savermask(rsave);
11642     
11643     to = parms[0];
11644     from = parms[1];
11645     count = parms[2];
11646
11647     aopOp (from, ic->next, FALSE, FALSE);
11648
11649     /* get from into DPTR1 */
11650     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11651     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11652     if (options.model == MODEL_FLAT24) {
11653         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11654     }
11655
11656     freeAsmop (from, NULL, ic, FALSE);
11657     aopOp (to, ic, FALSE, FALSE);
11658     /* get "to" into DPTR */
11659     /* if the operand is already in dptr
11660        then we do nothing else we move the value to dptr */
11661     if (AOP_TYPE (to) != AOP_STR) {
11662         /* if already in DPTR then we need to push */
11663         if (AOP_TYPE(to) == AOP_DPTR) {
11664             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11665             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11666             if (options.model == MODEL_FLAT24)
11667                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11668             emitcode ("pop", "dph");
11669             emitcode ("pop", "dpl");        
11670         } else {
11671             _startLazyDPSEvaluation ();
11672             /* if this is remateriazable */
11673             if (AOP_TYPE (to) == AOP_IMMD) {
11674                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11675             } else {                    /* we need to get it byte by byte */
11676                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11677                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11678                 if (options.model == MODEL_FLAT24) {
11679                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11680                 }
11681             }
11682             _endLazyDPSEvaluation ();
11683         }
11684     }
11685     freeAsmop (to, NULL, ic, FALSE);
11686
11687     _G.dptrInUse = _G.dptr1InUse = 1;
11688     aopOp (count, ic->next->next, FALSE,FALSE);
11689     lbl =newiTempLabel(NULL);
11690
11691     /* now for the actual copy */
11692     if (AOP_TYPE(count) == AOP_LIT && 
11693         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11694         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11695         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11696         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11697         emitcode ("","!tlabeldef",lbl->key+100);
11698         emitcode ("movx", "a,@dptr");   /* read data from port */
11699         emitcode ("inc","dps");         /* switch to DPTR2 */
11700         emitcode ("movx", "@dptr,a");   /* save into location */
11701         emitcode ("inc", "dptr");       /* point to next area */
11702         emitcode ("dec","dps");         /* switch to DPTR */
11703         emitcode ("djnz","b,!tlabel",lbl->key+100);
11704         freeAsmop (count, NULL, ic, FALSE);
11705     } else {
11706         symbol *lbl1 = newiTempLabel(NULL);
11707         
11708         emitcode (";"," Auto increment but no djnz");
11709         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11710         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11711         freeAsmop (count, NULL, ic, FALSE);
11712         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11713         emitcode ("","!tlabeldef",lbl->key+100);
11714         emitcode ("movx", "a,@dptr");
11715         emitcode ("inc", "dptr");
11716         emitcode ("inc","dps");         /* switch to DPTR2 */
11717         emitcode ("movx", "@dptr,a");
11718         emitcode ("dec","dps");         /* switch to DPTR */
11719         emitcode ("mov","a,b");
11720         emitcode ("orl","a,_ap");
11721         emitcode ("jz","!tlabel",lbl1->key+100);
11722         emitcode ("mov","a,_ap");
11723         emitcode ("add","a,#!constbyte",0xFF);
11724         emitcode ("mov","_ap,a");
11725         emitcode ("mov","a,b");
11726         emitcode ("addc","a,#!constbyte",0xFF);
11727         emitcode ("mov","b,a");
11728         emitcode ("sjmp","!tlabel",lbl->key+100);
11729         emitcode ("","!tlabeldef",lbl1->key+100);
11730     }
11731     emitcode ("mov", "dps,#0"); 
11732     _G.dptrInUse = _G.dptr1InUse = 0;
11733     unsavermask(rsave);
11734
11735 }
11736
11737 /*-----------------------------------------------------------------*/
11738 /* genSwapW - swap lower & high order bytes                        */
11739 /*-----------------------------------------------------------------*/
11740 static void genSwapW(iCode *ic, int nparms, operand **parms)
11741 {
11742     operand *dest;
11743     operand *src;
11744     assert (nparms==1);
11745
11746     src = parms[0];
11747     dest=IC_RESULT(ic);
11748
11749     assert(getSize(operandType(src))==2);
11750
11751     aopOp (src, ic, FALSE, FALSE);
11752     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11753     _G.accInUse++;
11754     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11755     _G.accInUse--;
11756     freeAsmop (src, NULL, ic, FALSE);
11757     
11758     aopOp (dest,ic, FALSE, FALSE);
11759     aopPut(AOP(dest),"b",0);
11760     aopPut(AOP(dest),"a",1);
11761     freeAsmop (dest, NULL, ic, FALSE);    
11762 }
11763
11764 /*-----------------------------------------------------------------*/
11765 /* genMemsetX - gencode for memSetX data                           */
11766 /*-----------------------------------------------------------------*/
11767 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11768 {
11769     operand *to , *val , *count;
11770     symbol *lbl;
11771     char *l;
11772     int i;
11773     bitVect *rsave;
11774
11775     /* we know it has to be 3 parameters */
11776     assert (nparms == 3);
11777     
11778     to = parms[0];
11779     val = parms[1];
11780     count = parms[2];
11781         
11782     /* save DPTR if it needs to be saved */
11783     rsave = newBitVect(16);
11784     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11785             if (bitVectBitValue(ic->rMask,i))
11786                     rsave = bitVectSetBit(rsave,i);
11787     }
11788     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11789                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11790     savermask(rsave);
11791
11792     aopOp (to, ic, FALSE, FALSE);
11793     /* get "to" into DPTR */
11794     /* if the operand is already in dptr
11795        then we do nothing else we move the value to dptr */
11796     if (AOP_TYPE (to) != AOP_STR) {
11797         /* if already in DPTR then we need to push */
11798         if (AOP_TYPE(to) == AOP_DPTR) {
11799             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11800             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11801             if (options.model == MODEL_FLAT24)
11802                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11803             emitcode ("pop", "dph");
11804             emitcode ("pop", "dpl");        
11805         } else {
11806             _startLazyDPSEvaluation ();
11807             /* if this is remateriazable */
11808             if (AOP_TYPE (to) == AOP_IMMD) {
11809                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11810             } else {                    /* we need to get it byte by byte */
11811                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11812                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11813                 if (options.model == MODEL_FLAT24) {
11814                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11815                 }
11816             }
11817             _endLazyDPSEvaluation ();
11818         }
11819     }
11820     freeAsmop (to, NULL, ic, FALSE);
11821
11822     aopOp (val, ic->next->next, FALSE,FALSE);
11823     aopOp (count, ic->next->next, FALSE,FALSE);    
11824     lbl =newiTempLabel(NULL);
11825     /* now for the actual copy */
11826     if (AOP_TYPE(count) == AOP_LIT && 
11827         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11828         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11829         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11830         MOVA(l);
11831         emitcode ("","!tlabeldef",lbl->key+100);
11832         emitcode ("movx", "@dptr,a");
11833         emitcode ("inc", "dptr");
11834         emitcode ("djnz","b,!tlabel",lbl->key+100);
11835     } else {
11836         symbol *lbl1 = newiTempLabel(NULL);
11837         
11838         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11839         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11840         emitcode ("","!tlabeldef",lbl->key+100);
11841         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11842         emitcode ("movx", "@dptr,a");
11843         emitcode ("inc", "dptr");
11844         emitcode ("mov","a,b");
11845         emitcode ("orl","a,_ap");
11846         emitcode ("jz","!tlabel",lbl1->key+100);
11847         emitcode ("mov","a,_ap");
11848         emitcode ("add","a,#!constbyte",0xFF);
11849         emitcode ("mov","_ap,a");
11850         emitcode ("mov","a,b");
11851         emitcode ("addc","a,#!constbyte",0xFF);
11852         emitcode ("mov","b,a");
11853         emitcode ("sjmp","!tlabel",lbl->key+100);
11854         emitcode ("","!tlabeldef",lbl1->key+100);
11855     }
11856     freeAsmop (count, NULL, ic, FALSE);
11857     unsavermask(rsave);
11858 }
11859
11860 /*-----------------------------------------------------------------*/
11861 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11862 /*-----------------------------------------------------------------*/
11863 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11864 {
11865         bitVect *rsave ;
11866         operand *pnum, *result;
11867         int i;
11868     
11869         assert (nparms==1);
11870         /* save registers that need to be saved */
11871         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11872                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11873     
11874         pnum = parms[0]; 
11875         aopOp (pnum, ic, FALSE, FALSE);
11876         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11877         freeAsmop (pnum, NULL, ic, FALSE);
11878         emitcode ("lcall","NatLib_LoadPrimitive");
11879         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11880         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11881             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11882                 for (i = (size-1) ; i >= 0 ; i-- ) {
11883                         emitcode ("push","a%s",javaRet[i]);
11884                 }
11885                 for (i=0; i < size ; i++ ) {
11886                         emitcode ("pop","a%s",
11887                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11888                 }
11889         } else {
11890                 for (i = 0 ; i < size ; i++ ) {
11891                         aopPut(AOP(result),javaRet[i],i);
11892                 }
11893         }    
11894         freeAsmop (result, NULL, ic, FALSE);
11895         unsavermask(rsave);
11896 }
11897
11898 /*-----------------------------------------------------------------*/
11899 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11900 /*-----------------------------------------------------------------*/
11901 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11902 {
11903         bitVect *rsave ;
11904         operand *pnum, *result;
11905         int size = 3;
11906         int i;
11907     
11908         assert (nparms==1);
11909         /* save registers that need to be saved */
11910         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11911                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11912     
11913         pnum = parms[0]; 
11914         aopOp (pnum, ic, FALSE, FALSE);
11915         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11916         freeAsmop (pnum, NULL, ic, FALSE);
11917         emitcode ("lcall","NatLib_LoadPointer");
11918         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11919         if (AOP_TYPE(result)!=AOP_STR) {
11920                 for (i = 0 ; i < size ; i++ ) {
11921                         aopPut(AOP(result),fReturn[i],i);
11922                 }
11923         }    
11924         freeAsmop (result, NULL, ic, FALSE);
11925         unsavermask(rsave);
11926 }
11927
11928 /*-----------------------------------------------------------------*/
11929 /* genNatLibInstallStateBlock -                                    */
11930 /*-----------------------------------------------------------------*/
11931 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11932                                        operand **parms, const char *name)
11933 {
11934         bitVect *rsave ;
11935         operand *psb, *handle;
11936         assert (nparms==2);
11937
11938         /* save registers that need to be saved */
11939         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11940                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11941         psb = parms[0];
11942         handle = parms[1];
11943
11944         /* put pointer to state block into DPTR1 */
11945         aopOp (psb, ic, FALSE, FALSE);
11946         if (AOP_TYPE (psb) == AOP_IMMD) {
11947                 emitcode ("mov","dps,#1");
11948                 emitcode ("mov", "dptr,%s",
11949                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
11950                 emitcode ("mov","dps,#0");
11951         } else {
11952                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
11953                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
11954                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
11955         }
11956         freeAsmop (psb, NULL, ic, FALSE);
11957
11958         /* put libraryID into DPTR */
11959         emitcode ("mov","dptr,#LibraryID");
11960
11961         /* put handle into r3:r2 */
11962         aopOp (handle, ic, FALSE, FALSE);
11963         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11964                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
11965                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11966                 emitcode ("pop","ar3");
11967                 emitcode ("pop","ar2");
11968         } else {        
11969                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
11970                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
11971         }
11972         freeAsmop (psb, NULL, ic, FALSE);
11973
11974         /* make the call */
11975         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11976
11977         /* put return value into place*/
11978         _G.accInUse++;
11979         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11980         _G.accInUse--;
11981         aopPut(AOP(IC_RESULT(ic)),"a",0);
11982         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11983         unsavermask(rsave);
11984 }
11985
11986 /*-----------------------------------------------------------------*/
11987 /* genNatLibRemoveStateBlock -                                     */
11988 /*-----------------------------------------------------------------*/
11989 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11990 {
11991         bitVect *rsave ;
11992
11993         assert(nparms==0);
11994
11995         /* save registers that need to be saved */
11996         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11997                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11998
11999         /* put libraryID into DPTR */
12000         emitcode ("mov","dptr,#LibraryID");
12001         /* make the call */
12002         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12003         unsavermask(rsave);
12004 }
12005
12006 /*-----------------------------------------------------------------*/
12007 /* genNatLibGetStateBlock -                                        */
12008 /*-----------------------------------------------------------------*/
12009 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12010                                    operand **parms,const char *name)
12011 {
12012         bitVect *rsave ;
12013         symbol *lbl = newiTempLabel(NULL);
12014         
12015         assert(nparms==0);
12016         /* save registers that need to be saved */
12017         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12018                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12019
12020         /* put libraryID into DPTR */
12021         emitcode ("mov","dptr,#LibraryID");
12022         /* make the call */
12023         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12024         emitcode ("jnz","!tlabel",lbl->key+100);
12025
12026         /* put return value into place */
12027         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12028         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12029                 emitcode ("push","ar3");
12030                 emitcode ("push","ar2");
12031                 emitcode ("pop","%s",
12032                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12033                 emitcode ("pop","%s",
12034                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12035         } else {
12036                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12037                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12038         }
12039         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12040         emitcode ("","!tlabeldef",lbl->key+100);
12041         unsavermask(rsave);
12042 }
12043
12044 /*-----------------------------------------------------------------*/
12045 /* genMMMalloc -                                                   */
12046 /*-----------------------------------------------------------------*/
12047 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12048                          int size, const char *name)
12049 {
12050         bitVect *rsave ;
12051         operand *bsize;
12052         symbol *rsym;
12053         symbol *lbl = newiTempLabel(NULL);
12054
12055         assert (nparms == 1);
12056         /* save registers that need to be saved */
12057         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12058                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12059         
12060         bsize=parms[0];
12061         aopOp (bsize,ic,FALSE,FALSE);
12062
12063         /* put the size in R4-R2 */
12064         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12065                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12066                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12067                 if (size==3) {
12068                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12069                         emitcode("pop","ar4");
12070                 }
12071                 emitcode("pop","ar3");
12072                 emitcode("pop","ar2");          
12073         } else {
12074                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12075                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12076                 if (size==3) {
12077                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12078                 }
12079         }
12080         freeAsmop (bsize, NULL, ic, FALSE);
12081
12082         /* make the call */
12083         emitcode ("lcall","MM_%s",name);
12084         emitcode ("jz","!tlabel",lbl->key+100);
12085         emitcode ("mov","r2,#!constbyte",0xff);
12086         emitcode ("mov","r3,#!constbyte",0xff);
12087         emitcode ("","!tlabeldef",lbl->key+100);
12088         /* we don't care about the pointer : we just save the handle */
12089         rsym = OP_SYMBOL(IC_RESULT(ic));
12090         if (rsym->liveFrom != rsym->liveTo) {
12091                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12092                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12093                         emitcode ("push","ar3");
12094                         emitcode ("push","ar2");
12095                         emitcode ("pop","%s",
12096                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12097                         emitcode ("pop","%s",
12098                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12099                 } else {
12100                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12101                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12102                 }
12103                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12104         }
12105         unsavermask(rsave);
12106 }
12107
12108 /*-----------------------------------------------------------------*/
12109 /* genMMDeref -                                                    */
12110 /*-----------------------------------------------------------------*/
12111 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12112 {
12113         bitVect *rsave ;
12114         operand *handle;
12115
12116         assert (nparms == 1);
12117         /* save registers that need to be saved */
12118         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12119                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12120         
12121         handle=parms[0];
12122         aopOp (handle,ic,FALSE,FALSE);
12123
12124         /* put the size in R4-R2 */
12125         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12126                 emitcode("push","%s",
12127                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12128                 emitcode("push","%s",
12129                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12130                 emitcode("pop","ar3");
12131                 emitcode("pop","ar2");          
12132         } else {
12133                 emitcode ("mov","r2,%s",
12134                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12135                 emitcode ("mov","r3,%s",
12136                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12137         }
12138         freeAsmop (handle, NULL, ic, FALSE);
12139
12140         /* make the call */
12141         emitcode ("lcall","MM_Deref");
12142         
12143         {
12144                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12145                 if (rsym->liveFrom != rsym->liveTo) {                   
12146                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12147                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12148                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12149                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12150                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12151                         }
12152                 }
12153         }
12154         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12155         unsavermask(rsave);
12156 }
12157
12158 /*-----------------------------------------------------------------*/
12159 /* genMMUnrestrictedPersist -                                      */
12160 /*-----------------------------------------------------------------*/
12161 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12162 {
12163         bitVect *rsave ;
12164         operand *handle;
12165
12166         assert (nparms == 1);
12167         /* save registers that need to be saved */
12168         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12169                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12170         
12171         handle=parms[0];
12172         aopOp (handle,ic,FALSE,FALSE);
12173
12174         /* put the size in R3-R2 */
12175         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12176                 emitcode("push","%s",
12177                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12178                 emitcode("push","%s",
12179                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12180                 emitcode("pop","ar3");
12181                 emitcode("pop","ar2");          
12182         } else {
12183                 emitcode ("mov","r2,%s",
12184                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12185                 emitcode ("mov","r3,%s",
12186                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12187         }
12188         freeAsmop (handle, NULL, ic, FALSE);
12189
12190         /* make the call */
12191         emitcode ("lcall","MM_UnrestrictedPersist");
12192
12193         {
12194                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12195                 if (rsym->liveFrom != rsym->liveTo) {   
12196                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12197                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12198                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12199                 }
12200         }
12201         unsavermask(rsave);
12202 }
12203
12204 /*-----------------------------------------------------------------*/
12205 /* genSystemExecJavaProcess -                                      */
12206 /*-----------------------------------------------------------------*/
12207 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12208 {
12209         bitVect *rsave ;
12210         operand *handle, *pp;
12211
12212         assert (nparms==2);
12213         /* save registers that need to be saved */
12214         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12215                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12216         
12217         pp = parms[0];
12218         handle = parms[1];
12219         
12220         /* put the handle in R3-R2 */
12221         aopOp (handle,ic,FALSE,FALSE);
12222         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12223                 emitcode("push","%s",
12224                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12225                 emitcode("push","%s",
12226                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12227                 emitcode("pop","ar3");
12228                 emitcode("pop","ar2");          
12229         } else {
12230                 emitcode ("mov","r2,%s",
12231                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12232                 emitcode ("mov","r3,%s",
12233                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12234         }
12235         freeAsmop (handle, NULL, ic, FALSE);
12236         
12237         /* put pointer in DPTR */
12238         aopOp (pp,ic,FALSE,FALSE);
12239         if (AOP_TYPE(pp) == AOP_IMMD) {
12240                 emitcode ("mov", "dptr,%s",
12241                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12242         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12243                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12244                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12245                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12246         }
12247         freeAsmop (handle, NULL, ic, FALSE);
12248
12249         /* make the call */
12250         emitcode ("lcall","System_ExecJavaProcess");
12251         
12252         /* put result in place */
12253         {
12254                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12255                 if (rsym->liveFrom != rsym->liveTo) {   
12256                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12257                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12258                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12259                 }
12260         }
12261         
12262         unsavermask(rsave);
12263 }
12264
12265 /*-----------------------------------------------------------------*/
12266 /* genSystemRTCRegisters -                                         */
12267 /*-----------------------------------------------------------------*/
12268 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12269                                   char *name)
12270 {
12271         bitVect *rsave ;
12272         operand *pp;
12273
12274         assert (nparms==1);
12275         /* save registers that need to be saved */
12276         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12277                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12278         
12279         pp=parms[0];
12280         /* put pointer in DPTR */
12281         aopOp (pp,ic,FALSE,FALSE);
12282         if (AOP_TYPE (pp) == AOP_IMMD) {
12283                 emitcode ("mov","dps,#1");
12284                 emitcode ("mov", "dptr,%s", 
12285                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12286                 emitcode ("mov","dps,#0");
12287         } else {
12288                 emitcode ("mov","dpl1,%s",
12289                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12290                 emitcode ("mov","dph1,%s",
12291                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12292                 emitcode ("mov","dpx1,%s",
12293                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12294         }
12295         freeAsmop (pp, NULL, ic, FALSE);
12296
12297         /* make the call */
12298         emitcode ("lcall","System_%sRTCRegisters",name);
12299
12300         unsavermask(rsave);
12301 }
12302
12303 /*-----------------------------------------------------------------*/
12304 /* genSystemThreadSleep -                                          */
12305 /*-----------------------------------------------------------------*/
12306 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12307 {
12308         bitVect *rsave ;
12309         operand *to, *s;
12310
12311         assert (nparms==1);
12312         /* save registers that need to be saved */
12313         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12314                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12315
12316         to = parms[0];
12317         aopOp(to,ic,FALSE,FALSE);
12318         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12319             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12320                 emitcode ("push","%s",
12321                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12322                 emitcode ("push","%s",
12323                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12324                 emitcode ("push","%s",
12325                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12326                 emitcode ("push","%s",
12327                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12328                 emitcode ("pop","ar3");
12329                 emitcode ("pop","ar2");
12330                 emitcode ("pop","ar1");
12331                 emitcode ("pop","ar0");
12332         } else {
12333                 emitcode ("mov","r0,%s",
12334                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12335                 emitcode ("mov","r1,%s",
12336                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12337                 emitcode ("mov","r2,%s",
12338                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12339                 emitcode ("mov","r3,%s",
12340                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12341         }
12342         freeAsmop (to, NULL, ic, FALSE);
12343
12344         /* suspend in acc */
12345         s = parms[1];
12346         aopOp(s,ic,FALSE,FALSE);
12347         emitcode ("mov","a,%s",
12348                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12349         freeAsmop (s, NULL, ic, FALSE);
12350
12351         /* make the call */
12352         emitcode ("lcall","System_%s",name);
12353
12354         unsavermask(rsave);
12355 }
12356
12357 /*-----------------------------------------------------------------*/
12358 /* genSystemThreadResume -                                         */
12359 /*-----------------------------------------------------------------*/
12360 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12361 {
12362         bitVect *rsave ;
12363         operand *tid,*pid;
12364
12365         assert (nparms==2);
12366         /* save registers that need to be saved */
12367         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12368                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12369         
12370         tid = parms[0];
12371         pid = parms[1];
12372         
12373         /* PID in R0 */
12374         aopOp(pid,ic,FALSE,FALSE);
12375         emitcode ("mov","r0,%s",
12376                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12377         freeAsmop (pid, NULL, ic, FALSE);
12378         
12379         /* tid into ACC */
12380         aopOp(tid,ic,FALSE,FALSE);
12381         emitcode ("mov","a,%s",
12382                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12383         freeAsmop (tid, NULL, ic, FALSE);
12384         
12385         emitcode ("lcall","System_ThreadResume");
12386
12387         /* put result into place */
12388         {
12389                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12390                 if (rsym->liveFrom != rsym->liveTo) {   
12391                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12392                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12393                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12394                 }
12395         }
12396         unsavermask(rsave);
12397 }
12398
12399 /*-----------------------------------------------------------------*/
12400 /* genSystemProcessResume -                                        */
12401 /*-----------------------------------------------------------------*/
12402 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12403 {
12404         bitVect *rsave ;
12405         operand *pid;
12406
12407         assert (nparms==1);
12408         /* save registers that need to be saved */
12409         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12410                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12411         
12412         pid = parms[0];
12413         
12414         /* pid into ACC */
12415         aopOp(pid,ic,FALSE,FALSE);
12416         emitcode ("mov","a,%s",
12417                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12418         freeAsmop (pid, NULL, ic, FALSE);
12419         
12420         emitcode ("lcall","System_ProcessResume");
12421
12422         unsavermask(rsave);
12423 }
12424
12425 /*-----------------------------------------------------------------*/
12426 /* genSystem -                                                     */
12427 /*-----------------------------------------------------------------*/
12428 static void genSystem (iCode *ic,int nparms,char *name)
12429 {
12430         assert(nparms == 0);
12431
12432         emitcode ("lcall","System_%s",name);
12433 }
12434
12435 /*-----------------------------------------------------------------*/
12436 /* genSystemPoll -                                                  */
12437 /*-----------------------------------------------------------------*/
12438 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12439 {
12440         bitVect *rsave ;
12441         operand *fp;
12442
12443         assert (nparms==1);
12444         /* save registers that need to be saved */
12445         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12446                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12447
12448         fp = parms[0];
12449         aopOp (fp,ic,FALSE,FALSE);
12450         if (AOP_TYPE (fp) == AOP_IMMD) {
12451                 emitcode ("mov", "dptr,%s", 
12452                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12453         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12454                 emitcode ("mov","dpl,%s",
12455                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12456                 emitcode ("mov","dph,%s",
12457                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12458                 emitcode ("mov","dpx,%s",
12459                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12460         }
12461         freeAsmop (fp, NULL, ic, FALSE);
12462
12463         emitcode ("lcall","System_%sPoll",name);
12464
12465         /* put result into place */
12466         {
12467                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12468                 if (rsym->liveFrom != rsym->liveTo) {   
12469                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12470                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12471                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12472                 }
12473         }
12474         unsavermask(rsave);
12475 }
12476
12477 /*-----------------------------------------------------------------*/
12478 /* genSystemGetCurrentID -                                         */
12479 /*-----------------------------------------------------------------*/
12480 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12481 {
12482         assert (nparms==0);
12483
12484         emitcode ("lcall","System_GetCurrent%sId",name);
12485         /* put result into place */
12486         {
12487                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12488                 if (rsym->liveFrom != rsym->liveTo) {   
12489                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12490                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12491                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12492                 }
12493         }
12494 }
12495
12496 /*-----------------------------------------------------------------*/
12497 /* genBuiltIn - calls the appropriate function to  generating code */
12498 /* for a built in function                                         */
12499 /*-----------------------------------------------------------------*/
12500 static void genBuiltIn (iCode *ic)
12501 {
12502         operand *bi_parms[MAX_BUILTIN_ARGS];
12503         int nbi_parms;
12504         iCode *bi_iCode;
12505         symbol *bif;
12506
12507         /* get all the arguments for a built in function */
12508         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12509
12510         /* which function is it */
12511         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12512         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12513                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12514         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12515                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12516         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12517                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12518         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12519                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12520         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12521                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12522         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12523                 genInp(bi_iCode,nbi_parms,bi_parms);
12524         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12525                 genOutp(bi_iCode,nbi_parms,bi_parms);
12526         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12527                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12528                 /* JavaNative builtIns */               
12529         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12530                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12531         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12532                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12533         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12534                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12535         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12536                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12537         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12538                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12539         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12540                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12541         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12542                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12543         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12544                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12545         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12546                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12547         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12548                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12549         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12550                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12551         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12552                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12553         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12554                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12555         } else if (strcmp(bif->name,"MM_Free")==0) {
12556                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12557         } else if (strcmp(bif->name,"MM_Deref")==0) {
12558                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12559         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12560                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12561         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12562                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12563         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12564                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12565         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12566                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12567         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12568                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12569         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12570                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12571         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12572                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12573         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12574                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12575         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12576                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12577         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12578                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12579         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12580                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12581         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12582                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12583         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12584                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12585         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12586                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12587         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12588                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12589         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12590                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12591         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12592                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12593         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12594                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12595         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12596                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12597         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12598                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12599         } else {
12600                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12601                 return ;
12602         }
12603         return ;    
12604 }
12605
12606 /*-----------------------------------------------------------------*/
12607 /* gen390Code - generate code for Dallas 390 based controllers     */
12608 /*-----------------------------------------------------------------*/
12609 void
12610 gen390Code (iCode * lic)
12611 {
12612   iCode *ic;
12613   int cln = 0;
12614
12615   lineHead = lineCurr = NULL;
12616   dptrn[1][0] = "dpl1";
12617   dptrn[1][1] = "dph1";
12618   dptrn[1][2] = "dpx1";
12619   
12620   if (options.model == MODEL_FLAT24) {
12621     fReturnSizeDS390 = 5;
12622     fReturn = fReturn24;
12623   } else {
12624     fReturnSizeDS390 = 4;
12625     fReturn = fReturn16;
12626     options.stack10bit=0;
12627   }
12628 #if 1
12629   /* print the allocation information */
12630   if (allocInfo)
12631     printAllocInfo (currFunc, codeOutFile);
12632 #endif
12633   /* if debug information required */
12634   if (options.debug && currFunc)
12635     {
12636       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12637       _G.debugLine = 1;
12638       if (IS_STATIC (currFunc->etype))
12639         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12640       else
12641         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12642       _G.debugLine = 0;
12643     }
12644   /* stack pointer name */
12645   if (options.useXstack)
12646     spname = "_spx";
12647   else
12648     spname = "sp";
12649
12650
12651   for (ic = lic; ic; ic = ic->next)
12652     {
12653
12654       if (ic->lineno && cln != ic->lineno)
12655         {
12656           if (options.debug)
12657             {
12658               _G.debugLine = 1;
12659               emitcode ("", "C$%s$%d$%d$%d ==.",
12660                         FileBaseName (ic->filename), ic->lineno,
12661                         ic->level, ic->block);
12662               _G.debugLine = 0;
12663             }
12664           if (!options.noCcodeInAsm) {
12665             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12666                       printCLine(ic->filename, ic->lineno));
12667           }
12668           cln = ic->lineno;
12669         }
12670       if (options.iCodeInAsm) {
12671         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12672       }
12673       /* if the result is marked as
12674          spilt and rematerializable or code for
12675          this has already been generated then
12676          do nothing */
12677       if (resultRemat (ic) || ic->generated)
12678         continue;
12679
12680       /* depending on the operation */
12681       switch (ic->op)
12682         {
12683         case '!':
12684           genNot (ic);
12685           break;
12686
12687         case '~':
12688           genCpl (ic);
12689           break;
12690
12691         case UNARYMINUS:
12692           genUminus (ic);
12693           break;
12694
12695         case IPUSH:
12696           genIpush (ic);
12697           break;
12698
12699         case IPOP:
12700           /* IPOP happens only when trying to restore a
12701              spilt live range, if there is an ifx statement
12702              following this pop then the if statement might
12703              be using some of the registers being popped which
12704              would destory the contents of the register so
12705              we need to check for this condition and handle it */
12706           if (ic->next &&
12707               ic->next->op == IFX &&
12708               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12709             genIfx (ic->next, ic);
12710           else
12711             genIpop (ic);
12712           break;
12713
12714         case CALL:
12715           genCall (ic);
12716           break;
12717
12718         case PCALL:
12719           genPcall (ic);
12720           break;
12721
12722         case FUNCTION:
12723           genFunction (ic);
12724           break;
12725
12726         case ENDFUNCTION:
12727           genEndFunction (ic);
12728           break;
12729
12730         case RETURN:
12731           genRet (ic);
12732           break;
12733
12734         case LABEL:
12735           genLabel (ic);
12736           break;
12737
12738         case GOTO:
12739           genGoto (ic);
12740           break;
12741
12742         case '+':
12743           genPlus (ic);
12744           break;
12745
12746         case '-':
12747           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12748             genMinus (ic);
12749           break;
12750
12751         case '*':
12752           genMult (ic);
12753           break;
12754
12755         case '/':
12756           genDiv (ic);
12757           break;
12758
12759         case '%':
12760           genMod (ic);
12761           break;
12762
12763         case '>':
12764           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12765           break;
12766
12767         case '<':
12768           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12769           break;
12770
12771         case LE_OP:
12772         case GE_OP:
12773         case NE_OP:
12774
12775           /* note these two are xlated by algebraic equivalence
12776              during parsing SDCC.y */
12777           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12778                   "got '>=' or '<=' shouldn't have come here");
12779           break;
12780
12781         case EQ_OP:
12782           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12783           break;
12784
12785         case AND_OP:
12786           genAndOp (ic);
12787           break;
12788
12789         case OR_OP:
12790           genOrOp (ic);
12791           break;
12792
12793         case '^':
12794           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12795           break;
12796
12797         case '|':
12798           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12799           break;
12800
12801         case BITWISEAND:
12802           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12803           break;
12804
12805         case INLINEASM:
12806           genInline (ic);
12807           break;
12808
12809         case RRC:
12810           genRRC (ic);
12811           break;
12812
12813         case RLC:
12814           genRLC (ic);
12815           break;
12816
12817         case GETHBIT:
12818           genGetHbit (ic);
12819           break;
12820
12821         case LEFT_OP:
12822           genLeftShift (ic);
12823           break;
12824
12825         case RIGHT_OP:
12826           genRightShift (ic);
12827           break;
12828
12829         case GET_VALUE_AT_ADDRESS:
12830           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12831           break;
12832
12833         case '=':
12834           if (POINTER_SET (ic))
12835             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12836           else
12837             genAssign (ic);
12838           break;
12839
12840         case IFX:
12841           genIfx (ic, NULL);
12842           break;
12843
12844         case ADDRESS_OF:
12845           genAddrOf (ic);
12846           break;
12847
12848         case JUMPTABLE:
12849           genJumpTab (ic);
12850           break;
12851
12852         case CAST:
12853           genCast (ic);
12854           break;
12855
12856         case RECEIVE:
12857           genReceive (ic);
12858           break;
12859
12860         case SEND:
12861           if (ic->builtinSEND) genBuiltIn(ic);
12862           else addSet (&_G.sendSet, ic);
12863           break;
12864
12865         case ARRAYINIT:
12866             genArrayInit(ic);
12867             break;
12868             
12869         default:
12870           ic = ic;
12871         }
12872     }
12873
12874
12875   /* now we are ready to call the
12876      peep hole optimizer */
12877   if (!options.nopeep)
12878     peepHole (&lineHead);
12879
12880   /* now do the actual printing */
12881   printLine (lineHead, codeOutFile);
12882   return;
12883 }