* src/ds390/gen.c: added missing #include "main.h"
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "main.h"
35 #include "ralloc.h"
36 #include "gen.h"
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #define BETTER_LITERAL_SHIFT
41
42 char *aopLiteral (value * val, int offset);
43 extern int allocInfo;
44
45 /* this is the down and dirty file with all kinds of
46    kludgy & hacky stuff. This is what it is all about
47    CODE GENERATION for a specific MCU . some of the
48    routines may be reusable, will have to see */
49
50 static char *zero = "#0";
51 static char *one = "#1";
52 static char *spname;
53
54 #define D(x) x
55
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58
59 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
66 {"a", "b"};
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
70
71 static struct
72   {
73     short r0Pushed;
74     short r1Pushed;
75     short accInUse;
76     short bInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     short dptrInUse;
81     short dptr1InUse;
82     set *sendSet;
83     iCode *current_iCode;
84   }
85 _G;
86
87 static char *rb1regs[] = {
88     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 };
90
91 static void saveRBank (int, iCode *, bool);
92
93 #define RESULTONSTACK(x) \
94                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
95                          IC_RESULT(x)->aop->type == AOP_STK )
96
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
99                 
100 #define CLRC    emitcode("clr","c")
101 #define SETC    emitcode("setb","c")
102
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG  "_ap"
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112  0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115  0x07, 0x03, 0x01, 0x00};
116
117 #define LSB     0
118 #define MSB16   1
119 #define MSB24   2
120 #define MSB32   3
121 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
122                                 symbol *lbl = newiTempLabel(NULL);              \
123                                 emitcode ("setb","F1");                         \
124                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
125                                 emitcode ("clr","F1");                          \
126                                 emitcode ("","!tlabeldef",lbl->key+100);        \
127                         }}
128 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
129                                 symbol *lbl = newiTempLabel(NULL);              \
130                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
131                                 emitcode ("setb","EA");                         \
132                                 emitcode ("","!tlabeldef",lbl->key+100);        \
133                         }}
134
135 static int _currentDPS;         /* Current processor DPS. */
136 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
138
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple    */
141 /*-----------------------------------------------------------------*/
142 static void
143 emitcode (char *inst, char *fmt,...)
144 {
145     va_list ap;
146     char lb[INITIAL_INLINEASM];
147     char *lbp = lb;
148     
149     va_start (ap, fmt);
150     
151     if (inst && *inst)
152     {
153         if (fmt && *fmt)
154         {
155             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
156         }
157         else
158         {
159             SNPRINTF (lb, sizeof(lb), "%s", inst);
160         }
161         
162         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
163                    fmt, ap);
164     }
165     else
166     {
167         tvsprintf (lb, sizeof(lb), fmt, ap);
168     }
169     
170
171     while (isspace (*lbp))
172     {
173         lbp++;
174     }
175
176     if (lbp && *lbp)
177     {
178         lineCurr = (lineCurr ?
179                     connectLine (lineCurr, newLineNode (lb)) :
180                     (lineHead = newLineNode (lb)));
181     }
182     
183     lineCurr->isInline = _G.inLine;
184     lineCurr->isDebug = _G.debugLine;
185     lineCurr->ic = _G.current_iCode;
186     lineCurr->aln = ds390newAsmLineNode(_currentDPS);
187     va_end (ap);
188 }
189
190 //
191 // Move the passed value into A unless it is already there.
192 // 
193 static void
194 _movA(const char *s)
195 {
196     if (strcmp(s,"a") && strcmp(s,"acc"))
197     { 
198         emitcode("mov","a,%s",s);
199     } 
200 }
201
202 //
203 // Move the passed value into B unless it is already there.
204 // 
205 static void
206 _movB(const char *s)
207 {
208     if (strcmp(s,"b"))
209     { 
210         emitcode("mov","b,%s",s);
211     } 
212 }
213
214 /*-----------------------------------------------------------------*/
215 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
216 /*-----------------------------------------------------------------*/
217 static regs *
218 getFreePtr (iCode * ic, asmop ** aopp, bool result)
219 {
220   bool r0iu, r1iu;
221   bool r0ou, r1ou;
222
223   /* the logic: if r0 & r1 used in the instruction
224      then we are in trouble otherwise */
225
226   /* first check if r0 & r1 are used by this
227      instruction, in which case we are in trouble */
228   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
229   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
230   if (r0iu && r1iu) {
231       goto endOfWorld;
232     }
233
234   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
235   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
236
237   /* if no usage of r0 then return it */
238   if (!r0iu && !r0ou)
239     {
240       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
241       (*aopp)->type = AOP_R0;
242
243       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
244     }
245
246   /* if no usage of r1 then return it */
247   if (!r1iu && !r1ou)
248     {
249       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
250       (*aopp)->type = AOP_R1;
251
252       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
253     }
254
255   /* now we know they both have usage */
256   /* if r0 not used in this instruction */
257   if (!r0iu)
258     {
259       /* push it if not already pushed */
260       if (!_G.r0Pushed)
261         {
262           emitcode ("push", "%s",
263                     ds390_regWithIdx (R0_IDX)->dname);
264           _G.r0Pushed++;
265         }
266
267       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
268       (*aopp)->type = AOP_R0;
269
270       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
271     }
272
273   /* if r1 not used then */
274
275   if (!r1iu)
276     {
277       /* push it if not already pushed */
278       if (!_G.r1Pushed)
279         {
280           emitcode ("push", "%s",
281                     ds390_regWithIdx (R1_IDX)->dname);
282           _G.r1Pushed++;
283         }
284
285       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
286       (*aopp)->type = AOP_R1;
287       return ds390_regWithIdx (R1_IDX);
288     }
289
290 endOfWorld:
291   /* I said end of world but not quite end of world yet */
292   /* if this is a result then we can push it on the stack */
293   if (result)
294     {
295       (*aopp)->type = AOP_STK;
296       return NULL;
297     }
298
299   /* other wise this is true end of the world */
300   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
301           "getFreePtr should never reach here");
302   exit (1);
303     
304   return NULL; // notreached, but makes compiler happy.
305 }
306
307 /*-----------------------------------------------------------------*/
308 /* newAsmop - creates a new asmOp                                  */
309 /*-----------------------------------------------------------------*/
310 static asmop *
311 newAsmop (short type)
312 {
313   asmop *aop;
314
315   aop = Safe_calloc (1, sizeof (asmop));
316   aop->type = type;
317   return aop;
318 }
319
320
321 /*-----------------------------------------------------------------*/
322 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
323 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
324 /* alternate DPTR (DPL1/DPH1/DPX1).          */
325 /*-----------------------------------------------------------------*/
326 static void
327 genSetDPTR (int n)
328 {
329
330   /* If we are doing lazy evaluation, simply note the desired
331    * change, but don't emit any code yet.
332    */
333   if (_lazyDPS)
334     {
335       _desiredDPS = n;
336       return;
337     }
338
339   if (!n)
340     {
341       emitcode ("mov", "dps,#0");
342     }
343   else
344     {
345       TR_DPTR("#1");
346       emitcode ("mov", "dps,#1");
347     }
348 }
349
350 /*-----------------------------------------------------------------*/
351 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
352 /*                   */
353 /* Any code that operates on DPTR (NB: not on the individual     */
354 /* components, like DPH) *must* call _flushLazyDPS() before using  */
355 /* DPTR within a lazy DPS evaluation block.        */
356 /*                   */
357 /* Note that aopPut and aopGet already contain the proper calls to */
358 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
359 /* DPS evaluation block.             */
360 /*                   */
361 /* Also, _flushLazyDPS must be called before any flow control      */
362 /* operations that could potentially branch out of the block.    */
363 /*                         */
364 /* Lazy DPS evaluation is simply an optimization (though an      */
365 /* important one), so if in doubt, leave it out.       */
366 /*-----------------------------------------------------------------*/
367 static void
368 _startLazyDPSEvaluation (void)
369 {
370   _currentDPS = 0;
371   _desiredDPS = 0;
372 #ifdef BETTER_LITERAL_SHIFT  
373   _lazyDPS++;
374 #else
375   _lazyDPS = 1;
376 #endif  
377 }
378
379 /*-----------------------------------------------------------------*/
380 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
381 /* desired one. Call before using DPTR within a lazy DPS evaluation */
382 /* block.                */
383 /*-----------------------------------------------------------------*/
384 static void
385 _flushLazyDPS (void)
386 {
387   if (!_lazyDPS)
388     {
389       /* nothing to do. */
390       return;
391     }
392
393   if (_desiredDPS != _currentDPS)
394     {
395       if (_desiredDPS)
396         {
397           emitcode ("inc", "dps");
398         }
399       else
400         {
401           emitcode ("dec", "dps");
402         }
403       _currentDPS = _desiredDPS;
404     }
405 }
406
407 /*-----------------------------------------------------------------*/
408 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
409 /*                   */
410 /* Forces us back to the safe state (standard DPTR selected).    */
411 /*-----------------------------------------------------------------*/
412 static void
413 _endLazyDPSEvaluation (void)
414 {
415 #ifdef BETTER_LITERAL_SHIFT  
416   _lazyDPS--;
417 #else
418   _lazyDPS = 0;
419 #endif    
420   if (!_lazyDPS)
421   {
422     if (_currentDPS)
423     {
424       genSetDPTR (0);
425       _flushLazyDPS ();
426     }
427     _currentDPS = 0;
428     _desiredDPS = 0;
429   }
430 }
431
432
433
434 /*-----------------------------------------------------------------*/
435 /* pointerCode - returns the code for a pointer type               */
436 /*-----------------------------------------------------------------*/
437 static int
438 pointerCode (sym_link * etype)
439 {
440
441   return PTR_TYPE (SPEC_OCLS (etype));
442
443 }
444
445 /*-----------------------------------------------------------------*/
446 /* leftRightUseAcc - returns size of accumulator use by operands   */
447 /*-----------------------------------------------------------------*/
448 static int
449 leftRightUseAcc(iCode *ic)
450 {
451   operand *op;
452   int size;
453   int accuseSize = 0;
454   int accuse = 0;
455   
456   if (!ic)
457     {
458       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
459               "null iCode pointer");
460       return 0;
461     }
462
463   if (ic->op == IFX)
464     {
465       op = IC_COND (ic);
466       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
467         {
468           accuse = 1;
469           size = getSize (OP_SYMBOL (op)->type);
470           if (size>accuseSize)
471             accuseSize = size;
472         }
473     }
474   else if (ic->op == JUMPTABLE)
475     {
476       op = IC_JTCOND (ic);
477       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
478         {
479           accuse = 1;
480           size = getSize (OP_SYMBOL (op)->type);
481           if (size>accuseSize)
482             accuseSize = size;
483         }
484     }
485   else
486     {
487       op = IC_LEFT (ic);
488       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
489         {
490           accuse = 1;
491           size = getSize (OP_SYMBOL (op)->type);
492           if (size>accuseSize)
493             accuseSize = size;
494         }
495       op = IC_RIGHT (ic);
496       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
497         {
498           accuse = 1;
499           size = getSize (OP_SYMBOL (op)->type);
500           if (size>accuseSize)
501             accuseSize = size;
502         }
503     }
504   
505   if (accuseSize)
506     return accuseSize;
507   else
508     return accuse;
509 }
510
511 /*-----------------------------------------------------------------*/
512 /* aopForSym - for a true symbol                                   */
513 /*-----------------------------------------------------------------*/
514 static asmop *
515 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
516 {
517   asmop *aop;
518   memmap *space = SPEC_OCLS (sym->etype);
519   int accuse = leftRightUseAcc (ic);
520
521   /* if already has one */
522   if (sym->aop)
523     {
524       if ((sym->aop->type == AOP_DPTR && useDP2)
525           || (sym->aop->type == AOP_DPTR2 && !useDP2))
526         sym->aop = NULL;
527       else
528         return sym->aop;
529     }
530
531   /* assign depending on the storage class */
532   /* if it is on the stack or indirectly addressable */
533   /* space we need to assign either r0 or r1 to it   */
534   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
535     {
536       sym->aop = aop = newAsmop (0);
537       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
538       aop->size = getSize (sym->type);
539
540       /* now assign the address of the variable to
541          the pointer register */
542       if (aop->type != AOP_STK)
543         {
544
545           if (sym->onStack)
546             {
547               if (_G.accInUse || accuse)
548                 emitcode ("push", "acc");
549
550               if (_G.bInUse || (accuse>1))
551                 emitcode ("push", "b");
552
553               emitcode ("mov", "a,_bp");
554               emitcode ("add", "a,#!constbyte",
555                         ((sym->stack < 0) ?
556                          ((char) (sym->stack - _G.nRegsSaved)) :
557                          ((char) sym->stack)) & 0xff);
558               emitcode ("mov", "%s,a",
559                         aop->aopu.aop_ptr->name);
560
561               if (_G.bInUse || (accuse>1))
562                 emitcode ("pop", "b");
563
564               if (_G.accInUse || accuse)
565                 emitcode ("pop", "acc");
566             }
567           else
568             emitcode ("mov", "%s,#%s",
569                       aop->aopu.aop_ptr->name,
570                       sym->rname);
571           aop->paged = space->paged;
572         }
573       else
574         aop->aopu.aop_stk = sym->stack;
575       return aop;
576     }
577
578   if (sym->onStack && options.stack10bit)
579     {
580         short stack_val = -((sym->stack < 0) ?
581                             ((short) (sym->stack - _G.nRegsSaved)) :
582                             ((short) sym->stack)) ;
583         if (useDP2 && _G.dptr1InUse) {
584             emitcode ("push","dpl1");
585             emitcode ("push","dph1");
586             emitcode ("push","dpx1");
587         } else if (_G.dptrInUse ) {
588             emitcode ("push","dpl");
589             emitcode ("push","dph");
590             emitcode ("push","dpx");
591         }
592       /* It's on the 10 bit stack, which is located in
593        * far data space.
594        */           
595         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
596             if (useDP2) {
597                 if (options.model == MODEL_FLAT24)
598                 {
599                     emitcode ("mov", "dpx1,#!constbyte",
600                               (options.stack_loc >> 16) & 0xff);
601                 }
602                 emitcode ("mov", "dph1,_bpx+1");
603                 
604                 emitcode ("mov", "dpl1,_bpx");
605                 emitcode ("mov","dps,#1");
606             } else {
607                 if (options.model == MODEL_FLAT24)
608                 {
609                     emitcode ("mov", "dpx,#!constbyte",
610                               (options.stack_loc >> 16) & 0xff);
611                 }
612                 emitcode ("mov", "dph,_bpx+1");
613                 emitcode ("mov", "dpl,_bpx");
614             }
615             stack_val = -stack_val;
616             while (stack_val--) {
617                 emitcode ("inc","dptr");
618             }
619             if (useDP2) {
620                 emitcode("mov","dps,#0");
621             }
622         }  else {
623             if (_G.accInUse || accuse)
624                 emitcode ("push", "acc");
625             
626             if (_G.bInUse || (accuse>1))
627                 emitcode ("push", "b");
628         
629             emitcode ("mov", "a,_bpx");
630             emitcode ("clr","c");
631             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
632             emitcode ("mov","b,a");
633             emitcode ("mov","a,_bpx+1");
634             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
635             if (useDP2) {
636                 if (options.model == MODEL_FLAT24)
637                 {
638                     emitcode ("mov", "dpx1,#!constbyte",
639                               (options.stack_loc >> 16) & 0xff);
640                 }
641                 emitcode ("mov", "dph1,a");
642                 emitcode ("mov", "dpl1,b");
643             } else {
644                 if (options.model == MODEL_FLAT24)
645                 {
646                     emitcode ("mov", "dpx,#!constbyte",
647                               (options.stack_loc >> 16) & 0xff);
648                 }
649                 emitcode ("mov", "dph,a");
650                 emitcode ("mov", "dpl,b");
651             }
652             
653             if (_G.bInUse || (accuse>1))
654                 emitcode ("pop", "b");
655             
656             if (_G.accInUse || accuse)
657                 emitcode ("pop", "acc");
658         }
659         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
660         aop->size = getSize (sym->type);
661         return aop;
662     }
663
664   /* if in bit space */
665   if (IN_BITSPACE (space))
666     {
667       sym->aop = aop = newAsmop (AOP_CRY);
668       aop->aopu.aop_dir = sym->rname;
669       aop->size = getSize (sym->type);
670       return aop;
671     }
672   /* if it is in direct space */
673   if (IN_DIRSPACE (space))
674     {
675       sym->aop = aop = newAsmop (AOP_DIR);
676       aop->aopu.aop_dir = sym->rname;
677       aop->size = getSize (sym->type);
678       return aop;
679     }
680
681   /* special case for a function */
682   if (IS_FUNC (sym->type) && !(sym->isitmp))
683     {
684       sym->aop = aop = newAsmop (AOP_IMMD);
685       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
686       aop->size = FPTRSIZE;
687       return aop;
688     }
689
690   /* only remaining is far space */
691   /* in which case DPTR gets the address */
692   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
693   if (useDP2)
694     {
695       genSetDPTR (1);
696       _flushLazyDPS ();
697       emitcode ("mov", "dptr,#%s", sym->rname);
698       genSetDPTR (0);
699     }
700   else
701     {
702       emitcode ("mov", "dptr,#%s", sym->rname);
703     }
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type =0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = DCL_TYPE(from_type);
735               if (ptr_type == IPOINTER) {
736                 // bug #481053
737                 ptr_type = POINTER;
738               }
739               continue ;
740       } else break;
741       
742       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743     }
744
745   if (val)
746   {
747       SNPRINTF (buffer, sizeof(buffer),
748                 "(%s %c 0x%04x)",
749                 OP_SYMBOL (IC_LEFT (ic))->rname,
750                 val >= 0 ? '+' : '-',
751                 abs (val) & 0xffffff);
752   }
753   else 
754   {
755       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
756       {
757           SNPRINTF(buffer, sizeof(buffer), 
758                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
759       }
760       else
761       {
762           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
763       }
764   }
765
766   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
767   /* set immd2 field if required */
768   if (aop->aopu.aop_immd.from_cast_remat) 
769   {
770       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
771       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
772   }
773
774   return aop;
775 }
776
777 /*-----------------------------------------------------------------*/
778 /* aopHasRegs - returns true if aop has regs between from-to       */
779 /*-----------------------------------------------------------------*/
780 static int aopHasRegs(asmop *aop, int from, int to)
781 {
782     int size =0;
783
784     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
785
786     for (; size < aop->size ; size++) {
787         int reg;
788         for (reg = from ; reg <= to ; reg++)
789             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
790     }
791     return 0;
792 }
793
794 /*-----------------------------------------------------------------*/
795 /* regsInCommon - two operands have some registers in common       */
796 /*-----------------------------------------------------------------*/
797 static bool
798 regsInCommon (operand * op1, operand * op2)
799 {
800   symbol *sym1, *sym2;
801   int i;
802
803   /* if they have registers in common */
804   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
805     return FALSE;
806
807   sym1 = OP_SYMBOL (op1);
808   sym2 = OP_SYMBOL (op2);
809
810   if (sym1->nRegs == 0 || sym2->nRegs == 0)
811     return FALSE;
812
813   for (i = 0; i < sym1->nRegs; i++)
814     {
815       int j;
816       if (!sym1->regs[i])
817         continue;
818
819       for (j = 0; j < sym2->nRegs; j++)
820         {
821           if (!sym2->regs[j])
822             continue;
823
824           if (sym2->regs[j] == sym1->regs[i])
825             return TRUE;
826         }
827     }
828
829   return FALSE;
830 }
831
832 /*-----------------------------------------------------------------*/
833 /* operandsEqu - equivalent                                        */
834 /*-----------------------------------------------------------------*/
835 static bool
836 operandsEqu (operand * op1, operand * op2)
837 {
838   symbol *sym1, *sym2;
839
840   /* if they not symbols */
841   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
842     return FALSE;
843
844   sym1 = OP_SYMBOL (op1);
845   sym2 = OP_SYMBOL (op2);
846
847   /* if both are itemps & one is spilt
848      and the other is not then false */
849   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
850       sym1->isspilt != sym2->isspilt)
851     return FALSE;
852
853   /* if they are the same */
854   if (sym1 == sym2)
855     return TRUE;
856
857   if (strcmp (sym1->rname, sym2->rname) == 0)
858     return TRUE;
859
860
861   /* if left is a tmp & right is not */
862   if (IS_ITEMP (op1) &&
863       !IS_ITEMP (op2) &&
864       sym1->isspilt &&
865       (sym1->usl.spillLoc == sym2))
866     return TRUE;
867
868   if (IS_ITEMP (op2) &&
869       !IS_ITEMP (op1) &&
870       sym2->isspilt &&
871       sym1->level > 0 &&
872       (sym2->usl.spillLoc == sym1))
873     return TRUE;
874
875   /* are they spilt to the same location */
876   if (IS_ITEMP (op2) &&
877       IS_ITEMP (op1) &&
878       sym2->isspilt &&
879       sym1->isspilt &&
880       (sym1->usl.spillLoc == sym2->usl.spillLoc))
881     return TRUE;
882     
883   return FALSE;
884 }
885
886 /*-----------------------------------------------------------------*/
887 /* sameRegs - two asmops have the same registers                   */
888 /*-----------------------------------------------------------------*/
889 static bool
890 sameRegs (asmop * aop1, asmop * aop2)
891 {
892   int i;
893
894   if (aop1 == aop2)
895     {
896       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
897         {
898           return FALSE;
899         }
900       return TRUE;
901     }
902
903   if (aop1->type != AOP_REG ||
904       aop2->type != AOP_REG)
905     return FALSE;
906
907   if (aop1->size != aop2->size)
908     return FALSE;
909
910   for (i = 0; i < aop1->size; i++)
911     if (aop1->aopu.aop_reg[i] !=
912         aop2->aopu.aop_reg[i])
913       return FALSE;
914
915   return TRUE;
916 }
917
918 /*-----------------------------------------------------------------*/
919 /* aopOp - allocates an asmop for an operand  :                    */
920 /*-----------------------------------------------------------------*/
921 static void
922 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
923 {
924   asmop *aop;
925   symbol *sym;
926   int i;
927
928   if (!op)
929     return;
930
931   /* if this a literal */
932   if (IS_OP_LITERAL (op))
933     {
934       op->aop = aop = newAsmop (AOP_LIT);
935       aop->aopu.aop_lit = op->operand.valOperand;
936       aop->size = getSize (operandType (op));
937       return;
938     }
939
940   /* if already has a asmop then continue */
941   if (op->aop)
942     {
943       if ((op->aop->type == AOP_DPTR && useDP2)
944           || (op->aop->type == AOP_DPTR2 && !useDP2))
945         op->aop = NULL;
946       else
947         return;
948     }
949
950   /* if the underlying symbol has a aop */
951   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
952     {
953       op->aop = OP_SYMBOL (op)->aop;
954       if ((op->aop->type == AOP_DPTR && useDP2)
955           || (op->aop->type == AOP_DPTR2 && !useDP2))
956         op->aop = NULL;
957       else
958         return;
959     }
960
961   /* if this is a true symbol */
962   if (IS_TRUE_SYMOP (op))
963     {
964       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
965       return;
966     }
967
968   /* this is a temporary : this has
969      only four choices :
970      a) register
971      b) spillocation
972      c) rematerialize
973      d) conditional
974      e) can be a return use only */
975
976   sym = OP_SYMBOL (op);
977
978
979   /* if the type is a conditional */
980   if (sym->regType == REG_CND)
981     {
982       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
983       aop->size = 0;
984       return;
985     }
986
987   /* if it is spilt then two situations
988      a) is rematerialize
989      b) has a spill location */
990   if (sym->isspilt || sym->nRegs == 0)
991     {
992
993       /* rematerialize it NOW */
994       if (sym->remat)
995         {
996           sym->aop = op->aop = aop =
997             aopForRemat (sym);
998           aop->size = getSize (sym->type);
999           return;
1000         }
1001
1002       if (sym->accuse)
1003         {
1004           int i;
1005           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1006           aop->size = getSize (sym->type);
1007           for (i = 0; i < 2; i++)
1008             aop->aopu.aop_str[i] = accUse[i];
1009           return;
1010         }
1011
1012       if (sym->ruonly)
1013         {
1014           int i;
1015
1016           if (useDP2)
1017             {
1018               /* a AOP_STR uses DPTR, but DPTR is already in use;
1019                * we're just hosed.
1020                */
1021                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1022             }
1023
1024           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1025           aop->size = getSize (sym->type);
1026           for (i = 0; i < (int) fReturnSizeDS390; i++)
1027             aop->aopu.aop_str[i] = fReturn[i];
1028           return;
1029         }
1030       
1031       if (sym->dptr) { /* has been allocated to a DPTRn */
1032           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1033           aop->size = getSize (sym->type);
1034           aop->aopu.dptr = sym->dptr;
1035           return ;
1036       }
1037       
1038       if (sym->usl.spillLoc)
1039         {
1040           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1041             {
1042               /* force a new aop if sizes differ */
1043               sym->usl.spillLoc->aop = NULL;
1044             }
1045           sym->aop = op->aop = aop =
1046                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1047           aop->size = getSize (sym->type);
1048           return;
1049         }
1050       
1051       /* else must be a dummy iTemp */
1052       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1053       aop->size = getSize (sym->type);
1054       return;
1055     }
1056
1057   /* must be in a register */
1058   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1059   aop->size = sym->nRegs;
1060   for (i = 0; i < sym->nRegs; i++)
1061     aop->aopu.aop_reg[i] = sym->regs[i];
1062 }
1063
1064 /*-----------------------------------------------------------------*/
1065 /* freeAsmop - free up the asmop given to an operand               */
1066 /*----------------------------------------------------------------*/
1067 static void
1068 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1069 {
1070   asmop *aop;
1071
1072   if (!op)
1073     aop = aaop;
1074   else
1075     aop = op->aop;
1076
1077   if (!aop)
1078     return;
1079
1080   if (aop->freed)
1081     goto dealloc;
1082
1083   aop->freed = 1;
1084
1085   /* depending on the asmop type only three cases need work AOP_RO
1086      , AOP_R1 && AOP_STK */
1087   switch (aop->type)
1088     {
1089     case AOP_R0:
1090       if (_G.r0Pushed)
1091         {
1092           if (pop)
1093             {
1094               emitcode ("pop", "ar0");
1095               _G.r0Pushed--;
1096             }
1097         }
1098       bitVectUnSetBit (ic->rUsed, R0_IDX);
1099       break;
1100
1101     case AOP_R1:
1102       if (_G.r1Pushed)
1103         {
1104           if (pop)
1105             {
1106               emitcode ("pop", "ar1");
1107               _G.r1Pushed--;
1108             }
1109         }
1110       bitVectUnSetBit (ic->rUsed, R1_IDX);
1111       break;
1112
1113     case AOP_STK:
1114       {
1115         int sz = aop->size;
1116         int stk = aop->aopu.aop_stk + aop->size;
1117         bitVectUnSetBit (ic->rUsed, R0_IDX);
1118         bitVectUnSetBit (ic->rUsed, R1_IDX);
1119
1120         getFreePtr (ic, &aop, FALSE);
1121
1122         if (options.stack10bit)
1123           {
1124             /* I'm not sure what to do here yet... */
1125             /* #STUB */
1126             fprintf (stderr,
1127                      "*** Warning: probably generating bad code for "
1128                      "10 bit stack mode.\n");
1129           }
1130
1131         if (stk)
1132           {
1133             emitcode ("mov", "a,_bp");
1134             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1135             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1136           }
1137         else
1138           {
1139             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1140           }
1141
1142         while (sz--)
1143           {
1144             emitcode ("pop", "acc");
1145             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1146             if (!sz)
1147               break;
1148             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1149           }
1150         op->aop = aop;
1151         freeAsmop (op, NULL, ic, TRUE);
1152         if (_G.r0Pushed)
1153           {
1154             emitcode ("pop", "ar0");
1155             _G.r0Pushed--;
1156           }
1157
1158         if (_G.r1Pushed)
1159           {
1160             emitcode ("pop", "ar1");
1161             _G.r1Pushed--;
1162           }
1163       }
1164     case AOP_DPTR2:
1165         if (_G.dptr1InUse) {
1166             emitcode ("pop","dpx1");
1167             emitcode ("pop","dph1");
1168             emitcode ("pop","dpl1");
1169         }
1170         break;
1171     case AOP_DPTR:
1172         if (_G.dptrInUse) {
1173             emitcode ("pop","dpx");
1174             emitcode ("pop","dph");
1175             emitcode ("pop","dpl");
1176         }
1177         break;
1178     }
1179 dealloc:
1180   /* all other cases just dealloc */
1181   if (op)
1182     {
1183       op->aop = NULL;
1184       if (IS_SYMOP (op))
1185         {
1186           OP_SYMBOL (op)->aop = NULL;
1187           /* if the symbol has a spill */
1188           if (SPIL_LOC (op))
1189             SPIL_LOC (op)->aop = NULL;
1190         }
1191     }
1192 }
1193
1194 #define DEFAULT_ACC_WARNING 0
1195 static int saveAccWarn = DEFAULT_ACC_WARNING;
1196
1197 /*-------------------------------------------------------------------*/
1198 /* aopGet - for fetching value of the aop                            */
1199 /*                                                                   */
1200 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1201 /* in the accumulator. Set it to the name of a free register         */
1202 /* if acc must be preserved; the register will be used to preserve   */
1203 /* acc temporarily and to return the result byte.                    */
1204 /*-------------------------------------------------------------------*/
1205
1206 static char *
1207 aopGet (asmop *aop,
1208         int   offset,
1209         bool  bit16,
1210         bool  dname,
1211         char  *saveAcc)
1212 {
1213   /* offset is greater than
1214      size then zero */
1215   if (offset > (aop->size - 1) &&
1216       aop->type != AOP_LIT)
1217     return zero;
1218
1219   /* depending on type */
1220   switch (aop->type)
1221     {
1222     case AOP_DUMMY:
1223       return zero;
1224
1225     case AOP_R0:
1226     case AOP_R1:
1227       /* if we need to increment it */
1228       while (offset > aop->coff)
1229         {
1230           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1231           aop->coff++;
1232         }
1233
1234       while (offset < aop->coff)
1235         {
1236           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1237           aop->coff--;
1238         }
1239
1240       aop->coff = offset;
1241       if (aop->paged)
1242         {
1243           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1244           return (dname ? "acc" : "a");
1245         }
1246       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1247       return Safe_strdup(buffer);       
1248
1249     case AOP_DPTRn:
1250         assert(offset <= 3);
1251         return dptrn[aop->aopu.dptr][offset];
1252
1253     case AOP_DPTR:
1254     case AOP_DPTR2:
1255
1256       if (aop->type == AOP_DPTR2)
1257         {
1258           genSetDPTR (1);
1259         }
1260         
1261       if (saveAcc)
1262         {
1263             TR_AP("#1");
1264 //          if (aop->type != AOP_DPTR2)
1265 //          {
1266 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1267 //              emitcode(";", "spanky: saveAcc for DPTR");
1268 //          }
1269             
1270             emitcode ("xch", "a, %s", saveAcc);
1271         }
1272
1273       _flushLazyDPS ();
1274
1275       while (offset > aop->coff)
1276         {
1277           emitcode ("inc", "dptr");
1278           aop->coff++;
1279         }
1280
1281       while (offset < aop->coff)
1282         {
1283           emitcode ("lcall", "__decdptr");
1284           aop->coff--;
1285         }
1286
1287       aop->coff = offset;
1288       if (aop->code)
1289         {
1290           emitcode ("clr", "a");
1291           emitcode ("movc", "a,@a+dptr");
1292         }
1293       else
1294         {
1295           emitcode ("movx", "a,@dptr");
1296         }
1297
1298       if (aop->type == AOP_DPTR2)
1299         {
1300           genSetDPTR (0);
1301         }
1302         
1303         if (saveAcc)
1304         {
1305        TR_AP("#2");
1306               emitcode ("xch", "a, %s", saveAcc);
1307 //            if (strcmp(saveAcc, "_ap"))
1308 //            {
1309 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1310 //            }
1311                   
1312               return saveAcc;
1313         }
1314       return (dname ? "acc" : "a");
1315
1316     case AOP_IMMD:
1317       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1318       {
1319           SNPRINTF(buffer, sizeof(buffer), 
1320                    "%s",aop->aopu.aop_immd.aop_immd2);
1321       } 
1322       else if (bit16)
1323       {
1324          SNPRINTF(buffer, sizeof(buffer), 
1325                   "#%s", aop->aopu.aop_immd.aop_immd1);
1326       }
1327       else if (offset) 
1328       {
1329           switch (offset) {
1330           case 1:
1331               tsprintf(buffer, sizeof(buffer),
1332                        "#!his",aop->aopu.aop_immd.aop_immd1);
1333               break;
1334           case 2:
1335               tsprintf(buffer, sizeof(buffer), 
1336                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1337               break;
1338           case 3:
1339               tsprintf(buffer, sizeof(buffer),
1340                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1341               break;
1342           default: /* should not need this (just in case) */
1343               SNPRINTF (buffer, sizeof(buffer), 
1344                         "#(%s >> %d)",
1345                        aop->aopu.aop_immd.aop_immd1,
1346                        offset * 8);
1347           }
1348       }
1349       else
1350       {
1351         SNPRINTF (buffer, sizeof(buffer), 
1352                   "#%s", aop->aopu.aop_immd.aop_immd1);
1353       }
1354       return Safe_strdup(buffer);       
1355
1356     case AOP_DIR:
1357       if (offset)
1358       {
1359         SNPRINTF (buffer, sizeof(buffer),
1360                   "(%s + %d)",
1361                  aop->aopu.aop_dir,
1362                  offset);
1363       }
1364       else
1365       {
1366         SNPRINTF(buffer, sizeof(buffer), 
1367                  "%s", aop->aopu.aop_dir);
1368       }
1369
1370       return Safe_strdup(buffer);
1371
1372     case AOP_REG:
1373       if (dname)
1374         return aop->aopu.aop_reg[offset]->dname;
1375       else
1376         return aop->aopu.aop_reg[offset]->name;
1377
1378     case AOP_CRY:
1379       emitcode ("clr", "a");
1380       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1381       emitcode ("rlc", "a");
1382       return (dname ? "acc" : "a");
1383
1384     case AOP_ACC:
1385       if (!offset && dname)
1386         return "acc";
1387       return aop->aopu.aop_str[offset];
1388
1389     case AOP_LIT:
1390       return aopLiteral (aop->aopu.aop_lit, offset);
1391
1392     case AOP_STR:
1393       aop->coff = offset;
1394       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1395           dname)
1396         return "acc";
1397
1398       return aop->aopu.aop_str[offset];
1399
1400     }
1401
1402   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1403           "aopget got unsupported aop->type");
1404   exit (1);
1405     
1406   return NULL;  // not reached, but makes compiler happy.
1407 }
1408 /*-----------------------------------------------------------------*/
1409 /* aopPut - puts a string for a aop                                */
1410 /*-----------------------------------------------------------------*/
1411 static void
1412 aopPut (asmop * aop, char *s, int offset)
1413 {
1414   if (aop->size && offset > (aop->size - 1))
1415     {
1416       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1417               "aopPut got offset > aop->size");
1418       exit (1);
1419     }
1420
1421   /* will assign value to value */
1422   /* depending on where it is ofcourse */
1423   switch (aop->type)
1424     {
1425     case AOP_DUMMY:
1426       MOVA (s);         /* read s in case it was volatile */
1427       break;
1428       
1429     case AOP_DIR:
1430         if (offset)
1431         {
1432             SNPRINTF (buffer, sizeof(buffer),
1433                       "(%s + %d)",
1434                       aop->aopu.aop_dir, offset);
1435         }
1436         else
1437         {
1438             SNPRINTF (buffer, sizeof(buffer), 
1439                      "%s", aop->aopu.aop_dir);
1440         }
1441         
1442
1443         if (strcmp (buffer, s))
1444         {
1445             emitcode ("mov", "%s,%s", buffer, s);
1446         }
1447       break;
1448
1449     case AOP_REG:
1450       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1451           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1452         {
1453           if (*s == '@' ||
1454               strcmp (s, "r0") == 0 ||
1455               strcmp (s, "r1") == 0 ||
1456               strcmp (s, "r2") == 0 ||
1457               strcmp (s, "r3") == 0 ||
1458               strcmp (s, "r4") == 0 ||
1459               strcmp (s, "r5") == 0 ||
1460               strcmp (s, "r6") == 0 ||
1461               strcmp (s, "r7") == 0)
1462             {
1463                 emitcode ("mov", "%s,%s",
1464                           aop->aopu.aop_reg[offset]->dname, s);
1465             }
1466             else
1467             {
1468                 emitcode ("mov", "%s,%s",
1469                           aop->aopu.aop_reg[offset]->name, s);
1470             }
1471         }
1472       break;
1473
1474     case AOP_DPTRn:
1475         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1476         break;
1477
1478     case AOP_DPTR:
1479     case AOP_DPTR2:
1480
1481       if (aop->type == AOP_DPTR2)
1482         {
1483           genSetDPTR (1);
1484         }
1485       _flushLazyDPS ();
1486
1487       if (aop->code)
1488         {
1489           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1490                   "aopPut writting to code space");
1491           exit (1);
1492         }
1493
1494       while (offset > aop->coff)
1495         {
1496           aop->coff++;
1497           emitcode ("inc", "dptr");
1498         }
1499
1500       while (offset < aop->coff)
1501         {
1502           aop->coff--;
1503           emitcode ("lcall", "__decdptr");
1504         }
1505
1506       aop->coff = offset;
1507
1508       /* if not in accumulater */
1509       MOVA (s);
1510
1511       emitcode ("movx", "@dptr,a");
1512
1513       if (aop->type == AOP_DPTR2)
1514         {
1515           genSetDPTR (0);
1516         }
1517       break;
1518
1519     case AOP_R0:
1520     case AOP_R1:
1521       while (offset > aop->coff)
1522         {
1523           aop->coff++;
1524           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1525         }
1526       while (offset < aop->coff)
1527         {
1528           aop->coff--;
1529           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1530         }
1531       aop->coff = offset;
1532
1533       if (aop->paged)
1534         {
1535           MOVA (s);
1536           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1537
1538         }
1539       else if (*s == '@')
1540         {
1541           MOVA (s);
1542           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1543         }
1544       else if (strcmp (s, "r0") == 0 ||
1545                strcmp (s, "r1") == 0 ||
1546                strcmp (s, "r2") == 0 ||
1547                strcmp (s, "r3") == 0 ||
1548                strcmp (s, "r4") == 0 ||
1549                strcmp (s, "r5") == 0 ||
1550                strcmp (s, "r6") == 0 ||
1551                strcmp (s, "r7") == 0)
1552         {
1553           char buff[10];
1554           SNPRINTF(buff, sizeof(buff), 
1555                    "a%s", s);
1556           emitcode ("mov", "@%s,%s",
1557                     aop->aopu.aop_ptr->name, buff);
1558         }
1559         else
1560         {
1561             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1562         }
1563       break;
1564
1565     case AOP_STK:
1566       if (strcmp (s, "a") == 0)
1567         emitcode ("push", "acc");
1568       else
1569         if (*s=='@') {
1570           MOVA(s);
1571           emitcode ("push", "acc");
1572         } else {
1573           emitcode ("push", s);
1574         }
1575
1576       break;
1577
1578     case AOP_CRY:
1579       /* if bit variable */
1580       if (!aop->aopu.aop_dir)
1581         {
1582           emitcode ("clr", "a");
1583           emitcode ("rlc", "a");
1584         }
1585       else
1586         {
1587           if (s == zero)
1588             emitcode ("clr", "%s", aop->aopu.aop_dir);
1589           else if (s == one)
1590             emitcode ("setb", "%s", aop->aopu.aop_dir);
1591           else if (!strcmp (s, "c"))
1592             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1593           else
1594             {
1595               if (strcmp (s, "a"))
1596                 {
1597                   MOVA (s);
1598                 }
1599               {
1600                 /* set C, if a >= 1 */
1601                 emitcode ("add", "a,#!constbyte",0xff);
1602                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1603               }
1604             }
1605         }
1606       break;
1607
1608     case AOP_STR:
1609       aop->coff = offset;
1610       if (strcmp (aop->aopu.aop_str[offset], s))
1611         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1612       break;
1613
1614     case AOP_ACC:
1615       aop->coff = offset;
1616       if (!offset && (strcmp (s, "acc") == 0))
1617         break;
1618
1619       if (strcmp (aop->aopu.aop_str[offset], s))
1620         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1621       break;
1622
1623     default:
1624       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1625               "aopPut got unsupported aop->type");
1626       exit (1);
1627     }
1628
1629 }
1630
1631
1632 /*--------------------------------------------------------------------*/
1633 /* reAdjustPreg - points a register back to where it should (coff==0) */
1634 /*--------------------------------------------------------------------*/
1635 static void
1636 reAdjustPreg (asmop * aop)
1637 {
1638   if ((aop->coff==0) || (aop->size <= 1)) {
1639     return;
1640   }
1641
1642   switch (aop->type)
1643     {
1644     case AOP_R0:
1645     case AOP_R1:
1646       while (aop->coff--)
1647         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1648       break;
1649     case AOP_DPTR:
1650     case AOP_DPTR2:
1651       if (aop->type == AOP_DPTR2)
1652         {
1653           genSetDPTR (1);
1654           _flushLazyDPS ();
1655         }
1656       while (aop->coff--)
1657         {
1658           emitcode ("lcall", "__decdptr");
1659         }
1660
1661       if (aop->type == AOP_DPTR2)
1662         {
1663           genSetDPTR (0);
1664         }
1665       break;
1666
1667     }
1668   aop->coff=0;
1669 }
1670
1671 #define AOP(op) op->aop
1672 #define AOP_TYPE(op) AOP(op)->type
1673 #define AOP_SIZE(op) AOP(op)->size
1674 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1675                        AOP_TYPE(x) == AOP_R0))
1676
1677 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1678                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1679                          AOP(x)->paged))
1680
1681 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1682                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1683                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1684 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1685 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1686 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1687
1688 // The following two macros can be used even if the aop has not yet been aopOp'd.
1689 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1690 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1691
1692 /* Workaround for DS80C390 bug: div ab may return bogus results
1693  * if A is accessed in instruction immediately before the div.
1694  *
1695  * Will be fixed in B4 rev of processor, Dallas claims.
1696  */
1697
1698 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1699     if (!AOP_NEEDSACC(RIGHT))         \
1700     {               \
1701       /* We can load A first, then B, since     \
1702        * B (the RIGHT operand) won't clobber A,   \
1703        * thus avoiding touching A right before the div. \
1704        */             \
1705       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1706       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1707       MOVA(L);            \
1708       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1709       MOVB(L); \
1710     }               \
1711     else              \
1712     {               \
1713       /* Just stuff in a nop after loading A. */    \
1714       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1715       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1716       MOVA(L);            \
1717       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1718     }
1719
1720
1721 /*-----------------------------------------------------------------*/
1722 /* opIsGptr: returns non-zero if the passed operand is       */
1723 /* a generic pointer type.             */
1724 /*-----------------------------------------------------------------*/
1725 static int
1726 opIsGptr (operand * op)
1727 {
1728   sym_link *type = operandType (op);
1729
1730   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1731     {
1732       return 1;
1733     }
1734   return 0;
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* getDataSize - get the operand data size                         */
1739 /*-----------------------------------------------------------------*/
1740 static int
1741 getDataSize (operand * op)
1742 {
1743   int size;
1744   size = AOP_SIZE (op);
1745   if (size == GPTRSIZE)
1746     {
1747       sym_link *type = operandType (op);
1748       if (IS_GENPTR (type))
1749         {
1750           /* generic pointer; arithmetic operations
1751            * should ignore the high byte (pointer type).
1752            */
1753           size--;
1754         }
1755     }
1756   return size;
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* outAcc - output Acc                                             */
1761 /*-----------------------------------------------------------------*/
1762 static void
1763 outAcc (operand * result)
1764 {
1765   int size, offset;
1766   size = getDataSize (result);
1767   if (size)
1768     {
1769       aopPut (AOP (result), "a", 0);
1770       size--;
1771       offset = 1;
1772       /* unsigned or positive */
1773       while (size--)
1774         {
1775           aopPut (AOP (result), zero, offset++);
1776         }
1777     }
1778 }
1779
1780 /*-----------------------------------------------------------------*/
1781 /* outBitC - output a bit C                                        */
1782 /*-----------------------------------------------------------------*/
1783 static void
1784 outBitC (operand * result)
1785 {
1786   /* if the result is bit */
1787   if (AOP_TYPE (result) == AOP_CRY)
1788     {
1789       aopPut (AOP (result), "c", 0);
1790     }
1791   else
1792     {
1793       emitcode ("clr", "a");
1794       emitcode ("rlc", "a");
1795       outAcc (result);
1796     }
1797 }
1798
1799 /*-----------------------------------------------------------------*/
1800 /* toBoolean - emit code for orl a,operator(sizeop)                */
1801 /*-----------------------------------------------------------------*/
1802 static void
1803 toBoolean (operand * oper)
1804 {
1805   int   size = AOP_SIZE (oper) - 1;
1806   int   offset = 1;
1807   bool usedB = FALSE;
1808
1809   /* The generic part of a generic pointer should
1810    * not participate in it's truth value.
1811    *
1812    * i.e. 0x10000000 is zero.
1813    */
1814   if (opIsGptr (oper))
1815     {
1816       D (emitcode (";", "toBoolean: generic ptr special case."););
1817       size--;
1818     }
1819
1820   _startLazyDPSEvaluation ();
1821   if (AOP_NEEDSACC (oper) && size)
1822     {
1823       usedB = TRUE;
1824       if (_G.bInUse)
1825       {
1826           emitcode ("push", "b");
1827       }
1828       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1829     }
1830   else
1831     {
1832       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1833     }
1834     
1835   while (size--)
1836     {
1837       if (usedB)
1838         {
1839           emitcode ("orl", "b,%s",
1840                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1841         }
1842       else
1843         {
1844           emitcode ("orl", "a,%s",
1845                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1846         }
1847     }
1848   _endLazyDPSEvaluation ();
1849
1850   if (usedB)
1851     {
1852       emitcode ("mov", "a,b");
1853       if (_G.bInUse)
1854       {
1855           emitcode ("pop", "b");
1856       }
1857         
1858     }
1859 }
1860
1861
1862 /*-----------------------------------------------------------------*/
1863 /* genNot - generate code for ! operation                          */
1864 /*-----------------------------------------------------------------*/
1865 static void
1866 genNot (iCode * ic)
1867 {
1868   symbol *tlbl;
1869
1870   D (emitcode (";", "genNot "););
1871
1872   /* assign asmOps to operand & result */
1873   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1874   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1875
1876   /* if in bit space then a special case */
1877   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1878     {
1879       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1880       emitcode ("cpl", "c");
1881       outBitC (IC_RESULT (ic));
1882       goto release;
1883     }
1884
1885   toBoolean (IC_LEFT (ic));
1886
1887   tlbl = newiTempLabel (NULL);
1888   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1889   emitcode ("", "!tlabeldef", tlbl->key + 100);
1890   outBitC (IC_RESULT (ic));
1891
1892 release:
1893   /* release the aops */
1894   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1895   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1896 }
1897
1898
1899 /*-----------------------------------------------------------------*/
1900 /* genCpl - generate code for complement                           */
1901 /*-----------------------------------------------------------------*/
1902 static void
1903 genCpl (iCode * ic)
1904 {
1905   int offset = 0;
1906   int size;
1907   symbol *tlbl;
1908
1909   D (emitcode (";", "genCpl "););
1910
1911
1912   /* assign asmOps to operand & result */
1913   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1914   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1915
1916   /* special case if in bit space */
1917   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1918     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1919       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1920       emitcode ("cpl", "c");
1921       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1922       goto release;
1923     }
1924     tlbl=newiTempLabel(NULL);
1925     emitcode ("cjne", "%s,#0x01,%05d$", 
1926               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1927     emitcode ("", "%05d$:", tlbl->key+100);
1928     outBitC (IC_RESULT(ic));
1929     goto release;
1930   }
1931
1932   size = AOP_SIZE (IC_RESULT (ic));
1933   _startLazyDPSEvaluation ();
1934   while (size--)
1935     {
1936       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1937       emitcode ("cpl", "a");
1938       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1939     }
1940   _endLazyDPSEvaluation ();
1941
1942
1943 release:
1944   /* release the aops */
1945   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1946   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* genUminusFloat - unary minus for floating points                */
1951 /*-----------------------------------------------------------------*/
1952 static void
1953 genUminusFloat (operand * op, operand * result)
1954 {
1955   int size, offset = 0;
1956     
1957   D(emitcode (";", "genUminusFloat"););
1958   
1959   /* for this we just copy and then flip the bit */
1960     
1961   _startLazyDPSEvaluation ();
1962   size = AOP_SIZE (op) - 1;
1963
1964   while (size--)
1965   {
1966       aopPut (AOP (result),
1967               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1968               offset);
1969       offset++;
1970     }
1971   
1972   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1973
1974   emitcode ("cpl", "acc.7");
1975   aopPut (AOP (result), "a", offset);    
1976   _endLazyDPSEvaluation ();
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /* genUminus - unary minus code generation                         */
1981 /*-----------------------------------------------------------------*/
1982 static void
1983 genUminus (iCode * ic)
1984 {
1985   int offset, size;
1986   sym_link *optype;
1987
1988   D (emitcode (";", "genUminus "););
1989
1990   /* assign asmops */
1991   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1992   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1993
1994   /* if both in bit space then special
1995      case */
1996   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1997       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1998     {
1999
2000       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2001       emitcode ("cpl", "c");
2002       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2003       goto release;
2004     }
2005
2006   optype = operandType (IC_LEFT (ic));
2007
2008   /* if float then do float stuff */
2009   if (IS_FLOAT (optype))
2010     {
2011       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2012       goto release;
2013     }
2014
2015   /* otherwise subtract from zero */
2016   size = AOP_SIZE (IC_LEFT (ic));
2017   offset = 0;
2018   _startLazyDPSEvaluation ();
2019   while (size--)
2020     {
2021       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2022       if (!strcmp (l, "a"))
2023         {
2024           if (offset == 0)
2025             SETC;
2026           emitcode ("cpl", "a");
2027           emitcode ("addc", "a,#0");
2028         }
2029       else
2030         {
2031           if (offset == 0)
2032             CLRC;
2033           emitcode ("clr", "a");
2034           emitcode ("subb", "a,%s", l);
2035         }
2036       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2037     }
2038   _endLazyDPSEvaluation ();
2039
2040   /* if any remaining bytes in the result */
2041   /* we just need to propagate the sign   */
2042   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2043     {
2044       emitcode ("rlc", "a");
2045       emitcode ("subb", "a,acc");
2046       while (size--)
2047         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2048     }
2049
2050 release:
2051   /* release the aops */
2052   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2053   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2054 }
2055
2056 /*-----------------------------------------------------------------*/
2057 /* savermask - saves registers in the mask                         */
2058 /*-----------------------------------------------------------------*/
2059 static void savermask(bitVect *rs_mask)
2060 {
2061     int i;
2062     if (options.useXstack) {
2063         if (bitVectBitValue (rs_mask, R0_IDX))
2064             emitcode ("mov", "b,r0");
2065         emitcode ("mov", "r0,%s", spname);
2066         for (i = 0; i < ds390_nRegs; i++) {
2067             if (bitVectBitValue (rs_mask, i)) {
2068                 if (i == R0_IDX)
2069                     emitcode ("mov", "a,b");
2070                 else
2071                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2072                 emitcode ("movx", "@r0,a");
2073                 emitcode ("inc", "r0");
2074             }
2075         }
2076         emitcode ("mov", "%s,r0", spname);
2077         if (bitVectBitValue (rs_mask, R0_IDX))
2078             emitcode ("mov", "r0,b");
2079     } else {
2080         for (i = 0; i < ds390_nRegs; i++) {
2081             if (bitVectBitValue (rs_mask, i))
2082                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2083         }
2084     }
2085 }
2086
2087 /*-----------------------------------------------------------------*/
2088 /* saveRegisters - will look for a call and save the registers     */
2089 /*-----------------------------------------------------------------*/
2090 static void
2091 saveRegisters (iCode * lic)
2092 {
2093   iCode *ic;
2094   bitVect *rsave;
2095
2096   /* look for call */
2097   for (ic = lic; ic; ic = ic->next)
2098     if (ic->op == CALL || ic->op == PCALL)
2099       break;
2100
2101   if (!ic)
2102     {
2103       fprintf (stderr, "found parameter push with no function call\n");
2104       return;
2105     }
2106
2107   /* if the registers have been saved already then
2108      do nothing */
2109   if (ic->regsSaved 
2110       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2111     return ;
2112
2113   /* special case if DPTR alive across a function call then must save it 
2114      even though callee saves */
2115   if (IS_SYMOP(IC_LEFT(ic)) &&
2116       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2117       int i;
2118       rsave = newBitVect(ic->rMask->size);
2119       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2120           if (bitVectBitValue(ic->rMask,i))
2121               rsave = bitVectSetBit(rsave,i);
2122       }
2123       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2124   } else {
2125     /* safe the registers in use at this time but skip the
2126        ones for the result */
2127     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128                            ds390_rUmaskForOp (IC_RESULT(ic)));
2129   }
2130   ic->regsSaved = 1;
2131   savermask(rsave);
2132 }
2133
2134 /*-----------------------------------------------------------------*/
2135 /* usavermask - restore registers with mask                        */
2136 /*-----------------------------------------------------------------*/
2137 static void unsavermask(bitVect *rs_mask)
2138 {
2139     int i;
2140     if (options.useXstack) {
2141         emitcode ("mov", "r0,%s", spname);
2142         for (i = ds390_nRegs; i >= 0; i--) {
2143             if (bitVectBitValue (rs_mask, i)) {
2144                 emitcode ("dec", "r0");
2145                 emitcode ("movx", "a,@r0");
2146                 if (i == R0_IDX)
2147                     emitcode ("mov", "b,a");
2148                 else
2149                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2150             }       
2151         }
2152         emitcode ("mov", "%s,r0", spname);
2153         if (bitVectBitValue (rs_mask, R0_IDX))
2154             emitcode ("mov", "r0,b");
2155     } else {
2156         for (i = ds390_nRegs; i >= 0; i--) {
2157             if (bitVectBitValue (rs_mask, i))
2158                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2159         }
2160     }
2161 }
2162
2163 /*-----------------------------------------------------------------*/
2164 /* unsaveRegisters - pop the pushed registers                      */
2165 /*-----------------------------------------------------------------*/
2166 static void
2167 unsaveRegisters (iCode * ic)
2168 {
2169   bitVect *rsave;
2170
2171   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2172       int i;
2173       rsave = newBitVect(ic->rMask->size);
2174       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2175           if (bitVectBitValue(ic->rMask,i))
2176               rsave = bitVectSetBit(rsave,i);
2177       }
2178       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2179   } else {
2180     /* restore the registers in use at this time but skip the
2181        ones for the result */
2182     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2183                            ds390_rUmaskForOp (IC_RESULT(ic)));
2184   }
2185   unsavermask(rsave);
2186 }
2187
2188
2189 /*-----------------------------------------------------------------*/
2190 /* pushSide -                */
2191 /*-----------------------------------------------------------------*/
2192 static void
2193 pushSide (operand * oper, int size)
2194 {
2195   int offset = 0;
2196   _startLazyDPSEvaluation ();
2197   while (size--)
2198     {
2199       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2200       if (AOP_TYPE (oper) != AOP_REG &&
2201           AOP_TYPE (oper) != AOP_DIR &&
2202           strcmp (l, "a"))
2203         {
2204           emitcode ("mov", "a,%s", l);
2205           emitcode ("push", "acc");
2206         }
2207       else
2208         emitcode ("push", "%s", l);
2209     }
2210   _endLazyDPSEvaluation ();
2211 }
2212
2213 /*-----------------------------------------------------------------*/
2214 /* assignResultValue -               */
2215 /*-----------------------------------------------------------------*/
2216 static void
2217 assignResultValue (operand * oper)
2218 {
2219   int offset = 0;
2220   int size = AOP_SIZE (oper);
2221   bool pushedAcc = FALSE;
2222
2223   if (size == fReturnSizeDS390)
2224   {
2225       /* I don't think this case can ever happen... */
2226       /* ACC is the last part of this. If writing the result
2227        * uses AC, we must preserve it.
2228        */
2229       if (AOP_NEEDSACC(oper))
2230       {
2231           emitcode(";", "assignResultValue special case for ACC.");
2232           emitcode("push", "acc");
2233           pushedAcc = TRUE;
2234           size--;
2235       }
2236   }
2237     
2238     
2239   _startLazyDPSEvaluation ();
2240   while (size--)
2241     {
2242       aopPut (AOP (oper), fReturn[offset], offset);
2243       offset++;
2244     }
2245   _endLazyDPSEvaluation ();
2246     
2247   if (pushedAcc)
2248     {
2249         emitcode("pop", "acc");
2250         aopPut(AOP(oper), "a", offset);
2251     }
2252 }
2253
2254
2255 /*-----------------------------------------------------------------*/
2256 /* genXpush - pushes onto the external stack                       */
2257 /*-----------------------------------------------------------------*/
2258 static void
2259 genXpush (iCode * ic)
2260 {
2261   asmop *aop = newAsmop (0);
2262   regs *r;
2263   int size, offset = 0;
2264
2265   D (emitcode (";", "genXpush ");
2266     );
2267
2268   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2269   r = getFreePtr (ic, &aop, FALSE);
2270
2271
2272   emitcode ("mov", "%s,_spx", r->name);
2273
2274   size = AOP_SIZE (IC_LEFT (ic));
2275   _startLazyDPSEvaluation ();
2276   while (size--)
2277     {
2278
2279       MOVA (aopGet (AOP (IC_LEFT (ic)),
2280                         offset++, FALSE, FALSE, NULL));
2281       emitcode ("movx", "@%s,a", r->name);
2282       emitcode ("inc", "%s", r->name);
2283
2284     }
2285   _endLazyDPSEvaluation ();
2286
2287
2288   emitcode ("mov", "_spx,%s", r->name);
2289
2290   freeAsmop (NULL, aop, ic, TRUE);
2291   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2292 }
2293
2294 /*-----------------------------------------------------------------*/
2295 /* genIpush - generate code for pushing this gets a little complex  */
2296 /*-----------------------------------------------------------------*/
2297 static void
2298 genIpush (iCode * ic)
2299 {
2300   int size, offset = 0;
2301   char *l;
2302
2303   D (emitcode (";", "genIpush ");
2304     );
2305
2306   /* if this is not a parm push : ie. it is spill push
2307      and spill push is always done on the local stack */
2308   if (!ic->parmPush)
2309     {
2310
2311       /* and the item is spilt then do nothing */
2312       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2313         return;
2314
2315       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2316       size = AOP_SIZE (IC_LEFT (ic));
2317       /* push it on the stack */
2318       _startLazyDPSEvaluation ();
2319       while (size--)
2320         {
2321           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2322           if (*l == '#')
2323             {
2324               MOVA (l);
2325               l = "acc";
2326             }
2327           emitcode ("push", "%s", l);
2328         }
2329       _endLazyDPSEvaluation ();
2330       return;
2331     }
2332
2333   /* this is a paramter push: in this case we call
2334      the routine to find the call and save those
2335      registers that need to be saved */
2336   saveRegisters (ic);
2337
2338   /* if use external stack then call the external
2339      stack pushing routine */
2340   if (options.useXstack)
2341     {
2342       genXpush (ic);
2343       return;
2344     }
2345
2346   /* then do the push */
2347   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2348
2349   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2350   size = AOP_SIZE (IC_LEFT (ic));
2351
2352   _startLazyDPSEvaluation ();
2353   while (size--)
2354     {
2355       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2356       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2357           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2358           strcmp (l, "acc"))
2359         {
2360           emitcode ("mov", "a,%s", l);
2361           emitcode ("push", "acc");
2362         }
2363       else
2364         {
2365             emitcode ("push", "%s", l);
2366         }
2367     }
2368   _endLazyDPSEvaluation ();
2369
2370   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* genIpop - recover the registers: can happen only for spilling   */
2375 /*-----------------------------------------------------------------*/
2376 static void
2377 genIpop (iCode * ic)
2378 {
2379   int size, offset;
2380
2381   D (emitcode (";", "genIpop ");
2382     );
2383
2384
2385   /* if the temp was not pushed then */
2386   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2387     return;
2388
2389   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2390   size = AOP_SIZE (IC_LEFT (ic));
2391   offset = (size - 1);
2392   _startLazyDPSEvaluation ();
2393   while (size--)
2394     {
2395       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2396                                      FALSE, TRUE, NULL));
2397     }
2398   _endLazyDPSEvaluation ();
2399
2400   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2401 }
2402
2403 /*-----------------------------------------------------------------*/
2404 /* unsaveRBank - restores the resgister bank from stack            */
2405 /*-----------------------------------------------------------------*/
2406 static void
2407 unsaveRBank (int bank, iCode * ic, bool popPsw)
2408 {
2409   int i;
2410   asmop *aop = NULL;
2411   regs *r = NULL;
2412
2413   if (options.useXstack)
2414   {
2415       if (!ic)
2416       {
2417           /* Assume r0 is available for use. */
2418           r = ds390_regWithIdx (R0_IDX);;          
2419       } 
2420       else
2421       {
2422           aop = newAsmop (0);
2423           r = getFreePtr (ic, &aop, FALSE);
2424       }
2425       emitcode ("mov", "%s,_spx", r->name);      
2426   }
2427   
2428   if (popPsw)
2429     {
2430       if (options.useXstack)
2431       {
2432           emitcode ("movx", "a,@%s", r->name);
2433           emitcode ("mov", "psw,a");
2434           emitcode ("dec", "%s", r->name);
2435         }
2436       else
2437       {
2438         emitcode ("pop", "psw");
2439       }
2440     }
2441
2442   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2443     {
2444       if (options.useXstack)
2445         {
2446           emitcode ("movx", "a,@%s", r->name);
2447           emitcode ("mov", "(%s+%d),a",
2448                     regs390[i].base, 8 * bank + regs390[i].offset);
2449           emitcode ("dec", "%s", r->name);
2450
2451         }
2452       else
2453         emitcode ("pop", "(%s+%d)",
2454                   regs390[i].base, 8 * bank + regs390[i].offset);
2455     }
2456
2457   if (options.useXstack)
2458     {
2459       emitcode ("mov", "_spx,%s", r->name);
2460     }
2461     
2462   if (aop)
2463   {
2464       freeAsmop (NULL, aop, ic, TRUE);  
2465   }    
2466 }
2467
2468 /*-----------------------------------------------------------------*/
2469 /* saveRBank - saves an entire register bank on the stack          */
2470 /*-----------------------------------------------------------------*/
2471 static void
2472 saveRBank (int bank, iCode * ic, bool pushPsw)
2473 {
2474   int i;
2475   asmop *aop = NULL;
2476   regs *r = NULL;
2477
2478   if (options.useXstack)
2479     {
2480         if (!ic)
2481         {
2482           /* Assume r0 is available for use. */
2483                   r = ds390_regWithIdx (R0_IDX);;
2484         }
2485         else
2486         {
2487           aop = newAsmop (0);
2488           r = getFreePtr (ic, &aop, FALSE);
2489         }
2490         emitcode ("mov", "%s,_spx", r->name);    
2491     }
2492
2493   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2494     {
2495       if (options.useXstack)
2496         {
2497           emitcode ("inc", "%s", r->name);
2498           emitcode ("mov", "a,(%s+%d)",
2499                     regs390[i].base, 8 * bank + regs390[i].offset);
2500           emitcode ("movx", "@%s,a", r->name);
2501         }
2502       else
2503         emitcode ("push", "(%s+%d)",
2504                   regs390[i].base, 8 * bank + regs390[i].offset);
2505     }
2506
2507   if (pushPsw)
2508     {
2509       if (options.useXstack)
2510         {
2511           emitcode ("mov", "a,psw");
2512           emitcode ("movx", "@%s,a", r->name);
2513           emitcode ("inc", "%s", r->name);
2514           emitcode ("mov", "_spx,%s", r->name);
2515         }
2516       else
2517       {
2518         emitcode ("push", "psw");
2519       }
2520
2521       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2522     }
2523   
2524   if (aop)
2525   {
2526        freeAsmop (NULL, aop, ic, TRUE);
2527   }    
2528     
2529   if (ic)
2530   {  
2531       ic->bankSaved = 1;
2532   }
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /* genSend - gen code for SEND                                     */
2537 /*-----------------------------------------------------------------*/
2538 static void genSend(set *sendSet)
2539 {
2540     iCode *sic;
2541     int sendCount = 0 ;
2542     static int rb1_count = 0;
2543
2544     for (sic = setFirstItem (sendSet); sic;
2545          sic = setNextItem (sendSet)) {     
2546         int size, offset = 0;
2547         
2548         size=getSize(operandType(IC_LEFT(sic)));
2549         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2550         if (sendCount == 0) { /* first parameter */
2551             // we know that dpl(hxb) is the result, so
2552             rb1_count = 0 ;
2553             _startLazyDPSEvaluation ();
2554             if (size>1) {
2555                 aopOp (IC_LEFT (sic), sic, FALSE, 
2556                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2557             } else {
2558                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2559             }
2560             while (size--) {
2561                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2562                                   FALSE, FALSE, NULL);
2563                 if (strcmp (l, fReturn[offset])) {
2564                     emitcode ("mov", "%s,%s",
2565                               fReturn[offset],
2566                               l);
2567                 }
2568                 offset++;
2569             }
2570             _endLazyDPSEvaluation ();
2571             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2572             rb1_count =0;
2573         } else { /* if more parameter in registers */
2574             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2575             while (size--) {
2576                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2577                                                                 FALSE, FALSE, NULL));
2578             }
2579             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2580         }
2581         sendCount++;
2582     }
2583 }
2584
2585 static void
2586 adjustEsp(const char *reg)
2587 {
2588     emitcode ("anl","%s,#3", reg);
2589     if (TARGET_IS_DS400)
2590     {
2591         emitcode ("orl","%s,#!constbyte",
2592                   reg,
2593                   (options.stack_loc >> 8) & 0xff);
2594     }
2595 }
2596
2597 /*-----------------------------------------------------------------*/
2598 /* genCall - generates a call statement                            */
2599 /*-----------------------------------------------------------------*/
2600 static void
2601 genCall (iCode * ic)
2602 {
2603   sym_link *dtype;
2604   bool restoreBank = FALSE;
2605   bool swapBanks = FALSE;
2606
2607   D (emitcode (";", "genCall "););
2608
2609   /* if we are calling a not _naked function that is not using
2610      the same register bank then we need to save the
2611      destination registers on the stack */
2612   dtype = operandType (IC_LEFT (ic));
2613   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2614       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2615       IFFUNC_ISISR (currFunc->type))
2616   {
2617       if (!ic->bankSaved) 
2618       {
2619            /* This is unexpected; the bank should have been saved in
2620             * genFunction.
2621             */
2622            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2623            restoreBank = TRUE;
2624       }
2625       swapBanks = TRUE;
2626   }
2627   
2628     /* if caller saves & we have not saved then */
2629     if (!ic->regsSaved)
2630       saveRegisters (ic);
2631   
2632   /* if send set is not empty the assign */
2633   /* We've saved all the registers we care about;
2634   * therefore, we may clobber any register not used
2635   * in the calling convention (i.e. anything not in
2636   * fReturn.
2637   */
2638   if (_G.sendSet)
2639     {
2640         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2641             genSend(reverseSet(_G.sendSet));
2642         } else {
2643             genSend(_G.sendSet);
2644         }
2645       _G.sendSet = NULL;
2646     }  
2647     
2648   if (swapBanks)
2649   {
2650         emitcode ("mov", "psw,#!constbyte", 
2651            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2652   }
2653
2654   /* make the call */
2655   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2656                             OP_SYMBOL (IC_LEFT (ic))->rname :
2657                             OP_SYMBOL (IC_LEFT (ic))->name));
2658
2659   if (swapBanks)
2660   {
2661        emitcode ("mov", "psw,#!constbyte", 
2662           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2663   }
2664
2665   /* if we need assign a result value */
2666   if ((IS_ITEMP (IC_RESULT (ic)) &&
2667        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2668         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2669         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2670       IS_TRUE_SYMOP (IC_RESULT (ic)))
2671     {
2672       if (isOperandInFarSpace (IC_RESULT (ic))
2673           && getSize (operandType (IC_RESULT (ic))) <= 2)
2674         {
2675           int size = getSize (operandType (IC_RESULT (ic)));
2676
2677           /* Special case for 1 or 2 byte return in far space. */
2678           MOVA (fReturn[0]);
2679           if (size > 1)
2680             {
2681               emitcode ("mov", "b,%s", fReturn[1]);
2682               _G.bInUse++;
2683             }
2684
2685           _G.accInUse++;
2686           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2687           _G.accInUse--;
2688           
2689           if (size > 1)
2690             _G.bInUse--;
2691
2692           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2693
2694           if (size > 1)
2695             {
2696               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2697             }
2698           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2699         }
2700       else
2701         {
2702           _G.bInUse++;
2703           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2704           _G.bInUse--;
2705
2706           assignResultValue (IC_RESULT (ic));
2707
2708           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2709         }
2710     }
2711
2712   /* adjust the stack for parameters if
2713      required */
2714   if (ic->parmBytes) {
2715       int i;
2716       if (options.stack10bit) {
2717           if (ic->parmBytes <= 10) {
2718               emitcode(";","stack adjustment for parms");
2719               for (i=0; i < ic->parmBytes ; i++) {
2720                   emitcode("pop","acc");
2721               }
2722           } else {            
2723               PROTECT_SP;
2724               emitcode ("clr","c");
2725               emitcode ("mov","a,sp");
2726               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2727               emitcode ("mov","sp,a");
2728               emitcode ("mov","a,esp");
2729               adjustEsp("a");
2730               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2731               emitcode ("mov","esp,a");   
2732               UNPROTECT_SP;
2733           }
2734       } else {
2735           if (ic->parmBytes > 3) {
2736               emitcode ("mov", "a,%s", spname);
2737               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2738               emitcode ("mov", "%s,a", spname);
2739           } else
2740               for (i = 0; i < ic->parmBytes; i++)
2741                   emitcode ("dec", "%s", spname);
2742       }
2743   }
2744
2745   /* if we hade saved some registers then unsave them */
2746   if (ic->regsSaved)
2747     unsaveRegisters (ic);
2748
2749   /* if register bank was saved then pop them */
2750   if (restoreBank)
2751     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2752 }
2753
2754 /*-----------------------------------------------------------------*/
2755 /* genPcall - generates a call by pointer statement                */
2756 /*-----------------------------------------------------------------*/
2757 static void
2758 genPcall (iCode * ic)
2759 {
2760   sym_link *dtype;
2761   symbol *rlbl = newiTempLabel (NULL);
2762   bool restoreBank=FALSE;
2763
2764   D (emitcode (";", "genPcall ");
2765     );
2766
2767
2768   /* if caller saves & we have not saved then */
2769   if (!ic->regsSaved)
2770     saveRegisters (ic);
2771
2772   /* if we are calling a function that is not using
2773      the same register bank then we need to save the
2774      destination registers on the stack */
2775   dtype = operandType (IC_LEFT (ic));
2776   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2777       IFFUNC_ISISR (currFunc->type) &&
2778       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2779     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2780     restoreBank=TRUE;
2781   }
2782
2783   /* push the return address on to the stack */
2784   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2785   emitcode ("push", "acc");
2786   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2787   emitcode ("push", "acc");
2788
2789   if (options.model == MODEL_FLAT24)
2790     {
2791       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2792       emitcode ("push", "acc");
2793     }
2794
2795   /* now push the calling address */
2796   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2797
2798   pushSide (IC_LEFT (ic), FPTRSIZE);
2799
2800   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2801
2802   /* if send set is not empty the assign */
2803   if (_G.sendSet)
2804     {
2805         genSend(reverseSet(_G.sendSet));
2806         _G.sendSet = NULL;
2807     }
2808
2809   emitcode ("ret", "");
2810   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2811
2812
2813   /* if we need assign a result value */
2814   if ((IS_ITEMP (IC_RESULT (ic)) &&
2815        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2816         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2817       IS_TRUE_SYMOP (IC_RESULT (ic)))
2818     {
2819
2820       _G.accInUse++;
2821       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2822       _G.accInUse--;
2823
2824       assignResultValue (IC_RESULT (ic));
2825
2826       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2827     }
2828
2829   /* adjust the stack for parameters if
2830      required */
2831   if (ic->parmBytes)
2832     {
2833       int i;
2834       if (options.stack10bit) {
2835           if (ic->parmBytes <= 10) {
2836               emitcode(";","stack adjustment for parms");
2837               for (i=0; i < ic->parmBytes ; i++) {
2838                   emitcode("pop","acc");
2839               }
2840           } else {            
2841               PROTECT_SP;
2842               emitcode ("clr","c");
2843               emitcode ("mov","a,sp");
2844               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2845               emitcode ("mov","sp,a");
2846               emitcode ("mov","a,esp");
2847               adjustEsp("a");
2848               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2849               emitcode ("mov","esp,a");   
2850               UNPROTECT_SP;
2851           }
2852       } else {
2853           if (ic->parmBytes > 3) {
2854               emitcode ("mov", "a,%s", spname);
2855               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2856               emitcode ("mov", "%s,a", spname);
2857           }
2858           else
2859               for (i = 0; i < ic->parmBytes; i++)
2860                   emitcode ("dec", "%s", spname);
2861           
2862       }
2863     }
2864   /* if register bank was saved then unsave them */
2865   if (restoreBank)
2866     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2867   
2868   /* if we hade saved some registers then
2869      unsave them */
2870   if (ic->regsSaved)
2871     unsaveRegisters (ic);
2872
2873 }
2874
2875 /*-----------------------------------------------------------------*/
2876 /* resultRemat - result  is rematerializable                       */
2877 /*-----------------------------------------------------------------*/
2878 static int
2879 resultRemat (iCode * ic)
2880 {
2881   if (SKIP_IC (ic) || ic->op == IFX)
2882     return 0;
2883
2884   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2885     {
2886       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2887       if (sym->remat && !POINTER_SET (ic))
2888         return 1;
2889     }
2890
2891   return 0;
2892 }
2893
2894 #if defined(__BORLANDC__) || defined(_MSC_VER)
2895 #define STRCASECMP stricmp
2896 #else
2897 #define STRCASECMP strcasecmp
2898 #endif
2899
2900 /*-----------------------------------------------------------------*/
2901 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2902 /*-----------------------------------------------------------------*/
2903 static int
2904 regsCmp(void *p1, void *p2)
2905 {
2906   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2907 }
2908
2909 static bool
2910 inExcludeList (char *s)
2911 {
2912   const char *p = setFirstItem(options.excludeRegsSet);
2913
2914   if (p == NULL || STRCASECMP(p, "none") == 0)
2915     return FALSE;
2916
2917
2918   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2919 }
2920
2921 /*-----------------------------------------------------------------*/
2922 /* genFunction - generated code for function entry                 */
2923 /*-----------------------------------------------------------------*/
2924 static void
2925 genFunction (iCode * ic)
2926 {
2927   symbol *sym;
2928   sym_link *ftype;
2929   bool   switchedPSW = FALSE;
2930
2931   D (emitcode (";", "genFunction "););
2932
2933   _G.nRegsSaved = 0;
2934   /* create the function header */
2935   emitcode (";", "-----------------------------------------");
2936   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2937   emitcode (";", "-----------------------------------------");
2938
2939   emitcode ("", "%s:", sym->rname);
2940   ftype = operandType (IC_LEFT (ic));
2941
2942   if (IFFUNC_ISNAKED(ftype))
2943   {
2944       emitcode(";", "naked function: no prologue.");
2945       return;
2946   }
2947   
2948   if (options.stack_probe) 
2949       emitcode ("lcall","__stack_probe");
2950
2951   /* here we need to generate the equates for the
2952      register bank if required */
2953   if (FUNC_REGBANK (ftype) != rbank)
2954     {
2955       int i;
2956
2957       rbank = FUNC_REGBANK (ftype);
2958       for (i = 0; i < ds390_nRegs; i++)
2959         {
2960           if (regs390[i].print) {
2961               if (strcmp (regs390[i].base, "0") == 0)
2962                   emitcode ("", "%s !equ !constbyte",
2963                             regs390[i].dname,
2964                             8 * rbank + regs390[i].offset);
2965               else
2966                   emitcode ("", "%s !equ %s + !constbyte",
2967                             regs390[i].dname,
2968                             regs390[i].base,
2969                             8 * rbank + regs390[i].offset);
2970           }
2971         }
2972     }
2973
2974   /* if this is an interrupt service routine then
2975      save acc, b, dpl, dph  */
2976   if (IFFUNC_ISISR (sym->type))
2977       { /* is ISR */
2978       if (!inExcludeList ("acc"))
2979         emitcode ("push", "acc");
2980       if (!inExcludeList ("b"))
2981         emitcode ("push", "b");
2982       if (!inExcludeList ("dpl"))
2983         emitcode ("push", "dpl");
2984       if (!inExcludeList ("dph"))
2985         emitcode ("push", "dph");
2986       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2987         {
2988           emitcode ("push", "dpx");
2989           /* Make sure we're using standard DPTR */
2990           emitcode ("push", "dps");
2991           emitcode ("mov", "dps,#0");
2992           if (options.stack10bit)
2993             {
2994               /* This ISR could conceivably use DPTR2. Better save it. */
2995               emitcode ("push", "dpl1");
2996               emitcode ("push", "dph1");
2997               emitcode ("push", "dpx1");
2998               emitcode ("push",  DP2_RESULT_REG);
2999             }
3000         }
3001       /* if this isr has no bank i.e. is going to
3002          run with bank 0 , then we need to save more
3003          registers :-) */
3004       if (!FUNC_REGBANK (sym->type))
3005         {
3006             int i;
3007
3008           /* if this function does not call any other
3009              function then we can be economical and
3010              save only those registers that are used */
3011           if (!IFFUNC_HASFCALL(sym->type))
3012             {
3013
3014               /* if any registers used */
3015               if (sym->regsUsed)
3016                 {
3017                   /* save the registers used */
3018                   for (i = 0; i < sym->regsUsed->size; i++)
3019                     {
3020                       if (bitVectBitValue (sym->regsUsed, i) ||
3021                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3022                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3023                     }
3024                 }
3025               else if (ds390_ptrRegReq)
3026                 {
3027                   emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3028                   emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3029                 }
3030
3031             }
3032           else
3033             {
3034               /* this function has  a function call cannot
3035                  determines register usage so we will have to push the
3036                  entire bank */
3037               saveRBank (0, ic, FALSE);
3038               if (options.parms_in_bank1) {
3039                   for (i=0; i < 8 ; i++ ) {
3040                       emitcode ("push","%s",rb1regs[i]);
3041                   }
3042               }
3043             }
3044         }
3045         else
3046         {
3047             /* This ISR uses a non-zero bank.
3048              *
3049              * We assume that the bank is available for our
3050              * exclusive use.
3051              *
3052              * However, if this ISR calls a function which uses some
3053              * other bank, we must save that bank entirely.
3054              */
3055             unsigned long banksToSave = 0;
3056             
3057             if (IFFUNC_HASFCALL(sym->type))
3058             {
3059
3060 #define MAX_REGISTER_BANKS 4
3061
3062                 iCode *i;
3063                 int ix;
3064
3065                 for (i = ic; i; i = i->next)
3066                 {
3067                     if (i->op == ENDFUNCTION)
3068                     {
3069                         /* we got to the end OK. */
3070                         break;
3071                     }
3072                     
3073                     if (i->op == CALL)
3074                     {
3075                         sym_link *dtype;
3076                         
3077                         dtype = operandType (IC_LEFT(i));
3078                         if (dtype 
3079                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3080                         {
3081                              /* Mark this bank for saving. */
3082                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3083                              {
3084                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3085                              }
3086                              else
3087                              {
3088                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3089                              }
3090                              
3091                              /* And note that we don't need to do it in 
3092                               * genCall.
3093                               */
3094                              i->bankSaved = 1;
3095                         }
3096                     }
3097                     if (i->op == PCALL)
3098                     {
3099                         /* This is a mess; we have no idea what
3100                          * register bank the called function might
3101                          * use.
3102                          *
3103                          * The only thing I can think of to do is
3104                          * throw a warning and hope.
3105                          */
3106                         werror(W_FUNCPTR_IN_USING_ISR);   
3107                     }
3108                 }
3109
3110                 if (banksToSave && options.useXstack)
3111                 {
3112                     /* Since we aren't passing it an ic, 
3113                      * saveRBank will assume r0 is available to abuse.
3114                      *
3115                      * So switch to our (trashable) bank now, so
3116                      * the caller's R0 isn't trashed.
3117                      */
3118                     emitcode ("push", "psw");
3119                     emitcode ("mov", "psw,#!constbyte", 
3120                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3121                     switchedPSW = TRUE;
3122                 }
3123                 
3124                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3125                 {
3126                      if (banksToSave & (1 << ix))
3127                      {
3128                          saveRBank(ix, NULL, FALSE);
3129                      }
3130                 }
3131             }
3132             // TODO: this needs a closer look
3133             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3134         }
3135     }
3136   else
3137     {
3138       /* if callee-save to be used for this function
3139          then save the registers being used in this function */
3140       if (IFFUNC_CALLEESAVES(sym->type))
3141         {
3142           int i;
3143
3144           /* if any registers used */
3145           if (sym->regsUsed)
3146             {
3147               /* save the registers used */
3148               for (i = 0; i < sym->regsUsed->size; i++)
3149                 {
3150                   if (bitVectBitValue (sym->regsUsed, i) ||
3151                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3152                     {
3153                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3154                       _G.nRegsSaved++;
3155                     }
3156                 }
3157             }
3158           else if (ds390_ptrRegReq)
3159             {
3160               emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3161               emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3162               _G.nRegsSaved += 2;
3163             }
3164         }
3165     }
3166
3167   /* set the register bank to the desired value */
3168   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3169    && !switchedPSW)
3170     {
3171       emitcode ("push", "psw");
3172       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3173     }
3174
3175   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3176        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3177       if (options.stack10bit) {
3178           emitcode ("push","_bpx");
3179           emitcode ("push","_bpx+1");
3180           emitcode ("mov","_bpx,%s",spname);
3181           emitcode ("mov","_bpx+1,esp");
3182           adjustEsp("_bpx+1");
3183       } else {
3184           if (options.useXstack) {
3185               emitcode ("mov", "r0,%s", spname);
3186               emitcode ("mov", "a,_bp");
3187               emitcode ("movx", "@r0,a");
3188               emitcode ("inc", "%s", spname);
3189           } else {
3190               /* set up the stack */
3191               emitcode ("push", "_bp"); /* save the callers stack  */
3192           }
3193           emitcode ("mov", "_bp,%s", spname);
3194       }
3195   }
3196
3197   /* adjust the stack for the function */
3198   if (sym->stack) {
3199       int i = sym->stack;
3200       if (options.stack10bit) {
3201           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3202           assert (sym->recvSize <= 4);
3203           if (sym->stack <= 8) {
3204               while (i--) emitcode ("push","acc");
3205           } else {
3206               PROTECT_SP;
3207               emitcode ("mov","a,sp");
3208               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3209               emitcode ("mov","sp,a");
3210               emitcode ("mov","a,esp");
3211               adjustEsp("a");
3212               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3213               emitcode ("mov","esp,a");
3214               UNPROTECT_SP;
3215           }
3216       } else {
3217           if (i > 256)
3218               werror (W_STACK_OVERFLOW, sym->name);
3219           
3220           if (i > 3 && sym->recvSize < 4) {
3221               
3222               emitcode ("mov", "a,sp");
3223               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3224               emitcode ("mov", "sp,a");
3225               
3226           } else
3227               while (i--)
3228                   emitcode ("inc", "sp");
3229       }
3230   }
3231
3232   if (sym->xstack)
3233     {
3234
3235       emitcode ("mov", "a,_spx");
3236       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3237       emitcode ("mov", "_spx,a");
3238     }
3239   
3240   /* if critical function then turn interrupts off */
3241   if (IFFUNC_ISCRITICAL (ftype))
3242     {
3243       symbol *tlbl = newiTempLabel (NULL);
3244       emitcode ("setb", "c");
3245       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3246       emitcode ("clr", "c");
3247       emitcode ("", "%05d$:", (tlbl->key + 100));
3248       emitcode ("push", "psw"); /* save old ea via c in psw */
3249     }
3250
3251 }
3252
3253 /*-----------------------------------------------------------------*/
3254 /* genEndFunction - generates epilogue for functions               */
3255 /*-----------------------------------------------------------------*/
3256 static void
3257 genEndFunction (iCode * ic)
3258 {
3259   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3260   lineNode *lnp = lineCurr;
3261   bitVect *regsUsed;
3262   bitVect *regsUsedPrologue;
3263   bitVect *regsUnneeded;
3264   int idx;
3265
3266   D (emitcode (";", "genEndFunction "););
3267
3268   if (IFFUNC_ISNAKED(sym->type))
3269   {
3270       emitcode(";", "naked function: no epilogue.");
3271       return;
3272   }
3273
3274   if (IFFUNC_ISCRITICAL (sym->type))
3275     {
3276       emitcode ("pop", "psw"); /* restore ea via c in psw */
3277       emitcode ("mov", "ea,c");
3278     }
3279   
3280   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3281        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3282
3283       if (options.stack10bit) {
3284           PROTECT_SP;     
3285           emitcode ("mov", "sp,_bpx", spname);
3286           emitcode ("mov", "esp,_bpx+1", spname);
3287           UNPROTECT_SP;
3288       } else {
3289           emitcode ("mov", "%s,_bp", spname);
3290       }
3291   }
3292
3293   /* if use external stack but some variables were
3294      added to the local stack then decrement the
3295      local stack */
3296   if (options.useXstack && sym->stack) {
3297       emitcode ("mov", "a,sp");
3298       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3299       emitcode ("mov", "sp,a");
3300   }
3301
3302
3303   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3304        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3305
3306       if (options.useXstack) {
3307           emitcode ("mov", "r0,%s", spname);
3308           emitcode ("movx", "a,@r0");
3309           emitcode ("mov", "_bp,a");
3310           emitcode ("dec", "%s", spname);
3311       } else {
3312           if (options.stack10bit) {
3313               emitcode ("pop", "_bpx+1");
3314               emitcode ("pop", "_bpx");
3315           } else {
3316               emitcode ("pop", "_bp");
3317           }
3318       }
3319   }
3320
3321   /* restore the register bank  */
3322   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3323   {
3324     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3325      || !options.useXstack)
3326     {
3327         /* Special case of ISR using non-zero bank with useXstack
3328          * is handled below.
3329          */
3330         emitcode ("pop", "psw");
3331     }
3332   } 
3333
3334   if (IFFUNC_ISISR (sym->type))
3335       { /* is ISR */  
3336
3337       /* now we need to restore the registers */
3338       /* if this isr has no bank i.e. is going to
3339          run with bank 0 , then we need to save more
3340          registers :-) */
3341       if (!FUNC_REGBANK (sym->type))
3342         {
3343             int i;
3344           /* if this function does not call any other
3345              function then we can be economical and
3346              save only those registers that are used */
3347           if (!IFFUNC_HASFCALL(sym->type))
3348             {
3349
3350               /* if any registers used */
3351               if (sym->regsUsed)
3352                 {
3353                   /* save the registers used */
3354                   for (i = sym->regsUsed->size; i >= 0; i--)
3355                     {
3356                       if (bitVectBitValue (sym->regsUsed, i) ||
3357                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3358                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3359                     }
3360                 }
3361               else if (ds390_ptrRegReq)
3362                 {
3363                   emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3364                   emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3365                 }
3366
3367             }
3368           else
3369             {
3370               /* this function has  a function call cannot
3371                  determines register usage so we will have to pop the
3372                  entire bank */
3373               if (options.parms_in_bank1) {
3374                   for (i = 7 ; i >= 0 ; i-- ) {
3375                       emitcode ("pop","%s",rb1regs[i]);
3376                   }
3377               }
3378               unsaveRBank (0, ic, FALSE);
3379             }
3380         }
3381         else
3382         {
3383             /* This ISR uses a non-zero bank.
3384              *
3385              * Restore any register banks saved by genFunction
3386              * in reverse order.
3387              */
3388             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3389             int ix;
3390           
3391             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3392             {
3393                 if (savedBanks & (1 << ix))
3394                 {
3395                     unsaveRBank(ix, NULL, FALSE);
3396                 }
3397             }
3398             
3399             if (options.useXstack)
3400             {
3401                 /* Restore bank AFTER calling unsaveRBank,
3402                  * since it can trash r0.
3403                  */
3404                 emitcode ("pop", "psw");
3405             }
3406         }
3407
3408       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3409         {
3410           if (options.stack10bit)
3411             {
3412               emitcode ("pop", DP2_RESULT_REG);
3413               emitcode ("pop", "dpx1");
3414               emitcode ("pop", "dph1");
3415               emitcode ("pop", "dpl1");
3416             }
3417           emitcode ("pop", "dps");
3418           emitcode ("pop", "dpx");
3419         }
3420       if (!inExcludeList ("dph"))
3421         emitcode ("pop", "dph");
3422       if (!inExcludeList ("dpl"))
3423         emitcode ("pop", "dpl");
3424       if (!inExcludeList ("b"))
3425         emitcode ("pop", "b");
3426       if (!inExcludeList ("acc"))
3427         emitcode ("pop", "acc");
3428
3429       /* if debug then send end of function */
3430       if (options.debug && currFunc) {
3431           _G.debugLine = 1;
3432           emitcode ("", "C$%s$%d$%d$%d ==.",
3433                     FileBaseName (ic->filename), currFunc->lastLine,
3434                     ic->level, ic->block);
3435           if (IS_STATIC (currFunc->etype))
3436             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3437           else
3438             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3439           _G.debugLine = 0;
3440         }
3441
3442       emitcode ("reti", "");
3443     }
3444   else
3445     {
3446       if (IFFUNC_CALLEESAVES(sym->type))
3447         {
3448           int i;
3449
3450           /* if any registers used */
3451           if (sym->regsUsed)
3452             {
3453               /* save the registers used */
3454               for (i = sym->regsUsed->size; i >= 0; i--)
3455                 {
3456                   if (bitVectBitValue (sym->regsUsed, i) ||
3457                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3458                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3459                 }
3460             }
3461           else if (ds390_ptrRegReq)
3462             {
3463                emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3464                emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3465             }
3466
3467         }
3468
3469       /* if debug then send end of function */
3470       if (options.debug && currFunc)
3471         {
3472           _G.debugLine = 1;
3473           emitcode ("", "C$%s$%d$%d$%d ==.",
3474                     FileBaseName (ic->filename), currFunc->lastLine,
3475                     ic->level, ic->block);
3476           if (IS_STATIC (currFunc->etype))
3477             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3478           else
3479             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3480           _G.debugLine = 0;
3481         }
3482
3483       emitcode ("ret", "");
3484     }
3485
3486   if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3487     return;
3488   
3489   /* If this was an interrupt handler using bank 0 that called another */
3490   /* function, then all registers must be saved; nothing to optimized. */
3491   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3492       && !FUNC_REGBANK(sym->type))
3493     return;
3494     
3495   /* Compute the registers actually used */
3496   regsUsed = newBitVect (ds390_nRegs);
3497   regsUsedPrologue = newBitVect (ds390_nRegs);
3498   while (lnp)
3499     {
3500       if (lnp->ic && lnp->ic->op == FUNCTION)
3501         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3502       else
3503         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3504       
3505       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3506           && lnp->prev->ic && lnp->prev->ic->op != FUNCTION)
3507         break;
3508       if (!lnp->prev)
3509         break;
3510       lnp = lnp->prev;
3511     }
3512
3513   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3514       && !bitVectBitValue (regsUsed, DPS_IDX))
3515     {
3516       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3517     }
3518     
3519   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3520       && !bitVectBitValue (regsUsed, CND_IDX))
3521     {
3522       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3523       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3524           && !sym->stack)
3525         bitVectUnSetBit (regsUsed, CND_IDX);
3526     }
3527   else
3528     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3529     
3530   /* If this was an interrupt handler that called another function */
3531   /* function, then assume working registers may be modified by it. */
3532   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3533     {
3534       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3535       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3536       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3537       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3538       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3539       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3540       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3541       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3542       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3543       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3544       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3545     }
3546
3547   /* Remove the unneeded push/pops */
3548   regsUnneeded = newBitVect (ds390_nRegs);
3549   while (lnp)
3550     {
3551       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3552         {
3553           if (!strncmp(lnp->line, "push", 4))
3554             {
3555               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3556               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3557                 {
3558                   connectLine (lnp->prev, lnp->next);
3559                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3560                 }
3561             }
3562           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3563             {
3564               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3565               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3566                 {
3567                   connectLine (lnp->prev, lnp->next);
3568                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3569                 }
3570             }
3571         }
3572       lnp = lnp->next;
3573     }  
3574   
3575   for (idx = 0; idx < regsUnneeded->size; idx++)
3576     if (bitVectBitValue (regsUnneeded, idx))
3577       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3578   
3579   freeBitVect (regsUnneeded);
3580   freeBitVect (regsUsed);
3581   freeBitVect (regsUsedPrologue);
3582 }
3583
3584 /*-----------------------------------------------------------------*/
3585 /* genJavaNativeRet - generate code for return JavaNative          */
3586 /*-----------------------------------------------------------------*/
3587 static void genJavaNativeRet(iCode *ic)
3588 {
3589     int i, size;
3590
3591     aopOp (IC_LEFT (ic), ic, FALSE, 
3592            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3593     size = AOP_SIZE (IC_LEFT (ic));
3594
3595     assert (size <= 4);
3596
3597     /* it is assigned to GPR0-R3 then push them */
3598     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3599         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3600         for (i = 0 ; i < size ; i++ ) {
3601             emitcode ("push","%s",
3602                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3603         }
3604         for (i = (size-1) ; i >= 0 ; i--) {
3605             emitcode ("pop","a%s",javaRet[i]);
3606         }
3607     } else {
3608         for (i = 0 ; i < size ; i++) 
3609             emitcode ("mov","%s,%s",javaRet[i],
3610                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3611     }
3612     for (i = size ; i < 4 ; i++ )
3613             emitcode ("mov","%s,#0",javaRet[i]);
3614     return;
3615 }
3616
3617 /*-----------------------------------------------------------------*/
3618 /* genRet - generate code for return statement                     */
3619 /*-----------------------------------------------------------------*/
3620 static void
3621 genRet (iCode * ic)
3622 {
3623   int size, offset = 0, pushed = 0;
3624
3625   D (emitcode (";", "genRet "););
3626
3627   /* if we have no return value then
3628      just generate the "ret" */
3629   if (!IC_LEFT (ic))
3630     goto jumpret;
3631
3632   /* if this is a JavaNative function then return 
3633      value in different register */
3634   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3635       genJavaNativeRet(ic);
3636       goto jumpret;
3637   }
3638   /* we have something to return then
3639      move the return value into place */
3640   aopOp (IC_LEFT (ic), ic, FALSE, 
3641          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3642   size = AOP_SIZE (IC_LEFT (ic));
3643
3644   _startLazyDPSEvaluation ();
3645   while (size--)
3646     {
3647       char *l;
3648       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3649         {
3650           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3651                       FALSE, TRUE, NULL);
3652           emitcode ("push", "%s", l);
3653           pushed++;
3654         }
3655       else
3656         {
3657           /* Since A is the last element of fReturn,
3658            * is is OK to clobber it in the aopGet.
3659            */
3660           l = aopGet (AOP (IC_LEFT (ic)), offset,
3661                       FALSE, FALSE, NULL);
3662           if (strcmp (fReturn[offset], l))
3663             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3664         }
3665     }
3666   _endLazyDPSEvaluation ();
3667
3668   if (pushed)
3669     {
3670       while (pushed)
3671         {
3672           pushed--;
3673           if (strcmp (fReturn[pushed], "a"))
3674             emitcode ("pop", fReturn[pushed]);
3675           else
3676             emitcode ("pop", "acc");
3677         }
3678     }
3679   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3680
3681 jumpret:
3682   /* generate a jump to the return label
3683      if the next is not the return statement */
3684   if (!(ic->next && ic->next->op == LABEL &&
3685         IC_LABEL (ic->next) == returnLabel))
3686
3687     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3688
3689 }
3690
3691 /*-----------------------------------------------------------------*/
3692 /* genLabel - generates a label                                    */
3693 /*-----------------------------------------------------------------*/
3694 static void
3695 genLabel (iCode * ic)
3696 {
3697   /* special case never generate */
3698   if (IC_LABEL (ic) == entryLabel)
3699     return;
3700
3701   D (emitcode (";", "genLabel ");
3702     );
3703
3704   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* genGoto - generates a ljmp                                      */
3709 /*-----------------------------------------------------------------*/
3710 static void
3711 genGoto (iCode * ic)
3712 {
3713   D (emitcode (";", "genGoto ");
3714     );
3715   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3716 }
3717
3718 /*-----------------------------------------------------------------*/
3719 /* findLabelBackwards: walks back through the iCode chain looking  */
3720 /* for the given label. Returns number of iCode instructions     */
3721 /* between that label and given ic.          */
3722 /* Returns zero if label not found.          */
3723 /*-----------------------------------------------------------------*/
3724 static int
3725 findLabelBackwards (iCode * ic, int key)
3726 {
3727   int count = 0;
3728
3729   while (ic->prev)
3730     {
3731       ic = ic->prev;
3732       count++;
3733
3734       /* If we have any pushes or pops, we cannot predict the distance.
3735          I don't like this at all, this should be dealt with in the 
3736          back-end */
3737       if (ic->op == IPUSH || ic->op == IPOP) {
3738         return 0;
3739       }
3740
3741       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3742         {
3743           /* printf("findLabelBackwards = %d\n", count); */
3744           return count;
3745         }
3746     }
3747
3748   return 0;
3749 }
3750
3751 /*-----------------------------------------------------------------*/
3752 /* genPlusIncr :- does addition with increment if possible         */
3753 /*-----------------------------------------------------------------*/
3754 static bool
3755 genPlusIncr (iCode * ic)
3756 {
3757   unsigned int icount;
3758   unsigned int size = getDataSize (IC_RESULT (ic));
3759
3760   /* will try to generate an increment */
3761   /* if the right side is not a literal
3762      we cannot */
3763   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3764     return FALSE;
3765
3766   /* if the literal value of the right hand side
3767      is greater than 4 then it is not worth it */
3768   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3769     return FALSE;
3770
3771   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3772       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3773       while (icount--) {
3774           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3775       }
3776       return TRUE;
3777   }
3778   /* if increment 16 bits in register */
3779   if (
3780        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3781        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3782        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3783        (size > 1) &&
3784        (icount == 1))
3785     {
3786       symbol  *tlbl;
3787       int     emitTlbl;
3788       int     labelRange;
3789       char    *l;
3790
3791       /* If the next instruction is a goto and the goto target
3792        * is <= 5 instructions previous to this, we can generate
3793        * jumps straight to that target.
3794        */
3795       if (ic->next && ic->next->op == GOTO
3796           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3797           && labelRange <= 5)
3798         {
3799           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3800           tlbl = IC_LABEL (ic->next);
3801           emitTlbl = 0;
3802         }
3803       else
3804         {
3805           tlbl = newiTempLabel (NULL);
3806           emitTlbl = 1;
3807         }
3808         
3809       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3810       emitcode ("inc", "%s", l);
3811       
3812       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3813           IS_AOP_PREG (IC_RESULT (ic)))
3814       {   
3815         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3816       }
3817       else
3818       {
3819           emitcode ("clr", "a");
3820           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3821       }
3822
3823       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3824       emitcode ("inc", "%s", l);
3825       if (size > 2)
3826         {
3827             if (!strcmp(l, "acc"))
3828             {
3829                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3830             }
3831             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3832                      IS_AOP_PREG (IC_RESULT (ic)))
3833             {
3834                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3835             }
3836             else
3837             {
3838                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3839             }
3840
3841             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3842             emitcode ("inc", "%s", l);
3843         }
3844       if (size > 3)
3845         {
3846             if (!strcmp(l, "acc"))
3847             {
3848                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3849             }
3850             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3851                      IS_AOP_PREG (IC_RESULT (ic)))
3852             {
3853                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3854             }
3855             else
3856             {
3857                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3858             }
3859
3860             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3861             emitcode ("inc", "%s", l);  }
3862
3863       if (emitTlbl)
3864         {
3865           emitcode ("", "!tlabeldef", tlbl->key + 100);
3866         }
3867       return TRUE;
3868     }
3869
3870   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3871       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3872       options.model == MODEL_FLAT24 ) {
3873
3874       switch (size) {
3875       case 3:
3876           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3877       case 2:
3878           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3879       case 1:
3880           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3881           break;
3882       }
3883       while (icount--) emitcode ("inc","dptr");      
3884       return TRUE;
3885   }
3886
3887   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3888       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3889       icount <= 5 ) {
3890       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3891       while (icount--) emitcode ("inc","dptr");
3892       emitcode ("mov","dps,#0");
3893       return TRUE;
3894   }
3895
3896   /* if the sizes are greater than 1 then we cannot */
3897   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3898       AOP_SIZE (IC_LEFT (ic)) > 1)
3899     return FALSE;
3900
3901   /* we can if the aops of the left & result match or
3902      if they are in registers and the registers are the
3903      same */
3904   if (
3905        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3906        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3907        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3908     {
3909
3910       if (icount > 3)
3911         {
3912           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3913           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3914           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3915         }
3916       else
3917         {
3918
3919           _startLazyDPSEvaluation ();
3920           while (icount--)
3921             {
3922               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3923             }
3924           _endLazyDPSEvaluation ();
3925         }
3926
3927       return TRUE;
3928     }
3929
3930   return FALSE;
3931 }
3932
3933 /*-----------------------------------------------------------------*/
3934 /* outBitAcc - output a bit in acc                                 */
3935 /*-----------------------------------------------------------------*/
3936 static void
3937 outBitAcc (operand * result)
3938 {
3939   symbol *tlbl = newiTempLabel (NULL);
3940   /* if the result is a bit */
3941   if (AOP_TYPE (result) == AOP_CRY)
3942     {
3943       aopPut (AOP (result), "a", 0);
3944     }
3945   else
3946     {
3947       emitcode ("jz", "!tlabel", tlbl->key + 100);
3948       emitcode ("mov", "a,%s", one);
3949       emitcode ("", "!tlabeldef", tlbl->key + 100);
3950       outAcc (result);
3951     }
3952 }
3953
3954 /*-----------------------------------------------------------------*/
3955 /* genPlusBits - generates code for addition of two bits           */
3956 /*-----------------------------------------------------------------*/
3957 static void
3958 genPlusBits (iCode * ic)
3959 {
3960   D (emitcode (";", "genPlusBits "););
3961     
3962   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3963     {
3964       symbol *lbl = newiTempLabel (NULL);
3965       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3966       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3967       emitcode ("cpl", "c");
3968       emitcode ("", "!tlabeldef", (lbl->key + 100));
3969       outBitC (IC_RESULT (ic));
3970     }
3971   else
3972     {
3973       emitcode ("clr", "a");
3974       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3975       emitcode ("rlc", "a");
3976       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3977       emitcode ("addc", "a,#0");
3978       outAcc (IC_RESULT (ic));
3979     }
3980 }
3981
3982 static void
3983 adjustArithmeticResult (iCode * ic)
3984 {
3985   if (opIsGptr (IC_RESULT (ic)) &&
3986       opIsGptr (IC_LEFT (ic)) &&
3987       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3988     {
3989       aopPut (AOP (IC_RESULT (ic)),
3990               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3991               GPTRSIZE - 1);
3992     }
3993
3994   if (opIsGptr (IC_RESULT (ic)) &&
3995       opIsGptr (IC_RIGHT (ic)) &&
3996       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3997     {
3998       aopPut (AOP (IC_RESULT (ic)),
3999             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
4000               GPTRSIZE - 1);
4001     }
4002
4003   if (opIsGptr (IC_RESULT (ic)) &&
4004       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4005       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4006       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4007       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4008     {
4009       char buff[5];
4010       SNPRINTF (buff, sizeof(buff), 
4011                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4012       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4013     }
4014 }
4015
4016 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4017 // generates the result if possible. If result is generated, returns TRUE; otherwise
4018 // returns false and caller must deal with fact that result isn't aopOp'd.
4019 bool aopOp3(iCode * ic)
4020 {
4021     bool dp1InUse, dp2InUse;
4022     bool useDp2;
4023
4024     // First, generate the right opcode. DPTR may be used if neither left nor result are
4025     // of type AOP_STR.
4026     
4027 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4028 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4029 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4030 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4031 //      );
4032 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4033 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4034 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4035 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4036 //      );
4037     
4038     // Right uses DPTR unless left or result is an AOP_STR; however,
4039     // if right is an AOP_STR, it must use DPTR regardless.
4040     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4041      && !AOP_IS_STR(IC_RIGHT(ic)))
4042     {
4043         useDp2 = TRUE;
4044     }
4045     else
4046     {
4047         useDp2 = FALSE;
4048     }
4049         
4050     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4051     
4052     // if the right used DPTR, left MUST use DPTR2.
4053     // if the right used DPTR2, left MUST use DPTR.
4054     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4055     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4056     // enabling us to assign DPTR to result.
4057      
4058     if (AOP_USESDPTR(IC_RIGHT(ic)))
4059     {
4060         useDp2 = TRUE;
4061     }
4062     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4063     {
4064         useDp2 = FALSE;
4065     }
4066     else
4067     {
4068         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4069         {
4070             useDp2 = TRUE;
4071         }
4072         else
4073         {
4074             useDp2 = FALSE;
4075         }
4076     }
4077
4078     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4079
4080         
4081     // We've op'd the left & right. So, if left or right are the same operand as result, 
4082     // we know aopOp will succeed, and we can just do it & bail.
4083     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4084       {
4085         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4086         return TRUE;
4087       }
4088     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4089       {
4090 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4091         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4092         return TRUE;
4093       }
4094     
4095     // Operands may be equivalent (but not equal) if they share a spill location. If
4096     // so, use the same DPTR or DPTR2.
4097     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4098       {
4099         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4100         return TRUE;
4101       }
4102     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4103       {
4104         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4105         return TRUE;
4106       }
4107     
4108     // Note which dptrs are currently in use.
4109     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4110     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4111     
4112     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
4113     // generate it.
4114     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4115     {
4116         return FALSE;
4117     }
4118     
4119     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4120     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4121     {
4122         return FALSE;
4123     }
4124     
4125     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4126     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4127     {
4128         return FALSE;
4129     }
4130
4131     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4132
4133     // Some sanity checking...
4134     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4135     {
4136         fprintf(stderr,
4137                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4138                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4139         emitcode(";", ">>> unexpected DPTR here.");
4140     }
4141     
4142     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4143     {
4144         fprintf(stderr,
4145                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4146                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4147         emitcode(";", ">>> unexpected DPTR2 here.");
4148     }    
4149     
4150     return TRUE;
4151 }
4152
4153 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4154 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4155 // will be set TRUE. The caller must then handle the case specially, noting
4156 // that the IC_RESULT operand is not aopOp'd.
4157 // 
4158 #define AOP_OP_3_NOFATAL(ic, rc) \
4159             do { rc = !aopOp3(ic); } while (0)
4160
4161 // aopOp the left & right operands of an ic.
4162 #define AOP_OP_2(ic) \
4163     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4164     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4165
4166 // convienience macro.
4167 #define AOP_SET_LOCALS(ic) \
4168     left = IC_LEFT(ic); \
4169     right = IC_RIGHT(ic); \
4170     result = IC_RESULT(ic);
4171
4172
4173 // Given an integer value of pushedSize bytes on the stack,
4174 // adjust it to be resultSize bytes, either by discarding
4175 // the most significant bytes or by zero-padding.
4176 //
4177 // On exit from this macro, pushedSize will have been adjusted to
4178 // equal resultSize, and ACC may be trashed.
4179 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4180       /* If the pushed data is bigger than the result,          \
4181        * simply discard unused bytes. Icky, but works.          \
4182        */                                                       \
4183       while (pushedSize > resultSize)                           \
4184       {                                                         \
4185           D (emitcode (";", "discarding unused result byte."););\
4186           emitcode ("pop", "acc");                              \
4187           pushedSize--;                                         \
4188       }                                                         \
4189       if (pushedSize < resultSize)                              \
4190       {                                                         \
4191           emitcode ("clr", "a");                                \
4192           /* Conversly, we haven't pushed enough here.          \
4193            * just zero-pad, and all is well.                    \
4194            */                                                   \
4195           while (pushedSize < resultSize)                       \
4196           {                                                     \
4197               emitcode("push", "acc");                          \
4198               pushedSize++;                                     \
4199           }                                                     \
4200       }                                                         \
4201       assert(pushedSize == resultSize);
4202
4203 /*-----------------------------------------------------------------*/
4204 /* genPlus - generates code for addition                           */
4205 /*-----------------------------------------------------------------*/
4206 static void
4207 genPlus (iCode * ic)
4208 {
4209   int size, offset = 0;
4210   bool pushResult;
4211   int rSize;
4212
4213   D (emitcode (";", "genPlus "););
4214
4215   /* special cases :- */
4216   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4217       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4218       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4219       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4220       if (size <= 9) {
4221           while (size--) emitcode ("inc","dptr");
4222       } else {
4223           emitcode ("mov","a,dpl");
4224           emitcode ("add","a,#!constbyte",size & 0xff);
4225           emitcode ("mov","dpl,a");
4226           emitcode ("mov","a,dph");
4227           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4228           emitcode ("mov","dph,a");
4229           emitcode ("mov","a,dpx");
4230           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4231           emitcode ("mov","dpx,a");
4232       }
4233       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4234       return ;
4235   }
4236   if ( IS_SYMOP(IC_LEFT(ic)) && 
4237        OP_SYMBOL(IC_LEFT(ic))->remat &&
4238        isOperandInFarSpace(IC_RIGHT(ic))) {
4239       operand *op = IC_RIGHT(ic);
4240       IC_RIGHT(ic) = IC_LEFT(ic);
4241       IC_LEFT(ic) = op;
4242   }
4243                 
4244   AOP_OP_3_NOFATAL (ic, pushResult);
4245     
4246   if (pushResult)
4247     {
4248       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4249     }
4250
4251   if (!pushResult)
4252     {
4253       /* if literal, literal on the right or
4254          if left requires ACC or right is already
4255          in ACC */
4256       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4257        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4258           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4259         {
4260           operand *t = IC_RIGHT (ic);
4261           IC_RIGHT (ic) = IC_LEFT (ic);
4262           IC_LEFT (ic) = t;
4263           emitcode (";", "Swapped plus args.");
4264         }
4265
4266       /* if both left & right are in bit
4267          space */
4268       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4269           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4270         {
4271           genPlusBits (ic);
4272           goto release;
4273         }
4274
4275       /* if left in bit space & right literal */
4276       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4277           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4278         {
4279           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4280           /* if result in bit space */
4281           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4282             {
4283               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4284                 emitcode ("cpl", "c");
4285               outBitC (IC_RESULT (ic));
4286             }
4287           else
4288             {
4289               size = getDataSize (IC_RESULT (ic));
4290               _startLazyDPSEvaluation ();
4291               while (size--)
4292                 {
4293                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4294                   emitcode ("addc", "a,#0");
4295                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4296                 }
4297               _endLazyDPSEvaluation ();
4298             }
4299           goto release;
4300         }
4301
4302       /* if I can do an increment instead
4303          of add then GOOD for ME */
4304       if (genPlusIncr (ic) == TRUE)
4305         {
4306           emitcode (";", "did genPlusIncr");
4307           goto release;
4308         }
4309
4310     }
4311   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4312
4313   _startLazyDPSEvaluation ();
4314   while (size--)
4315     {
4316       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4317         {
4318           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4319           if (offset == 0)
4320             emitcode ("add", "a,%s",
4321                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4322           else
4323             emitcode ("addc", "a,%s",
4324                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4325         }
4326       else
4327         {
4328           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4329           {
4330               /* right is going to use ACC or we would have taken the
4331                * above branch.
4332                */
4333               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4334        TR_AP("#3");
4335               D(emitcode(";", "+ AOP_ACC special case."););
4336               emitcode("xch", "a, %s", DP2_RESULT_REG);
4337           }
4338           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4339           if (offset == 0)
4340           {
4341             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4342             {
4343          TR_AP("#4");
4344                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4345             }
4346             else
4347             {
4348                 emitcode ("add", "a,%s",
4349                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4350                                   DP2_RESULT_REG));
4351             }
4352           }
4353           else
4354           {
4355             emitcode ("addc", "a,%s",
4356                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4357                           DP2_RESULT_REG));
4358           }
4359         }
4360       if (!pushResult)
4361         {
4362           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4363         }
4364       else
4365         {
4366           emitcode ("push", "acc");
4367         }
4368       offset++;
4369     }
4370   _endLazyDPSEvaluation ();
4371
4372   if (pushResult)
4373     {
4374       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4375
4376       size = getDataSize (IC_LEFT (ic));
4377       rSize = getDataSize (IC_RESULT (ic));
4378
4379       ADJUST_PUSHED_RESULT(size, rSize);
4380
4381       _startLazyDPSEvaluation ();
4382       while (size--)
4383         {
4384           emitcode ("pop", "acc");
4385           aopPut (AOP (IC_RESULT (ic)), "a", size);
4386         }
4387       _endLazyDPSEvaluation ();
4388     }
4389
4390   adjustArithmeticResult (ic);
4391
4392 release:
4393   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4395   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4396 }
4397
4398 /*-----------------------------------------------------------------*/
4399 /* genMinusDec :- does subtraction with deccrement if possible     */
4400 /*-----------------------------------------------------------------*/
4401 static bool
4402 genMinusDec (iCode * ic)
4403 {
4404   unsigned int icount;
4405   unsigned int size = getDataSize (IC_RESULT (ic));
4406
4407   /* will try to generate an increment */
4408   /* if the right side is not a literal
4409      we cannot */
4410   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4411     return FALSE;
4412
4413   /* if the literal value of the right hand side
4414      is greater than 4 then it is not worth it */
4415   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4416     return FALSE;
4417
4418   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4419       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4420       while (icount--) {
4421           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4422       }
4423       return TRUE;
4424   }
4425   /* if decrement 16 bits in register */
4426   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4427       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4428       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4429       (size > 1) &&
4430       (icount == 1))
4431     {
4432       symbol *tlbl;
4433       int    emitTlbl;
4434       int    labelRange;
4435       char   *l;
4436
4437       /* If the next instruction is a goto and the goto target
4438          * is <= 5 instructions previous to this, we can generate
4439          * jumps straight to that target.
4440        */
4441       if (ic->next && ic->next->op == GOTO
4442           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4443           && labelRange <= 5)
4444         {
4445           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4446           tlbl = IC_LABEL (ic->next);
4447           emitTlbl = 0;
4448         }
4449       else
4450         {
4451           tlbl = newiTempLabel (NULL);
4452           emitTlbl = 1;
4453         }
4454
4455       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4456       emitcode ("dec", "%s", l);
4457  
4458       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4459           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4460           IS_AOP_PREG (IC_RESULT (ic)))
4461       {     
4462           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4463       }
4464       else
4465       {
4466           emitcode ("mov", "a,#!constbyte",0xff);
4467           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4468       }
4469       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4470       emitcode ("dec", "%s", l);
4471       if (size > 2)
4472         {
4473             if (!strcmp(l, "acc"))
4474             {
4475                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4476             }
4477             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4479                      IS_AOP_PREG (IC_RESULT (ic)))
4480             {       
4481                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4482             }
4483             else
4484             {
4485                 emitcode ("mov", "a,#!constbyte",0xff);
4486                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4487             }
4488             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4489             emitcode ("dec", "%s", l);
4490         }
4491       if (size > 3)
4492         {
4493             if (!strcmp(l, "acc"))
4494             {
4495                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4496             }
4497             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4498                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4499                      IS_AOP_PREG (IC_RESULT (ic)))
4500             {       
4501                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4502             }
4503             else
4504             {
4505                 emitcode ("mov", "a,#!constbyte",0xff);
4506                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4507             }       
4508             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4509             emitcode ("dec", "%s", l);
4510         }
4511       if (emitTlbl)
4512         {
4513           emitcode ("", "!tlabeldef", tlbl->key + 100);
4514         }
4515       return TRUE;
4516     }
4517
4518   /* if the sizes are greater than 1 then we cannot */
4519   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4520       AOP_SIZE (IC_LEFT (ic)) > 1)
4521     return FALSE;
4522
4523   /* we can if the aops of the left & result match or
4524      if they are in registers and the registers are the
4525      same */
4526   if (
4527        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4528        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4529        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4530     {
4531
4532       _startLazyDPSEvaluation ();
4533       while (icount--)
4534         {
4535           emitcode ("dec", "%s",
4536                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4537         }
4538       _endLazyDPSEvaluation ();
4539
4540       return TRUE;
4541     }
4542
4543   return FALSE;
4544 }
4545
4546 /*-----------------------------------------------------------------*/
4547 /* addSign - complete with sign                                    */
4548 /*-----------------------------------------------------------------*/
4549 static void
4550 addSign (operand * result, int offset, int sign)
4551 {
4552   int size = (getDataSize (result) - offset);
4553   if (size > 0)
4554     {
4555       _startLazyDPSEvaluation();
4556       if (sign)
4557         {
4558           emitcode ("rlc", "a");
4559           emitcode ("subb", "a,acc");
4560           while (size--)
4561           {
4562             aopPut (AOP (result), "a", offset++);
4563           }
4564         }
4565       else
4566       {
4567         while (size--)
4568         {
4569           aopPut (AOP (result), zero, offset++);
4570         }
4571       }
4572       _endLazyDPSEvaluation();
4573     }
4574 }
4575
4576 /*-----------------------------------------------------------------*/
4577 /* genMinusBits - generates code for subtraction  of two bits      */
4578 /*-----------------------------------------------------------------*/
4579 static void
4580 genMinusBits (iCode * ic)
4581 {
4582   symbol *lbl = newiTempLabel (NULL);
4583
4584   D (emitcode (";", "genMinusBits "););
4585
4586   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4587     {
4588       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4589       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4590       emitcode ("cpl", "c");
4591       emitcode ("", "!tlabeldef", (lbl->key + 100));
4592       outBitC (IC_RESULT (ic));
4593     }
4594   else
4595     {
4596       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4597       emitcode ("subb", "a,acc");
4598       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4599       emitcode ("inc", "a");
4600       emitcode ("", "!tlabeldef", (lbl->key + 100));
4601       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4602       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4603     }
4604 }
4605
4606 /*-----------------------------------------------------------------*/
4607 /* genMinus - generates code for subtraction                       */
4608 /*-----------------------------------------------------------------*/
4609 static void
4610 genMinus (iCode * ic)
4611 {
4612     int size, offset = 0;
4613     int rSize;
4614     long lit = 0L;
4615     bool pushResult;
4616
4617     D (emitcode (";", "genMinus "););
4618
4619     AOP_OP_3_NOFATAL(ic, pushResult);   
4620
4621     if (!pushResult)
4622     {
4623       /* special cases :- */
4624       /* if both left & right are in bit space */
4625       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4626           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4627         {
4628           genMinusBits (ic);
4629           goto release;
4630         }
4631
4632       /* if I can do an decrement instead
4633          of subtract then GOOD for ME */
4634       if (genMinusDec (ic) == TRUE)
4635         goto release;
4636
4637     }
4638
4639   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4640
4641   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4642     {
4643       CLRC;
4644     }
4645   else
4646     {
4647       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4648       lit = -lit;
4649     }
4650
4651
4652   /* if literal, add a,#-lit, else normal subb */
4653   _startLazyDPSEvaluation ();
4654   while (size--) {
4655       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4656           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4657               emitcode ("mov","b,%s",
4658                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4659               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4660               emitcode ("subb","a,b");
4661           } else {
4662               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4663               emitcode ("subb", "a,%s",
4664                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4665                                 DP2_RESULT_REG));
4666           }
4667       } else {
4668           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4669           /* first add without previous c */
4670           if (!offset) {
4671               if (!size && lit==-1) {
4672                   emitcode ("dec", "a");
4673               } else {
4674                   emitcode ("add", "a,#!constbyte",
4675                             (unsigned int) (lit & 0x0FFL));
4676               }
4677           } else {
4678               emitcode ("addc", "a,#!constbyte",
4679                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4680           }
4681       }
4682       
4683       if (pushResult) {
4684           emitcode ("push", "acc");
4685       } else {
4686           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4687       }
4688       offset++;
4689   }
4690   _endLazyDPSEvaluation ();
4691   
4692   if (pushResult)
4693     {
4694       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4695
4696       size = getDataSize (IC_LEFT (ic));
4697       rSize = getDataSize (IC_RESULT (ic));
4698
4699       ADJUST_PUSHED_RESULT(size, rSize);
4700
4701       _startLazyDPSEvaluation ();
4702       while (size--)
4703         {
4704           emitcode ("pop", "acc");
4705           aopPut (AOP (IC_RESULT (ic)), "a", size);
4706         }
4707       _endLazyDPSEvaluation ();
4708     }
4709
4710   adjustArithmeticResult (ic);
4711
4712 release:
4713   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4716 }
4717
4718
4719 /*-----------------------------------------------------------------*/
4720 /* genMultbits :- multiplication of bits                           */
4721 /*-----------------------------------------------------------------*/
4722 static void
4723 genMultbits (operand * left,
4724              operand * right,
4725              operand * result,
4726              iCode   * ic)
4727 {
4728   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4729   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4730   aopOp(result, ic, TRUE, FALSE);
4731   outBitC (result);
4732 }
4733
4734
4735 /*-----------------------------------------------------------------*/
4736 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4737 /*-----------------------------------------------------------------*/
4738 static void
4739 genMultOneByte (operand * left,
4740                 operand * right,
4741                 operand * result,
4742                 iCode   * ic)
4743 {
4744   int size;
4745   symbol *lbl;
4746   bool runtimeSign, compiletimeSign;
4747   bool lUnsigned, rUnsigned;
4748   
4749
4750   /* (if two literals: the value is computed before) */
4751   /* if one literal, literal on the right */
4752   if (AOP_TYPE (left) == AOP_LIT)
4753     {
4754       operand *t = right;
4755       right = left;
4756       left = t;
4757       emitcode (";", "swapped left and right");
4758     }
4759
4760   /* (if two literals: the value is computed before) */
4761   /* if one literal, literal on the right */
4762   if (AOP_TYPE (left) == AOP_LIT)
4763     {
4764       operand *t = right;
4765       right = left;
4766       left = t;
4767       /* emitcode (";", "swapped left and right"); */
4768     }
4769   /* if no literal, unsigned on the right: shorter code */
4770   if (   AOP_TYPE (right) != AOP_LIT
4771       && SPEC_USIGN (getSpec (operandType (left))))
4772     {
4773       operand *t = right;
4774       right = left;
4775       left = t;
4776     }
4777
4778   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4779   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4780
4781   if ((lUnsigned && rUnsigned)
4782 /* sorry, I don't know how to get size
4783    without calling aopOp (result,...);
4784    see Feature Request  */
4785       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4786                    no need to take care about the signedness! */
4787     {
4788       /* just an unsigned 8 * 8 = 8 multiply
4789          or 8u * 8u = 16u */
4790       /* emitcode (";","unsigned"); */
4791       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4792       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4793       emitcode ("mul", "ab");
4794     
4795       _G.accInUse++; _G.bInUse++;
4796       aopOp (result, ic, TRUE, FALSE);
4797       size = AOP_SIZE (result);
4798   
4799       if (size < 1 || size > 2)
4800         {
4801           /* this should never happen */
4802           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4803                    size, __FILE__, lineno);
4804           exit (1);
4805         }
4806   
4807       aopPut (AOP (result), "a", 0);
4808       _G.accInUse--; _G.bInUse--;
4809       if (size == 2) 
4810         aopPut (AOP (result), "b", 1);
4811       return;
4812     }
4813
4814   /* we have to do a signed multiply */
4815   /* emitcode (";", "signed"); */
4816   
4817   /* now sign adjust for both left & right */
4818
4819   /* let's see what's needed: */
4820   /* apply negative sign during runtime */
4821   runtimeSign = FALSE;
4822   /* negative sign from literals */
4823   compiletimeSign = FALSE;
4824
4825   if (!lUnsigned)
4826     {
4827       if (AOP_TYPE(left) == AOP_LIT)
4828         {
4829           /* signed literal */
4830           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4831           if (val < 0)
4832             compiletimeSign = TRUE;
4833         }
4834       else
4835         /* signed but not literal */
4836         runtimeSign = TRUE;
4837     }
4838
4839   if (!rUnsigned)
4840     {
4841       if (AOP_TYPE(right) == AOP_LIT)
4842         {
4843           /* signed literal */
4844           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4845           if (val < 0)
4846             compiletimeSign ^= TRUE;
4847         }
4848       else
4849         /* signed but not literal */
4850         runtimeSign = TRUE;
4851     }
4852
4853   /* initialize F0, which stores the runtime sign */
4854   if (runtimeSign)
4855     {
4856       if (compiletimeSign)
4857         emitcode ("setb", "F0"); /* set sign flag */
4858       else
4859         emitcode ("clr", "F0"); /* reset sign flag */
4860     }
4861   
4862   /* save the signs of the operands */
4863   if (AOP_TYPE(right) == AOP_LIT)
4864     {
4865       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4866
4867       if (!rUnsigned && val < 0)
4868         emitcode ("mov", "b,#!constbyte", -val);
4869       else
4870         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4871     }
4872   else /* ! literal */
4873     {
4874       if (rUnsigned)  /* emitcode (";", "signed"); */
4875         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4876       else
4877         {
4878           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4879           lbl = newiTempLabel (NULL);
4880           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4881           emitcode ("cpl", "F0"); /* complement sign flag */
4882           emitcode ("cpl", "a");  /* 2's complement */
4883           emitcode ("inc", "a");
4884           emitcode ("", "!tlabeldef", lbl->key + 100);
4885           emitcode ("mov", "b,a");
4886         }
4887     }
4888
4889   if (AOP_TYPE(left) == AOP_LIT)
4890     {
4891       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4892
4893       if (!lUnsigned && val < 0)
4894         emitcode ("mov", "a,#!constbyte", -val);
4895       else
4896         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4897     }
4898   else /* ! literal */
4899     {
4900       if (lUnsigned)  /* emitcode (";", "signed"); */
4901
4902         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4903       else
4904         {
4905           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4906           lbl = newiTempLabel (NULL);
4907           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4908           emitcode ("cpl", "F0"); /* complement sign flag */
4909           emitcode ("cpl", "a");  /* 2's complement */
4910           emitcode ("inc", "a");
4911           emitcode ("", "!tlabeldef", lbl->key + 100);
4912         }
4913     }
4914
4915   /* now the multiplication */
4916   emitcode ("mul", "ab");
4917   _G.accInUse++;_G.bInUse++;
4918   aopOp(result, ic, TRUE, FALSE);
4919   size = AOP_SIZE (result);
4920
4921   if (size < 1 || size > 2) 
4922     {
4923       /* this should never happen */
4924       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4925                size, __FILE__, lineno);
4926       exit (1);
4927     }    
4928     
4929   if (runtimeSign || compiletimeSign)
4930     {
4931       lbl = newiTempLabel (NULL);
4932       if (runtimeSign)
4933         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4934       emitcode ("cpl", "a"); /* lsb 2's complement */
4935       if (size != 2)
4936         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4937       else
4938         {
4939           emitcode ("add", "a,#1"); /* this sets carry flag */
4940           emitcode ("xch", "a,b");
4941           emitcode ("cpl", "a"); /* msb 2's complement */
4942           emitcode ("addc", "a,#0");
4943           emitcode ("xch", "a,b");
4944         }
4945       emitcode ("", "!tlabeldef", lbl->key + 100);
4946     }
4947   aopPut (AOP (result), "a", 0);
4948   _G.accInUse--;_G.bInUse--;
4949   if (size == 2)
4950     aopPut (AOP (result), "b", 1);
4951 }
4952
4953 /*-----------------------------------------------------------------*/
4954 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4955 /*-----------------------------------------------------------------*/
4956 static void genMultTwoByte (operand *left, operand *right, 
4957                             operand *result, iCode *ic)
4958 {
4959         sym_link *retype = getSpec(operandType(right));
4960         sym_link *letype = getSpec(operandType(left));
4961         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4962         symbol *lbl;
4963
4964         if (AOP_TYPE (left) == AOP_LIT) {
4965                 operand *t = right;
4966                 right = left;
4967                 left = t;
4968         }
4969         /* save EA bit in F1 */
4970         lbl = newiTempLabel(NULL);
4971         emitcode ("setb","F1");
4972         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4973         emitcode ("clr","F1");
4974         emitcode("","!tlabeldef",lbl->key+100);
4975
4976         /* load up MB with right */
4977         if (!umult) {
4978                 emitcode("clr","F0");
4979                 if (AOP_TYPE(right) == AOP_LIT) {
4980                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4981                         if (val < 0) {
4982                                 emitcode("setb","F0");
4983                                 val = -val;
4984                         }
4985                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4986                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4987                 } else {
4988                         lbl = newiTempLabel(NULL);
4989                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4990                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4991                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4992                         emitcode ("xch", "a,b");
4993                         emitcode ("cpl","a");
4994                         emitcode ("add", "a,#1");
4995                         emitcode ("xch", "a,b");
4996                         emitcode ("cpl", "a"); // msb
4997                         emitcode ("addc", "a,#0");
4998                         emitcode ("setb","F0");
4999                         emitcode ("","!tlabeldef",lbl->key+100);
5000                         emitcode ("mov","mb,b");
5001                         emitcode ("mov","mb,a");
5002                 }
5003         } else {
5004                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5005                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5006         }
5007         /* load up MA with left */
5008         if (!umult) {
5009                 lbl = newiTempLabel(NULL);
5010                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5011                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5012                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5013                 emitcode ("xch", "a,b");
5014                 emitcode ("cpl","a");
5015                 emitcode ("add", "a,#1");
5016                 emitcode ("xch", "a,b");
5017                 emitcode ("cpl", "a"); // msb
5018                 emitcode ("addc","a,#0");
5019                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5020                 emitcode ("setb","F0");
5021                 emitcode ("","!tlabeldef",lbl->key+100);
5022                 emitcode ("mov","ma,b");
5023                 emitcode ("mov","ma,a");
5024         } else {
5025                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5026                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5027         }
5028         /* wait for multiplication to finish */
5029         lbl = newiTempLabel(NULL);
5030         emitcode("","!tlabeldef", lbl->key+100);
5031         emitcode("mov","a,mcnt1");
5032         emitcode("anl","a,#!constbyte",0x80);
5033         emitcode("jnz","!tlabel",lbl->key+100);
5034         
5035         freeAsmop (left, NULL, ic, TRUE);
5036         freeAsmop (right, NULL, ic,TRUE);
5037         aopOp(result, ic, TRUE, FALSE);
5038
5039         /* if unsigned then simple */   
5040         if (umult) {
5041                 emitcode ("mov","a,ma");
5042                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5043                 emitcode ("mov","a,ma");
5044                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5045                 aopPut(AOP(result),"ma",1);
5046                 aopPut(AOP(result),"ma",0);
5047         } else {
5048                 emitcode("push","ma");
5049                 emitcode("push","ma");
5050                 emitcode("push","ma");
5051                 MOVA("ma");
5052                 /* negate result if needed */
5053                 lbl = newiTempLabel(NULL);      
5054                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055                 emitcode("cpl","a");
5056                 emitcode("add","a,#1");
5057                 emitcode("","!tlabeldef", lbl->key+100);
5058                 if (AOP_TYPE(result) == AOP_ACC)
5059                 {
5060                     D(emitcode(";", "ACC special case."););
5061                     /* We know result is the only live aop, and 
5062                      * it's obviously not a DPTR2, so AP is available.
5063                      */
5064                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5065                 }
5066                 else
5067                 {
5068                     aopPut(AOP(result),"a",0);
5069                 }
5070             
5071                 emitcode("pop","acc");
5072                 lbl = newiTempLabel(NULL);      
5073                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5074                 emitcode("cpl","a");
5075                 emitcode("addc","a,#0");
5076                 emitcode("","!tlabeldef", lbl->key+100);
5077                 aopPut(AOP(result),"a",1);
5078                 emitcode("pop","acc");
5079                 if (AOP_SIZE(result) >= 3) {
5080                         lbl = newiTempLabel(NULL);      
5081                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5082                         emitcode("cpl","a");
5083                         emitcode("addc","a,#0");                        
5084                         emitcode("","!tlabeldef", lbl->key+100);
5085                         aopPut(AOP(result),"a",2);
5086                 }
5087                 emitcode("pop","acc");
5088                 if (AOP_SIZE(result) >= 4) {
5089                         lbl = newiTempLabel(NULL);      
5090                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5091                         emitcode("cpl","a");
5092                         emitcode("addc","a,#0");                        
5093                         emitcode("","!tlabeldef", lbl->key+100);
5094                         aopPut(AOP(result),"a",3);
5095                 }
5096                 if (AOP_TYPE(result) == AOP_ACC)
5097                 {
5098                     /* We stashed the result away above. */
5099                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5100                 }           
5101                 
5102         }
5103         freeAsmop (result, NULL, ic, TRUE);
5104
5105         /* restore EA bit in F1 */
5106         lbl = newiTempLabel(NULL);
5107         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5108         emitcode ("setb","EA");
5109         emitcode("","!tlabeldef",lbl->key+100);
5110         return ;
5111 }
5112
5113 /*-----------------------------------------------------------------*/
5114 /* genMult - generates code for multiplication                     */
5115 /*-----------------------------------------------------------------*/
5116 static void
5117 genMult (iCode * ic)
5118 {
5119   operand *left = IC_LEFT (ic);
5120   operand *right = IC_RIGHT (ic);
5121   operand *result = IC_RESULT (ic);
5122
5123   D (emitcode (";", "genMult "););
5124
5125   /* assign the amsops */
5126   AOP_OP_2 (ic);
5127
5128   /* special cases first */
5129   /* both are bits */
5130   if (AOP_TYPE (left) == AOP_CRY &&
5131       AOP_TYPE (right) == AOP_CRY)
5132     {
5133       genMultbits (left, right, result, ic);
5134       goto release;
5135     }
5136
5137   /* if both are of size == 1 */
5138   if (AOP_SIZE (left) == 1 &&
5139       AOP_SIZE (right) == 1)
5140     {
5141       genMultOneByte (left, right, result, ic);
5142       goto release;
5143     }
5144
5145   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5146           /* use the ds390 ARITHMETIC accel UNIT */
5147           genMultTwoByte (left, right, result, ic);
5148           return ;
5149   }
5150   /* should have been converted to function call */
5151   assert (0);
5152
5153 release:
5154   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5156   freeAsmop (result, NULL, ic, TRUE);
5157 }
5158
5159 /*-----------------------------------------------------------------*/
5160 /* genDivbits :- division of bits                                  */
5161 /*-----------------------------------------------------------------*/
5162 static void
5163 genDivbits (operand * left,
5164             operand * right,
5165             operand * result,
5166             iCode   * ic)
5167 {
5168
5169   char *l;
5170
5171   /* the result must be bit */
5172   LOAD_AB_FOR_DIV (left, right, l);
5173   emitcode ("div", "ab");
5174   emitcode ("rrc", "a");
5175   aopOp(result, ic, TRUE, FALSE);
5176     
5177   aopPut (AOP (result), "c", 0);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* genDivOneByte : 8 bit division                                  */
5182 /*-----------------------------------------------------------------*/
5183 static void
5184 genDivOneByte (operand * left,
5185                operand * right,
5186                operand * result,
5187                iCode   * ic)
5188 {
5189   bool lUnsigned, rUnsigned;
5190   bool runtimeSign, compiletimeSign;
5191   char *l;
5192   symbol *lbl;
5193   int size, offset;
5194
5195   offset = 1;
5196   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5197   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5198   
5199   /* signed or unsigned */
5200   if (lUnsigned && rUnsigned)
5201     {
5202       /* unsigned is easy */
5203       LOAD_AB_FOR_DIV (left, right, l);
5204       emitcode ("div", "ab");
5205
5206       _G.accInUse++;
5207       aopOp (result, ic, TRUE, FALSE);
5208       aopPut (AOP (result), "a", 0);
5209       _G.accInUse--;
5210
5211       size = AOP_SIZE (result) - 1;
5212       
5213       while (size--)
5214         aopPut (AOP (result), zero, offset++);
5215       return;
5216     }
5217
5218   /* signed is a little bit more difficult */
5219
5220   /* now sign adjust for both left & right */
5221
5222   /* let's see what's needed: */
5223   /* apply negative sign during runtime */
5224   runtimeSign = FALSE;
5225   /* negative sign from literals */
5226   compiletimeSign = FALSE;
5227
5228   if (!lUnsigned)
5229     {
5230       if (AOP_TYPE(left) == AOP_LIT)
5231         {
5232           /* signed literal */
5233           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5234           if (val < 0)
5235             compiletimeSign = TRUE;
5236         }
5237       else
5238         /* signed but not literal */
5239         runtimeSign = TRUE;
5240     }
5241
5242   if (!rUnsigned)
5243     {
5244       if (AOP_TYPE(right) == AOP_LIT)
5245         {
5246           /* signed literal */
5247           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5248           if (val < 0)
5249             compiletimeSign ^= TRUE;
5250         }
5251       else
5252         /* signed but not literal */
5253         runtimeSign = TRUE;
5254     }
5255
5256   /* initialize F0, which stores the runtime sign */
5257   if (runtimeSign)
5258     {
5259       if (compiletimeSign)
5260         emitcode ("setb", "F0"); /* set sign flag */
5261       else
5262         emitcode ("clr", "F0"); /* reset sign flag */
5263     }
5264
5265   /* save the signs of the operands */
5266   if (AOP_TYPE(right) == AOP_LIT)
5267     {
5268       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5269
5270       if (!rUnsigned && val < 0)
5271         emitcode ("mov", "b,#0x%02x", -val);
5272       else
5273         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5274     }
5275   else /* ! literal */
5276     {
5277       if (rUnsigned)
5278         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5279       else
5280         {
5281           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5282           lbl = newiTempLabel (NULL);
5283           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5284           emitcode ("cpl", "F0"); /* complement sign flag */
5285           emitcode ("cpl", "a");  /* 2's complement */
5286           emitcode ("inc", "a");
5287           emitcode ("", "!tlabeldef", lbl->key + 100);
5288           emitcode ("mov", "b,a");
5289         }
5290     }
5291
5292   if (AOP_TYPE(left) == AOP_LIT)
5293     {
5294       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5295
5296       if (!lUnsigned && val < 0)
5297         emitcode ("mov", "a,#0x%02x", -val);
5298       else
5299         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5300     }
5301   else /* ! literal */
5302     {
5303       if (lUnsigned)
5304         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5305       else
5306         {
5307           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5308           lbl = newiTempLabel (NULL);
5309           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5310           emitcode ("cpl", "F0"); /* complement sign flag */
5311           emitcode ("cpl", "a");  /* 2's complement */
5312           emitcode ("inc", "a");
5313           emitcode ("", "!tlabeldef", lbl->key + 100);
5314         }
5315     }
5316   
5317   /* now the division */
5318   emitcode ("nop", "; workaround for DS80C390 div bug.");
5319   emitcode ("div", "ab");
5320   
5321   if (runtimeSign || compiletimeSign)
5322     {
5323       lbl = newiTempLabel (NULL);
5324       if (runtimeSign)
5325         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5326       emitcode ("cpl", "a"); /* lsb 2's complement */
5327       emitcode ("inc", "a");
5328       emitcode ("", "!tlabeldef", lbl->key + 100);
5329
5330       _G.accInUse++;     _G.bInUse++;
5331       aopOp (result, ic, TRUE, FALSE);
5332       size = AOP_SIZE (result) - 1;
5333
5334       if (size > 0)
5335         {
5336           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5337              then the result will be in b, a */
5338           emitcode ("mov", "b,a"); /* 1 */
5339           /* msb is 0x00 or 0xff depending on the sign */
5340           if (runtimeSign)
5341             {
5342               emitcode ("mov",  "c,F0");
5343               emitcode ("subb", "a,acc");
5344               emitcode ("xch",  "a,b"); /* 2 */
5345               while (size--)
5346                 aopPut (AOP (result), "b", offset++); /* write msb's */
5347             }
5348           else /* compiletimeSign */
5349             while (size--)
5350               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5351         }
5352       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5353     }
5354   else
5355     {
5356       _G.accInUse++;     _G.bInUse++;
5357       aopOp(result, ic, TRUE, FALSE);
5358       size = AOP_SIZE (result) - 1;
5359       
5360       aopPut (AOP (result), "a", 0);
5361       while (size--)
5362         aopPut (AOP (result), zero, offset++);
5363     }
5364   _G.accInUse--;     _G.bInUse--;
5365
5366 }
5367
5368 /*-----------------------------------------------------------------*/
5369 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5370 /*-----------------------------------------------------------------*/
5371 static void genDivTwoByte (operand *left, operand *right, 
5372                             operand *result, iCode *ic)
5373 {
5374         sym_link *retype = getSpec(operandType(right));
5375         sym_link *letype = getSpec(operandType(left));
5376         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5377         symbol *lbl;
5378
5379         /* save EA bit in F1 */
5380         lbl = newiTempLabel(NULL);
5381         emitcode ("setb","F1");
5382         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5383         emitcode ("clr","F1");
5384         emitcode("","!tlabeldef",lbl->key+100);
5385
5386         /* load up MA with left */
5387         if (!umult) {
5388                 emitcode("clr","F0");
5389                 lbl = newiTempLabel(NULL);
5390                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5391                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5392                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5393                 emitcode ("xch", "a,b");
5394                 emitcode ("cpl","a");
5395                 emitcode ("add", "a,#1");
5396                 emitcode ("xch", "a,b");
5397                 emitcode ("cpl", "a"); // msb
5398                 emitcode ("addc","a,#0");
5399                 emitcode ("setb","F0");
5400                 emitcode ("","!tlabeldef",lbl->key+100);
5401                 emitcode ("mov","ma,b");
5402                 emitcode ("mov","ma,a");
5403         } else {
5404                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5405                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5406         }
5407
5408         /* load up MB with right */
5409         if (!umult) {
5410                 if (AOP_TYPE(right) == AOP_LIT) {
5411                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5412                         if (val < 0) {
5413                                 lbl = newiTempLabel(NULL);
5414                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5415                                 emitcode("setb","F0");
5416                                 emitcode ("","!tlabeldef",lbl->key+100);
5417                                 val = -val;
5418                         } 
5419                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5420                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5421                 } else {
5422                         lbl = newiTempLabel(NULL);
5423                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5424                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5425                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5426                         emitcode ("xch", "a,b");
5427                         emitcode ("cpl","a");
5428                         emitcode ("add", "a,#1");
5429                         emitcode ("xch", "a,b");
5430                         emitcode ("cpl", "a"); // msb
5431                         emitcode ("addc", "a,#0");
5432                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5433                         emitcode ("setb","F0");
5434                         emitcode ("","!tlabeldef",lbl->key+100);
5435                         emitcode ("mov","mb,b");
5436                         emitcode ("mov","mb,a");
5437                 }
5438         } else {
5439                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5440                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5441         }
5442
5443         /* wait for multiplication to finish */
5444         lbl = newiTempLabel(NULL);
5445         emitcode("","!tlabeldef", lbl->key+100);
5446         emitcode("mov","a,mcnt1");
5447         emitcode("anl","a,#!constbyte",0x80);
5448         emitcode("jnz","!tlabel",lbl->key+100);
5449         
5450         freeAsmop (left, NULL, ic, TRUE);
5451         freeAsmop (right, NULL, ic,TRUE);
5452         aopOp(result, ic, TRUE, FALSE);
5453
5454         /* if unsigned then simple */   
5455         if (umult) {
5456                 aopPut(AOP(result),"ma",1);
5457                 aopPut(AOP(result),"ma",0);
5458         } else {
5459                 emitcode("push","ma");
5460                 MOVA("ma");
5461                 /* negate result if needed */
5462                 lbl = newiTempLabel(NULL);      
5463                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5464                 emitcode("cpl","a");
5465                 emitcode("add","a,#1");
5466                 emitcode("","!tlabeldef", lbl->key+100);
5467                 aopPut(AOP(result),"a",0);
5468                 emitcode("pop","acc");
5469                 lbl = newiTempLabel(NULL);      
5470                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5471                 emitcode("cpl","a");
5472                 emitcode("addc","a,#0");
5473                 emitcode("","!tlabeldef", lbl->key+100);
5474                 aopPut(AOP(result),"a",1);
5475         }
5476         freeAsmop (result, NULL, ic, TRUE);
5477         /* restore EA bit in F1 */
5478         lbl = newiTempLabel(NULL);
5479         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5480         emitcode ("setb","EA");
5481         emitcode("","!tlabeldef",lbl->key+100);
5482         return ;
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* genDiv - generates code for division                            */
5487 /*-----------------------------------------------------------------*/
5488 static void
5489 genDiv (iCode * ic)
5490 {
5491   operand *left = IC_LEFT (ic);
5492   operand *right = IC_RIGHT (ic);
5493   operand *result = IC_RESULT (ic);
5494
5495   D (emitcode (";", "genDiv "););
5496
5497   /* assign the amsops */
5498   AOP_OP_2 (ic);
5499
5500   /* special cases first */
5501   /* both are bits */
5502   if (AOP_TYPE (left) == AOP_CRY &&
5503       AOP_TYPE (right) == AOP_CRY)
5504     {
5505       genDivbits (left, right, result, ic);
5506       goto release;
5507     }
5508
5509   /* if both are of size == 1 */
5510   if (AOP_SIZE (left) == 1 &&
5511       AOP_SIZE (right) == 1)
5512     {
5513       genDivOneByte (left, right, result, ic);
5514       goto release;
5515     }
5516
5517   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5518           /* use the ds390 ARITHMETIC accel UNIT */
5519           genDivTwoByte (left, right, result, ic);
5520           return ;
5521   }
5522   /* should have been converted to function call */
5523   assert (0);
5524 release:
5525   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527   freeAsmop (result, NULL, ic, TRUE);
5528 }
5529
5530 /*-----------------------------------------------------------------*/
5531 /* genModbits :- modulus of bits                                   */
5532 /*-----------------------------------------------------------------*/
5533 static void
5534 genModbits (operand * left,
5535             operand * right,
5536             operand * result,
5537             iCode   * ic)
5538 {
5539
5540   char *l;
5541
5542   /* the result must be bit */
5543   LOAD_AB_FOR_DIV (left, right, l);
5544   emitcode ("div", "ab");
5545   emitcode ("mov", "a,b");
5546   emitcode ("rrc", "a");
5547   aopOp(result, ic, TRUE, FALSE);
5548   aopPut (AOP (result), "c", 0);
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* genModOneByte : 8 bit modulus                                   */
5553 /*-----------------------------------------------------------------*/
5554 static void
5555 genModOneByte (operand * left,
5556                operand * right,
5557                operand * result,
5558                iCode   * ic)
5559 {
5560   bool lUnsigned, rUnsigned;
5561   bool runtimeSign, compiletimeSign;
5562   char *l;
5563   symbol *lbl;
5564   int size, offset;
5565
5566   offset = 1;
5567   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5568   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5569   
5570   /* signed or unsigned */
5571   if (lUnsigned && rUnsigned)
5572     {
5573       /* unsigned is easy */
5574       LOAD_AB_FOR_DIV (left, right, l);
5575       emitcode ("div", "ab");
5576       aopOp (result, ic, TRUE, FALSE);  
5577       aopPut (AOP (result), "b", 0);
5578
5579       for (size = AOP_SIZE (result) - 1; size--;)
5580         aopPut (AOP (result), zero, offset++);
5581       return;
5582     }
5583
5584   /* signed is a little bit more difficult */
5585
5586   /* now sign adjust for both left & right */
5587
5588   /* modulus: sign of the right operand has no influence on the result! */
5589   if (AOP_TYPE(right) == AOP_LIT)
5590     {
5591       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5592
5593       if (!rUnsigned && val < 0)
5594         emitcode ("mov", "b,#0x%02x", -val);
5595       else
5596         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5597     }
5598   else /* ! literal */
5599     {
5600       if (rUnsigned)
5601         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5602       else
5603         {
5604           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5605           lbl = newiTempLabel (NULL);
5606           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5607           emitcode ("cpl", "a");  /* 2's complement */
5608           emitcode ("inc", "a");
5609           emitcode ("", "!tlabeldef", lbl->key + 100);
5610           emitcode ("mov", "b,a");
5611         }
5612     }
5613   
5614   /* let's see what's needed: */
5615   /* apply negative sign during runtime */
5616   runtimeSign = FALSE;
5617   /* negative sign from literals */
5618   compiletimeSign = FALSE;
5619
5620   /* sign adjust left side */
5621   if (AOP_TYPE(left) == AOP_LIT)
5622     {
5623       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5624
5625       if (!lUnsigned && val < 0)
5626         {
5627           compiletimeSign = TRUE; /* set sign flag */
5628           emitcode ("mov", "a,#0x%02x", -val);
5629         }
5630       else
5631         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5632     }
5633   else /* ! literal */
5634     {
5635       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5636       
5637       if (!lUnsigned)
5638         {
5639           runtimeSign = TRUE;
5640           emitcode ("clr", "F0"); /* clear sign flag */
5641           
5642           lbl = newiTempLabel (NULL);
5643           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5644           emitcode ("setb", "F0"); /* set sign flag */
5645           emitcode ("cpl", "a");   /* 2's complement */
5646           emitcode ("inc", "a");
5647           emitcode ("", "!tlabeldef", lbl->key + 100);
5648         }
5649     }
5650   
5651   /* now the modulus */
5652   emitcode ("nop", "; workaround for DS80C390 div bug.");
5653   emitcode ("div", "ab");
5654   
5655   if (runtimeSign || compiletimeSign)
5656     {
5657       emitcode ("mov", "a,b");
5658       lbl = newiTempLabel (NULL);
5659       if (runtimeSign)
5660         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5661       emitcode ("cpl", "a"); /* lsb 2's complement */
5662       emitcode ("inc", "a");
5663       emitcode ("", "!tlabeldef", lbl->key + 100);
5664
5665       _G.accInUse++;     _G.bInUse++;
5666       aopOp (result, ic, TRUE, FALSE);
5667       size = AOP_SIZE (result) - 1;
5668       
5669       if (size > 0)
5670         {
5671           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5672              then the result will be in b, a */
5673           emitcode ("mov", "b,a"); /* 1 */
5674           /* msb is 0x00 or 0xff depending on the sign */
5675           if (runtimeSign)
5676             {
5677               emitcode ("mov",  "c,F0");
5678               emitcode ("subb", "a,acc");
5679               emitcode ("xch",  "a,b"); /* 2 */
5680               while (size--)
5681                 aopPut (AOP (result), "b", offset++); /* write msb's */
5682             }
5683           else /* compiletimeSign */
5684             while (size--)
5685               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5686         }
5687       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5688     }
5689   else
5690     {
5691       _G.accInUse++;     _G.bInUse++;
5692       aopOp(result, ic, TRUE, FALSE);
5693       size = AOP_SIZE (result) - 1;
5694       
5695       aopPut (AOP (result), "b", 0);
5696       while (size--)
5697         aopPut (AOP (result), zero, offset++);
5698     }
5699   _G.accInUse--;     _G.bInUse--;
5700
5701 }
5702
5703 /*-----------------------------------------------------------------*/
5704 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5705 /*-----------------------------------------------------------------*/
5706 static void genModTwoByte (operand *left, operand *right, 
5707                             operand *result, iCode *ic)
5708 {
5709         sym_link *retype = getSpec(operandType(right));
5710         sym_link *letype = getSpec(operandType(left));
5711         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5712         symbol *lbl;
5713
5714         /* load up MA with left */
5715         /* save EA bit in F1 */
5716         lbl = newiTempLabel(NULL);
5717         emitcode ("setb","F1");
5718         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5719         emitcode ("clr","F1");
5720         emitcode("","!tlabeldef",lbl->key+100);
5721
5722         if (!umult) {
5723                 lbl = newiTempLabel(NULL);
5724                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5725                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5726                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5727                 emitcode ("xch", "a,b");
5728                 emitcode ("cpl","a");
5729                 emitcode ("add", "a,#1");
5730                 emitcode ("xch", "a,b");
5731                 emitcode ("cpl", "a"); // msb
5732                 emitcode ("addc","a,#0");
5733                 emitcode ("","!tlabeldef",lbl->key+100);
5734                 emitcode ("mov","ma,b");
5735                 emitcode ("mov","ma,a");
5736         } else {
5737                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5738                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5739         }
5740
5741         /* load up MB with right */
5742         if (!umult) {
5743                 if (AOP_TYPE(right) == AOP_LIT) {
5744                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5745                         if (val < 0) {
5746                                 val = -val;
5747                         } 
5748                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5749                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5750                 } else {
5751                         lbl = newiTempLabel(NULL);
5752                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5753                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5754                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5755                         emitcode ("xch", "a,b");
5756                         emitcode ("cpl","a");
5757                         emitcode ("add", "a,#1");
5758                         emitcode ("xch", "a,b");
5759                         emitcode ("cpl", "a"); // msb
5760                         emitcode ("addc", "a,#0");
5761                         emitcode ("","!tlabeldef",lbl->key+100);
5762                         emitcode ("mov","mb,b");
5763                         emitcode ("mov","mb,a");
5764                 }
5765         } else {
5766                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5767                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5768         }
5769
5770         /* wait for multiplication to finish */
5771         lbl = newiTempLabel(NULL);
5772         emitcode("","!tlabeldef", lbl->key+100);
5773         emitcode("mov","a,mcnt1");
5774         emitcode("anl","a,#!constbyte",0x80);
5775         emitcode("jnz","!tlabel",lbl->key+100);
5776         
5777         freeAsmop (left, NULL, ic, TRUE);
5778         freeAsmop (right, NULL, ic,TRUE);
5779         aopOp(result, ic, TRUE, FALSE);
5780
5781         aopPut(AOP(result),"mb",1);
5782         aopPut(AOP(result),"mb",0);
5783         freeAsmop (result, NULL, ic, TRUE);
5784
5785         /* restore EA bit in F1 */
5786         lbl = newiTempLabel(NULL);
5787         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5788         emitcode ("setb","EA");
5789         emitcode("","!tlabeldef",lbl->key+100);
5790         return ;
5791 }
5792
5793 /*-----------------------------------------------------------------*/
5794 /* genMod - generates code for division                            */
5795 /*-----------------------------------------------------------------*/
5796 static void
5797 genMod (iCode * ic)
5798 {
5799   operand *left = IC_LEFT (ic);
5800   operand *right = IC_RIGHT (ic);
5801   operand *result = IC_RESULT (ic);
5802
5803   D (emitcode (";", "genMod "); );
5804
5805   /* assign the amsops */
5806   AOP_OP_2 (ic);
5807
5808   /* special cases first */
5809   /* both are bits */
5810   if (AOP_TYPE (left) == AOP_CRY &&
5811       AOP_TYPE (right) == AOP_CRY)
5812     {
5813       genModbits (left, right, result, ic);
5814       goto release;
5815     }
5816
5817   /* if both are of size == 1 */
5818   if (AOP_SIZE (left) == 1 &&
5819       AOP_SIZE (right) == 1)
5820     {
5821       genModOneByte (left, right, result, ic);
5822       goto release;
5823     }
5824
5825   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5826           /* use the ds390 ARITHMETIC accel UNIT */
5827           genModTwoByte (left, right, result, ic);
5828           return ;
5829   }
5830
5831   /* should have been converted to function call */
5832   assert (0);
5833
5834 release:
5835   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837   freeAsmop (result, NULL, ic, TRUE);
5838 }
5839
5840 /*-----------------------------------------------------------------*/
5841 /* genIfxJump :- will create a jump depending on the ifx           */
5842 /*-----------------------------------------------------------------*/
5843 static void
5844 genIfxJump (iCode * ic, char *jval)
5845 {
5846   symbol *jlbl;
5847   symbol *tlbl = newiTempLabel (NULL);
5848   char *inst;
5849
5850   D (emitcode (";", "genIfxJump"););
5851
5852   /* if true label then we jump if condition
5853      supplied is true */
5854   if (IC_TRUE (ic))
5855     {
5856       jlbl = IC_TRUE (ic);
5857       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5858                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5859     }
5860   else
5861     {
5862       /* false label is present */
5863       jlbl = IC_FALSE (ic);
5864       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5865                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5866     }
5867   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5868     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5869   else
5870     emitcode (inst, "!tlabel", tlbl->key + 100);
5871   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5872   emitcode ("", "!tlabeldef", tlbl->key + 100);
5873
5874   /* mark the icode as generated */
5875   ic->generated = 1;
5876 }
5877
5878 /*-----------------------------------------------------------------*/
5879 /* genCmp :- greater or less than comparison                       */
5880 /*-----------------------------------------------------------------*/
5881 static void
5882 genCmp (operand * left, operand * right,
5883         iCode * ic, iCode * ifx, int sign)
5884 {
5885   int size, offset = 0;
5886   unsigned long lit = 0L;
5887   operand *result;
5888
5889   D (emitcode (";", "genCmp"););
5890
5891   result = IC_RESULT (ic);
5892
5893   /* if left & right are bit variables */
5894   if (AOP_TYPE (left) == AOP_CRY &&
5895       AOP_TYPE (right) == AOP_CRY)
5896     {
5897       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5898       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5899     }
5900   else
5901     {
5902       /* subtract right from left if at the
5903          end the carry flag is set then we know that
5904          left is greater than right */
5905       size = max (AOP_SIZE (left), AOP_SIZE (right));
5906
5907       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5908       if ((size == 1) && !sign 
5909           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5910         {
5911           symbol *lbl = newiTempLabel (NULL);
5912           emitcode ("cjne", "%s,%s,!tlabel",
5913                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5914                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5915                     lbl->key + 100);
5916           emitcode ("", "!tlabeldef", lbl->key + 100);
5917         }
5918       else
5919         {
5920           if (AOP_TYPE (right) == AOP_LIT)
5921             {
5922               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5923               /* optimize if(x < 0) or if(x >= 0) */
5924               if (lit == 0L)
5925                 {
5926                   if (!sign)
5927                     {
5928                       CLRC;
5929                     }
5930                   else
5931                     {
5932                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5933
5934                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936
5937                       aopOp (result, ic, FALSE, FALSE);
5938
5939                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5940                         {
5941                           freeAsmop (result, NULL, ic, TRUE);
5942                           genIfxJump (ifx, "acc.7");
5943                           return;
5944                         }
5945                       else
5946                         {
5947                           emitcode ("rlc", "a");
5948                         }
5949                       goto release_freedLR;
5950                     }
5951                   goto release;
5952                 }
5953             }
5954           CLRC;
5955           while (size--)
5956             {
5957               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5958               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5959               // emitcode (";", "genCmp #2");
5960               if (sign && (size == 0))
5961                 {
5962                   // emitcode (";", "genCmp #3");
5963                   emitcode ("xrl", "a,#!constbyte",0x80);
5964                   if (AOP_TYPE (right) == AOP_LIT)
5965                     {
5966                       unsigned long lit = (unsigned long)
5967                       floatFromVal (AOP (right)->aopu.aop_lit);
5968                       // emitcode (";", "genCmp #3.1");
5969                       emitcode ("subb", "a,#!constbyte",
5970                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5971                     }
5972                   else
5973                     {
5974                       // emitcode (";", "genCmp #3.2");
5975                       saveAccWarn = 0;  
5976                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5977                       saveAccWarn = DEFAULT_ACC_WARNING;
5978                       emitcode ("xrl", "b,#!constbyte",0x80);
5979                       emitcode ("subb", "a,b");
5980                     }
5981                 }
5982               else
5983                 {
5984                   const char *s;
5985
5986                   // emitcode (";", "genCmp #4");
5987                   saveAccWarn = 0;
5988                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5989                   saveAccWarn = DEFAULT_ACC_WARNING;
5990
5991                   emitcode ("subb", "a,%s", s);
5992                 }
5993             }
5994         }
5995     }
5996
5997 release:
5998 /* Don't need the left & right operands any more; do need the result. */
5999   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001
6002   aopOp (result, ic, FALSE, FALSE);
6003
6004 release_freedLR:
6005
6006   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6007     {
6008       outBitC (result);
6009     }
6010   else
6011     {
6012       /* if the result is used in the next
6013          ifx conditional branch then generate
6014          code a little differently */
6015       if (ifx)
6016         {
6017           genIfxJump (ifx, "c");
6018         }
6019       else
6020         {
6021           outBitC (result);
6022         }
6023       /* leave the result in acc */
6024     }
6025   freeAsmop (result, NULL, ic, TRUE);
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpGt :- greater than comparison                             */
6030 /*-----------------------------------------------------------------*/
6031 static void
6032 genCmpGt (iCode * ic, iCode * ifx)
6033 {
6034   operand *left, *right;
6035   sym_link *letype, *retype;
6036   int sign;
6037
6038   D (emitcode (";", "genCmpGt ");
6039     );
6040
6041   left = IC_LEFT (ic);
6042   right = IC_RIGHT (ic);
6043
6044   letype = getSpec (operandType (left));
6045   retype = getSpec (operandType (right));
6046   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6047
6048   /* assign the left & right amsops */
6049   AOP_OP_2 (ic);
6050
6051   genCmp (right, left, ic, ifx, sign);
6052 }
6053
6054 /*-----------------------------------------------------------------*/
6055 /* genCmpLt - less than comparisons                                */
6056 /*-----------------------------------------------------------------*/
6057 static void
6058 genCmpLt (iCode * ic, iCode * ifx)
6059 {
6060   operand *left, *right;
6061   sym_link *letype, *retype;
6062   int sign;
6063
6064   D (emitcode (";", "genCmpLt "););
6065
6066   left = IC_LEFT (ic);
6067   right = IC_RIGHT (ic);
6068
6069   letype = getSpec (operandType (left));
6070   retype = getSpec (operandType (right));
6071   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6072
6073   /* assign the left & right amsops */
6074   AOP_OP_2 (ic);
6075
6076   genCmp (left, right, ic, ifx, sign);
6077 }
6078
6079 /*-----------------------------------------------------------------*/
6080 /* gencjneshort - compare and jump if not equal                    */
6081 /*-----------------------------------------------------------------*/
6082 static void
6083 gencjneshort (operand * left, operand * right, symbol * lbl)
6084 {
6085   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6086   int offset = 0;
6087   unsigned long lit = 0L;
6088
6089   D (emitcode (";", "gencjneshort");
6090     );
6091
6092   /* if the left side is a literal or
6093      if the right is in a pointer register and left
6094      is not */
6095   if ((AOP_TYPE (left) == AOP_LIT) ||
6096       (AOP_TYPE (left) == AOP_IMMD) ||
6097       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6098     {
6099       operand *t = right;
6100       right = left;
6101       left = t;
6102     }
6103
6104   if (AOP_TYPE (right) == AOP_LIT)
6105     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6106
6107   if (opIsGptr (left) || opIsGptr (right))
6108     {
6109       /* We are comparing a generic pointer to something.
6110        * Exclude the generic type byte from the comparison.
6111        */
6112       size--;
6113       D (emitcode (";", "cjneshort: generic ptr special case."););
6114     }
6115
6116
6117   /* if the right side is a literal then anything goes */
6118   if (AOP_TYPE (right) == AOP_LIT &&
6119       AOP_TYPE (left) != AOP_DIR)
6120     {
6121       while (size--)
6122         {
6123           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6124           emitcode ("cjne", "a,%s,!tlabel",
6125                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6126                     lbl->key + 100);
6127           offset++;
6128         }
6129     }
6130
6131   /* if the right side is in a register or in direct space or
6132      if the left is a pointer register & right is not */
6133   else if (AOP_TYPE (right) == AOP_REG ||
6134            AOP_TYPE (right) == AOP_DIR ||
6135            AOP_TYPE (right) == AOP_LIT ||
6136            AOP_TYPE (right) == AOP_IMMD ||
6137            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6138            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6139     {
6140       while (size--)
6141         {
6142           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6143           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6144               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6145             emitcode ("jnz", "!tlabel", lbl->key + 100);
6146           else
6147             emitcode ("cjne", "a,%s,!tlabel",
6148                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6149                       lbl->key + 100);
6150           offset++;
6151         }
6152     }
6153   else
6154     {
6155       /* right is a pointer reg need both a & b */
6156       while (size--)
6157         {
6158           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6159           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6160           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6161           offset++;
6162         }
6163     }
6164 }
6165
6166 /*-----------------------------------------------------------------*/
6167 /* gencjne - compare and jump if not equal                         */
6168 /*-----------------------------------------------------------------*/
6169 static void
6170 gencjne (operand * left, operand * right, symbol * lbl)
6171 {
6172   symbol *tlbl = newiTempLabel (NULL);
6173
6174   D (emitcode (";", "gencjne");
6175     );
6176
6177   gencjneshort (left, right, lbl);
6178
6179   emitcode ("mov", "a,%s", one);
6180   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6181   emitcode ("", "!tlabeldef", lbl->key + 100);
6182   emitcode ("clr", "a");
6183   emitcode ("", "!tlabeldef", tlbl->key + 100);
6184 }
6185
6186 /*-----------------------------------------------------------------*/
6187 /* genCmpEq - generates code for equal to                          */
6188 /*-----------------------------------------------------------------*/
6189 static void
6190 genCmpEq (iCode * ic, iCode * ifx)
6191 {
6192   operand *left, *right, *result;
6193
6194   D (emitcode (";", "genCmpEq ");
6195     );
6196
6197   AOP_OP_2 (ic);
6198   AOP_SET_LOCALS (ic);
6199
6200   /* if literal, literal on the right or
6201      if the right is in a pointer register and left
6202      is not */
6203   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6204       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6205     {
6206       operand *t = IC_RIGHT (ic);
6207       IC_RIGHT (ic) = IC_LEFT (ic);
6208       IC_LEFT (ic) = t;
6209     }
6210
6211   if (ifx &&                    /* !AOP_SIZE(result) */
6212       OP_SYMBOL (result) &&
6213       OP_SYMBOL (result)->regType == REG_CND)
6214     {
6215       symbol *tlbl;
6216       /* if they are both bit variables */
6217       if (AOP_TYPE (left) == AOP_CRY &&
6218           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6219         {
6220           if (AOP_TYPE (right) == AOP_LIT)
6221             {
6222               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6223               if (lit == 0L)
6224                 {
6225                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6226                   emitcode ("cpl", "c");
6227                 }
6228               else if (lit == 1L)
6229                 {
6230                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6231                 }
6232               else
6233                 {
6234                   emitcode ("clr", "c");
6235                 }
6236               /* AOP_TYPE(right) == AOP_CRY */
6237             }
6238           else
6239             {
6240               symbol *lbl = newiTempLabel (NULL);
6241               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6242               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6243               emitcode ("cpl", "c");
6244               emitcode ("", "!tlabeldef", (lbl->key + 100));
6245             }
6246           /* if true label then we jump if condition
6247              supplied is true */
6248           tlbl = newiTempLabel (NULL);
6249           if (IC_TRUE (ifx))
6250             {
6251               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6252               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6253             }
6254           else
6255             {
6256               emitcode ("jc", "!tlabel", tlbl->key + 100);
6257               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6258             }
6259           emitcode ("", "!tlabeldef", tlbl->key + 100);
6260         }
6261       else
6262         {
6263           tlbl = newiTempLabel (NULL);
6264           gencjneshort (left, right, tlbl);
6265           if (IC_TRUE (ifx))
6266             {
6267               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6268               emitcode ("", "!tlabeldef", tlbl->key + 100);
6269             }
6270           else
6271             {
6272               symbol *lbl = newiTempLabel (NULL);
6273               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6274               emitcode ("", "!tlabeldef", tlbl->key + 100);
6275               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6276               emitcode ("", "!tlabeldef", lbl->key + 100);
6277             }
6278         }
6279       /* mark the icode as generated */
6280       ifx->generated = 1;
6281
6282       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6283       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6284       return;
6285     }
6286
6287   /* if they are both bit variables */
6288   if (AOP_TYPE (left) == AOP_CRY &&
6289       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6290     {
6291       if (AOP_TYPE (right) == AOP_LIT)
6292         {
6293           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6294           if (lit == 0L)
6295             {
6296               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297               emitcode ("cpl", "c");
6298             }
6299           else if (lit == 1L)
6300             {
6301               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6302             }
6303           else
6304             {
6305               emitcode ("clr", "c");
6306             }
6307           /* AOP_TYPE(right) == AOP_CRY */
6308         }
6309       else
6310         {
6311           symbol *lbl = newiTempLabel (NULL);
6312           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6313           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6314           emitcode ("cpl", "c");
6315           emitcode ("", "!tlabeldef", (lbl->key + 100));
6316         }
6317
6318       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6320
6321       aopOp (result, ic, TRUE, FALSE);
6322
6323       /* c = 1 if egal */
6324       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6325         {
6326           outBitC (result);
6327           goto release;
6328         }
6329       if (ifx)
6330         {
6331           genIfxJump (ifx, "c");
6332           goto release;
6333         }
6334       /* if the result is used in an arithmetic operation
6335          then put the result in place */
6336       outBitC (result);
6337     }
6338   else
6339     {
6340       gencjne (left, right, newiTempLabel (NULL));
6341
6342       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344
6345       aopOp (result, ic, TRUE, FALSE);
6346
6347       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6348         {
6349           aopPut (AOP (result), "a", 0);
6350           goto release;
6351         }
6352       if (ifx)
6353         {
6354           genIfxJump (ifx, "a");
6355           goto release;
6356         }
6357       /* if the result is used in an arithmetic operation
6358          then put the result in place */
6359       if (AOP_TYPE (result) != AOP_CRY)
6360         outAcc (result);
6361       /* leave the result in acc */
6362     }
6363
6364 release:
6365   freeAsmop (result, NULL, ic, TRUE);
6366 }
6367
6368 /*-----------------------------------------------------------------*/
6369 /* ifxForOp - returns the icode containing the ifx for operand     */
6370 /*-----------------------------------------------------------------*/
6371 static iCode *
6372 ifxForOp (operand * op, iCode * ic)
6373 {
6374   /* if true symbol then needs to be assigned */
6375   if (IS_TRUE_SYMOP (op))
6376     return NULL;
6377
6378   /* if this has register type condition and
6379      the next instruction is ifx with the same operand
6380      and live to of the operand is upto the ifx only then */
6381   if (ic->next &&
6382       ic->next->op == IFX &&
6383       IC_COND (ic->next)->key == op->key &&
6384       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6385     return ic->next;
6386
6387   return NULL;
6388 }
6389 /*-----------------------------------------------------------------*/
6390 /* hasInc - operand is incremented before any other use            */
6391 /*-----------------------------------------------------------------*/
6392 static iCode *
6393 hasInc (operand *op, iCode *ic, int osize)
6394 {
6395   sym_link *type = operandType(op);
6396   sym_link *retype = getSpec (type);
6397   iCode *lic = ic->next;
6398   int isize ;
6399   
6400   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6401   if (!IS_SYMOP(op)) return NULL;
6402
6403   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6404   if (IS_AGGREGATE(type->next)) return NULL;
6405   if (osize != (isize = getSize(type->next))) return NULL;
6406
6407   while (lic) {
6408       /* if operand of the form op = op + <sizeof *op> */
6409       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6410           isOperandEqual(IC_RESULT(lic),op) && 
6411           isOperandLiteral(IC_RIGHT(lic)) &&
6412           operandLitValue(IC_RIGHT(lic)) == isize) {
6413           return lic;
6414       }
6415       /* if the operand used or deffed */
6416       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6417           return NULL;
6418       }
6419       /* if GOTO or IFX */
6420       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6421       lic = lic->next;
6422   }
6423   return NULL;
6424 }
6425
6426 /*-----------------------------------------------------------------*/
6427 /* genAndOp - for && operation                                     */
6428 /*-----------------------------------------------------------------*/
6429 static void
6430 genAndOp (iCode * ic)
6431 {
6432   operand *left, *right, *result;
6433   symbol *tlbl;
6434
6435   D (emitcode (";", "genAndOp "););
6436
6437   /* note here that && operations that are in an
6438      if statement are taken away by backPatchLabels
6439      only those used in arthmetic operations remain */
6440   AOP_OP_2 (ic);
6441   AOP_SET_LOCALS (ic);
6442
6443   /* if both are bit variables */
6444   if (AOP_TYPE (left) == AOP_CRY &&
6445       AOP_TYPE (right) == AOP_CRY)
6446     {
6447       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6448       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6449       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451   
6452       aopOp (result,ic,FALSE, FALSE);
6453       outBitC (result);
6454     }
6455   else
6456     {
6457       tlbl = newiTempLabel (NULL);
6458       toBoolean (left);
6459       emitcode ("jz", "!tlabel", tlbl->key + 100);
6460       toBoolean (right);
6461       emitcode ("", "!tlabeldef", tlbl->key + 100);
6462       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464   
6465       aopOp (result,ic,FALSE, FALSE);
6466       outBitAcc (result);
6467     }
6468     freeAsmop (result, NULL, ic, TRUE);
6469 }
6470
6471
6472 /*-----------------------------------------------------------------*/
6473 /* genOrOp - for || operation                                      */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 genOrOp (iCode * ic)
6477 {
6478   operand *left, *right, *result;
6479   symbol *tlbl;
6480
6481   D (emitcode (";", "genOrOp "););
6482
6483   /* note here that || operations that are in an
6484      if statement are taken away by backPatchLabels
6485      only those used in arthmetic operations remain */
6486   AOP_OP_2 (ic);
6487   AOP_SET_LOCALS (ic);
6488
6489   /* if both are bit variables */
6490   if (AOP_TYPE (left) == AOP_CRY &&
6491       AOP_TYPE (right) == AOP_CRY)
6492     {
6493       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6494       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6495       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6496       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6497   
6498       aopOp (result,ic,FALSE, FALSE);
6499       
6500       outBitC (result);
6501     }
6502   else
6503     {
6504       tlbl = newiTempLabel (NULL);
6505       toBoolean (left);
6506       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6507       toBoolean (right);
6508       emitcode ("", "!tlabeldef", tlbl->key + 100);
6509       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511   
6512       aopOp (result,ic,FALSE, FALSE);
6513       
6514       outBitAcc (result);
6515     }
6516
6517   freeAsmop (result, NULL, ic, TRUE);
6518 }
6519
6520 /*-----------------------------------------------------------------*/
6521 /* isLiteralBit - test if lit == 2^n                               */
6522 /*-----------------------------------------------------------------*/
6523 static int
6524 isLiteralBit (unsigned long lit)
6525 {
6526   unsigned long pw[32] =
6527   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6528    0x100L, 0x200L, 0x400L, 0x800L,
6529    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6530    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6531    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6532    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6533    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6534   int idx;
6535
6536   for (idx = 0; idx < 32; idx++)
6537     if (lit == pw[idx])
6538       return idx + 1;
6539   return 0;
6540 }
6541
6542 /*-----------------------------------------------------------------*/
6543 /* continueIfTrue -                                                */
6544 /*-----------------------------------------------------------------*/
6545 static void
6546 continueIfTrue (iCode * ic)
6547 {
6548   if (IC_TRUE (ic))
6549     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6550   ic->generated = 1;
6551 }
6552
6553 /*-----------------------------------------------------------------*/
6554 /* jmpIfTrue -                                                     */
6555 /*-----------------------------------------------------------------*/
6556 static void
6557 jumpIfTrue (iCode * ic)
6558 {
6559   if (!IC_TRUE (ic))
6560     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6561   ic->generated = 1;
6562 }
6563
6564 /*-----------------------------------------------------------------*/
6565 /* jmpTrueOrFalse -                                                */
6566 /*-----------------------------------------------------------------*/
6567 static void
6568 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6569 {
6570   // ugly but optimized by peephole
6571   if (IC_TRUE (ic))
6572     {
6573       symbol *nlbl = newiTempLabel (NULL);
6574       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6575       emitcode ("", "!tlabeldef", tlbl->key + 100);
6576       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6577       emitcode ("", "!tlabeldef", nlbl->key + 100);
6578     }
6579   else
6580     {
6581       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6582       emitcode ("", "!tlabeldef", tlbl->key + 100);
6583     }
6584   ic->generated = 1;
6585 }
6586
6587 // Generate code to perform a bit-wise logic operation
6588 // on two operands in far space (assumed to already have been 
6589 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6590 // in far space. This requires pushing the result on the stack
6591 // then popping it into the result.
6592 static void
6593 genFarFarLogicOp(iCode *ic, char *logicOp)
6594 {
6595       int size, resultSize, compSize;
6596       int offset = 0;
6597       
6598       TR_AP("#5");
6599       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6600       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6601                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6602       
6603       _startLazyDPSEvaluation();
6604       for (size = compSize; (size--); offset++)
6605       {
6606           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6607           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6608           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6609           
6610           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6611           emitcode ("push", "acc");
6612       }
6613       _endLazyDPSEvaluation();
6614      
6615       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6617       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6618      
6619       resultSize = AOP_SIZE(IC_RESULT(ic));
6620
6621       ADJUST_PUSHED_RESULT(compSize, resultSize);
6622
6623       _startLazyDPSEvaluation();
6624       while (compSize--)
6625       {
6626           emitcode ("pop", "acc");
6627           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6628       }
6629       _endLazyDPSEvaluation();
6630       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6631 }
6632
6633
6634 /*-----------------------------------------------------------------*/
6635 /* genAnd  - code for and                                          */
6636 /*-----------------------------------------------------------------*/
6637 static void
6638 genAnd (iCode * ic, iCode * ifx)
6639 {
6640   operand *left, *right, *result;
6641   int size, offset = 0;
6642   unsigned long lit = 0L;
6643   int bytelit;
6644   char buff[10];
6645   bool pushResult;
6646
6647   D (emitcode (";", "genAnd "););
6648
6649   AOP_OP_3_NOFATAL (ic, pushResult);
6650   AOP_SET_LOCALS (ic);
6651
6652   if (pushResult)
6653   {
6654       genFarFarLogicOp(ic, "anl");
6655       return;
6656   }  
6657
6658 #ifdef DEBUG_TYPE
6659   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6660             AOP_TYPE (result),
6661             AOP_TYPE (left), AOP_TYPE (right));
6662   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6663             AOP_SIZE (result),
6664             AOP_SIZE (left), AOP_SIZE (right));
6665 #endif
6666
6667   /* if left is a literal & right is not then exchange them */
6668   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6669 #ifdef LOGIC_OPS_BROKEN      
6670     ||  AOP_NEEDSACC (left)
6671 #endif
6672     )
6673     {
6674       operand *tmp = right;
6675       right = left;
6676       left = tmp;
6677     }
6678
6679   /* if result = right then exchange them */
6680   if (sameRegs (AOP (result), AOP (right)))
6681     {
6682       operand *tmp = right;
6683       right = left;
6684       left = tmp;
6685     }
6686
6687   /* if right is bit then exchange them */
6688   if (AOP_TYPE (right) == AOP_CRY &&
6689       AOP_TYPE (left) != AOP_CRY)
6690     {
6691       operand *tmp = right;
6692       right = left;
6693       left = tmp;
6694     }
6695   if (AOP_TYPE (right) == AOP_LIT)
6696     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6697
6698   size = AOP_SIZE (result);
6699
6700   // if(bit & yy)
6701   // result = bit & yy;
6702   if (AOP_TYPE (left) == AOP_CRY)
6703     {
6704       // c = bit & literal;
6705       if (AOP_TYPE (right) == AOP_LIT)
6706         {
6707           if (lit & 1)
6708             {
6709               if (size && sameRegs (AOP (result), AOP (left)))
6710                 // no change
6711                 goto release;
6712               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6713             }
6714           else
6715             {
6716               // bit(result) = 0;
6717               if (size && (AOP_TYPE (result) == AOP_CRY))
6718                 {
6719                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6720                   goto release;
6721                 }
6722               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6723                 {
6724                   jumpIfTrue (ifx);
6725                   goto release;
6726                 }
6727               emitcode ("clr", "c");
6728             }
6729         }
6730       else
6731         {
6732           if (AOP_TYPE (right) == AOP_CRY)
6733             {
6734               // c = bit & bit;
6735               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6736               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6737             }
6738           else
6739             {
6740               // c = bit & val;
6741               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6742               // c = lsb
6743               emitcode ("rrc", "a");
6744               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6745             }
6746         }
6747       // bit = c
6748       // val = c
6749       if (size)
6750         outBitC (result);
6751       // if(bit & ...)
6752       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6753         genIfxJump (ifx, "c");
6754       goto release;
6755     }
6756
6757   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6758   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6759   if ((AOP_TYPE (right) == AOP_LIT) &&
6760       (AOP_TYPE (result) == AOP_CRY) &&
6761       (AOP_TYPE (left) != AOP_CRY))
6762     {
6763       int posbit = isLiteralBit (lit);
6764       /* left &  2^n */
6765       if (posbit)
6766         {
6767           posbit--;
6768           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6769           // bit = left & 2^n
6770           if (size)
6771             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6772           // if(left &  2^n)
6773           else
6774             {
6775               if (ifx)
6776                 {
6777                   SNPRINTF (buff, sizeof(buff), 
6778                             "acc.%d", posbit & 0x07);
6779                   genIfxJump (ifx, buff);
6780                 }
6781               else 
6782                   {
6783                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6784                   }
6785               goto release;
6786             }
6787         }
6788       else
6789         {
6790           symbol *tlbl = newiTempLabel (NULL);
6791           int sizel = AOP_SIZE (left);
6792           if (size)
6793             emitcode ("setb", "c");
6794           while (sizel--)
6795             {
6796               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6797                 {
6798                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799                   // byte ==  2^n ?
6800                   if ((posbit = isLiteralBit (bytelit)) != 0)
6801                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6802                   else
6803                     {
6804                       if (bytelit != 0x0FFL)
6805                         emitcode ("anl", "a,%s",
6806                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6807                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6808                     }
6809                 }
6810               offset++;
6811             }
6812           // bit = left & literal
6813           if (size)
6814             {
6815               emitcode ("clr", "c");
6816               emitcode ("", "!tlabeldef", tlbl->key + 100);
6817             }
6818           // if(left & literal)
6819           else
6820             {
6821               if (ifx)
6822                 jmpTrueOrFalse (ifx, tlbl);
6823               else
6824                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6825               goto release;
6826             }
6827         }
6828       outBitC (result);
6829       goto release;
6830     }
6831
6832   /* if left is same as result */
6833   if (sameRegs (AOP (result), AOP (left)))
6834     {
6835       for (; size--; offset++)
6836         {
6837           if (AOP_TYPE (right) == AOP_LIT)
6838             {
6839               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6840                 continue;
6841               else if (bytelit == 0)
6842                 aopPut (AOP (result), zero, offset);
6843               else if (IS_AOP_PREG (result))
6844                 {
6845                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6846                   emitcode ("anl", "a,%s",
6847                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6848                   aopPut (AOP (result), "a", offset);
6849                 }
6850               else
6851                 emitcode ("anl", "%s,%s",
6852                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6853                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6854             }
6855           else
6856             {
6857               if (AOP_TYPE (left) == AOP_ACC)
6858                 emitcode ("anl", "a,%s",
6859                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6860               else
6861                 {
6862                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6863                   if (IS_AOP_PREG (result))
6864                     {
6865                       emitcode ("anl", "a,%s",
6866                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6867                       aopPut (AOP (result), "a", offset);
6868                     }
6869                   else
6870                     emitcode ("anl", "%s,a",
6871                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6872                 }
6873             }
6874         }
6875     }
6876   else
6877     {
6878       // left & result in different registers
6879       if (AOP_TYPE (result) == AOP_CRY)
6880         {
6881           // result = bit
6882           // if(size), result in bit
6883           // if(!size && ifx), conditional oper: if(left & right)
6884           symbol *tlbl = newiTempLabel (NULL);
6885           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6886           if (size)
6887             emitcode ("setb", "c");
6888           while (sizer--)
6889             {
6890               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6891                 emitcode ("anl", "a,%s",
6892                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6893               } else {
6894                 if (AOP_TYPE(left)==AOP_ACC) {
6895                   emitcode("mov", "b,a");
6896                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6897                   emitcode("anl", "a,b");
6898                 }else {
6899                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6900                   emitcode ("anl", "a,%s",
6901                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6902                 }
6903               }
6904               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6905               offset++;
6906             }
6907           if (size)
6908             {
6909               CLRC;
6910               emitcode ("", "!tlabeldef", tlbl->key + 100);
6911               outBitC (result);
6912             }
6913           else if (ifx)
6914             jmpTrueOrFalse (ifx, tlbl);
6915           else
6916             emitcode ("", "!tlabeldef", tlbl->key + 100);
6917         }
6918       else
6919         {
6920           for (; (size--); offset++)
6921             {
6922               // normal case
6923               // result = left & right
6924               if (AOP_TYPE (right) == AOP_LIT)
6925                 {
6926                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6927                     {
6928                       aopPut (AOP (result),
6929                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6930                               offset);
6931                       continue;
6932                     }
6933                   else if (bytelit == 0)
6934                     {
6935                       aopPut (AOP (result), zero, offset);
6936                       continue;
6937                     }
6938                   D (emitcode (";", "better literal AND."););
6939                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6940                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6941                                                     FALSE, FALSE, DP2_RESULT_REG));
6942
6943                 }
6944               else
6945                 {
6946                   // faster than result <- left, anl result,right
6947                   // and better if result is SFR
6948                   if (AOP_TYPE (left) == AOP_ACC)
6949                     {
6950                       emitcode ("anl", "a,%s", 
6951                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6952                     }
6953                   else
6954                     {
6955                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6956                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6957                       {
6958                           emitcode("mov", "b,a");
6959                           rOp = "b";
6960                       }
6961                         
6962                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6963                       emitcode ("anl", "a,%s", rOp);
6964                     }                   
6965                 }
6966               aopPut (AOP (result), "a", offset);
6967             }
6968         }
6969     }
6970
6971 release:
6972   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6973   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6974   freeAsmop (result, NULL, ic, TRUE);
6975 }
6976
6977
6978 /*-----------------------------------------------------------------*/
6979 /* genOr  - code for or                                            */
6980 /*-----------------------------------------------------------------*/
6981 static void
6982 genOr (iCode * ic, iCode * ifx)
6983 {
6984   operand *left, *right, *result;
6985   int size, offset = 0;
6986   unsigned long lit = 0L;
6987   bool     pushResult;
6988
6989   D (emitcode (";", "genOr "););
6990
6991   AOP_OP_3_NOFATAL (ic, pushResult);
6992   AOP_SET_LOCALS (ic);
6993
6994   if (pushResult)
6995   {
6996       genFarFarLogicOp(ic, "orl");
6997       return;
6998   }
6999
7000
7001 #ifdef DEBUG_TYPE
7002   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7003             AOP_TYPE (result),
7004             AOP_TYPE (left), AOP_TYPE (right));
7005   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7006             AOP_SIZE (result),
7007             AOP_SIZE (left), AOP_SIZE (right));
7008 #endif
7009
7010   /* if left is a literal & right is not then exchange them */
7011   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7012 #ifdef LOGIC_OPS_BROKEN
7013    || AOP_NEEDSACC (left) // I think this is a net loss now.
7014 #endif      
7015       )
7016     {
7017       operand *tmp = right;
7018       right = left;
7019       left = tmp;
7020     }
7021
7022   /* if result = right then exchange them */
7023   if (sameRegs (AOP (result), AOP (right)))
7024     {
7025       operand *tmp = right;
7026       right = left;
7027       left = tmp;
7028     }
7029
7030   /* if right is bit then exchange them */
7031   if (AOP_TYPE (right) == AOP_CRY &&
7032       AOP_TYPE (left) != AOP_CRY)
7033     {
7034       operand *tmp = right;
7035       right = left;
7036       left = tmp;
7037     }
7038   if (AOP_TYPE (right) == AOP_LIT)
7039     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7040
7041   size = AOP_SIZE (result);
7042
7043   // if(bit | yy)
7044   // xx = bit | yy;
7045   if (AOP_TYPE (left) == AOP_CRY)
7046     {
7047       if (AOP_TYPE (right) == AOP_LIT)
7048         {
7049           // c = bit & literal;
7050           if (lit)
7051             {
7052               // lit != 0 => result = 1
7053               if (AOP_TYPE (result) == AOP_CRY)
7054                 {
7055                   if (size)
7056                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7057                   else if (ifx)
7058                     continueIfTrue (ifx);
7059                   goto release;
7060                 }
7061               emitcode ("setb", "c");
7062             }
7063           else
7064             {
7065               // lit == 0 => result = left
7066               if (size && sameRegs (AOP (result), AOP (left)))
7067                 goto release;
7068               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7069             }
7070         }
7071       else
7072         {
7073           if (AOP_TYPE (right) == AOP_CRY)
7074             {
7075               // c = bit | bit;
7076               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7077               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7078             }
7079           else
7080             {
7081               // c = bit | val;
7082               symbol *tlbl = newiTempLabel (NULL);
7083               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7084                 emitcode ("setb", "c");
7085               emitcode ("jb", "%s,!tlabel",
7086                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7087               toBoolean (right);
7088               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7089               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7090                 {
7091                   jmpTrueOrFalse (ifx, tlbl);
7092                   goto release;
7093                 }
7094               else
7095                 {
7096                   CLRC;
7097                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7098                 }
7099             }
7100         }
7101       // bit = c
7102       // val = c
7103       if (size)
7104         outBitC (result);
7105       // if(bit | ...)
7106       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7107            genIfxJump (ifx, "c");
7108       goto release;
7109     }
7110
7111   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7112   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7113   if ((AOP_TYPE (right) == AOP_LIT) &&
7114       (AOP_TYPE (result) == AOP_CRY) &&
7115       (AOP_TYPE (left) != AOP_CRY))
7116     {
7117       if (lit)
7118         {
7119           // result = 1
7120           if (size)
7121             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7122           else
7123             continueIfTrue (ifx);
7124           goto release;
7125         }
7126       else
7127         {
7128           // lit = 0, result = boolean(left)
7129           if (size)
7130             emitcode ("setb", "c");
7131           toBoolean (right);
7132           if (size)
7133             {
7134               symbol *tlbl = newiTempLabel (NULL);
7135               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7136               CLRC;
7137               emitcode ("", "!tlabeldef", tlbl->key + 100);
7138             }
7139           else
7140             {
7141               genIfxJump (ifx, "a");
7142               goto release;
7143             }
7144         }
7145       outBitC (result);
7146       goto release;
7147     }
7148
7149   /* if left is same as result */
7150   if (sameRegs (AOP (result), AOP (left)))
7151     {
7152       for (; size--; offset++)
7153         {
7154           if (AOP_TYPE (right) == AOP_LIT)
7155             {
7156               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7157                 {
7158                   continue;
7159                 }
7160               else
7161                 {
7162                   if (IS_AOP_PREG (left))
7163                     {
7164                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7165                       emitcode ("orl", "a,%s",
7166                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7167                       aopPut (AOP (result), "a", offset);
7168                     }
7169                   else
7170                     {
7171                       emitcode ("orl", "%s,%s",
7172                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7173                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7174                     }
7175                 }
7176             }
7177           else
7178             {
7179               if (AOP_TYPE (left) == AOP_ACC)
7180                 {
7181                   emitcode ("orl", "a,%s",
7182                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7183                 }
7184               else
7185                 {
7186                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7187                   if (IS_AOP_PREG (left))
7188                     {
7189                       emitcode ("orl", "a,%s", 
7190                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7191                       aopPut (AOP (result), "a", offset);
7192                     }
7193                   else
7194                     {
7195                       emitcode ("orl", "%s,a",
7196                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7197                     }
7198                 }
7199             }
7200         }
7201     }
7202   else
7203     {
7204       // left & result in different registers
7205       if (AOP_TYPE (result) == AOP_CRY)
7206         {
7207           // result = bit
7208           // if(size), result in bit
7209           // if(!size && ifx), conditional oper: if(left | right)
7210           symbol *tlbl = newiTempLabel (NULL);
7211           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7212           if (size)
7213             emitcode ("setb", "c");
7214           while (sizer--)
7215             {
7216               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7217                 emitcode ("orl", "a,%s",
7218                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7219               } else {
7220                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7221                 emitcode ("orl", "a,%s",
7222                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7223               }
7224               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7225               offset++;
7226             }
7227           if (size)
7228             {
7229               CLRC;
7230               emitcode ("", "!tlabeldef", tlbl->key + 100);
7231               outBitC (result);
7232             }
7233           else if (ifx)
7234             jmpTrueOrFalse (ifx, tlbl);
7235           else
7236             emitcode ("", "!tlabeldef", tlbl->key + 100);
7237         }
7238       else
7239         {
7240             _startLazyDPSEvaluation();
7241           for (; (size--); offset++)
7242             {
7243               // normal case
7244               // result = left & right
7245               if (AOP_TYPE (right) == AOP_LIT)
7246                 {
7247                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7248                     {
7249                       aopPut (AOP (result),
7250                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7251                               offset);
7252                       continue;
7253                     }
7254                   D (emitcode (";", "better literal OR."););
7255                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7256                   emitcode ("orl", "a, %s",
7257                             aopGet (AOP (right), offset,
7258                                     FALSE, FALSE, DP2_RESULT_REG));
7259
7260                 }
7261               else
7262                 {
7263                   // faster than result <- left, anl result,right
7264                   // and better if result is SFR
7265                   if (AOP_TYPE (left) == AOP_ACC)
7266                     {
7267                       emitcode ("orl", "a,%s",
7268                                 aopGet (AOP (right), offset,
7269                                         FALSE, FALSE, DP2_RESULT_REG));
7270                     }
7271                   else
7272                     {
7273                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7274                         
7275                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7276                       {
7277                           emitcode("mov", "b,a");
7278                           rOp = "b";
7279                       }
7280                         
7281                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7282                       emitcode ("orl", "a,%s", rOp);
7283                     }
7284                 }
7285               aopPut (AOP (result), "a", offset);
7286             }
7287             _endLazyDPSEvaluation();
7288         }
7289     }
7290
7291 release:
7292   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7293   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7294   freeAsmop (result, NULL, ic, TRUE);
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* genXor - code for xclusive or                                   */
7299 /*-----------------------------------------------------------------*/
7300 static void
7301 genXor (iCode * ic, iCode * ifx)
7302 {
7303   operand *left, *right, *result;
7304   int size, offset = 0;
7305   unsigned long lit = 0L;
7306   bool pushResult;
7307
7308   D (emitcode (";", "genXor "););
7309
7310   AOP_OP_3_NOFATAL (ic, pushResult);
7311   AOP_SET_LOCALS (ic);
7312
7313   if (pushResult)
7314   {
7315       genFarFarLogicOp(ic, "xrl");
7316       return;
7317   }  
7318
7319 #ifdef DEBUG_TYPE
7320   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7321             AOP_TYPE (result),
7322             AOP_TYPE (left), AOP_TYPE (right));
7323   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7324             AOP_SIZE (result),
7325             AOP_SIZE (left), AOP_SIZE (right));
7326 #endif
7327
7328   /* if left is a literal & right is not ||
7329      if left needs acc & right does not */
7330   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
7331 #ifdef LOGIC_OPS_BROKEN      
7332       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7333 #endif
7334      )
7335     {
7336       operand *tmp = right;
7337       right = left;
7338       left = tmp;
7339     }
7340
7341   /* if result = right then exchange them */
7342   if (sameRegs (AOP (result), AOP (right)))
7343     {
7344       operand *tmp = right;
7345       right = left;
7346       left = tmp;
7347     }
7348
7349   /* if right is bit then exchange them */
7350   if (AOP_TYPE (right) == AOP_CRY &&
7351       AOP_TYPE (left) != AOP_CRY)
7352     {
7353       operand *tmp = right;
7354       right = left;
7355       left = tmp;
7356     }
7357   if (AOP_TYPE (right) == AOP_LIT)
7358     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7359
7360   size = AOP_SIZE (result);
7361
7362   // if(bit ^ yy)
7363   // xx = bit ^ yy;
7364   if (AOP_TYPE (left) == AOP_CRY)
7365     {
7366       if (AOP_TYPE (right) == AOP_LIT)
7367         {
7368           // c = bit & literal;
7369           if (lit >> 1)
7370             {
7371               // lit>>1  != 0 => result = 1
7372               if (AOP_TYPE (result) == AOP_CRY)
7373                 {
7374                   if (size)
7375                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7376                   else if (ifx)
7377                     continueIfTrue (ifx);
7378                   goto release;
7379                 }
7380               emitcode ("setb", "c");
7381             }
7382           else
7383             {
7384               // lit == (0 or 1)
7385               if (lit == 0)
7386                 {
7387                   // lit == 0, result = left
7388                   if (size && sameRegs (AOP (result), AOP (left)))
7389                     goto release;
7390                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7391                 }
7392               else
7393                 {
7394                   // lit == 1, result = not(left)
7395                   if (size && sameRegs (AOP (result), AOP (left)))
7396                     {
7397                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7398                       goto release;
7399                     }
7400                   else
7401                     {
7402                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7403                       emitcode ("cpl", "c");
7404                     }
7405                 }
7406             }
7407
7408         }
7409       else
7410         {
7411           // right != literal
7412           symbol *tlbl = newiTempLabel (NULL);
7413           if (AOP_TYPE (right) == AOP_CRY)
7414             {
7415               // c = bit ^ bit;
7416               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7417             }
7418           else
7419             {
7420               int sizer = AOP_SIZE (right);
7421               // c = bit ^ val
7422               // if val>>1 != 0, result = 1
7423               emitcode ("setb", "c");
7424               while (sizer)
7425                 {
7426                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7427                   if (sizer == 1)
7428                     // test the msb of the lsb
7429                     emitcode ("anl", "a,#!constbyte",0xfe);
7430                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7431                   sizer--;
7432                 }
7433               // val = (0,1)
7434               emitcode ("rrc", "a");
7435             }
7436           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7437           emitcode ("cpl", "c");
7438           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7439         }
7440       // bit = c
7441       // val = c
7442       if (size)
7443         outBitC (result);
7444       // if(bit | ...)
7445       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7446         genIfxJump (ifx, "c");
7447       goto release;
7448     }
7449
7450   if (sameRegs (AOP (result), AOP (left)))
7451     {
7452       /* if left is same as result */
7453       for (; size--; offset++)
7454         {
7455           if (AOP_TYPE (right) == AOP_LIT)
7456             {
7457               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7458                 continue;
7459               else if (IS_AOP_PREG (left))
7460                 {
7461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7462                   emitcode ("xrl", "a,%s",
7463                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7464                   aopPut (AOP (result), "a", offset);
7465                 }
7466               else
7467                 emitcode ("xrl", "%s,%s",
7468                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7469                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7470             }
7471           else
7472             {
7473               if (AOP_TYPE (left) == AOP_ACC)
7474                 emitcode ("xrl", "a,%s",
7475                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7476               else
7477                 {
7478                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7479                   if (IS_AOP_PREG (left))
7480                     {
7481                       emitcode ("xrl", "a,%s",
7482                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7483                       aopPut (AOP (result), "a", offset);
7484                     }
7485                   else
7486                     emitcode ("xrl", "%s,a",
7487                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7488                 }
7489             }
7490         }
7491     }
7492   else
7493     {
7494       // left & result in different registers
7495       if (AOP_TYPE (result) == AOP_CRY)
7496         {
7497           // result = bit
7498           // if(size), result in bit
7499           // if(!size && ifx), conditional oper: if(left ^ right)
7500           symbol *tlbl = newiTempLabel (NULL);
7501           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7502                   
7503           if (size)
7504             emitcode ("setb", "c");
7505           while (sizer--)
7506             {
7507               if ((AOP_TYPE (right) == AOP_LIT) &&
7508                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7509                 {
7510                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7511                 }
7512               else
7513                 {
7514                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7515                     emitcode ("xrl", "a,%s",
7516                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7517                   } else {
7518                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7519                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7520                       {
7521                           emitcode("mov", "b,a");
7522                           rOp = "b";
7523                       }
7524                         
7525                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7526                       emitcode ("xrl", "a,%s", rOp);                  
7527                   }
7528                 }
7529               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7530               offset++;
7531             }
7532           if (size)
7533             {
7534               CLRC;
7535               emitcode ("", "!tlabeldef", tlbl->key + 100);
7536               outBitC (result);
7537             }
7538           else if (ifx)
7539             jmpTrueOrFalse (ifx, tlbl);
7540         }
7541       else
7542         {
7543         for (; (size--); offset++)
7544           {
7545             // normal case
7546             // result = left & right
7547             if (AOP_TYPE (right) == AOP_LIT)
7548               {
7549                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7550                   {
7551                     aopPut (AOP (result),
7552                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7553                             offset);
7554                     continue;
7555                   }
7556                 D (emitcode (";", "better literal XOR."););
7557                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7558                 emitcode ("xrl", "a, %s",
7559                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7560               }
7561             else
7562               {
7563                 // faster than result <- left, anl result,right
7564                 // and better if result is SFR
7565                 if (AOP_TYPE (left) == AOP_ACC)
7566                   {
7567                     emitcode ("xrl", "a,%s",
7568                               aopGet (AOP (right), offset,
7569                                       FALSE, FALSE, DP2_RESULT_REG));
7570                   }
7571                 else
7572                   {
7573                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7574                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7575                       {
7576                           emitcode("mov", "b,a");
7577                           rOp = "b";
7578                       }
7579                         
7580                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7581                       emitcode ("xrl", "a,%s", rOp);
7582                   }
7583               }
7584             aopPut (AOP (result), "a", offset);
7585           }
7586         }
7587         
7588     }
7589
7590 release:
7591   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7592   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7593   freeAsmop (result, NULL, ic, TRUE);
7594 }
7595
7596 /*-----------------------------------------------------------------*/
7597 /* genInline - write the inline code out                           */
7598 /*-----------------------------------------------------------------*/
7599 static void
7600 genInline (iCode * ic)
7601 {
7602   char *buffer, *bp, *bp1;
7603
7604   D (emitcode (";", "genInline "); );
7605
7606   _G.inLine += (!options.asmpeep);
7607
7608   buffer = Safe_strdup(IC_INLINE(ic));
7609   bp = buffer;
7610   bp1 = buffer;
7611
7612   /* emit each line as a code */
7613   while (*bp)
7614     {
7615       if (*bp == '\n')
7616         {
7617           *bp++ = '\0';
7618           emitcode (bp1, "");
7619           bp1 = bp;
7620         }
7621       else
7622         {
7623           if (*bp == ':')
7624             {
7625               bp++;
7626               *bp = '\0';
7627               bp++;
7628               emitcode (bp1, "");
7629               bp1 = bp;
7630             }
7631           else
7632             bp++;
7633         }
7634     }
7635   if (bp1 != bp)
7636     emitcode (bp1, "");
7637   /*     emitcode("",buffer); */
7638   _G.inLine -= (!options.asmpeep);
7639 }
7640
7641 /*-----------------------------------------------------------------*/
7642 /* genRRC - rotate right with carry                                */
7643 /*-----------------------------------------------------------------*/
7644 static void
7645 genRRC (iCode * ic)
7646 {
7647   operand *left, *result;
7648   int     size, offset;
7649
7650   D (emitcode (";", "genRRC "););
7651
7652   /* rotate right with carry */
7653   left = IC_LEFT (ic);
7654   result = IC_RESULT (ic);
7655   aopOp (left, ic, FALSE, FALSE);
7656   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7657
7658   /* move it to the result */
7659   size = AOP_SIZE (result);
7660   offset = size - 1;
7661   CLRC;
7662
7663   _startLazyDPSEvaluation ();
7664   while (size--)
7665     {
7666       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7667       emitcode ("rrc", "a");
7668       if (AOP_SIZE (result) > 1)
7669         aopPut (AOP (result), "a", offset--);
7670     }
7671   _endLazyDPSEvaluation ();
7672
7673   /* now we need to put the carry into the
7674      highest order byte of the result */
7675   if (AOP_SIZE (result) > 1)
7676     {
7677       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7678     }
7679   emitcode ("mov", "acc.7,c");
7680   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7681   freeAsmop (left, NULL, ic, TRUE);
7682   freeAsmop (result, NULL, ic, TRUE);
7683 }
7684
7685 /*-----------------------------------------------------------------*/
7686 /* genRLC - generate code for rotate left with carry               */
7687 /*-----------------------------------------------------------------*/
7688 static void
7689 genRLC (iCode * ic)
7690 {
7691   operand *left, *result;
7692   int size, offset;
7693   char *l;
7694
7695   D (emitcode (";", "genRLC "););
7696
7697   /* rotate right with carry */
7698   left = IC_LEFT (ic);
7699   result = IC_RESULT (ic);
7700   aopOp (left, ic, FALSE, FALSE);
7701   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7702
7703   /* move it to the result */
7704   size = AOP_SIZE (result);
7705   offset = 0;
7706   if (size--)
7707     {
7708       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7709       MOVA (l);
7710       emitcode ("add", "a,acc");
7711       if (AOP_SIZE (result) > 1)
7712         {
7713           aopPut (AOP (result), "a", offset++);
7714         }
7715
7716       _startLazyDPSEvaluation ();
7717       while (size--)
7718         {
7719           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7720           MOVA (l);
7721           emitcode ("rlc", "a");
7722           if (AOP_SIZE (result) > 1)
7723             aopPut (AOP (result), "a", offset++);
7724         }
7725       _endLazyDPSEvaluation ();
7726     }
7727   /* now we need to put the carry into the
7728      highest order byte of the result */
7729   if (AOP_SIZE (result) > 1)
7730     {
7731       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7732       MOVA (l);
7733     }
7734   emitcode ("mov", "acc.0,c");
7735   aopPut (AOP (result), "a", 0);
7736   freeAsmop (left, NULL, ic, TRUE);
7737   freeAsmop (result, NULL, ic, TRUE);
7738 }
7739
7740 /*-----------------------------------------------------------------*/
7741 /* genGetHbit - generates code get highest order bit               */
7742 /*-----------------------------------------------------------------*/
7743 static void
7744 genGetHbit (iCode * ic)
7745 {
7746   operand *left, *result;
7747   left = IC_LEFT (ic);
7748   result = IC_RESULT (ic);
7749   aopOp (left, ic, FALSE, FALSE);
7750   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7751
7752   D (emitcode (";", "genGetHbit "););
7753
7754   /* get the highest order byte into a */
7755   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7756   if (AOP_TYPE (result) == AOP_CRY)
7757     {
7758       emitcode ("rlc", "a");
7759       outBitC (result);
7760     }
7761   else
7762     {
7763       emitcode ("rl", "a");
7764       emitcode ("anl", "a,#1");
7765       outAcc (result);
7766     }
7767
7768
7769   freeAsmop (left, NULL, ic, TRUE);
7770   freeAsmop (result, NULL, ic, TRUE);
7771 }
7772
7773 /*-----------------------------------------------------------------*/
7774 /* genSwap - generates code to swap nibbles or bytes               */
7775 /*-----------------------------------------------------------------*/
7776 static void
7777 genSwap (iCode * ic)
7778 {
7779   operand *left, *result;
7780
7781   D(emitcode (";     genSwap",""));
7782
7783   left = IC_LEFT (ic);
7784   result = IC_RESULT (ic);
7785   aopOp (left, ic, FALSE, FALSE);
7786   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7787   
7788   _startLazyDPSEvaluation ();
7789   switch (AOP_SIZE (left))
7790     {
7791     case 1: /* swap nibbles in byte */
7792       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7793       emitcode ("swap", "a");
7794       aopPut (AOP (result), "a", 0);
7795       break;
7796     case 2: /* swap bytes in word */
7797       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7798         {
7799           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7800           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7801           aopPut (AOP (result), "a", 1);
7802         }
7803       else if (operandsEqu (left, result))
7804         {
7805           char * reg = "a";
7806           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7807           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7808             {
7809               emitcode ("mov", "b,a");
7810               reg = "b";
7811               _G.bInUse=1;
7812             }
7813           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7814           aopPut (AOP (result), reg, 1);
7815           _G.bInUse=0;
7816         }
7817       else
7818         {
7819           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7820           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7821         }
7822       break;
7823     default:
7824       wassertl(FALSE, "unsupported SWAP operand size");
7825     }
7826   _endLazyDPSEvaluation ();
7827   
7828   freeAsmop (left, NULL, ic, TRUE);
7829   freeAsmop (result, NULL, ic, TRUE);
7830 }
7831
7832 /*-----------------------------------------------------------------*/
7833 /* AccRol - rotate left accumulator by known count                 */
7834 /*-----------------------------------------------------------------*/
7835 static void
7836 AccRol (int shCount)
7837 {
7838   shCount &= 0x0007;            // shCount : 0..7
7839
7840   switch (shCount)
7841     {
7842     case 0:
7843       break;
7844     case 1:
7845       emitcode ("rl", "a");
7846       break;
7847     case 2:
7848       emitcode ("rl", "a");
7849       emitcode ("rl", "a");
7850       break;
7851     case 3:
7852       emitcode ("swap", "a");
7853       emitcode ("rr", "a");
7854       break;
7855     case 4:
7856       emitcode ("swap", "a");
7857       break;
7858     case 5:
7859       emitcode ("swap", "a");
7860       emitcode ("rl", "a");
7861       break;
7862     case 6:
7863       emitcode ("rr", "a");
7864       emitcode ("rr", "a");
7865       break;
7866     case 7:
7867       emitcode ("rr", "a");
7868       break;
7869     }
7870 }
7871
7872 /*-----------------------------------------------------------------*/
7873 /* AccLsh - left shift accumulator by known count                  */
7874 /*-----------------------------------------------------------------*/
7875 static void
7876 AccLsh (int shCount)
7877 {
7878   if (shCount != 0)
7879     {
7880       if (shCount == 1)
7881         emitcode ("add", "a,acc");
7882       else if (shCount == 2)
7883         {
7884           emitcode ("add", "a,acc");
7885           emitcode ("add", "a,acc");
7886         }
7887       else
7888         {
7889           /* rotate left accumulator */
7890           AccRol (shCount);
7891           /* and kill the lower order bits */
7892           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7893         }
7894     }
7895 }
7896
7897 /*-----------------------------------------------------------------*/
7898 /* AccRsh - right shift accumulator by known count                 */
7899 /*-----------------------------------------------------------------*/
7900 static void
7901 AccRsh (int shCount)
7902 {
7903   if (shCount != 0)
7904     {
7905       if (shCount == 1)
7906         {
7907           CLRC;
7908           emitcode ("rrc", "a");
7909         }
7910       else
7911         {
7912           /* rotate right accumulator */
7913           AccRol (8 - shCount);
7914           /* and kill the higher order bits */
7915           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7916         }
7917     }
7918 }
7919
7920 #ifdef BETTER_LITERAL_SHIFT
7921 /*-----------------------------------------------------------------*/
7922 /* AccSRsh - signed right shift accumulator by known count                 */
7923 /*-----------------------------------------------------------------*/
7924 static void
7925 AccSRsh (int shCount)
7926 {
7927   symbol *tlbl;
7928   if (shCount != 0)
7929     {
7930       if (shCount == 1)
7931         {
7932           emitcode ("mov", "c,acc.7");
7933           emitcode ("rrc", "a");
7934         }
7935       else if (shCount == 2)
7936         {
7937           emitcode ("mov", "c,acc.7");
7938           emitcode ("rrc", "a");
7939           emitcode ("mov", "c,acc.7");
7940           emitcode ("rrc", "a");
7941         }
7942       else
7943         {
7944           tlbl = newiTempLabel (NULL);
7945           /* rotate right accumulator */
7946           AccRol (8 - shCount);
7947           /* and kill the higher order bits */
7948           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7949           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7950           emitcode ("orl", "a,#!constbyte",
7951                     (unsigned char) ~SRMask[shCount]);
7952           emitcode ("", "!tlabeldef", tlbl->key + 100);
7953         }
7954     }
7955 }
7956 #endif
7957
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* shiftR1Left2Result - shift right one byte from left to result   */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 shiftR1Left2Result (operand * left, int offl,
7964                     operand * result, int offr,
7965                     int shCount, int sign)
7966 {
7967   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7968   /* shift right accumulator */
7969   if (sign)
7970     AccSRsh (shCount);
7971   else
7972     AccRsh (shCount);
7973   aopPut (AOP (result), "a", offr);
7974 }
7975 #endif
7976
7977 #ifdef BETTER_LITERAL_SHIFT
7978 /*-----------------------------------------------------------------*/
7979 /* shiftL1Left2Result - shift left one byte from left to result    */
7980 /*-----------------------------------------------------------------*/
7981 static void
7982 shiftL1Left2Result (operand * left, int offl,
7983                     operand * result, int offr, int shCount)
7984 {
7985   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7986   /* shift left accumulator */
7987   AccLsh (shCount);
7988   aopPut (AOP (result), "a", offr);
7989 }
7990 #endif
7991
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* movLeft2Result - move byte from left to result                  */
7995 /*-----------------------------------------------------------------*/
7996 static void
7997 movLeft2Result (operand * left, int offl,
7998                 operand * result, int offr, int sign)
7999 {
8000   char *l;
8001   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8002   {
8003       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8004
8005       if (*l == '@' && (IS_AOP_PREG (result)))
8006       {
8007           emitcode ("mov", "a,%s", l);
8008           aopPut (AOP (result), "a", offr);
8009       }
8010       else
8011       {
8012           if (!sign)
8013           {
8014             aopPut (AOP (result), l, offr);
8015           }
8016           else
8017             {
8018               /* MSB sign in acc.7 ! */
8019               if (getDataSize (left) == offl + 1)
8020                 {
8021                   emitcode ("mov", "a,%s", l);
8022                   aopPut (AOP (result), "a", offr);
8023                 }
8024             }
8025       }
8026   }
8027 }
8028 #endif
8029
8030 #ifdef BETTER_LITERAL_SHIFT
8031 /*-----------------------------------------------------------------*/
8032 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8033 /*-----------------------------------------------------------------*/
8034 static void
8035 AccAXRrl1 (char *x)
8036 {
8037   emitcode ("rrc", "a");
8038   emitcode ("xch", "a,%s", x);
8039   emitcode ("rrc", "a");
8040   emitcode ("xch", "a,%s", x);
8041 }
8042 #endif
8043
8044 #ifdef BETTER_LITERAL_SHIFT
8045 //REMOVE ME!!!
8046 /*-----------------------------------------------------------------*/
8047 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 AccAXLrl1 (char *x)
8051 {
8052   emitcode ("xch", "a,%s", x);
8053   emitcode ("rlc", "a");
8054   emitcode ("xch", "a,%s", x);
8055   emitcode ("rlc", "a");
8056 }
8057 #endif
8058
8059 #ifdef BETTER_LITERAL_SHIFT
8060 /*-----------------------------------------------------------------*/
8061 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8062 /*-----------------------------------------------------------------*/
8063 static void
8064 AccAXLsh1 (char *x)
8065 {
8066   emitcode ("xch", "a,%s", x);
8067   emitcode ("add", "a,acc");
8068   emitcode ("xch", "a,%s", x);
8069   emitcode ("rlc", "a");
8070 }
8071 #endif
8072
8073 #ifdef BETTER_LITERAL_SHIFT
8074 /*-----------------------------------------------------------------*/
8075 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8076 /*-----------------------------------------------------------------*/
8077 static void
8078 AccAXLsh (char *x, int shCount)
8079 {
8080   switch (shCount)
8081     {
8082     case 0:
8083       break;
8084     case 1:
8085       AccAXLsh1 (x);
8086       break;
8087     case 2:
8088       AccAXLsh1 (x);
8089       AccAXLsh1 (x);
8090       break;
8091     case 3:
8092     case 4:
8093     case 5:                     // AAAAABBB:CCCCCDDD
8094
8095       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8096
8097       emitcode ("anl", "a,#!constbyte",
8098                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8099
8100       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8101
8102       AccRol (shCount);         // DDDCCCCC:BBB00000
8103
8104       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8105
8106       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8107
8108       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8109
8110       emitcode ("anl", "a,#!constbyte",
8111                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8112
8113       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8114
8115       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8116
8117       break;
8118     case 6:                     // AAAAAABB:CCCCCCDD
8119       emitcode ("anl", "a,#!constbyte",
8120                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8121       emitcode ("mov", "c,acc.0");      // c = B
8122       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8123 #if 0
8124       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8125       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8126 #else
8127       emitcode("rrc","a"); 
8128       emitcode("xch","a,%s", x); 
8129       emitcode("rrc","a"); 
8130       emitcode("mov","c,acc.0"); //<< get correct bit 
8131       emitcode("xch","a,%s", x); 
8132
8133       emitcode("rrc","a"); 
8134       emitcode("xch","a,%s", x); 
8135       emitcode("rrc","a"); 
8136       emitcode("xch","a,%s", x); 
8137 #endif
8138       break;
8139     case 7:                     // a:x <<= 7
8140
8141       emitcode ("anl", "a,#!constbyte",
8142                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8143
8144       emitcode ("mov", "c,acc.0");      // c = B
8145
8146       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8147
8148       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8149
8150       break;
8151     default:
8152       break;
8153     }
8154 }
8155 #endif
8156
8157 #ifdef BETTER_LITERAL_SHIFT
8158 //REMOVE ME!!!
8159 /*-----------------------------------------------------------------*/
8160 /* AccAXRsh - right shift a:x known count (0..7)                   */
8161 /*-----------------------------------------------------------------*/
8162 static void
8163 AccAXRsh (char *x, int shCount)
8164 {
8165   switch (shCount)
8166     {
8167     case 0:
8168       break;
8169     case 1:
8170       CLRC;
8171       AccAXRrl1 (x);            // 0->a:x
8172
8173       break;
8174     case 2:
8175       CLRC;
8176       AccAXRrl1 (x);            // 0->a:x
8177
8178       CLRC;
8179       AccAXRrl1 (x);            // 0->a:x
8180
8181       break;
8182     case 3:
8183     case 4:
8184     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8185
8186       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8187
8188       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8189
8190       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8191
8192       emitcode ("anl", "a,#!constbyte",
8193                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8194
8195       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8196
8197       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8198
8199       emitcode ("anl", "a,#!constbyte",
8200                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8201
8202       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8203
8204       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8205
8206       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8207
8208       break;
8209     case 6:                     // AABBBBBB:CCDDDDDD
8210
8211       emitcode ("mov", "c,acc.7");
8212       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8213
8214       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8215
8216       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8217
8218       emitcode ("anl", "a,#!constbyte",
8219                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8220
8221       break;
8222     case 7:                     // ABBBBBBB:CDDDDDDD
8223
8224       emitcode ("mov", "c,acc.7");      // c = A
8225
8226       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8227
8228       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8229
8230       emitcode ("anl", "a,#!constbyte",
8231                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8232
8233       break;
8234     default:
8235       break;
8236     }
8237 }
8238 #endif
8239
8240 #ifdef BETTER_LITERAL_SHIFT
8241 /*-----------------------------------------------------------------*/
8242 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8243 /*-----------------------------------------------------------------*/
8244 static void
8245 AccAXRshS (char *x, int shCount)
8246 {
8247   symbol *tlbl;
8248   switch (shCount)
8249     {
8250     case 0:
8251       break;
8252     case 1:
8253       emitcode ("mov", "c,acc.7");
8254       AccAXRrl1 (x);            // s->a:x
8255
8256       break;
8257     case 2:
8258       emitcode ("mov", "c,acc.7");
8259       AccAXRrl1 (x);            // s->a:x
8260
8261       emitcode ("mov", "c,acc.7");
8262       AccAXRrl1 (x);            // s->a:x
8263
8264       break;
8265     case 3:
8266     case 4:
8267     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8268
8269       tlbl = newiTempLabel (NULL);
8270       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8271
8272       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8273
8274       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8275
8276       emitcode ("anl", "a,#!constbyte",
8277                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8278
8279       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8280
8281       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8282
8283       emitcode ("anl", "a,#!constbyte",
8284                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8285
8286       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8287
8288       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8289
8290       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8291
8292       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8293       emitcode ("orl", "a,#!constbyte",
8294                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8295
8296       emitcode ("", "!tlabeldef", tlbl->key + 100);
8297       break;                    // SSSSAAAA:BBBCCCCC
8298
8299     case 6:                     // AABBBBBB:CCDDDDDD
8300
8301       tlbl = newiTempLabel (NULL);
8302       emitcode ("mov", "c,acc.7");
8303       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8304
8305       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8306
8307       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8308
8309       emitcode ("anl", "a,#!constbyte",
8310                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8311
8312       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8313       emitcode ("orl", "a,#!constbyte",
8314                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8315
8316       emitcode ("", "!tlabeldef", tlbl->key + 100);
8317       break;
8318     case 7:                     // ABBBBBBB:CDDDDDDD
8319
8320       tlbl = newiTempLabel (NULL);
8321       emitcode ("mov", "c,acc.7");      // c = A
8322
8323       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8324
8325       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8326
8327       emitcode ("anl", "a,#!constbyte",
8328                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8329
8330       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8331       emitcode ("orl", "a,#!constbyte",
8332                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8333
8334       emitcode ("", "!tlabeldef", tlbl->key + 100);
8335       break;
8336     default:
8337       break;
8338     }
8339 }
8340 #endif
8341
8342 #ifdef BETTER_LITERAL_SHIFT
8343 static void
8344 _loadLeftIntoAx(char    **lsb, 
8345                 operand *left, 
8346                 operand *result,
8347                 int     offl,
8348                 int     offr)
8349 {
8350   // Get the initial value from left into a pair of registers.
8351   // MSB must be in A, LSB can be any register.
8352   //
8353   // If the result is held in registers, it is an optimization
8354   // if the LSB can be held in the register which will hold the,
8355   // result LSB since this saves us from having to copy it into
8356   // the result following AccAXLsh.
8357   //
8358   // If the result is addressed indirectly, this is not a gain.
8359   if (AOP_NEEDSACC(result))
8360   {
8361        char *leftByte;
8362        
8363        _startLazyDPSEvaluation();
8364       if (AOP_TYPE(left) == AOP_DPTR2)
8365        {
8366            // Get MSB in A.
8367            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8368            // get LSB in DP2_RESULT_REG.
8369            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8370            assert(!strcmp(leftByte, DP2_RESULT_REG));
8371        }
8372        else
8373        {
8374            // get LSB into DP2_RESULT_REG
8375            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8376            if (strcmp(leftByte, DP2_RESULT_REG))
8377            {
8378                TR_AP("#7");
8379                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8380            }
8381            // And MSB in A.
8382            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8383            assert(strcmp(leftByte, DP2_RESULT_REG));
8384            MOVA(leftByte);
8385        }
8386        _endLazyDPSEvaluation();
8387        *lsb = DP2_RESULT_REG;
8388   }
8389   else
8390   {
8391       if (sameRegs (AOP (result), AOP (left)) &&
8392         ((offl + MSB16) == offr))
8393       {
8394           /* don't crash result[offr] */
8395           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8396           emitcode ("xch", "a,%s", 
8397                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8398       }
8399       else
8400       {
8401           movLeft2Result (left, offl, result, offr, 0);
8402           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8403       }
8404       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8405       assert(strcmp(*lsb,"a"));      
8406   }
8407 }
8408
8409 static void
8410 _storeAxResults(char    *lsb,
8411                 operand *result,
8412                 int     offr)
8413 {
8414   _startLazyDPSEvaluation();
8415   if (AOP_NEEDSACC(result))
8416   {
8417       /* We have to explicitly update the result LSB.
8418        */
8419       emitcode("xch","a,%s", lsb);
8420       aopPut(AOP(result), "a", offr);
8421       emitcode("mov","a,%s", lsb);
8422   }
8423   if (getDataSize (result) > 1)
8424   {
8425       aopPut (AOP (result), "a", offr + MSB16);
8426   }
8427   _endLazyDPSEvaluation();
8428 }
8429
8430 /*-----------------------------------------------------------------*/
8431 /* shiftL2Left2Result - shift left two bytes from left to result   */
8432 /*-----------------------------------------------------------------*/
8433 static void
8434 shiftL2Left2Result (operand * left, int offl,
8435                     operand * result, int offr, int shCount)
8436 {
8437   char *lsb;
8438
8439   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8440   
8441   AccAXLsh (lsb, shCount);
8442   
8443   _storeAxResults(lsb, result, offr);
8444 }
8445 #endif
8446
8447 #ifdef BETTER_LITERAL_SHIFT
8448 /*-----------------------------------------------------------------*/
8449 /* shiftR2Left2Result - shift right two bytes from left to result  */
8450 /*-----------------------------------------------------------------*/
8451 static void
8452 shiftR2Left2Result (operand * left, int offl,
8453                     operand * result, int offr,
8454                     int shCount, int sign)
8455 {
8456   char *lsb;
8457   
8458   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8459   
8460   /* a:x >> shCount (x = lsb(result)) */
8461   if (sign)
8462   {
8463      AccAXRshS(lsb, shCount);
8464   }
8465   else
8466   {
8467     AccAXRsh(lsb, shCount);
8468   }
8469   
8470   _storeAxResults(lsb, result, offr);
8471 }
8472 #endif
8473
8474 /*-----------------------------------------------------------------*/
8475 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8476 /*-----------------------------------------------------------------*/
8477 static void
8478 shiftLLeftOrResult (operand * left, int offl,
8479                     operand * result, int offr, int shCount)
8480 {
8481   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8482   /* shift left accumulator */
8483   AccLsh (shCount);
8484   /* or with result */
8485   emitcode ("orl", "a,%s",
8486             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8487   /* back to result */
8488   aopPut (AOP (result), "a", offr);
8489 }
8490
8491 #if 0
8492 //REMOVE ME!!!
8493 /*-----------------------------------------------------------------*/
8494 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8495 /*-----------------------------------------------------------------*/
8496 static void
8497 shiftRLeftOrResult (operand * left, int offl,
8498                     operand * result, int offr, int shCount)
8499 {
8500   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8501   /* shift right accumulator */
8502   AccRsh (shCount);
8503   /* or with result */
8504   emitcode ("orl", "a,%s",
8505             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8506   /* back to result */
8507   aopPut (AOP (result), "a", offr);
8508 }
8509 #endif
8510
8511 #ifdef BETTER_LITERAL_SHIFT
8512 /*-----------------------------------------------------------------*/
8513 /* genlshOne - left shift a one byte quantity by known count       */
8514 /*-----------------------------------------------------------------*/
8515 static void
8516 genlshOne (operand * result, operand * left, int shCount)
8517 {
8518   D (emitcode (";", "genlshOne "););
8519   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8520 }
8521 #endif
8522
8523 #ifdef BETTER_LITERAL_SHIFT
8524 /*-----------------------------------------------------------------*/
8525 /* genlshTwo - left shift two bytes by known amount != 0           */
8526 /*-----------------------------------------------------------------*/
8527 static void
8528 genlshTwo (operand * result, operand * left, int shCount)
8529 {
8530   int size;
8531
8532   D (emitcode (";", "genlshTwo "););
8533
8534   size = getDataSize (result);
8535
8536   /* if shCount >= 8 */
8537   if (shCount >= 8)
8538   {
8539       shCount -= 8;
8540
8541       _startLazyDPSEvaluation();
8542
8543       if (size > 1)
8544         {
8545           if (shCount)
8546           {
8547             _endLazyDPSEvaluation();
8548             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8549             aopPut (AOP (result), zero, LSB);       
8550           }
8551           else
8552           {
8553             movLeft2Result (left, LSB, result, MSB16, 0);
8554             aopPut (AOP (result), zero, LSB);
8555             _endLazyDPSEvaluation();
8556           }
8557         }
8558         else
8559         {
8560           aopPut (AOP (result), zero, LSB);
8561           _endLazyDPSEvaluation();
8562         }
8563   }
8564
8565   /*  1 <= shCount <= 7 */
8566   else
8567     {
8568       if (size == 1)
8569       {
8570         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8571       }
8572       else
8573       {
8574         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8575       }
8576     }
8577 }
8578 #endif
8579
8580 #if 0
8581 //REMOVE ME!!!
8582 /*-----------------------------------------------------------------*/
8583 /* shiftLLong - shift left one long from left to result            */
8584 /* offl = LSB or MSB16                                             */
8585 /*-----------------------------------------------------------------*/
8586 static void
8587 shiftLLong (operand * left, operand * result, int offr)
8588 {
8589   char *l;
8590   int size = AOP_SIZE (result);
8591
8592   if (size >= LSB + offr)
8593     {
8594       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8595       MOVA (l);
8596       emitcode ("add", "a,acc");
8597       if (sameRegs (AOP (left), AOP (result)) &&
8598           size >= MSB16 + offr && offr != LSB)
8599         emitcode ("xch", "a,%s",
8600                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8601       else
8602         aopPut (AOP (result), "a", LSB + offr);
8603     }
8604
8605   if (size >= MSB16 + offr)
8606     {
8607       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8608         {
8609           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8610         }
8611       emitcode ("rlc", "a");
8612       if (sameRegs (AOP (left), AOP (result)) &&
8613           size >= MSB24 + offr && offr != LSB)
8614         emitcode ("xch", "a,%s",
8615                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8616       else
8617         aopPut (AOP (result), "a", MSB16 + offr);
8618     }
8619
8620   if (size >= MSB24 + offr)
8621     {
8622       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8623         {
8624           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8625         }
8626       emitcode ("rlc", "a");
8627       if (sameRegs (AOP (left), AOP (result)) &&
8628           size >= MSB32 + offr && offr != LSB)
8629         emitcode ("xch", "a,%s",
8630                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8631       else
8632         aopPut (AOP (result), "a", MSB24 + offr);
8633     }
8634
8635   if (size > MSB32 + offr)
8636     {
8637       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8638         {
8639           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8640         }
8641       emitcode ("rlc", "a");
8642       aopPut (AOP (result), "a", MSB32 + offr);
8643     }
8644   if (offr != LSB)
8645     aopPut (AOP (result), zero, LSB);
8646 }
8647 #endif
8648
8649 #if 0
8650 //REMOVE ME!!!
8651 /*-----------------------------------------------------------------*/
8652 /* genlshFour - shift four byte by a known amount != 0             */
8653 /*-----------------------------------------------------------------*/
8654 static void
8655 genlshFour (operand * result, operand * left, int shCount)
8656 {
8657   int size;
8658
8659   D (emitcode (";", "genlshFour ");
8660     );
8661
8662   size = AOP_SIZE (result);
8663
8664   /* if shifting more that 3 bytes */
8665   if (shCount >= 24)
8666     {
8667       shCount -= 24;
8668       if (shCount)
8669         /* lowest order of left goes to the highest
8670            order of the destination */
8671         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8672       else
8673         movLeft2Result (left, LSB, result, MSB32, 0);
8674       aopPut (AOP (result), zero, LSB);
8675       aopPut (AOP (result), zero, MSB16);
8676       aopPut (AOP (result), zero, MSB24);
8677       return;
8678     }
8679
8680   /* more than two bytes */
8681   else if (shCount >= 16)
8682     {
8683       /* lower order two bytes goes to higher order two bytes */
8684       shCount -= 16;
8685       /* if some more remaining */
8686       if (shCount)
8687         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8688       else
8689         {
8690           movLeft2Result (left, MSB16, result, MSB32, 0);
8691           movLeft2Result (left, LSB, result, MSB24, 0);
8692         }
8693       aopPut (AOP (result), zero, MSB16);
8694       aopPut (AOP (result), zero, LSB);
8695       return;
8696     }
8697
8698   /* if more than 1 byte */
8699   else if (shCount >= 8)
8700     {
8701       /* lower order three bytes goes to higher order  three bytes */
8702       shCount -= 8;
8703       if (size == 2)
8704         {
8705           if (shCount)
8706             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8707           else
8708             movLeft2Result (left, LSB, result, MSB16, 0);
8709         }
8710       else
8711         {                       /* size = 4 */
8712           if (shCount == 0)
8713             {
8714               movLeft2Result (left, MSB24, result, MSB32, 0);
8715               movLeft2Result (left, MSB16, result, MSB24, 0);
8716               movLeft2Result (left, LSB, result, MSB16, 0);
8717               aopPut (AOP (result), zero, LSB);
8718             }
8719           else if (shCount == 1)
8720             shiftLLong (left, result, MSB16);
8721           else
8722             {
8723               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8724               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8725               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8726               aopPut (AOP (result), zero, LSB);
8727             }
8728         }
8729     }
8730
8731   /* 1 <= shCount <= 7 */
8732   else if (shCount <= 2)
8733     {
8734       shiftLLong (left, result, LSB);
8735       if (shCount == 2)
8736         shiftLLong (result, result, LSB);
8737     }
8738   /* 3 <= shCount <= 7, optimize */
8739   else
8740     {
8741       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8742       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8743       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8744     }
8745 }
8746 #endif
8747
8748 #ifdef BETTER_LITERAL_SHIFT
8749 /*-----------------------------------------------------------------*/
8750 /* genLeftShiftLiteral - left shifting by known count              */
8751 /*-----------------------------------------------------------------*/
8752 static bool
8753 genLeftShiftLiteral (operand * left,
8754                      operand * right,
8755                      operand * result,
8756                      iCode * ic)
8757 {
8758   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8759   int size;
8760
8761   size = getSize (operandType (result));
8762
8763   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8764
8765   /* We only handle certain easy cases so far. */
8766   if ((shCount != 0)
8767    && (shCount < (size * 8))
8768    && (size != 1)
8769    && (size != 2))
8770   {
8771       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8772       return FALSE;
8773   }
8774
8775   freeAsmop (right, NULL, ic, TRUE);
8776
8777   aopOp(left, ic, FALSE, FALSE);
8778   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8779
8780 #if 0 // debug spew
8781   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8782   {
8783         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8784         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8785         {
8786            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8787         }
8788   }
8789   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8790   {
8791         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8792         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8793         {
8794            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8795         }       
8796   }  
8797 #endif
8798   
8799 #if VIEW_SIZE
8800   emitcode ("; shift left ", "result %d, left %d", size,
8801             AOP_SIZE (left));
8802 #endif
8803
8804   /* I suppose that the left size >= result size */
8805   if (shCount == 0)
8806   {
8807         _startLazyDPSEvaluation();
8808         while (size--)
8809         {
8810           movLeft2Result (left, size, result, size, 0);
8811         }
8812         _endLazyDPSEvaluation();
8813   }
8814   else if (shCount >= (size * 8))
8815   {
8816     _startLazyDPSEvaluation();
8817     while (size--)
8818     {
8819       aopPut (AOP (result), zero, size);
8820     }
8821     _endLazyDPSEvaluation();
8822   }
8823   else
8824   {
8825       switch (size)
8826         {
8827         case 1:
8828           genlshOne (result, left, shCount);
8829           break;
8830
8831         case 2:
8832           genlshTwo (result, left, shCount);
8833           break;
8834 #if 0
8835         case 4:
8836           genlshFour (result, left, shCount);
8837           break;
8838 #endif
8839         default:
8840           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8841           break;
8842         }
8843     }
8844   freeAsmop (left, NULL, ic, TRUE);
8845   freeAsmop (result, NULL, ic, TRUE);
8846   return TRUE;
8847 }
8848 #endif
8849
8850 /*-----------------------------------------------------------------*/
8851 /* genLeftShift - generates code for left shifting                 */
8852 /*-----------------------------------------------------------------*/
8853 static void
8854 genLeftShift (iCode * ic)
8855 {
8856   operand *left, *right, *result;
8857   int size, offset;
8858   char *l;
8859   symbol *tlbl, *tlbl1;
8860
8861   D (emitcode (";", "genLeftShift "););
8862
8863   right = IC_RIGHT (ic);
8864   left = IC_LEFT (ic);
8865   result = IC_RESULT (ic);
8866
8867   aopOp (right, ic, FALSE, FALSE);
8868
8869
8870 #ifdef BETTER_LITERAL_SHIFT
8871   /* if the shift count is known then do it
8872      as efficiently as possible */
8873   if (AOP_TYPE (right) == AOP_LIT)
8874     {
8875       if (genLeftShiftLiteral (left, right, result, ic))
8876       {
8877         return;
8878       }
8879     }
8880 #endif
8881
8882   /* shift count is unknown then we have to form
8883      a loop get the loop count in B : Note: we take
8884      only the lower order byte since shifting
8885      more that 32 bits make no sense anyway, ( the
8886      largest size of an object can be only 32 bits ) */
8887
8888   if (AOP_TYPE (right) == AOP_LIT)
8889   {
8890       /* Really should be handled by genLeftShiftLiteral,
8891        * but since I'm too lazy to fix that today, at least we can make
8892        * some small improvement.
8893        */
8894        emitcode("mov", "b,#!constbyte",
8895                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8896   }
8897   else
8898   {
8899       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8900       emitcode ("inc", "b");
8901   }
8902   freeAsmop (right, NULL, ic, TRUE);
8903   aopOp (left, ic, FALSE, FALSE);
8904   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8905
8906   /* now move the left to the result if they are not the
8907      same */
8908   if (!sameRegs (AOP (left), AOP (result)) &&
8909       AOP_SIZE (result) > 1)
8910     {
8911
8912       size = AOP_SIZE (result);
8913       offset = 0;
8914       _startLazyDPSEvaluation ();
8915       while (size--)
8916         {
8917           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8918           if (*l == '@' && (IS_AOP_PREG (result)))
8919             {
8920
8921               emitcode ("mov", "a,%s", l);
8922               aopPut (AOP (result), "a", offset);
8923             }
8924           else
8925             aopPut (AOP (result), l, offset);
8926           offset++;
8927         }
8928       _endLazyDPSEvaluation ();
8929     }
8930
8931   tlbl = newiTempLabel (NULL);
8932   size = AOP_SIZE (result);
8933   offset = 0;
8934   tlbl1 = newiTempLabel (NULL);
8935
8936   /* if it is only one byte then */
8937   if (size == 1)
8938     {
8939       symbol *tlbl1 = newiTempLabel (NULL);
8940
8941       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8942       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8943       emitcode ("", "!tlabeldef", tlbl->key + 100);
8944       emitcode ("add", "a,acc");
8945       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8946       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8947       aopPut (AOP (result), "a", 0);
8948       goto release;
8949     }
8950
8951   reAdjustPreg (AOP (result));
8952
8953   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8954   emitcode ("", "!tlabeldef", tlbl->key + 100);
8955   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8956   emitcode ("add", "a,acc");
8957   aopPut (AOP (result), "a", offset++);
8958   _startLazyDPSEvaluation ();
8959   while (--size)
8960     {
8961       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8962       emitcode ("rlc", "a");
8963       aopPut (AOP (result), "a", offset++);
8964     }
8965   _endLazyDPSEvaluation ();
8966   reAdjustPreg (AOP (result));
8967
8968   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8969   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8970 release:
8971   freeAsmop (left, NULL, ic, TRUE);
8972   freeAsmop (result, NULL, ic, TRUE);
8973 }
8974
8975 #ifdef BETTER_LITERAL_SHIFT
8976 /*-----------------------------------------------------------------*/
8977 /* genrshOne - right shift a one byte quantity by known count      */
8978 /*-----------------------------------------------------------------*/
8979 static void
8980 genrshOne (operand * result, operand * left,
8981            int shCount, int sign)
8982 {
8983   D (emitcode (";", "genrshOne"););
8984   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8985 }
8986 #endif
8987
8988 #ifdef BETTER_LITERAL_SHIFT
8989 /*-----------------------------------------------------------------*/
8990 /* genrshTwo - right shift two bytes by known amount != 0          */
8991 /*-----------------------------------------------------------------*/
8992 static void
8993 genrshTwo (operand * result, operand * left,
8994            int shCount, int sign)
8995 {
8996   D (emitcode (";", "genrshTwo"););
8997
8998   /* if shCount >= 8 */
8999   if (shCount >= 8)
9000     {
9001       shCount -= 8;
9002       _startLazyDPSEvaluation();
9003       if (shCount)
9004       {
9005         shiftR1Left2Result (left, MSB16, result, LSB,
9006                             shCount, sign);
9007       }                     
9008       else
9009       {
9010         movLeft2Result (left, MSB16, result, LSB, sign);
9011       }
9012       addSign (result, MSB16, sign);
9013       _endLazyDPSEvaluation();
9014     }
9015
9016   /*  1 <= shCount <= 7 */
9017   else
9018   {
9019     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9020   }
9021 }
9022 #endif
9023
9024 /*-----------------------------------------------------------------*/
9025 /* shiftRLong - shift right one long from left to result           */
9026 /* offl = LSB or MSB16                                             */
9027 /*-----------------------------------------------------------------*/
9028 static void
9029 shiftRLong (operand * left, int offl,
9030             operand * result, int sign)
9031 {
9032   int isSameRegs=sameRegs(AOP(left),AOP(result));
9033
9034   if (isSameRegs && offl>1) {
9035     // we are in big trouble, but this shouldn't happen
9036     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9037   }
9038
9039   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9040   
9041   if (offl==MSB16) {
9042     // shift is > 8
9043     if (sign) {
9044       emitcode ("rlc", "a");
9045       emitcode ("subb", "a,acc");
9046       emitcode ("xch", "a,%s",
9047                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9048     } else {
9049       aopPut (AOP(result), zero, MSB32);
9050     }
9051   }
9052
9053   if (!sign) {
9054     emitcode ("clr", "c");
9055   } else {
9056     emitcode ("mov", "c,acc.7");
9057   }
9058
9059   emitcode ("rrc", "a");
9060
9061   if (isSameRegs && offl==MSB16) {
9062     emitcode ("xch",
9063               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9064   } else {
9065     aopPut (AOP (result), "a", MSB32);
9066     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9067   }
9068
9069   emitcode ("rrc", "a");
9070   if (isSameRegs && offl==1) {
9071     emitcode ("xch", "a,%s",
9072               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9073   } else {
9074     aopPut (AOP (result), "a", MSB24);
9075     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9076   }
9077   emitcode ("rrc", "a");
9078   aopPut (AOP (result), "a", MSB16 - offl);
9079
9080   if (offl == LSB)
9081     {
9082       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9083       emitcode ("rrc", "a");
9084       aopPut (AOP (result), "a", LSB);
9085     }
9086 }
9087
9088 /*-----------------------------------------------------------------*/
9089 /* genrshFour - shift four byte by a known amount != 0             */
9090 /*-----------------------------------------------------------------*/
9091 static void
9092 genrshFour (operand * result, operand * left,
9093             int shCount, int sign)
9094 {
9095   D (emitcode (";", "genrshFour"););
9096
9097   /* if shifting more that 3 bytes */
9098   if (shCount >= 24)
9099     {
9100       shCount -= 24;
9101       _startLazyDPSEvaluation();
9102       if (shCount)
9103         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9104       else
9105         movLeft2Result (left, MSB32, result, LSB, sign);
9106       addSign (result, MSB16, sign);
9107       _endLazyDPSEvaluation();
9108     }
9109   else if (shCount >= 16)
9110     {
9111       shCount -= 16;
9112       _startLazyDPSEvaluation();
9113       if (shCount)
9114         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9115       else
9116         {
9117           movLeft2Result (left, MSB24, result, LSB, 0);
9118           movLeft2Result (left, MSB32, result, MSB16, sign);
9119         }
9120       addSign (result, MSB24, sign);
9121       _endLazyDPSEvaluation();
9122     }
9123   else if (shCount >= 8)
9124     {
9125       shCount -= 8;
9126       _startLazyDPSEvaluation();
9127       if (shCount == 1)
9128         {
9129             shiftRLong (left, MSB16, result, sign);
9130         }
9131       else if (shCount == 0)
9132         {
9133           movLeft2Result (left, MSB16, result, LSB, 0);
9134           movLeft2Result (left, MSB24, result, MSB16, 0);
9135           movLeft2Result (left, MSB32, result, MSB24, sign);
9136           addSign (result, MSB32, sign);
9137         }
9138       else
9139         {
9140           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9141           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9142           /* the last shift is signed */
9143           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9144           addSign (result, MSB32, sign);
9145         }
9146         _endLazyDPSEvaluation();
9147     }
9148   else
9149     {   
9150         /* 1 <= shCount <= 7 */
9151       if (shCount <= 2)
9152         {
9153           shiftRLong (left, LSB, result, sign);
9154           if (shCount == 2)
9155             shiftRLong (result, LSB, result, sign);
9156         }
9157       else
9158         {
9159           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9160           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9161           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9162         }
9163     }
9164 }
9165
9166 #ifdef BETTER_LITERAL_SHIFT
9167 /*-----------------------------------------------------------------*/
9168 /* genRightShiftLiteral - right shifting by known count            */
9169 /*-----------------------------------------------------------------*/
9170 static bool
9171 genRightShiftLiteral (operand * left,
9172                       operand * right,
9173                       operand * result,
9174                       iCode * ic,
9175                       int sign)
9176 {
9177   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9178   int size;
9179
9180   size = getSize (operandType (result));
9181
9182   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9183
9184   /* We only handle certain easy cases so far. */
9185   if ((shCount != 0)
9186    && (shCount < (size * 8))
9187    && (size != 1)
9188    && (size != 2)
9189    && (size != 4))
9190   {
9191       D(emitcode (";", "genRightShiftLiteral wimping out"););
9192       return FALSE;
9193   }
9194
9195   freeAsmop (right, NULL, ic, TRUE);
9196
9197   aopOp (left, ic, FALSE, FALSE);
9198   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9199
9200 #if VIEW_SIZE
9201   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9202             AOP_SIZE (left));
9203 #endif
9204
9205   /* test the LEFT size !!! */
9206
9207   /* I suppose that the left size >= result size */
9208   if (shCount == 0)
9209   {
9210       size = getDataSize (result);
9211       _startLazyDPSEvaluation();
9212       while (size--)
9213       {
9214         movLeft2Result (left, size, result, size, 0);
9215       }
9216       _endLazyDPSEvaluation();
9217   }
9218   else if (shCount >= (size * 8))
9219     {
9220       if (sign)
9221       {
9222         /* get sign in acc.7 */
9223         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9224       }
9225       addSign (result, LSB, sign);
9226     }
9227   else
9228     {
9229       switch (size)
9230         {
9231         case 1:
9232           genrshOne (result, left, shCount, sign);
9233           break;
9234
9235         case 2:
9236           genrshTwo (result, left, shCount, sign);
9237           break;
9238 #if 1
9239         case 4:
9240           genrshFour (result, left, shCount, sign);
9241           break;
9242 #endif    
9243         default:
9244           break;
9245         }
9246     }
9247   freeAsmop (left, NULL, ic, TRUE);
9248   freeAsmop (result, NULL, ic, TRUE);
9249   
9250   return TRUE;
9251 }
9252 #endif
9253
9254 /*-----------------------------------------------------------------*/
9255 /* genSignedRightShift - right shift of signed number              */
9256 /*-----------------------------------------------------------------*/
9257 static void
9258 genSignedRightShift (iCode * ic)
9259 {
9260   operand *right, *left, *result;
9261   int size, offset;
9262   char *l;
9263   symbol *tlbl, *tlbl1;
9264
9265   D (emitcode (";", "genSignedRightShift "););
9266
9267   /* we do it the hard way put the shift count in b
9268      and loop thru preserving the sign */
9269
9270   right = IC_RIGHT (ic);
9271   left = IC_LEFT (ic);
9272   result = IC_RESULT (ic);
9273
9274   aopOp (right, ic, FALSE, FALSE);
9275
9276 #ifdef BETTER_LITERAL_SHIFT
9277   if (AOP_TYPE (right) == AOP_LIT)
9278     {
9279       if (genRightShiftLiteral (left, right, result, ic, 1))
9280       {
9281         return;
9282       }
9283     }
9284 #endif
9285   /* shift count is unknown then we have to form
9286      a loop get the loop count in B : Note: we take
9287      only the lower order byte since shifting
9288      more that 32 bits make no sense anyway, ( the
9289      largest size of an object can be only 32 bits ) */
9290
9291   if (AOP_TYPE (right) == AOP_LIT)
9292   {
9293       /* Really should be handled by genRightShiftLiteral,
9294        * but since I'm too lazy to fix that today, at least we can make
9295        * some small improvement.
9296        */
9297        emitcode("mov", "b,#!constbyte",
9298                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9299   }
9300   else
9301   {
9302         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9303         emitcode ("inc", "b");
9304   }
9305   freeAsmop (right, NULL, ic, TRUE);
9306   aopOp (left, ic, FALSE, FALSE);
9307   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
9308
9309   /* now move the left to the result if they are not the
9310      same */
9311   if (!sameRegs (AOP (left), AOP (result)) &&
9312       AOP_SIZE (result) > 1)
9313     {
9314
9315       size = AOP_SIZE (result);
9316       offset = 0;
9317       _startLazyDPSEvaluation ();
9318       while (size--)
9319         {
9320           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9321           if (*l == '@' && IS_AOP_PREG (result))
9322             {
9323
9324               emitcode ("mov", "a,%s", l);
9325               aopPut (AOP (result), "a", offset);
9326             }
9327           else
9328             aopPut (AOP (result), l, offset);
9329           offset++;
9330         }
9331       _endLazyDPSEvaluation ();
9332     }
9333
9334   /* mov the highest order bit to OVR */
9335   tlbl = newiTempLabel (NULL);
9336   tlbl1 = newiTempLabel (NULL);
9337
9338   size = AOP_SIZE (result);
9339   offset = size - 1;
9340   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9341   emitcode ("rlc", "a");
9342   emitcode ("mov", "ov,c");
9343   /* if it is only one byte then */
9344   if (size == 1)
9345     {
9346       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9347       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9348       emitcode ("", "!tlabeldef", tlbl->key + 100);
9349       emitcode ("mov", "c,ov");
9350       emitcode ("rrc", "a");
9351       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9352       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9353       aopPut (AOP (result), "a", 0);
9354       goto release;
9355     }
9356
9357   reAdjustPreg (AOP (result));
9358   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9359   emitcode ("", "!tlabeldef", tlbl->key + 100);
9360   emitcode ("mov", "c,ov");
9361   _startLazyDPSEvaluation ();
9362   while (size--)
9363     {
9364       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9365       emitcode ("rrc", "a");
9366       aopPut (AOP (result), "a", offset--);
9367     }
9368   _endLazyDPSEvaluation ();
9369   reAdjustPreg (AOP (result));
9370   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9371   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9372
9373 release:
9374   freeAsmop (left, NULL, ic, TRUE);
9375   freeAsmop (result, NULL, ic, TRUE);
9376 }
9377
9378 /*-----------------------------------------------------------------*/
9379 /* genRightShift - generate code for right shifting                */
9380 /*-----------------------------------------------------------------*/
9381 static void
9382 genRightShift (iCode * ic)
9383 {
9384   operand *right, *left, *result;
9385   sym_link *letype;
9386   int size, offset;
9387   char *l;
9388   symbol *tlbl, *tlbl1;
9389
9390   D (emitcode (";", "genRightShift "););
9391
9392   /* if signed then we do it the hard way preserve the
9393      sign bit moving it inwards */
9394   letype = getSpec (operandType (IC_LEFT (ic)));
9395
9396   if (!SPEC_USIGN (letype))
9397     {
9398       genSignedRightShift (ic);
9399       return;
9400     }
9401
9402   /* signed & unsigned types are treated the same : i.e. the
9403      signed is NOT propagated inwards : quoting from the
9404      ANSI - standard : "for E1 >> E2, is equivalent to division
9405      by 2**E2 if unsigned or if it has a non-negative value,
9406      otherwise the result is implementation defined ", MY definition
9407      is that the sign does not get propagated */
9408
9409   right = IC_RIGHT (ic);
9410   left = IC_LEFT (ic);
9411   result = IC_RESULT (ic);
9412
9413   aopOp (right, ic, FALSE, FALSE);
9414
9415 #ifdef BETTER_LITERAL_SHIFT
9416   /* if the shift count is known then do it
9417      as efficiently as possible */
9418   if (AOP_TYPE (right) == AOP_LIT)
9419     {
9420       if (genRightShiftLiteral (left, right, result, ic, 0))
9421       {
9422         return;
9423       }
9424     }
9425 #endif
9426
9427   /* shift count is unknown then we have to form
9428      a loop get the loop count in B : Note: we take
9429      only the lower order byte since shifting
9430      more that 32 bits make no sense anyway, ( the
9431      largest size of an object can be only 32 bits ) */
9432   
9433   if (AOP_TYPE (right) == AOP_LIT)
9434   {
9435       /* Really should be handled by genRightShiftLiteral,
9436        * but since I'm too lazy to fix that today, at least we can make
9437        * some small improvement.
9438        */
9439        emitcode("mov", "b,#!constbyte",
9440                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9441   }
9442   else
9443   {
9444       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9445       emitcode ("inc", "b");
9446   }
9447   freeAsmop (right, NULL, ic, TRUE);
9448   aopOp (left, ic, FALSE, FALSE);
9449   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9450
9451   /* now move the left to the result if they are not the
9452      same */
9453   if (!sameRegs (AOP (left), AOP (result)) &&
9454       AOP_SIZE (result) > 1)
9455     {
9456
9457       size = AOP_SIZE (result);
9458       offset = 0;
9459       _startLazyDPSEvaluation ();
9460       while (size--)
9461         {
9462           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9463           if (*l == '@' && IS_AOP_PREG (result))
9464             {
9465
9466               emitcode ("mov", "a,%s", l);
9467               aopPut (AOP (result), "a", offset);
9468             }
9469           else
9470             aopPut (AOP (result), l, offset);
9471           offset++;
9472         }
9473       _endLazyDPSEvaluation ();
9474     }
9475
9476   tlbl = newiTempLabel (NULL);
9477   tlbl1 = newiTempLabel (NULL);
9478   size = AOP_SIZE (result);
9479   offset = size - 1;
9480
9481   /* if it is only one byte then */
9482   if (size == 1)
9483     {
9484       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9485       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9486       emitcode ("", "!tlabeldef", tlbl->key + 100);
9487       CLRC;
9488       emitcode ("rrc", "a");
9489       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9490       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9491       aopPut (AOP (result), "a", 0);
9492       goto release;
9493     }
9494
9495   reAdjustPreg (AOP (result));
9496   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9497   emitcode ("", "!tlabeldef", tlbl->key + 100);
9498   CLRC;
9499   _startLazyDPSEvaluation ();
9500   while (size--)
9501     {
9502       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9503       emitcode ("rrc", "a");
9504       aopPut (AOP (result), "a", offset--);
9505     }
9506   _endLazyDPSEvaluation ();
9507   reAdjustPreg (AOP (result));
9508
9509   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9510   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9511
9512 release:
9513   freeAsmop (left, NULL, ic, TRUE);
9514   freeAsmop (result, NULL, ic, TRUE);
9515 }
9516
9517
9518 /*-----------------------------------------------------------------*/
9519 /* emitPtrByteGet - emits code to get a byte into A through a      */
9520 /*                  pointer register (R0, R1, or DPTR). The        */
9521 /*                  original value of A can be preserved in B.     */
9522 /*-----------------------------------------------------------------*/
9523 static void
9524 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9525 {
9526   switch (p_type)
9527     {
9528     case IPOINTER:
9529     case POINTER:
9530       if (preserveAinB)
9531         emitcode ("mov", "b,a");
9532       emitcode ("mov", "a,@%s", rname);
9533       break;
9534
9535     case PPOINTER:
9536       if (preserveAinB)
9537         emitcode ("mov", "b,a");
9538       emitcode ("movx", "a,@%s", rname);
9539       break;
9540       
9541     case FPOINTER:
9542       if (preserveAinB)
9543         emitcode ("mov", "b,a");
9544       emitcode ("movx", "a,@dptr");
9545       break;
9546
9547     case CPOINTER:
9548       if (preserveAinB)
9549         emitcode ("mov", "b,a");
9550       emitcode ("clr", "a");
9551       emitcode ("movc", "a,@a+dptr");
9552       break;
9553
9554     case GPOINTER:
9555       if (preserveAinB)
9556         {
9557           emitcode ("push", "b");
9558           emitcode ("push", "acc");
9559         }
9560       emitcode ("lcall", "__gptrget");
9561       if (preserveAinB)
9562         emitcode ("pop", "b");
9563       break;
9564     }
9565 }
9566
9567 /*-----------------------------------------------------------------*/
9568 /* emitPtrByteSet - emits code to set a byte from src through a    */
9569 /*                  pointer register (R0, R1, or DPTR).            */
9570 /*-----------------------------------------------------------------*/
9571 static void
9572 emitPtrByteSet (char *rname, int p_type, char *src)
9573 {
9574   switch (p_type)
9575     {
9576     case IPOINTER:
9577     case POINTER:
9578       if (*src=='@')
9579         {
9580           MOVA (src);
9581           emitcode ("mov", "@%s,a", rname);
9582         }
9583       else
9584         emitcode ("mov", "@%s,%s", rname, src);
9585       break;
9586
9587     case PPOINTER:
9588       MOVA (src);
9589       emitcode ("movx", "@%s,a", rname);
9590       break;
9591       
9592     case FPOINTER:
9593       MOVA (src);
9594       emitcode ("movx", "@dptr,a");
9595       break;
9596
9597     case GPOINTER:
9598       MOVA (src);
9599       emitcode ("lcall", "__gptrput");
9600       break;
9601     }
9602 }
9603
9604 /*-----------------------------------------------------------------*/
9605 /* genUnpackBits - generates code for unpacking bits               */
9606 /*-----------------------------------------------------------------*/
9607 static void
9608 genUnpackBits (operand * result, char *rname, int ptype)
9609 {
9610   int offset = 0;       /* result byte offset */
9611   int rsize;            /* result size */
9612   int rlen = 0;         /* remaining bitfield length */
9613   sym_link *etype;      /* bitfield type information */
9614   int blen;             /* bitfield length */
9615   int bstr;             /* bitfield starting bit within byte */
9616
9617   D(emitcode (";     genUnpackBits",""));
9618
9619   etype = getSpec (operandType (result));
9620   rsize = getSize (operandType (result));
9621   blen = SPEC_BLEN (etype);
9622   bstr = SPEC_BSTR (etype);
9623
9624   /* If the bitfield length is less than a byte */
9625   if (blen < 8)
9626     {
9627       emitPtrByteGet (rname, ptype, FALSE);
9628       AccRsh (bstr);
9629       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9630       aopPut (AOP (result), "a", offset++);
9631       goto finish;
9632     }
9633
9634   /* Bit field did not fit in a byte. Copy all
9635      but the partial byte at the end.  */
9636   for (rlen=blen;rlen>=8;rlen-=8)
9637     {
9638       emitPtrByteGet (rname, ptype, FALSE);
9639       aopPut (AOP (result), "a", offset++);
9640       if (rlen>8)
9641         emitcode ("inc", "%s", rname);
9642     }
9643
9644   /* Handle the partial byte at the end */
9645   if (rlen)
9646     {
9647       emitPtrByteGet (rname, ptype, FALSE);
9648       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9649       aopPut (AOP (result), "a", offset++);
9650     }
9651
9652 finish:
9653   if (offset < rsize)
9654     {
9655       rsize -= offset;
9656       while (rsize--)
9657         aopPut (AOP (result), zero, offset++);
9658     }
9659 }
9660
9661
9662 /*-----------------------------------------------------------------*/
9663 /* genDataPointerGet - generates code when ptr offset is known     */
9664 /*-----------------------------------------------------------------*/
9665 static void
9666 genDataPointerGet (operand * left,
9667                    operand * result,
9668                    iCode * ic)
9669 {
9670   char *l;
9671   char buff[256];
9672   int size, offset = 0;
9673   aopOp (result, ic, TRUE, FALSE);
9674
9675   /* get the string representation of the name */
9676   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9677   size = AOP_SIZE (result);
9678   _startLazyDPSEvaluation ();
9679   while (size--)
9680     {
9681         if (offset)
9682         {
9683             SNPRINTF (buff, sizeof(buff), 
9684                       "(%s + %d)", l + 1, offset);
9685         }
9686         else
9687         {
9688             SNPRINTF (buff, sizeof(buff), 
9689                       "%s", l + 1);
9690         }
9691       aopPut (AOP (result), buff, offset++);
9692     }
9693   _endLazyDPSEvaluation ();
9694
9695   freeAsmop (left, NULL, ic, TRUE);
9696   freeAsmop (result, NULL, ic, TRUE);
9697 }
9698
9699 /*-----------------------------------------------------------------*/
9700 /* genNearPointerGet - emitcode for near pointer fetch             */
9701 /*-----------------------------------------------------------------*/
9702 static void
9703 genNearPointerGet (operand * left,
9704                    operand * result,
9705                    iCode * ic,
9706                    iCode *pi)
9707 {
9708   asmop *aop = NULL;
9709   regs *preg;
9710   char *rname;
9711   sym_link *rtype, *retype, *letype;
9712   sym_link *ltype = operandType (left);
9713   char buff[80];
9714
9715   rtype = operandType (result);
9716   retype = getSpec (rtype);
9717   letype = getSpec (ltype);
9718
9719   aopOp (left, ic, FALSE, FALSE);
9720
9721   /* if left is rematerialisable and
9722      result is not bitfield variable type and
9723      the left is pointer to data space i.e
9724      lower 128 bytes of space */
9725   if (AOP_TYPE (left) == AOP_IMMD &&
9726       !IS_BITFIELD (retype) &&
9727       !IS_BITFIELD (letype) &&
9728       DCL_TYPE (ltype) == POINTER)
9729     {
9730       genDataPointerGet (left, result, ic);
9731       return;
9732     }
9733
9734   /* if the value is already in a pointer register
9735      then don't need anything more */
9736   if (!AOP_INPREG (AOP (left)))
9737     {
9738       /* otherwise get a free pointer register */
9739       aop = newAsmop (0);
9740       preg = getFreePtr (ic, &aop, FALSE);
9741       emitcode ("mov", "%s,%s",
9742                 preg->name,
9743                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9744       rname = preg->name;
9745     }
9746   else
9747     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9748
9749   freeAsmop (left, NULL, ic, TRUE);
9750   aopOp (result, ic, FALSE, FALSE);
9751
9752   /* if bitfield then unpack the bits */
9753   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9754     genUnpackBits (result, rname, POINTER);
9755   else
9756     {
9757       /* we have can just get the values */
9758       int size = AOP_SIZE (result);
9759       int offset = 0;
9760
9761       while (size--)
9762         {
9763           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9764             {
9765
9766               emitcode ("mov", "a,@%s", rname);
9767               aopPut (AOP (result), "a", offset);
9768             }
9769           else
9770             {
9771               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9772               aopPut (AOP (result), buff, offset);
9773             }
9774           offset++;
9775           if (size || pi)
9776             {
9777                 emitcode ("inc", "%s", rname);
9778             }
9779         }
9780     }
9781
9782   /* now some housekeeping stuff */
9783   if (aop)
9784     {
9785       /* we had to allocate for this iCode */
9786       if (pi) { /* post increment present */
9787         aopPut(AOP ( left ),rname,0);
9788       }
9789       freeAsmop (NULL, aop, ic, TRUE);
9790     }
9791   else
9792     {
9793       /* we did not allocate which means left
9794          already in a pointer register, then
9795          if size > 0 && this could be used again
9796          we have to point it back to where it
9797          belongs */
9798       if (AOP_SIZE (result) > 1 &&
9799           !OP_SYMBOL (left)->remat &&
9800           (OP_SYMBOL (left)->liveTo > ic->seq ||
9801            ic->depth) &&
9802           !pi)
9803         {
9804           int size = AOP_SIZE (result) - 1;
9805           while (size--)
9806             emitcode ("dec", "%s", rname);
9807         }
9808     }
9809
9810   /* done */
9811   freeAsmop (result, NULL, ic, TRUE);
9812   if (pi) pi->generated = 1;
9813 }
9814
9815 /*-----------------------------------------------------------------*/
9816 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9817 /*-----------------------------------------------------------------*/
9818 static void
9819 genPagedPointerGet (operand * left,
9820                     operand * result,
9821                     iCode * ic,
9822                     iCode * pi)
9823 {
9824   asmop *aop = NULL;
9825   regs *preg;
9826   char *rname;
9827   sym_link *rtype, *retype, *letype;
9828
9829   rtype = operandType (result);
9830   retype = getSpec (rtype);
9831   letype = getSpec (operandType (left));
9832   aopOp (left, ic, FALSE, FALSE);
9833
9834   /* if the value is already in a pointer register
9835      then don't need anything more */
9836   if (!AOP_INPREG (AOP (left)))
9837     {
9838       /* otherwise get a free pointer register */
9839       aop = newAsmop (0);
9840       preg = getFreePtr (ic, &aop, FALSE);
9841       emitcode ("mov", "%s,%s",
9842                 preg->name,
9843                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9844       rname = preg->name;
9845     }
9846   else
9847     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9848
9849   freeAsmop (left, NULL, ic, TRUE);
9850   aopOp (result, ic, FALSE, FALSE);
9851
9852   /* if bitfield then unpack the bits */
9853   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9854     genUnpackBits (result, rname, PPOINTER);
9855   else
9856     {
9857       /* we have can just get the values */
9858       int size = AOP_SIZE (result);
9859       int offset = 0;
9860
9861       while (size--)
9862         {
9863
9864           emitcode ("movx", "a,@%s", rname);
9865           aopPut (AOP (result), "a", offset);
9866
9867           offset++;
9868
9869           if (size || pi)
9870             emitcode ("inc", "%s", rname);
9871         }
9872     }
9873
9874   /* now some housekeeping stuff */
9875   if (aop)
9876     {
9877       /* we had to allocate for this iCode */
9878       if (pi) aopPut ( AOP (left), rname, 0);
9879       freeAsmop (NULL, aop, ic, TRUE);
9880     }
9881   else
9882     {
9883       /* we did not allocate which means left
9884          already in a pointer register, then
9885          if size > 0 && this could be used again
9886          we have to point it back to where it
9887          belongs */
9888       if (AOP_SIZE (result) > 1 &&
9889           !OP_SYMBOL (left)->remat &&
9890           (OP_SYMBOL (left)->liveTo > ic->seq ||
9891            ic->depth) &&
9892           !pi)
9893         {
9894           int size = AOP_SIZE (result) - 1;
9895           while (size--)
9896             emitcode ("dec", "%s", rname);
9897         }
9898     }
9899
9900   /* done */
9901   freeAsmop (result, NULL, ic, TRUE);
9902   if (pi) pi->generated = 1;
9903 }
9904
9905 /*-----------------------------------------------------------------*/
9906 /* genFarPointerGet - gget value from far space                    */
9907 /*-----------------------------------------------------------------*/
9908 static void
9909 genFarPointerGet (operand * left,
9910                   operand * result, iCode * ic, iCode *pi)
9911 {
9912     int size, offset, dopi=1;
9913   sym_link *retype = getSpec (operandType (result));
9914   sym_link *letype = getSpec (operandType (left));
9915   D (emitcode (";", "genFarPointerGet"););
9916
9917   aopOp (left, ic, FALSE, FALSE);
9918
9919   /* if the operand is already in dptr
9920      then we do nothing else we move the value to dptr */
9921   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9922     {
9923       /* if this is remateriazable */
9924       if (AOP_TYPE (left) == AOP_IMMD)
9925         {
9926           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9927         }
9928       else
9929         {
9930           /* we need to get it byte by byte */
9931           _startLazyDPSEvaluation ();
9932           if (AOP_TYPE (left) != AOP_DPTR)
9933             {
9934               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9935               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9936               if (options.model == MODEL_FLAT24)
9937                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9938             }
9939           else
9940             {
9941               /* We need to generate a load to DPTR indirect through DPTR. */
9942               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9943               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9944               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9945               if (options.model == MODEL_FLAT24)
9946                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9947               emitcode ("pop", "dph");
9948               emitcode ("pop", "dpl");
9949               dopi =0;
9950             }
9951           _endLazyDPSEvaluation ();
9952         }
9953     }
9954   /* so dptr know contains the address */
9955   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9956
9957   /* if bit then unpack */
9958   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9959       if (AOP_INDPTRn(left)) {
9960           genSetDPTR(AOP(left)->aopu.dptr);
9961       }
9962       genUnpackBits (result, "dptr", FPOINTER);
9963       if (AOP_INDPTRn(left)) {
9964           genSetDPTR(0);
9965       }
9966   } else
9967     {
9968       size = AOP_SIZE (result);
9969       offset = 0;
9970
9971       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9972           while (size--) {
9973               genSetDPTR(AOP(left)->aopu.dptr);
9974               emitcode ("movx", "a,@dptr");
9975               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9976                   emitcode ("inc", "dptr");
9977               genSetDPTR (0);
9978               aopPut (AOP (result), "a", offset++);
9979           }
9980       } else {
9981           _startLazyDPSEvaluation ();
9982           while (size--) {
9983               if (AOP_INDPTRn(left)) {
9984                   genSetDPTR(AOP(left)->aopu.dptr);
9985               } else {
9986                   genSetDPTR (0);
9987               }
9988               _flushLazyDPS ();
9989               
9990               emitcode ("movx", "a,@dptr");
9991               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9992                   emitcode ("inc", "dptr");
9993               
9994               aopPut (AOP (result), "a", offset++);
9995           }
9996           _endLazyDPSEvaluation ();
9997       }
9998     }
9999   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10000       if (!AOP_INDPTRn(left)) {
10001           _startLazyDPSEvaluation ();
10002           aopPut ( AOP (left), "dpl", 0);
10003           aopPut ( AOP (left), "dph", 1);
10004           if (options.model == MODEL_FLAT24)
10005               aopPut ( AOP (left), "dpx", 2);
10006           _endLazyDPSEvaluation ();
10007       }
10008     pi->generated = 1;
10009   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
10010              AOP_SIZE(result) > 1 &&
10011              IS_SYMOP(left) &&
10012              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10013       
10014       size = AOP_SIZE (result) - 1;
10015       if (AOP_INDPTRn(left)) {
10016           genSetDPTR(AOP(left)->aopu.dptr);
10017       }
10018       while (size--) emitcode ("lcall","__decdptr");
10019       if (AOP_INDPTRn(left)) {
10020           genSetDPTR(0);
10021       }
10022   }
10023
10024   freeAsmop (left, NULL, ic, TRUE);
10025   freeAsmop (result, NULL, ic, TRUE);
10026 }
10027
10028 /*-----------------------------------------------------------------*/
10029 /* genCodePointerGet - get value from code space                  */
10030 /*-----------------------------------------------------------------*/
10031 static void
10032 genCodePointerGet (operand * left,
10033                     operand * result, iCode * ic, iCode *pi)
10034 {
10035   int size, offset, dopi=1;
10036   sym_link *retype = getSpec (operandType (result));
10037
10038   aopOp (left, ic, FALSE, FALSE);
10039
10040   /* if the operand is already in dptr
10041      then we do nothing else we move the value to dptr */
10042   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10043     {
10044       /* if this is remateriazable */
10045       if (AOP_TYPE (left) == AOP_IMMD)
10046         {
10047           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10048         }
10049       else
10050         {                       /* we need to get it byte by byte */
10051           _startLazyDPSEvaluation ();
10052           if (AOP_TYPE (left) != AOP_DPTR)
10053             {
10054               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10055               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10056               if (options.model == MODEL_FLAT24)
10057                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10058             }
10059           else
10060             {
10061               /* We need to generate a load to DPTR indirect through DPTR. */
10062               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10063               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10064               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10065               if (options.model == MODEL_FLAT24)
10066                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10067               emitcode ("pop", "dph");
10068               emitcode ("pop", "dpl");
10069               dopi=0;
10070             }
10071           _endLazyDPSEvaluation ();
10072         }
10073     }
10074   /* so dptr know contains the address */
10075   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10076
10077   /* if bit then unpack */
10078   if (IS_BITFIELD (retype)) {
10079       if (AOP_INDPTRn(left)) {
10080           genSetDPTR(AOP(left)->aopu.dptr);
10081       }
10082       genUnpackBits (result, "dptr", CPOINTER);
10083       if (AOP_INDPTRn(left)) {
10084           genSetDPTR(0);
10085       }
10086   } else
10087     {
10088       size = AOP_SIZE (result);
10089       offset = 0;
10090       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10091           while (size--) {
10092               genSetDPTR(AOP(left)->aopu.dptr);
10093               emitcode ("clr", "a");
10094               emitcode ("movc", "a,@a+dptr");
10095               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10096                   emitcode ("inc", "dptr");
10097               genSetDPTR (0);
10098               aopPut (AOP (result), "a", offset++);
10099           }
10100       } else {
10101           _startLazyDPSEvaluation ();
10102           while (size--)
10103               {
10104                   if (AOP_INDPTRn(left)) {
10105                       genSetDPTR(AOP(left)->aopu.dptr);
10106                   } else {
10107                       genSetDPTR (0);
10108                   }
10109                   _flushLazyDPS ();
10110                   
10111                   emitcode ("clr", "a");
10112                   emitcode ("movc", "a,@a+dptr");
10113                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10114                       emitcode ("inc", "dptr");
10115                   aopPut (AOP (result), "a", offset++);
10116               }
10117           _endLazyDPSEvaluation ();
10118       }
10119     }
10120   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10121       if (!AOP_INDPTRn(left)) {
10122           _startLazyDPSEvaluation ();
10123           
10124           aopPut ( AOP (left), "dpl", 0);
10125           aopPut ( AOP (left), "dph", 1);
10126           if (options.model == MODEL_FLAT24)
10127               aopPut ( AOP (left), "dpx", 2);
10128
10129           _endLazyDPSEvaluation ();
10130       }
10131       pi->generated = 1;
10132   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
10133              AOP_SIZE(result) > 1 &&
10134              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10135       
10136       size = AOP_SIZE (result) - 1;
10137       if (AOP_INDPTRn(left)) {
10138           genSetDPTR(AOP(left)->aopu.dptr);
10139       }
10140       while (size--) emitcode ("lcall","__decdptr");
10141       if (AOP_INDPTRn(left)) {
10142           genSetDPTR(0);
10143       }
10144   }
10145   
10146   freeAsmop (left, NULL, ic, TRUE);
10147   freeAsmop (result, NULL, ic, TRUE);
10148 }
10149
10150 /*-----------------------------------------------------------------*/
10151 /* genGenPointerGet - gget value from generic pointer space        */
10152 /*-----------------------------------------------------------------*/
10153 static void
10154 genGenPointerGet (operand * left,
10155                   operand * result, iCode * ic, iCode * pi)
10156 {
10157   int size, offset;
10158   sym_link *retype = getSpec (operandType (result));
10159   sym_link *letype = getSpec (operandType (left));
10160
10161   D (emitcode (";", "genGenPointerGet "); );
10162
10163   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10164
10165   /* if the operand is already in dptr
10166      then we do nothing else we move the value to dptr */
10167   if (AOP_TYPE (left) != AOP_STR)
10168     {
10169       /* if this is remateriazable */
10170       if (AOP_TYPE (left) == AOP_IMMD)
10171         {
10172           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10173           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
10174             {
10175                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10176             }
10177             else
10178             {
10179                 emitcode ("mov", "b,#%d", pointerCode (retype));
10180             }
10181         }
10182       else
10183         {                       /* we need to get it byte by byte */
10184             _startLazyDPSEvaluation ();
10185             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10186             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10187             if (options.model == MODEL_FLAT24) {
10188                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10189                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10190             } else {
10191                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10192             }
10193             _endLazyDPSEvaluation ();
10194         }
10195     }
10196
10197   /* so dptr-b now contains the address */
10198   _G.bInUse++;
10199   aopOp (result, ic, FALSE, TRUE);
10200   _G.bInUse--;
10201
10202   /* if bit then unpack */
10203   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10204   {
10205     genUnpackBits (result, "dptr", GPOINTER);
10206   }
10207   else
10208     {
10209         size = AOP_SIZE (result);
10210         offset = 0;
10211
10212         while (size--)
10213         {
10214             if (size)
10215             {
10216                 // Get two bytes at a time, results in _AP & A.
10217                 // dptr will be incremented ONCE by __gptrgetWord.
10218                 //
10219                 // Note: any change here must be coordinated
10220                 // with the implementation of __gptrgetWord
10221                 // in device/lib/_gptrget.c
10222                 emitcode ("lcall", "__gptrgetWord");
10223                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10224                 aopPut (AOP (result), "a", offset++);
10225                 size--;
10226             }
10227             else
10228             {
10229                 // Only one byte to get.
10230                 emitcode ("lcall", "__gptrget");
10231                 aopPut (AOP (result), "a", offset++);
10232             }
10233             
10234             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10235             {
10236                 emitcode ("inc", "dptr");
10237             }
10238         }
10239     }
10240
10241   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10242     _startLazyDPSEvaluation ();
10243       
10244     aopPut ( AOP (left), "dpl", 0);
10245     aopPut ( AOP (left), "dph", 1);
10246     if (options.model == MODEL_FLAT24) {
10247         aopPut ( AOP (left), "dpx", 2);
10248         aopPut ( AOP (left), "b", 3);   
10249     } else  aopPut ( AOP (left), "b", 2);       
10250     
10251     _endLazyDPSEvaluation ();
10252       
10253     pi->generated = 1;
10254   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10255              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10256       
10257       size = AOP_SIZE (result) - 1;
10258       while (size--) emitcode ("lcall","__decdptr");
10259   }
10260
10261   freeAsmop (left, NULL, ic, TRUE);
10262   freeAsmop (result, NULL, ic, TRUE);
10263 }
10264
10265 /*-----------------------------------------------------------------*/
10266 /* genPointerGet - generate code for pointer get                   */
10267 /*-----------------------------------------------------------------*/
10268 static void
10269 genPointerGet (iCode * ic, iCode *pi)
10270 {
10271   operand *left, *result;
10272   sym_link *type, *etype;
10273   int p_type;
10274
10275   D (emitcode (";", "genPointerGet ");
10276     );
10277
10278   left = IC_LEFT (ic);
10279   result = IC_RESULT (ic);
10280
10281   /* depending on the type of pointer we need to
10282      move it to the correct pointer register */
10283   type = operandType (left);
10284   etype = getSpec (type);
10285   /* if left is of type of pointer then it is simple */
10286   if (IS_PTR (type) && !IS_FUNC (type->next))
10287     p_type = DCL_TYPE (type);
10288   else
10289     {
10290       /* we have to go by the storage class */
10291       p_type = PTR_TYPE (SPEC_OCLS (etype));
10292     }
10293   /* special case when cast remat */
10294   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10295       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10296           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10297           type = operandType (left);
10298           p_type = DCL_TYPE (type);
10299   }
10300   /* now that we have the pointer type we assign
10301      the pointer values */
10302   switch (p_type)
10303     {
10304
10305     case POINTER:
10306     case IPOINTER:
10307       genNearPointerGet (left, result, ic, pi);
10308       break;
10309
10310     case PPOINTER:
10311       genPagedPointerGet (left, result, ic, pi);
10312       break;
10313
10314     case FPOINTER:
10315       genFarPointerGet (left, result, ic, pi);
10316       break;
10317
10318     case CPOINTER:
10319       genCodePointerGet (left, result, ic, pi);
10320       break;
10321
10322     case GPOINTER:
10323       genGenPointerGet (left, result, ic, pi);
10324       break;
10325     }
10326
10327 }
10328
10329 /*-----------------------------------------------------------------*/
10330 /* genPackBits - generates code for packed bit storage             */
10331 /*-----------------------------------------------------------------*/
10332 static void
10333 genPackBits (sym_link * etype,
10334              operand * right,
10335              char *rname, int p_type)
10336 {
10337   int offset = 0;       /* source byte offset */
10338   int rlen = 0;         /* remaining bitfield length */
10339   int blen;             /* bitfield length */
10340   int bstr;             /* bitfield starting bit within byte */
10341   int litval;           /* source literal value (if AOP_LIT) */
10342   unsigned char mask;   /* bitmask within current byte */
10343
10344   D(emitcode (";     genPackBits",""));
10345
10346   blen = SPEC_BLEN (etype);
10347   bstr = SPEC_BSTR (etype);
10348
10349   /* If the bitfield length is less than a byte */
10350   if (blen < 8)
10351     {
10352       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10353               (unsigned char) (0xFF >> (8 - bstr)));
10354
10355       if (AOP_TYPE (right) == AOP_LIT)
10356         {
10357           /* Case with a bitfield length <8 and literal source
10358           */
10359           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10360           litval <<= bstr;
10361           litval &= (~mask) & 0xff;
10362           emitPtrByteGet (rname, p_type, FALSE);
10363           if ((mask|litval)!=0xff)
10364             emitcode ("anl","a,#!constbyte", mask);
10365           if (litval)
10366             emitcode ("orl","a,#!constbyte", litval);
10367         }
10368       else
10369         {
10370           if ((blen==1) && (p_type!=GPOINTER))
10371             {
10372               /* Case with a bitfield length == 1 and no generic pointer
10373               */
10374               if (AOP_TYPE (right) == AOP_CRY)
10375                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10376               else
10377                 {
10378                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10379                   emitcode ("rrc","a");
10380                 }
10381               emitPtrByteGet (rname, p_type, FALSE);
10382               emitcode ("mov","acc.%d,c",bstr);
10383             }
10384           else
10385             {
10386               /* Case with a bitfield length < 8 and arbitrary source
10387               */
10388               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10389               /* shift and mask source value */
10390               AccLsh (bstr);
10391               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10392
10393               /* transfer A to B and get next byte */
10394               emitPtrByteGet (rname, p_type, TRUE);
10395
10396               emitcode ("anl", "a,#!constbyte", mask);
10397               emitcode ("orl", "a,b");
10398               if (p_type == GPOINTER)
10399                 emitcode ("pop", "b");
10400            }
10401         }
10402
10403       emitPtrByteSet (rname, p_type, "a");
10404       return;
10405     }
10406
10407   /* Bit length is greater than 7 bits. In this case, copy  */
10408   /* all except the partial byte at the end                 */
10409   for (rlen=blen;rlen>=8;rlen-=8)
10410     {
10411       emitPtrByteSet (rname, p_type, 
10412                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10413       if (rlen>8)
10414         emitcode ("inc", "%s", rname);
10415     }
10416
10417   /* If there was a partial byte at the end */
10418   if (rlen)
10419     {
10420       mask = (((unsigned char) -1 << rlen) & 0xff);
10421       
10422       if (AOP_TYPE (right) == AOP_LIT)
10423         {
10424           /* Case with partial byte and literal source
10425           */
10426           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10427           litval >>= (blen-rlen);
10428           litval &= (~mask) & 0xff;
10429           emitPtrByteGet (rname, p_type, FALSE);
10430           if ((mask|litval)!=0xff)
10431             emitcode ("anl","a,#!constbyte", mask);
10432           if (litval)
10433             emitcode ("orl","a,#!constbyte", litval);
10434         }
10435       else
10436         {
10437           /* Case with partial byte and arbitrary source
10438           */
10439           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10440           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10441
10442           /* transfer A to B and get next byte */
10443           emitPtrByteGet (rname, p_type, TRUE);
10444
10445           emitcode ("anl", "a,#!constbyte", mask);
10446           emitcode ("orl", "a,b");
10447           if (p_type == GPOINTER)
10448             emitcode ("pop", "b");
10449         }
10450       emitPtrByteSet (rname, p_type, "a");
10451     }
10452
10453 }
10454
10455
10456 /*-----------------------------------------------------------------*/
10457 /* genDataPointerSet - remat pointer to data space                 */
10458 /*-----------------------------------------------------------------*/
10459 static void
10460 genDataPointerSet (operand * right,
10461                    operand * result,
10462                    iCode * ic)
10463 {
10464   int size, offset = 0;
10465   char *l, buff[256];
10466
10467   aopOp (right, ic, FALSE, FALSE);
10468
10469   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10470   size = AOP_SIZE (right);
10471   while (size--)
10472     {
10473       if (offset)
10474         {
10475             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10476         }
10477       else
10478         {
10479             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10480         }
10481         
10482       emitcode ("mov", "%s,%s", buff,
10483                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10484     }
10485
10486   freeAsmop (right, NULL, ic, TRUE);
10487   freeAsmop (result, NULL, ic, TRUE);
10488 }
10489
10490 /*-----------------------------------------------------------------*/
10491 /* genNearPointerSet - emitcode for near pointer put                */
10492 /*-----------------------------------------------------------------*/
10493 static void
10494 genNearPointerSet (operand * right,
10495                    operand * result,
10496                    iCode * ic,
10497                    iCode * pi)
10498 {
10499   asmop *aop = NULL;
10500   char *rname, *l;
10501   sym_link *retype, *letype;
10502   sym_link *ptype = operandType (result);
10503
10504   retype = getSpec (operandType (right));
10505   letype = getSpec (ptype);
10506
10507   aopOp (result, ic, FALSE, FALSE);
10508
10509   /* if the result is rematerializable &
10510      in data space & not a bit variable */
10511   if (AOP_TYPE (result) == AOP_IMMD &&
10512       DCL_TYPE (ptype) == POINTER &&
10513       !IS_BITVAR (retype) &&
10514       !IS_BITVAR (letype))
10515     {
10516       genDataPointerSet (right, result, ic);
10517       return;
10518     }
10519
10520   /* if the value is already in a pointer register
10521      then don't need anything more */
10522   if (!AOP_INPREG (AOP (result)))
10523     {
10524       /* otherwise get a free pointer register */
10525       regs *preg;
10526         
10527       aop = newAsmop (0);
10528       preg = getFreePtr (ic, &aop, FALSE);
10529       emitcode ("mov", "%s,%s",
10530                 preg->name,
10531                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10532       rname = preg->name;
10533     }
10534   else
10535     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10536
10537   aopOp (right, ic, FALSE, FALSE);
10538
10539   /* if bitfield then unpack the bits */
10540   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10541     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10542   else
10543     {
10544       /* we have can just get the values */
10545       int size = AOP_SIZE (right);
10546       int offset = 0;
10547
10548       while (size--)
10549         {
10550           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10551           if (*l == '@')
10552             {
10553               MOVA (l);
10554               emitcode ("mov", "@%s,a", rname);
10555             }
10556           else
10557             emitcode ("mov", "@%s,%s", rname, l);
10558           if (size || pi)
10559             emitcode ("inc", "%s", rname);
10560           offset++;
10561         }
10562     }
10563
10564   /* now some housekeeping stuff */
10565   if (aop)
10566     {
10567       /* we had to allocate for this iCode */
10568       if (pi) aopPut (AOP (result),rname,0);
10569       freeAsmop (NULL, aop, ic, TRUE);
10570     }
10571   else
10572     {
10573       /* we did not allocate which means left
10574          already in a pointer register, then
10575          if size > 0 && this could be used again
10576          we have to point it back to where it
10577          belongs */
10578       if (AOP_SIZE (right) > 1 &&
10579           !OP_SYMBOL (result)->remat &&
10580           (OP_SYMBOL (result)->liveTo > ic->seq ||
10581            ic->depth) &&
10582           !pi)
10583         {
10584           int size = AOP_SIZE (right) - 1;
10585           while (size--)
10586             emitcode ("dec", "%s", rname);
10587         }
10588     }
10589
10590   /* done */
10591   if (pi) pi->generated = 1;
10592   freeAsmop (result, NULL, ic, TRUE);
10593   freeAsmop (right, NULL, ic, TRUE);
10594
10595
10596 }
10597
10598 /*-----------------------------------------------------------------*/
10599 /* genPagedPointerSet - emitcode for Paged pointer put             */
10600 /*-----------------------------------------------------------------*/
10601 static void
10602 genPagedPointerSet (operand * right,
10603                     operand * result,
10604                     iCode * ic,
10605                     iCode *pi)
10606 {
10607   asmop *aop = NULL;
10608   char *rname;
10609   sym_link *retype, *letype;
10610
10611   retype = getSpec (operandType (right));
10612   letype = getSpec (operandType (result));
10613
10614   aopOp (result, ic, FALSE, FALSE);
10615
10616   /* if the value is already in a pointer register
10617      then don't need anything more */
10618   if (!AOP_INPREG (AOP (result)))
10619     {
10620       /* otherwise get a free pointer register */
10621       regs *preg;
10622         
10623       aop = newAsmop (0);
10624       preg = getFreePtr (ic, &aop, FALSE);
10625       emitcode ("mov", "%s,%s",
10626                 preg->name,
10627                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10628       rname = preg->name;
10629     }
10630   else
10631     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10632
10633   aopOp (right, ic, FALSE, FALSE);
10634
10635   /* if bitfield then unpack the bits */
10636   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10637     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10638   else
10639     {
10640       /* we have can just get the values */
10641       int size = AOP_SIZE (right);
10642       int offset = 0;
10643
10644       while (size--)
10645         {
10646           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10647
10648           emitcode ("movx", "@%s,a", rname);
10649
10650           if (size || pi)
10651             emitcode ("inc", "%s", rname);
10652
10653           offset++;
10654         }
10655     }
10656
10657   /* now some housekeeping stuff */
10658   if (aop)
10659     {
10660       if (pi) aopPut (AOP (result),rname,0);
10661       /* we had to allocate for this iCode */
10662       freeAsmop (NULL, aop, ic, TRUE);
10663     }
10664   else
10665     {
10666       /* we did not allocate which means left
10667          already in a pointer register, then
10668          if size > 0 && this could be used again
10669          we have to point it back to where it
10670          belongs */
10671       if (AOP_SIZE (right) > 1 &&
10672           !OP_SYMBOL (result)->remat &&
10673           (OP_SYMBOL (result)->liveTo > ic->seq ||
10674            ic->depth) &&
10675           !pi)
10676         {
10677           int size = AOP_SIZE (right) - 1;
10678           while (size--)
10679             emitcode ("dec", "%s", rname);
10680         }
10681     }
10682
10683   /* done */
10684   if (pi) pi->generated = 1;
10685   freeAsmop (result, NULL, ic, TRUE);
10686   freeAsmop (right, NULL, ic, TRUE);
10687
10688
10689 }
10690
10691 /*-----------------------------------------------------------------*/
10692 /* genFarPointerSet - set value from far space                     */
10693 /*-----------------------------------------------------------------*/
10694 static void
10695 genFarPointerSet (operand * right,
10696                   operand * result, iCode * ic, iCode *pi)
10697 {
10698   int size, offset, dopi=1;
10699   sym_link *retype = getSpec (operandType (right));
10700   sym_link *letype = getSpec (operandType (result));
10701
10702   aopOp (result, ic, FALSE, FALSE);
10703
10704   /* if the operand is already in dptr
10705      then we do nothing else we move the value to dptr */
10706   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10707     {
10708       /* if this is remateriazable */
10709       if (AOP_TYPE (result) == AOP_IMMD)
10710         emitcode ("mov", "dptr,%s", 
10711                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10712       else
10713         {
10714           /* we need to get it byte by byte */
10715           _startLazyDPSEvaluation ();
10716           if (AOP_TYPE (result) != AOP_DPTR)
10717             {
10718               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10719               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10720               if (options.model == MODEL_FLAT24)
10721                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10722             }
10723           else
10724             {
10725               /* We need to generate a load to DPTR indirect through DPTR. */
10726               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10727                 
10728               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10729               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10730               if (options.model == MODEL_FLAT24)
10731                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10732               emitcode ("pop", "dph");
10733               emitcode ("pop", "dpl");
10734               dopi=0;
10735             }
10736           _endLazyDPSEvaluation ();
10737         }
10738     }
10739   /* so dptr know contains the address */
10740   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10741
10742   /* if bit then unpack */
10743   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10744       if (AOP_INDPTRn(result)) {
10745           genSetDPTR(AOP(result)->aopu.dptr);
10746       }
10747       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10748       if (AOP_INDPTRn(result)) {
10749           genSetDPTR(0);
10750       }
10751   } else {
10752       size = AOP_SIZE (right);
10753       offset = 0;
10754       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10755           while (size--) {
10756               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10757               
10758               genSetDPTR(AOP(result)->aopu.dptr);
10759               emitcode ("movx", "@dptr,a");
10760               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10761                   emitcode ("inc", "dptr");
10762               genSetDPTR (0);
10763           }
10764       } else {
10765           _startLazyDPSEvaluation ();
10766           while (size--) {
10767               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10768               
10769               if (AOP_INDPTRn(result)) {
10770                   genSetDPTR(AOP(result)->aopu.dptr);
10771               } else {
10772                   genSetDPTR (0);
10773               }
10774               _flushLazyDPS ();
10775               
10776               emitcode ("movx", "@dptr,a");
10777               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10778                   emitcode ("inc", "dptr");
10779           }
10780           _endLazyDPSEvaluation ();
10781       }
10782   }
10783   
10784   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10785       if (!AOP_INDPTRn(result)) {
10786           _startLazyDPSEvaluation ();
10787           
10788           aopPut (AOP(result),"dpl",0);
10789           aopPut (AOP(result),"dph",1);
10790           if (options.model == MODEL_FLAT24)
10791               aopPut (AOP(result),"dpx",2);
10792
10793           _endLazyDPSEvaluation ();
10794       }
10795       pi->generated=1;
10796   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10797              AOP_SIZE(right) > 1 &&
10798              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10799       
10800       size = AOP_SIZE (right) - 1;
10801       if (AOP_INDPTRn(result)) {
10802           genSetDPTR(AOP(result)->aopu.dptr);
10803       } 
10804       while (size--) emitcode ("lcall","__decdptr");
10805       if (AOP_INDPTRn(result)) {
10806           genSetDPTR(0);
10807       }
10808   }
10809   freeAsmop (result, NULL, ic, TRUE);
10810   freeAsmop (right, NULL, ic, TRUE);
10811 }
10812
10813 /*-----------------------------------------------------------------*/
10814 /* genGenPointerSet - set value from generic pointer space         */
10815 /*-----------------------------------------------------------------*/
10816 static void
10817 genGenPointerSet (operand * right,
10818                   operand * result, iCode * ic, iCode *pi)
10819 {
10820   int size, offset;
10821   sym_link *retype = getSpec (operandType (right));
10822   sym_link *letype = getSpec (operandType (result));
10823
10824   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10825
10826   /* if the operand is already in dptr
10827      then we do nothing else we move the value to dptr */
10828   if (AOP_TYPE (result) != AOP_STR)
10829     {
10830       _startLazyDPSEvaluation ();
10831       /* if this is remateriazable */
10832       if (AOP_TYPE (result) == AOP_IMMD)
10833         {
10834           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10835           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10836           {
10837               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10838           }
10839           else
10840           {
10841               emitcode ("mov", 
10842                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10843           }
10844         }
10845       else
10846         {                       /* we need to get it byte by byte */
10847           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10848           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10849           if (options.model == MODEL_FLAT24) {
10850             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10851             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10852           } else {
10853             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10854           }
10855         }
10856       _endLazyDPSEvaluation ();
10857     }
10858   /* so dptr + b now contains the address */
10859   _G.bInUse++;
10860   aopOp (right, ic, FALSE, TRUE);
10861   _G.bInUse--;
10862     
10863
10864   /* if bit then unpack */
10865   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10866     {
10867         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10868     }
10869   else
10870     {
10871         size = AOP_SIZE (right);
10872         offset = 0;
10873
10874         _startLazyDPSEvaluation ();
10875         while (size--)
10876         {
10877             if (size)
10878             {
10879                 // Set two bytes at a time, passed in _AP & A.
10880                 // dptr will be incremented ONCE by __gptrputWord.
10881                 //
10882                 // Note: any change here must be coordinated
10883                 // with the implementation of __gptrputWord
10884                 // in device/lib/_gptrput.c
10885                 emitcode("mov", "_ap, %s", 
10886                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10887                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10888                 
10889                 genSetDPTR (0);
10890                 _flushLazyDPS ();
10891                 emitcode ("lcall", "__gptrputWord");
10892                 size--;
10893             }
10894             else
10895             {
10896                 // Only one byte to put.
10897                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10898
10899                 genSetDPTR (0);
10900                 _flushLazyDPS ();               
10901                 emitcode ("lcall", "__gptrput");
10902             }
10903             
10904             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10905             {
10906                 emitcode ("inc", "dptr");
10907             }
10908         }
10909         _endLazyDPSEvaluation ();
10910     }
10911
10912   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10913       _startLazyDPSEvaluation ();
10914       
10915       aopPut (AOP(result),"dpl",0);
10916       aopPut (AOP(result),"dph",1);
10917       if (options.model == MODEL_FLAT24) {
10918           aopPut (AOP(result),"dpx",2);
10919           aopPut (AOP(result),"b",3);
10920       } else {
10921           aopPut (AOP(result),"b",2);
10922       }
10923       _endLazyDPSEvaluation ();
10924       
10925       pi->generated=1;
10926   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10927              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10928       
10929       size = AOP_SIZE (right) - 1;
10930       while (size--) emitcode ("lcall","__decdptr");
10931   }
10932   freeAsmop (result, NULL, ic, TRUE);
10933   freeAsmop (right, NULL, ic, TRUE);
10934 }
10935
10936 /*-----------------------------------------------------------------*/
10937 /* genPointerSet - stores the value into a pointer location        */
10938 /*-----------------------------------------------------------------*/
10939 static void
10940 genPointerSet (iCode * ic, iCode *pi)
10941 {
10942   operand *right, *result;
10943   sym_link *type, *etype;
10944   int p_type;
10945
10946   D (emitcode (";", "genPointerSet "););
10947
10948   right = IC_RIGHT (ic);
10949   result = IC_RESULT (ic);
10950
10951   /* depending on the type of pointer we need to
10952      move it to the correct pointer register */
10953   type = operandType (result);
10954   etype = getSpec (type);
10955   /* if left is of type of pointer then it is simple */
10956   if (IS_PTR (type) && !IS_FUNC (type->next))
10957     {
10958       p_type = DCL_TYPE (type);
10959     }
10960   else
10961     {
10962       /* we have to go by the storage class */
10963       p_type = PTR_TYPE (SPEC_OCLS (etype));
10964     }
10965   /* special case when cast remat */
10966   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10967       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10968           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10969           type = operandType (result);
10970           p_type = DCL_TYPE (type);
10971   }
10972
10973   /* now that we have the pointer type we assign
10974      the pointer values */
10975   switch (p_type)
10976     {
10977
10978     case POINTER:
10979     case IPOINTER:
10980       genNearPointerSet (right, result, ic, pi);
10981       break;
10982
10983     case PPOINTER:
10984       genPagedPointerSet (right, result, ic, pi);
10985       break;
10986
10987     case FPOINTER:
10988       genFarPointerSet (right, result, ic, pi);
10989       break;
10990
10991     case GPOINTER:
10992       genGenPointerSet (right, result, ic, pi);
10993       break;
10994
10995     default:
10996       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10997               "genPointerSet: illegal pointer type");
10998     }
10999
11000 }
11001
11002 /*-----------------------------------------------------------------*/
11003 /* genIfx - generate code for Ifx statement                        */
11004 /*-----------------------------------------------------------------*/
11005 static void
11006 genIfx (iCode * ic, iCode * popIc)
11007 {
11008   operand *cond = IC_COND (ic);
11009   int isbit = 0;
11010
11011   D (emitcode (";", "genIfx "););
11012
11013   aopOp (cond, ic, FALSE, FALSE);
11014
11015   /* get the value into acc */
11016   if (AOP_TYPE (cond) != AOP_CRY)
11017     {
11018         toBoolean (cond);
11019     }
11020   else
11021     {
11022         isbit = 1;
11023     }
11024     
11025   /* the result is now in the accumulator */
11026   freeAsmop (cond, NULL, ic, TRUE);
11027
11028   /* if there was something to be popped then do it */
11029   if (popIc)
11030     genIpop (popIc);
11031
11032   /* if the condition is  a bit variable */
11033   if (isbit && IS_ITEMP (cond) &&
11034       SPIL_LOC (cond))
11035     {
11036         genIfxJump (ic, SPIL_LOC (cond)->rname);
11037     }
11038   else if (isbit && !IS_ITEMP (cond))
11039     {
11040         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11041     }
11042   else
11043     {
11044         genIfxJump (ic, "a");
11045     }
11046
11047   ic->generated = 1;
11048 }
11049
11050 /*-----------------------------------------------------------------*/
11051 /* genAddrOf - generates code for address of                       */
11052 /*-----------------------------------------------------------------*/
11053 static void
11054 genAddrOf (iCode * ic)
11055 {
11056   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11057   int size, offset;
11058
11059   D (emitcode (";", "genAddrOf ");
11060     );
11061
11062   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11063
11064   /* if the operand is on the stack then we
11065      need to get the stack offset of this
11066      variable */
11067   if (sym->onStack) {
11068       
11069       /* if 10 bit stack */
11070       if (options.stack10bit) {
11071           char buff[10];
11072           int  offset;
11073           
11074           tsprintf(buff, sizeof(buff), 
11075                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11076           /* if it has an offset then we need to compute it */
11077 /*        emitcode ("subb", "a,#!constbyte", */
11078 /*                  -((sym->stack < 0) ? */
11079 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11080 /*                    ((short) sym->stack)) & 0xff); */
11081 /*        emitcode ("mov","b,a"); */
11082 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11083 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11084 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11085           if (sym->stack) {
11086               emitcode ("mov", "a,_bpx");
11087               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
11088                                              ((char) (sym->stack - _G.nRegsSaved)) :
11089                                              ((char) sym->stack )) & 0xff);
11090               emitcode ("mov", "b,a");
11091               emitcode ("mov", "a,_bpx+1");
11092               
11093               offset = (((sym->stack < 0) ? 
11094                          ((short) (sym->stack - _G.nRegsSaved)) :
11095                          ((short) sym->stack )) >> 8) & 0xff;
11096           
11097               emitcode ("addc","a,#!constbyte", offset);
11098
11099               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11100               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11101               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11102           } else {
11103               /* we can just move _bp */
11104               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11105               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11106               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11107           }       
11108       } else {
11109           /* if it has an offset then we need to compute it */
11110           if (sym->stack) {
11111               emitcode ("mov", "a,_bp");
11112               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11113               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11114           } else {
11115               /* we can just move _bp */
11116               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11117           }
11118           /* fill the result with zero */
11119           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11120           
11121           
11122           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11123               fprintf (stderr,
11124                        "*** warning: pointer to stack var truncated.\n");
11125           }
11126
11127           offset = 1;
11128           while (size--) {
11129               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11130           }      
11131       }
11132       goto release;
11133   }
11134
11135   /* object not on stack then we need the name */
11136   size = AOP_SIZE (IC_RESULT (ic));
11137   offset = 0;
11138
11139   while (size--)
11140     {
11141       char s[SDCC_NAME_MAX];
11142       if (offset) {
11143           switch (offset) {
11144           case 1:
11145               tsprintf(s, sizeof(s), "#!his",sym->rname);
11146               break;
11147           case 2:
11148               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11149               break;
11150           case 3:
11151               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11152               break;
11153           default: /* should not need this (just in case) */
11154               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11155                        sym->rname,
11156                        offset * 8);
11157           }
11158       } 
11159       else
11160       {
11161           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11162       }
11163         
11164       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11165     }
11166
11167 release:
11168   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11169
11170 }
11171
11172 #if 0 // obsolete, and buggy for != xdata
11173 /*-----------------------------------------------------------------*/
11174 /* genArrayInit - generates code for address of                       */
11175 /*-----------------------------------------------------------------*/
11176 static void
11177 genArrayInit (iCode * ic)
11178 {
11179     literalList *iLoop;
11180     int         ix, count;
11181     int         elementSize = 0, eIndex;
11182     unsigned    val, lastVal;
11183     sym_link    *type;
11184     operand     *left=IC_LEFT(ic);
11185     
11186     D (emitcode (";", "genArrayInit "););
11187
11188     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11189     
11190     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11191     {
11192         // Load immediate value into DPTR.
11193         emitcode("mov", "dptr, %s",
11194              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11195     }
11196     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11197     {
11198 #if 0
11199       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11200               "Unexpected operand to genArrayInit.\n");
11201       exit(1);
11202 #else
11203       // a regression because of SDCCcse.c:1.52
11204       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11205       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11206       if (options.model == MODEL_FLAT24)
11207         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11208 #endif
11209     }
11210     
11211     type = operandType(IC_LEFT(ic));
11212     
11213     if (type && type->next)
11214     {
11215         elementSize = getSize(type->next);
11216     }
11217     else
11218     {
11219         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11220                                 "can't determine element size in genArrayInit.\n");
11221         exit(1);
11222     }
11223     
11224     iLoop = IC_ARRAYILIST(ic);
11225     lastVal = 0xffff;
11226     
11227     while (iLoop)
11228     {
11229         bool firstpass = TRUE;
11230         
11231         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
11232                  iLoop->count, (int)iLoop->literalValue, elementSize);
11233         
11234         ix = iLoop->count;
11235         
11236         while (ix)
11237         {
11238             symbol *tlbl = NULL;
11239             
11240             count = ix > 256 ? 256 : ix;
11241             
11242             if (count > 1)
11243             {
11244                 tlbl = newiTempLabel (NULL);
11245                 if (firstpass || (count & 0xff))
11246                 {
11247                     emitcode("mov", "b, #!constbyte", count & 0xff);
11248                 }
11249                 
11250                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11251             }
11252             
11253             firstpass = FALSE;
11254                 
11255             for (eIndex = 0; eIndex < elementSize; eIndex++)
11256             {
11257                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11258                 if (val != lastVal)
11259                 {
11260                     emitcode("mov", "a, #!constbyte", val);
11261                     lastVal = val;
11262                 }
11263                 
11264                 emitcode("movx", "@dptr, a");
11265                 emitcode("inc", "dptr");
11266             }
11267             
11268             if (count > 1)
11269             {
11270                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11271             }
11272             
11273             ix -= count;
11274         }
11275         
11276         iLoop = iLoop->next;
11277     }
11278     
11279     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11280 }
11281 #endif
11282
11283 /*-----------------------------------------------------------------*/
11284 /* genFarFarAssign - assignment when both are in far space         */
11285 /*-----------------------------------------------------------------*/
11286 static void
11287 genFarFarAssign (operand * result, operand * right, iCode * ic)
11288 {
11289   int size = AOP_SIZE (right);
11290   int offset = 0;
11291   symbol *rSym = NULL;
11292
11293   if (size == 1)
11294   {
11295       /* quick & easy case. */
11296       D(emitcode(";","genFarFarAssign (1 byte case)"););      
11297       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11298       freeAsmop (right, NULL, ic, FALSE);
11299       /* now assign DPTR to result */
11300       _G.accInUse++;
11301       aopOp(result, ic, FALSE, FALSE);
11302       _G.accInUse--;
11303       aopPut(AOP(result), "a", 0);
11304       freeAsmop(result, NULL, ic, FALSE);
11305       return;
11306   }
11307   
11308   /* See if we've got an underlying symbol to abuse. */
11309   if (IS_SYMOP(result) && OP_SYMBOL(result))
11310   {
11311       if (IS_TRUE_SYMOP(result))
11312       {
11313           rSym = OP_SYMBOL(result);
11314       }
11315       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11316       {
11317           rSym = OP_SYMBOL(result)->usl.spillLoc;
11318       }
11319   }
11320              
11321   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11322   {
11323       /* We can use the '390 auto-toggle feature to good effect here. */
11324       
11325       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11326       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11327       emitcode ("mov", "dptr,#%s", rSym->rname); 
11328       /* DP2 = result, DP1 = right, DP1 is current. */
11329       while (size)
11330       {
11331           emitcode("movx", "a,@dptr");
11332           emitcode("movx", "@dptr,a");
11333           if (--size)
11334           {
11335                emitcode("inc", "dptr");
11336                emitcode("inc", "dptr");
11337           }
11338       }
11339       emitcode("mov", "dps,#0");
11340       freeAsmop (right, NULL, ic, FALSE);
11341 #if 0
11342 some alternative code for processors without auto-toggle
11343 no time to test now, so later well put in...kpb
11344         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11345         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11346         emitcode ("mov", "dptr,#%s", rSym->rname); 
11347         /* DP2 = result, DP1 = right, DP1 is current. */
11348         while (size)
11349         {
11350           --size;
11351           emitcode("movx", "a,@dptr");
11352           if (size)
11353             emitcode("inc", "dptr");
11354           emitcode("inc", "dps");
11355           emitcode("movx", "@dptr,a");
11356           if (size)
11357             emitcode("inc", "dptr");
11358           emitcode("inc", "dps");
11359         }
11360         emitcode("mov", "dps,#0");
11361         freeAsmop (right, NULL, ic, FALSE);
11362 #endif
11363   }
11364   else
11365   {
11366       D (emitcode (";", "genFarFarAssign"););
11367       aopOp (result, ic, TRUE, TRUE);
11368
11369       _startLazyDPSEvaluation ();
11370       
11371       while (size--)
11372         {
11373           aopPut (AOP (result),
11374                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11375           offset++;
11376         }
11377       _endLazyDPSEvaluation ();
11378       freeAsmop (result, NULL, ic, FALSE);
11379       freeAsmop (right, NULL, ic, FALSE);
11380   }
11381 }
11382
11383 /*-----------------------------------------------------------------*/
11384 /* genAssign - generate code for assignment                        */
11385 /*-----------------------------------------------------------------*/
11386 static void
11387 genAssign (iCode * ic)
11388 {
11389   operand *result, *right;
11390   int size, offset;
11391   unsigned long lit = 0L;
11392
11393   D (emitcode (";", "genAssign ");
11394     );
11395
11396   result = IC_RESULT (ic);
11397   right = IC_RIGHT (ic);
11398
11399   /* if they are the same */
11400   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11401     return;
11402
11403   aopOp (right, ic, FALSE, FALSE);
11404
11405   emitcode (";", "genAssign: resultIsFar = %s",
11406             isOperandInFarSpace (result) ?
11407             "TRUE" : "FALSE");
11408
11409   /* special case both in far space */
11410   if ((AOP_TYPE (right) == AOP_DPTR ||
11411        AOP_TYPE (right) == AOP_DPTR2) &&
11412   /* IS_TRUE_SYMOP(result)       && */
11413       isOperandInFarSpace (result))
11414     {
11415       genFarFarAssign (result, right, ic);
11416       return;
11417     }
11418
11419   aopOp (result, ic, TRUE, FALSE);
11420
11421   /* if they are the same registers */
11422   if (sameRegs (AOP (right), AOP (result)))
11423     goto release;
11424
11425   /* if the result is a bit */
11426   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11427     {
11428       /* if the right size is a literal then
11429          we know what the value is */
11430       if (AOP_TYPE (right) == AOP_LIT)
11431         {
11432           if (((int) operandLitValue (right)))
11433             aopPut (AOP (result), one, 0);
11434           else
11435             aopPut (AOP (result), zero, 0);
11436           goto release;
11437         }
11438
11439       /* the right is also a bit variable */
11440       if (AOP_TYPE (right) == AOP_CRY)
11441         {
11442           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11443           aopPut (AOP (result), "c", 0);
11444           goto release;
11445         }
11446
11447       /* we need to or */
11448       toBoolean (right);
11449       aopPut (AOP (result), "a", 0);
11450       goto release;
11451     }
11452
11453   /* bit variables done */
11454   /* general case */
11455   size = AOP_SIZE (result);
11456   offset = 0;
11457   if (AOP_TYPE (right) == AOP_LIT)
11458     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11459
11460   if ((size > 1) &&
11461       (AOP_TYPE (result) != AOP_REG) &&
11462       (AOP_TYPE (right) == AOP_LIT) &&
11463       !IS_FLOAT (operandType (right)))
11464     {
11465       _startLazyDPSEvaluation ();
11466       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11467         {
11468           aopPut (AOP (result),
11469                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11470                   offset);
11471           offset++;
11472           size--;
11473         }
11474       /* And now fill the rest with zeros. */
11475       if (size)
11476         {
11477           emitcode ("clr", "a");
11478         }
11479       while (size--)
11480         {
11481           aopPut (AOP (result), "a", offset++);
11482         }
11483       _endLazyDPSEvaluation ();
11484     }
11485   else
11486     {
11487       _startLazyDPSEvaluation ();
11488       while (size--)
11489         {
11490           aopPut (AOP (result),
11491                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11492                   offset);
11493           offset++;
11494         }
11495       _endLazyDPSEvaluation ();
11496     }
11497
11498 release:
11499   freeAsmop (right, NULL, ic, FALSE);
11500   freeAsmop (result, NULL, ic, TRUE);
11501 }
11502
11503 /*-----------------------------------------------------------------*/
11504 /* genJumpTab - generates code for jump table                      */
11505 /*-----------------------------------------------------------------*/
11506 static void
11507 genJumpTab (iCode * ic)
11508 {
11509   symbol *jtab;
11510   char *l;
11511
11512   D (emitcode (";", "genJumpTab ");
11513     );
11514
11515   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11516   /* get the condition into accumulator */
11517   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11518   MOVA (l);
11519   /* multiply by four! */
11520   emitcode ("add", "a,acc");
11521   emitcode ("add", "a,acc");
11522   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11523
11524   jtab = newiTempLabel (NULL);
11525   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11526   emitcode ("jmp", "@a+dptr");
11527   emitcode ("", "!tlabeldef", jtab->key + 100);
11528   /* now generate the jump labels */
11529   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11530        jtab = setNextItem (IC_JTLABELS (ic)))
11531     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11532
11533 }
11534
11535 /*-----------------------------------------------------------------*/
11536 /* genCast - gen code for casting                                  */
11537 /*-----------------------------------------------------------------*/
11538 static void
11539 genCast (iCode * ic)
11540 {
11541   operand *result = IC_RESULT (ic);
11542   sym_link *ctype = operandType (IC_LEFT (ic));
11543   sym_link *rtype = operandType (IC_RIGHT (ic));
11544   operand *right = IC_RIGHT (ic);
11545   int size, offset;
11546
11547   D (emitcode (";", "genCast "););
11548
11549   /* if they are equivalent then do nothing */
11550   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11551     return;
11552
11553   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11554   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11555
11556   /* if the result is a bit */
11557   if (IS_BITVAR (OP_SYMBOL (result)->type)
11558       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11559     {
11560       /* if the right size is a literal then
11561          we know what the value is */
11562       if (AOP_TYPE (right) == AOP_LIT)
11563         {
11564           if (((int) operandLitValue (right)))
11565             aopPut (AOP (result), one, 0);
11566           else
11567             aopPut (AOP (result), zero, 0);
11568
11569           goto release;
11570         }
11571
11572       /* the right is also a bit variable */
11573       if (AOP_TYPE (right) == AOP_CRY)
11574         {
11575           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11576           aopPut (AOP (result), "c", 0);
11577           goto release;
11578         }
11579
11580       /* we need to or */
11581       toBoolean (right);
11582       aopPut (AOP (result), "a", 0);
11583       goto release;
11584     }
11585
11586   /* if they are the same size : or less */
11587   if (AOP_SIZE (result) <= AOP_SIZE (right))
11588     {
11589
11590       /* if they are in the same place */
11591       if (sameRegs (AOP (right), AOP (result)))
11592         goto release;
11593
11594       /* if they in different places then copy */
11595       size = AOP_SIZE (result);
11596       offset = 0;
11597       _startLazyDPSEvaluation ();
11598       while (size--)
11599         {
11600           aopPut (AOP (result),
11601                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11602                   offset);
11603           offset++;
11604         }
11605       _endLazyDPSEvaluation ();
11606       goto release;
11607     }
11608
11609
11610   /* if the result is of type pointer */
11611   if (IS_PTR (ctype))
11612     {
11613
11614       int p_type;
11615       sym_link *type = operandType (right);
11616
11617       /* pointer to generic pointer */
11618       if (IS_GENPTR (ctype))
11619         {
11620           if (IS_PTR (type))
11621             {
11622               p_type = DCL_TYPE (type);
11623             }
11624           else
11625             {
11626 #if OLD_CAST_BEHAVIOR
11627               /* KV: we are converting a non-pointer type to
11628                * a generic pointer. This (ifdef'd out) code
11629                * says that the resulting generic pointer
11630                * should have the same class as the storage
11631                * location of the non-pointer variable.
11632                *
11633                * For example, converting an int (which happens
11634                * to be stored in DATA space) to a pointer results
11635                * in a DATA generic pointer; if the original int
11636                * in XDATA space, so will be the resulting pointer.
11637                *
11638                * I don't like that behavior, and thus this change:
11639                * all such conversions will be forced to XDATA and
11640                * throw a warning. If you want some non-XDATA
11641                * type, or you want to suppress the warning, you
11642                * must go through an intermediate cast, like so:
11643                *
11644                * char _generic *gp = (char _xdata *)(intVar);
11645                */
11646               sym_link *etype = getSpec (type);
11647
11648               /* we have to go by the storage class */
11649               if (SPEC_OCLS (etype) != generic)
11650                 {
11651                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11652                 }
11653               else
11654 #endif
11655                 {
11656                   /* Converting unknown class (i.e. register variable)
11657                    * to generic pointer. This is not good, but
11658                    * we'll make a guess (and throw a warning).
11659                    */
11660                   p_type = FPOINTER;
11661                   werror (W_INT_TO_GEN_PTR_CAST);
11662                 }
11663             }
11664
11665           /* the first two bytes are known */
11666           size = GPTRSIZE - 1;
11667           offset = 0;
11668           _startLazyDPSEvaluation ();
11669           while (size--)
11670             {
11671               aopPut (AOP (result),
11672                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11673                       offset);
11674               offset++;
11675             }
11676           _endLazyDPSEvaluation ();
11677
11678           /* the last byte depending on type */
11679             {
11680                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11681                 char gpValStr[10];
11682             
11683                 if (gpVal == -1)
11684                 {
11685                     // pointerTypeToGPByte will have bitched.
11686                     exit(1);
11687                 }
11688             
11689                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11690                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11691             }
11692           goto release;
11693         }
11694
11695       /* just copy the pointers */
11696       size = AOP_SIZE (result);
11697       offset = 0;
11698       _startLazyDPSEvaluation ();
11699       while (size--)
11700         {
11701           aopPut (AOP (result),
11702                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11703                   offset);
11704           offset++;
11705         }
11706       _endLazyDPSEvaluation ();
11707       goto release;
11708     }
11709
11710   /* so we now know that the size of destination is greater
11711      than the size of the source */
11712   /* we move to result for the size of source */
11713   size = AOP_SIZE (right);
11714   offset = 0;
11715   _startLazyDPSEvaluation ();
11716   while (size--)
11717     {
11718       aopPut (AOP (result),
11719               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11720               offset);
11721       offset++;
11722     }
11723   _endLazyDPSEvaluation ();
11724
11725   /* now depending on the sign of the source && destination */
11726   size = AOP_SIZE (result) - AOP_SIZE (right);
11727   /* if unsigned or not an integral type */
11728   /* also, if the source is a bit, we don't need to sign extend, because
11729    * it can't possibly have set the sign bit.
11730    */
11731   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11732     {
11733       while (size--)
11734         {
11735           aopPut (AOP (result), zero, offset++);
11736         }
11737     }
11738   else
11739     {
11740       /* we need to extend the sign :{ */
11741       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11742                         FALSE, FALSE, NULL));
11743       emitcode ("rlc", "a");
11744       emitcode ("subb", "a,acc");
11745       while (size--)
11746         aopPut (AOP (result), "a", offset++);
11747     }
11748
11749   /* we are done hurray !!!! */
11750
11751 release:
11752   freeAsmop (right, NULL, ic, TRUE);
11753   freeAsmop (result, NULL, ic, TRUE);
11754
11755 }
11756
11757 /*-----------------------------------------------------------------*/
11758 /* genDjnz - generate decrement & jump if not zero instrucion      */
11759 /*-----------------------------------------------------------------*/
11760 static int
11761 genDjnz (iCode * ic, iCode * ifx)
11762 {
11763   symbol *lbl, *lbl1;
11764   if (!ifx)
11765     return 0;
11766
11767   /* if the if condition has a false label
11768      then we cannot save */
11769   if (IC_FALSE (ifx))
11770     return 0;
11771
11772   /* if the minus is not of the form
11773      a = a - 1 */
11774   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11775       !IS_OP_LITERAL (IC_RIGHT (ic)))
11776     return 0;
11777
11778   if (operandLitValue (IC_RIGHT (ic)) != 1)
11779     return 0;
11780
11781   /* if the size of this greater than one then no
11782      saving */
11783   if (getSize (operandType (IC_RESULT (ic))) > 1)
11784     return 0;
11785
11786   /* otherwise we can save BIG */
11787   D(emitcode(";", "genDjnz"););
11788
11789   lbl = newiTempLabel (NULL);
11790   lbl1 = newiTempLabel (NULL);
11791
11792   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11793
11794   if (AOP_NEEDSACC(IC_RESULT(ic)))
11795   {
11796       /* If the result is accessed indirectly via
11797        * the accumulator, we must explicitly write
11798        * it back after the decrement.
11799        */
11800       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11801       
11802       if (strcmp(rByte, "a"))
11803       {
11804            /* Something is hopelessly wrong */
11805            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11806                    __FILE__, __LINE__);
11807            /* We can just give up; the generated code will be inefficient,
11808             * but what the hey.
11809             */
11810            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11811            return 0;
11812       }
11813       emitcode ("dec", "%s", rByte);
11814       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11815       emitcode ("jnz", "!tlabel", lbl->key + 100);
11816   }
11817   else if (IS_AOP_PREG (IC_RESULT (ic)))
11818     {
11819       emitcode ("dec", "%s",
11820                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11821       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11822       emitcode ("jnz", "!tlabel", lbl->key + 100);
11823     }
11824   else
11825     {
11826       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11827                 lbl->key + 100);
11828     }
11829   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11830   emitcode ("", "!tlabeldef", lbl->key + 100);
11831   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11832   emitcode ("", "!tlabeldef", lbl1->key + 100);
11833
11834   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11835   ifx->generated = 1;
11836   return 1;
11837 }
11838
11839 /*-----------------------------------------------------------------*/
11840 /* genReceive - generate code for a receive iCode                  */
11841 /*-----------------------------------------------------------------*/
11842 static void
11843 genReceive (iCode * ic)
11844 {
11845     int size = getSize (operandType (IC_RESULT (ic)));
11846     int offset = 0;
11847     int rb1off ;
11848     
11849     D (emitcode (";", "genReceive "););
11850
11851     if (ic->argreg == 1) 
11852     {
11853         /* first parameter */
11854         if (AOP_IS_STR(IC_RESULT(ic)))
11855         {
11856             /* Nothing to do: it's already in the proper place. */
11857             return;
11858         }
11859         else
11860         {
11861             bool useDp2;
11862             
11863             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11864                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11865                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11866             
11867             _G.accInUse++;
11868             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11869             _G.accInUse--; 
11870             
11871             /* Sanity checking... */
11872             if (AOP_USESDPTR(IC_RESULT(ic)))
11873             {
11874                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11875                         "genReceive got unexpected DPTR.");
11876             }
11877             assignResultValue (IC_RESULT (ic));
11878         }
11879     } 
11880     else 
11881     { 
11882         /* second receive onwards */
11883         /* this gets a little tricky since unused recevies will be
11884          eliminated, we have saved the reg in the type field . and
11885          we use that to figure out which register to use */
11886         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11887         rb1off = ic->argreg;
11888         while (size--) 
11889         {
11890             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11891         }
11892     }
11893     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11894 }
11895
11896 /*-----------------------------------------------------------------*/
11897 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11898 /*-----------------------------------------------------------------*/
11899 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11900 {
11901     operand *from , *to , *count;
11902     symbol *lbl;
11903     bitVect *rsave;
11904     int i;
11905
11906     /* we know it has to be 3 parameters */
11907     assert (nparms == 3);
11908     
11909     rsave = newBitVect(16);
11910     /* save DPTR if it needs to be saved */
11911     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11912             if (bitVectBitValue(ic->rMask,i))
11913                     rsave = bitVectSetBit(rsave,i);
11914     }
11915     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11916                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11917     savermask(rsave);
11918     
11919     to = parms[0];
11920     from = parms[1];
11921     count = parms[2];
11922
11923     aopOp (from, ic->next, FALSE, FALSE);
11924
11925     /* get from into DPTR1 */
11926     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11927     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11928     if (options.model == MODEL_FLAT24) {
11929         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11930     }
11931
11932     freeAsmop (from, NULL, ic, FALSE);
11933     aopOp (to, ic, FALSE, FALSE);
11934     /* get "to" into DPTR */
11935     /* if the operand is already in dptr
11936        then we do nothing else we move the value to dptr */
11937     if (AOP_TYPE (to) != AOP_STR) {
11938         /* if already in DPTR then we need to push */
11939         if (AOP_TYPE(to) == AOP_DPTR) {
11940             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11941             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11942             if (options.model == MODEL_FLAT24)
11943                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11944             emitcode ("pop", "dph");
11945             emitcode ("pop", "dpl");        
11946         } else {
11947             _startLazyDPSEvaluation ();
11948             /* if this is remateriazable */
11949             if (AOP_TYPE (to) == AOP_IMMD) {
11950                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11951             } else {                    /* we need to get it byte by byte */
11952                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11953                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11954                 if (options.model == MODEL_FLAT24) {
11955                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11956                 }
11957             }
11958             _endLazyDPSEvaluation ();
11959         }
11960     }
11961     freeAsmop (to, NULL, ic, FALSE);
11962     _G.dptrInUse = _G.dptr1InUse = 1;
11963     aopOp (count, ic->next->next, FALSE,FALSE);
11964     lbl =newiTempLabel(NULL);
11965
11966     /* now for the actual copy */
11967     if (AOP_TYPE(count) == AOP_LIT && 
11968         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11969         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11970         if (fromc) {
11971             emitcode ("lcall","__bi_memcpyc2x_s");
11972         } else {
11973             emitcode ("lcall","__bi_memcpyx2x_s");
11974         }
11975         freeAsmop (count, NULL, ic, FALSE);
11976     } else {
11977         symbol *lbl1 = newiTempLabel(NULL);
11978         
11979         emitcode (";"," Auto increment but no djnz");
11980         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11981         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11982         freeAsmop (count, NULL, ic, FALSE);
11983         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11984         emitcode ("","!tlabeldef",lbl->key+100);
11985         if (fromc) {
11986             emitcode ("clr","a");
11987             emitcode ("movc", "a,@a+dptr");
11988         } else 
11989             emitcode ("movx", "a,@dptr");
11990         emitcode ("movx", "@dptr,a");
11991         emitcode ("inc", "dptr");
11992         emitcode ("inc", "dptr");
11993         emitcode ("mov","a,b");
11994         emitcode ("orl","a,_ap");
11995         emitcode ("jz","!tlabel",lbl1->key+100);
11996         emitcode ("mov","a,_ap");
11997         emitcode ("add","a,#!constbyte",0xFF);
11998         emitcode ("mov","_ap,a");
11999         emitcode ("mov","a,b");
12000         emitcode ("addc","a,#!constbyte",0xFF);
12001         emitcode ("mov","b,a");
12002         emitcode ("sjmp","!tlabel",lbl->key+100);
12003         emitcode ("","!tlabeldef",lbl1->key+100);
12004     }
12005     emitcode ("mov", "dps,#0"); 
12006     _G.dptrInUse = _G.dptr1InUse = 0;
12007     unsavermask(rsave);
12008
12009 }
12010
12011 /*-----------------------------------------------------------------*/
12012 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12013 /*-----------------------------------------------------------------*/
12014 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12015 {
12016     operand *from , *to , *count;
12017     symbol *lbl,*lbl2;
12018     bitVect *rsave;
12019     int i;
12020
12021     /* we know it has to be 3 parameters */
12022     assert (nparms == 3);
12023     
12024     rsave = newBitVect(16);
12025     /* save DPTR if it needs to be saved */
12026     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12027             if (bitVectBitValue(ic->rMask,i))
12028                     rsave = bitVectSetBit(rsave,i);
12029     }
12030     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12031                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12032     savermask(rsave);
12033     
12034     to = parms[0];
12035     from = parms[1];
12036     count = parms[2];
12037
12038     aopOp (from, ic->next, FALSE, FALSE);
12039
12040     /* get from into DPTR1 */
12041     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12042     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12043     if (options.model == MODEL_FLAT24) {
12044         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12045     }
12046
12047     freeAsmop (from, NULL, ic, FALSE);
12048     aopOp (to, ic, FALSE, FALSE);
12049     /* get "to" into DPTR */
12050     /* if the operand is already in dptr
12051        then we do nothing else we move the value to dptr */
12052     if (AOP_TYPE (to) != AOP_STR) {
12053         /* if already in DPTR then we need to push */
12054         if (AOP_TYPE(to) == AOP_DPTR) {
12055             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12056             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12057             if (options.model == MODEL_FLAT24)
12058                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12059             emitcode ("pop", "dph");
12060             emitcode ("pop", "dpl");        
12061         } else {
12062             _startLazyDPSEvaluation ();
12063             /* if this is remateriazable */
12064             if (AOP_TYPE (to) == AOP_IMMD) {
12065                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12066             } else {                    /* we need to get it byte by byte */
12067                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12068                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12069                 if (options.model == MODEL_FLAT24) {
12070                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12071                 }
12072             }
12073             _endLazyDPSEvaluation ();
12074         }
12075     }
12076     freeAsmop (to, NULL, ic, FALSE);
12077     _G.dptrInUse = _G.dptr1InUse = 1;
12078     aopOp (count, ic->next->next, FALSE,FALSE);
12079     lbl =newiTempLabel(NULL);
12080     lbl2 =newiTempLabel(NULL);
12081
12082     /* now for the actual compare */
12083     if (AOP_TYPE(count) == AOP_LIT && 
12084         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12085         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12086         if (fromc)
12087             emitcode("lcall","__bi_memcmpc2x_s");
12088         else
12089             emitcode("lcall","__bi_memcmpx2x_s");
12090         freeAsmop (count, NULL, ic, FALSE);
12091         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12092         aopPut(AOP(IC_RESULT(ic)),"a",0);
12093         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12094     } else {
12095         symbol *lbl1 = newiTempLabel(NULL);
12096
12097         emitcode("push","ar0");         
12098         emitcode (";"," Auto increment but no djnz");
12099         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12100         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12101         freeAsmop (count, NULL, ic, FALSE);
12102         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12103         emitcode ("","!tlabeldef",lbl->key+100);
12104         if (fromc) {
12105             emitcode ("clr","a");
12106             emitcode ("movc", "a,@a+dptr");
12107         } else 
12108             emitcode ("movx", "a,@dptr");
12109         emitcode ("mov","r0,a");
12110         emitcode ("movx", "a,@dptr");
12111         emitcode ("clr","c");
12112         emitcode ("subb","a,r0");
12113         emitcode ("jnz","!tlabel",lbl2->key+100);
12114         emitcode ("inc", "dptr");
12115         emitcode ("inc", "dptr");
12116         emitcode ("mov","a,b");
12117         emitcode ("orl","a,_ap");
12118         emitcode ("jz","!tlabel",lbl1->key+100);
12119         emitcode ("mov","a,_ap");
12120         emitcode ("add","a,#!constbyte",0xFF);
12121         emitcode ("mov","_ap,a");
12122         emitcode ("mov","a,b");
12123         emitcode ("addc","a,#!constbyte",0xFF);
12124         emitcode ("mov","b,a");
12125         emitcode ("sjmp","!tlabel",lbl->key+100);
12126         emitcode ("","!tlabeldef",lbl1->key+100);
12127         emitcode ("clr","a");
12128         emitcode ("","!tlabeldef",lbl2->key+100);
12129         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12130         aopPut(AOP(IC_RESULT(ic)),"a",0);
12131         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12132         emitcode("pop","ar0");
12133         emitcode ("mov", "dps,#0");      
12134     }
12135     _G.dptrInUse = _G.dptr1InUse = 0;
12136     unsavermask(rsave);
12137
12138 }
12139
12140 /*-----------------------------------------------------------------*/
12141 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12142 /* port, first parameter output area second parameter pointer to   */
12143 /* port third parameter count                                      */
12144 /*-----------------------------------------------------------------*/
12145 static void genInp( iCode *ic, int nparms, operand **parms)
12146 {
12147     operand *from , *to , *count;
12148     symbol *lbl;
12149     bitVect *rsave;
12150     int i;
12151
12152     /* we know it has to be 3 parameters */
12153     assert (nparms == 3);
12154     
12155     rsave = newBitVect(16);
12156     /* save DPTR if it needs to be saved */
12157     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12158             if (bitVectBitValue(ic->rMask,i))
12159                     rsave = bitVectSetBit(rsave,i);
12160     }
12161     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12162                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12163     savermask(rsave);
12164     
12165     to = parms[0];
12166     from = parms[1];
12167     count = parms[2];
12168
12169     aopOp (from, ic->next, FALSE, FALSE);
12170
12171     /* get from into DPTR1 */
12172     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12173     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12174     if (options.model == MODEL_FLAT24) {
12175         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12176     }
12177
12178     freeAsmop (from, NULL, ic, FALSE);
12179     aopOp (to, ic, FALSE, FALSE);
12180     /* get "to" into DPTR */
12181     /* if the operand is already in dptr
12182        then we do nothing else we move the value to dptr */
12183     if (AOP_TYPE (to) != AOP_STR) {
12184         /* if already in DPTR then we need to push */
12185         if (AOP_TYPE(to) == AOP_DPTR) {
12186             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12187             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12188             if (options.model == MODEL_FLAT24)
12189                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12190             emitcode ("pop", "dph");
12191             emitcode ("pop", "dpl");        
12192         } else {
12193             _startLazyDPSEvaluation ();
12194             /* if this is remateriazable */
12195             if (AOP_TYPE (to) == AOP_IMMD) {
12196                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12197             } else {                    /* we need to get it byte by byte */
12198                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12199                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12200                 if (options.model == MODEL_FLAT24) {
12201                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12202                 }
12203             }
12204             _endLazyDPSEvaluation ();
12205         }
12206     }
12207     freeAsmop (to, NULL, ic, FALSE);
12208
12209     _G.dptrInUse = _G.dptr1InUse = 1;
12210     aopOp (count, ic->next->next, FALSE,FALSE);
12211     lbl =newiTempLabel(NULL);
12212
12213     /* now for the actual copy */
12214     if (AOP_TYPE(count) == AOP_LIT && 
12215         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12216         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12217         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12218         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12219         freeAsmop (count, NULL, ic, FALSE);
12220         emitcode ("","!tlabeldef",lbl->key+100);
12221         emitcode ("movx", "a,@dptr");   /* read data from port */
12222         emitcode ("dec","dps");         /* switch to DPTR */
12223         emitcode ("movx", "@dptr,a");   /* save into location */
12224         emitcode ("inc", "dptr");       /* point to next area */
12225         emitcode ("inc","dps");         /* switch to DPTR2 */
12226         emitcode ("djnz","b,!tlabel",lbl->key+100);
12227     } else {
12228         symbol *lbl1 = newiTempLabel(NULL);
12229         
12230         emitcode (";"," Auto increment but no djnz");
12231         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12232         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12233         freeAsmop (count, NULL, ic, FALSE);
12234         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12235         emitcode ("","!tlabeldef",lbl->key+100);
12236         emitcode ("movx", "a,@dptr");
12237         emitcode ("dec","dps");         /* switch to DPTR */
12238         emitcode ("movx", "@dptr,a");
12239         emitcode ("inc", "dptr");
12240         emitcode ("inc","dps");         /* switch to DPTR2 */
12241 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12242 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12243         emitcode ("mov","a,b");
12244         emitcode ("orl","a,_ap");
12245         emitcode ("jz","!tlabel",lbl1->key+100);
12246         emitcode ("mov","a,_ap");
12247         emitcode ("add","a,#!constbyte",0xFF);
12248         emitcode ("mov","_ap,a");
12249         emitcode ("mov","a,b");
12250         emitcode ("addc","a,#!constbyte",0xFF);
12251         emitcode ("mov","b,a");
12252         emitcode ("sjmp","!tlabel",lbl->key+100);
12253         emitcode ("","!tlabeldef",lbl1->key+100);
12254     }
12255     emitcode ("mov", "dps,#0"); 
12256     _G.dptrInUse = _G.dptr1InUse = 0;
12257     unsavermask(rsave);
12258
12259 }
12260
12261 /*-----------------------------------------------------------------*/
12262 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12263 /* port, first parameter output area second parameter pointer to   */
12264 /* port third parameter count                                      */
12265 /*-----------------------------------------------------------------*/
12266 static void genOutp( iCode *ic, int nparms, operand **parms)
12267 {
12268     operand *from , *to , *count;
12269     symbol *lbl;
12270     bitVect *rsave;
12271     int i;
12272
12273     /* we know it has to be 3 parameters */
12274     assert (nparms == 3);
12275     
12276     rsave = newBitVect(16);
12277     /* save DPTR if it needs to be saved */
12278     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12279             if (bitVectBitValue(ic->rMask,i))
12280                     rsave = bitVectSetBit(rsave,i);
12281     }
12282     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12283                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12284     savermask(rsave);
12285     
12286     to = parms[0];
12287     from = parms[1];
12288     count = parms[2];
12289
12290     aopOp (from, ic->next, FALSE, FALSE);
12291
12292     /* get from into DPTR1 */
12293     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12294     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12295     if (options.model == MODEL_FLAT24) {
12296         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12297     }
12298
12299     freeAsmop (from, NULL, ic, FALSE);
12300     aopOp (to, ic, FALSE, FALSE);
12301     /* get "to" into DPTR */
12302     /* if the operand is already in dptr
12303        then we do nothing else we move the value to dptr */
12304     if (AOP_TYPE (to) != AOP_STR) {
12305         /* if already in DPTR then we need to push */
12306         if (AOP_TYPE(to) == AOP_DPTR) {
12307             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12308             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12309             if (options.model == MODEL_FLAT24)
12310                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12311             emitcode ("pop", "dph");
12312             emitcode ("pop", "dpl");        
12313         } else {
12314             _startLazyDPSEvaluation ();
12315             /* if this is remateriazable */
12316             if (AOP_TYPE (to) == AOP_IMMD) {
12317                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12318             } else {                    /* we need to get it byte by byte */
12319                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12320                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12321                 if (options.model == MODEL_FLAT24) {
12322                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12323                 }
12324             }
12325             _endLazyDPSEvaluation ();
12326         }
12327     }
12328     freeAsmop (to, NULL, ic, FALSE);
12329
12330     _G.dptrInUse = _G.dptr1InUse = 1;
12331     aopOp (count, ic->next->next, FALSE,FALSE);
12332     lbl =newiTempLabel(NULL);
12333
12334     /* now for the actual copy */
12335     if (AOP_TYPE(count) == AOP_LIT && 
12336         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12337         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12338         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12339         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12340         emitcode ("","!tlabeldef",lbl->key+100);
12341         emitcode ("movx", "a,@dptr");   /* read data from port */
12342         emitcode ("inc","dps");         /* switch to DPTR2 */
12343         emitcode ("movx", "@dptr,a");   /* save into location */
12344         emitcode ("inc", "dptr");       /* point to next area */
12345         emitcode ("dec","dps");         /* switch to DPTR */
12346         emitcode ("djnz","b,!tlabel",lbl->key+100);
12347         freeAsmop (count, NULL, ic, FALSE);
12348     } else {
12349         symbol *lbl1 = newiTempLabel(NULL);
12350         
12351         emitcode (";"," Auto increment but no djnz");
12352         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12353         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12354         freeAsmop (count, NULL, ic, FALSE);
12355         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12356         emitcode ("","!tlabeldef",lbl->key+100);
12357         emitcode ("movx", "a,@dptr");
12358         emitcode ("inc", "dptr");
12359         emitcode ("inc","dps");         /* switch to DPTR2 */
12360         emitcode ("movx", "@dptr,a");
12361         emitcode ("dec","dps");         /* switch to DPTR */
12362         emitcode ("mov","a,b");
12363         emitcode ("orl","a,_ap");
12364         emitcode ("jz","!tlabel",lbl1->key+100);
12365         emitcode ("mov","a,_ap");
12366         emitcode ("add","a,#!constbyte",0xFF);
12367         emitcode ("mov","_ap,a");
12368         emitcode ("mov","a,b");
12369         emitcode ("addc","a,#!constbyte",0xFF);
12370         emitcode ("mov","b,a");
12371         emitcode ("sjmp","!tlabel",lbl->key+100);
12372         emitcode ("","!tlabeldef",lbl1->key+100);
12373     }
12374     emitcode ("mov", "dps,#0"); 
12375     _G.dptrInUse = _G.dptr1InUse = 0;
12376     unsavermask(rsave);
12377
12378 }
12379
12380 /*-----------------------------------------------------------------*/
12381 /* genSwapW - swap lower & high order bytes                        */
12382 /*-----------------------------------------------------------------*/
12383 static void genSwapW(iCode *ic, int nparms, operand **parms)
12384 {
12385     operand *dest;
12386     operand *src;
12387     assert (nparms==1);
12388
12389     src = parms[0];
12390     dest=IC_RESULT(ic);
12391
12392     assert(getSize(operandType(src))==2);
12393
12394     aopOp (src, ic, FALSE, FALSE);
12395     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12396     _G.accInUse++;
12397     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12398     _G.accInUse--;
12399     freeAsmop (src, NULL, ic, FALSE);
12400     
12401     aopOp (dest,ic, FALSE, FALSE);
12402     aopPut(AOP(dest),"b",0);
12403     aopPut(AOP(dest),"a",1);
12404     freeAsmop (dest, NULL, ic, FALSE);    
12405 }
12406
12407 /*-----------------------------------------------------------------*/
12408 /* genMemsetX - gencode for memSetX data                           */
12409 /*-----------------------------------------------------------------*/
12410 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12411 {
12412     operand *to , *val , *count;
12413     symbol *lbl;
12414     char *l;
12415     int i;
12416     bitVect *rsave;
12417
12418     /* we know it has to be 3 parameters */
12419     assert (nparms == 3);
12420     
12421     to = parms[0];
12422     val = parms[1];
12423     count = parms[2];
12424         
12425     /* save DPTR if it needs to be saved */
12426     rsave = newBitVect(16);
12427     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12428             if (bitVectBitValue(ic->rMask,i))
12429                     rsave = bitVectSetBit(rsave,i);
12430     }
12431     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12432                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12433     savermask(rsave);
12434
12435     aopOp (to, ic, FALSE, FALSE);
12436     /* get "to" into DPTR */
12437     /* if the operand is already in dptr
12438        then we do nothing else we move the value to dptr */
12439     if (AOP_TYPE (to) != AOP_STR) {
12440         /* if already in DPTR then we need to push */
12441         if (AOP_TYPE(to) == AOP_DPTR) {
12442             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12443             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12444             if (options.model == MODEL_FLAT24)
12445                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12446             emitcode ("pop", "dph");
12447             emitcode ("pop", "dpl");        
12448         } else {
12449             _startLazyDPSEvaluation ();
12450             /* if this is remateriazable */
12451             if (AOP_TYPE (to) == AOP_IMMD) {
12452                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12453             } else {                    /* we need to get it byte by byte */
12454                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12455                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12456                 if (options.model == MODEL_FLAT24) {
12457                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12458                 }
12459             }
12460             _endLazyDPSEvaluation ();
12461         }
12462     }
12463     freeAsmop (to, NULL, ic, FALSE);
12464
12465     aopOp (val, ic->next->next, FALSE,FALSE);
12466     aopOp (count, ic->next->next, FALSE,FALSE);    
12467     lbl =newiTempLabel(NULL);
12468     /* now for the actual copy */
12469     if (AOP_TYPE(count) == AOP_LIT && 
12470         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12471         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12472         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12473         MOVA(l);
12474         emitcode ("","!tlabeldef",lbl->key+100);
12475         emitcode ("movx", "@dptr,a");
12476         emitcode ("inc", "dptr");
12477         emitcode ("djnz","b,!tlabel",lbl->key+100);
12478     } else {
12479         symbol *lbl1 = newiTempLabel(NULL);
12480         
12481         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12482         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12483         emitcode ("","!tlabeldef",lbl->key+100);
12484         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12485         emitcode ("movx", "@dptr,a");
12486         emitcode ("inc", "dptr");
12487         emitcode ("mov","a,b");
12488         emitcode ("orl","a,_ap");
12489         emitcode ("jz","!tlabel",lbl1->key+100);
12490         emitcode ("mov","a,_ap");
12491         emitcode ("add","a,#!constbyte",0xFF);
12492         emitcode ("mov","_ap,a");
12493         emitcode ("mov","a,b");
12494         emitcode ("addc","a,#!constbyte",0xFF);
12495         emitcode ("mov","b,a");
12496         emitcode ("sjmp","!tlabel",lbl->key+100);
12497         emitcode ("","!tlabeldef",lbl1->key+100);
12498     }
12499     freeAsmop (count, NULL, ic, FALSE);
12500     unsavermask(rsave);
12501 }
12502
12503 /*-----------------------------------------------------------------*/
12504 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12505 /*-----------------------------------------------------------------*/
12506 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12507 {
12508         bitVect *rsave ;
12509         operand *pnum, *result;
12510         int i;
12511     
12512         assert (nparms==1);
12513         /* save registers that need to be saved */
12514         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12515                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12516     
12517         pnum = parms[0]; 
12518         aopOp (pnum, ic, FALSE, FALSE);
12519         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12520         freeAsmop (pnum, NULL, ic, FALSE);
12521         emitcode ("lcall","NatLib_LoadPrimitive");
12522         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12523         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12524             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12525                 for (i = (size-1) ; i >= 0 ; i-- ) {
12526                         emitcode ("push","a%s",javaRet[i]);
12527                 }
12528                 for (i=0; i < size ; i++ ) {
12529                         emitcode ("pop","a%s",
12530                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12531                 }
12532         } else {
12533                 for (i = 0 ; i < size ; i++ ) {
12534                         aopPut(AOP(result),javaRet[i],i);
12535                 }
12536         }    
12537         freeAsmop (result, NULL, ic, FALSE);
12538         unsavermask(rsave);
12539 }
12540
12541 /*-----------------------------------------------------------------*/
12542 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12543 /*-----------------------------------------------------------------*/
12544 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12545 {
12546         bitVect *rsave ;
12547         operand *pnum, *result;
12548         int size = 3;
12549         int i;
12550     
12551         assert (nparms==1);
12552         /* save registers that need to be saved */
12553         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12555     
12556         pnum = parms[0]; 
12557         aopOp (pnum, ic, FALSE, FALSE);
12558         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12559         freeAsmop (pnum, NULL, ic, FALSE);
12560         emitcode ("lcall","NatLib_LoadPointer");
12561         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12562         if (AOP_TYPE(result)!=AOP_STR) {
12563                 for (i = 0 ; i < size ; i++ ) {
12564                         aopPut(AOP(result),fReturn[i],i);
12565                 }
12566         }    
12567         freeAsmop (result, NULL, ic, FALSE);
12568         unsavermask(rsave);
12569 }
12570
12571 /*-----------------------------------------------------------------*/
12572 /* genNatLibInstallStateBlock -                                    */
12573 /*-----------------------------------------------------------------*/
12574 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12575                                        operand **parms, const char *name)
12576 {
12577         bitVect *rsave ;
12578         operand *psb, *handle;
12579         assert (nparms==2);
12580
12581         /* save registers that need to be saved */
12582         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12583                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12584         psb = parms[0];
12585         handle = parms[1];
12586
12587         /* put pointer to state block into DPTR1 */
12588         aopOp (psb, ic, FALSE, FALSE);
12589         if (AOP_TYPE (psb) == AOP_IMMD) {
12590                 emitcode ("mov","dps,#1");
12591                 emitcode ("mov", "dptr,%s",
12592                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12593                 emitcode ("mov","dps,#0");
12594         } else {
12595                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12596                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12597                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12598         }
12599         freeAsmop (psb, NULL, ic, FALSE);
12600
12601         /* put libraryID into DPTR */
12602         emitcode ("mov","dptr,#LibraryID");
12603
12604         /* put handle into r3:r2 */
12605         aopOp (handle, ic, FALSE, FALSE);
12606         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12607                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12608                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12609                 emitcode ("pop","ar3");
12610                 emitcode ("pop","ar2");
12611         } else {        
12612                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12613                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12614         }
12615         freeAsmop (psb, NULL, ic, FALSE);
12616
12617         /* make the call */
12618         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12619
12620         /* put return value into place*/
12621         _G.accInUse++;
12622         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12623         _G.accInUse--;
12624         aopPut(AOP(IC_RESULT(ic)),"a",0);
12625         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12626         unsavermask(rsave);
12627 }
12628
12629 /*-----------------------------------------------------------------*/
12630 /* genNatLibRemoveStateBlock -                                     */
12631 /*-----------------------------------------------------------------*/
12632 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12633 {
12634         bitVect *rsave ;
12635
12636         assert(nparms==0);
12637
12638         /* save registers that need to be saved */
12639         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12640                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12641
12642         /* put libraryID into DPTR */
12643         emitcode ("mov","dptr,#LibraryID");
12644         /* make the call */
12645         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12646         unsavermask(rsave);
12647 }
12648
12649 /*-----------------------------------------------------------------*/
12650 /* genNatLibGetStateBlock -                                        */
12651 /*-----------------------------------------------------------------*/
12652 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12653                                    operand **parms,const char *name)
12654 {
12655         bitVect *rsave ;
12656         symbol *lbl = newiTempLabel(NULL);
12657         
12658         assert(nparms==0);
12659         /* save registers that need to be saved */
12660         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12661                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12662
12663         /* put libraryID into DPTR */
12664         emitcode ("mov","dptr,#LibraryID");
12665         /* make the call */
12666         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12667         emitcode ("jnz","!tlabel",lbl->key+100);
12668
12669         /* put return value into place */
12670         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12671         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12672                 emitcode ("push","ar3");
12673                 emitcode ("push","ar2");
12674                 emitcode ("pop","%s",
12675                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12676                 emitcode ("pop","%s",
12677                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12678         } else {
12679                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12680                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12681         }
12682         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12683         emitcode ("","!tlabeldef",lbl->key+100);
12684         unsavermask(rsave);
12685 }
12686
12687 /*-----------------------------------------------------------------*/
12688 /* genMMMalloc -                                                   */
12689 /*-----------------------------------------------------------------*/
12690 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12691                          int size, const char *name)
12692 {
12693         bitVect *rsave ;
12694         operand *bsize;
12695         symbol *rsym;
12696         symbol *lbl = newiTempLabel(NULL);
12697
12698         assert (nparms == 1);
12699         /* save registers that need to be saved */
12700         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12701                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12702         
12703         bsize=parms[0];
12704         aopOp (bsize,ic,FALSE,FALSE);
12705
12706         /* put the size in R4-R2 */
12707         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12708                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12709                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12710                 if (size==3) {
12711                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12712                         emitcode("pop","ar4");
12713                 }
12714                 emitcode("pop","ar3");
12715                 emitcode("pop","ar2");          
12716         } else {
12717                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12718                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12719                 if (size==3) {
12720                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12721                 }
12722         }
12723         freeAsmop (bsize, NULL, ic, FALSE);
12724
12725         /* make the call */
12726         emitcode ("lcall","MM_%s",name);
12727         emitcode ("jz","!tlabel",lbl->key+100);
12728         emitcode ("mov","r2,#!constbyte",0xff);
12729         emitcode ("mov","r3,#!constbyte",0xff);
12730         emitcode ("","!tlabeldef",lbl->key+100);
12731         /* we don't care about the pointer : we just save the handle */
12732         rsym = OP_SYMBOL(IC_RESULT(ic));
12733         if (rsym->liveFrom != rsym->liveTo) {
12734                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12735                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12736                         emitcode ("push","ar3");
12737                         emitcode ("push","ar2");
12738                         emitcode ("pop","%s",
12739                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12740                         emitcode ("pop","%s",
12741                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12742                 } else {
12743                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12744                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12745                 }
12746                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12747         }
12748         unsavermask(rsave);
12749 }
12750
12751 /*-----------------------------------------------------------------*/
12752 /* genMMDeref -                                                    */
12753 /*-----------------------------------------------------------------*/
12754 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12755 {
12756         bitVect *rsave ;
12757         operand *handle;
12758
12759         assert (nparms == 1);
12760         /* save registers that need to be saved */
12761         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12762                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12763         
12764         handle=parms[0];
12765         aopOp (handle,ic,FALSE,FALSE);
12766
12767         /* put the size in R4-R2 */
12768         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12769                 emitcode("push","%s",
12770                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12771                 emitcode("push","%s",
12772                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12773                 emitcode("pop","ar3");
12774                 emitcode("pop","ar2");          
12775         } else {
12776                 emitcode ("mov","r2,%s",
12777                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12778                 emitcode ("mov","r3,%s",
12779                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12780         }
12781         freeAsmop (handle, NULL, ic, FALSE);
12782
12783         /* make the call */
12784         emitcode ("lcall","MM_Deref");
12785         
12786         {
12787                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12788                 if (rsym->liveFrom != rsym->liveTo) {                   
12789                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12790                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12791                             _startLazyDPSEvaluation ();
12792                             
12793                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12794                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12795                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12796
12797                             _endLazyDPSEvaluation ();
12798                             
12799                         }
12800                 }
12801         }
12802         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12803         unsavermask(rsave);
12804 }
12805
12806 /*-----------------------------------------------------------------*/
12807 /* genMMUnrestrictedPersist -                                      */
12808 /*-----------------------------------------------------------------*/
12809 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12810 {
12811         bitVect *rsave ;
12812         operand *handle;
12813
12814         assert (nparms == 1);
12815         /* save registers that need to be saved */
12816         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12817                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12818         
12819         handle=parms[0];
12820         aopOp (handle,ic,FALSE,FALSE);
12821
12822         /* put the size in R3-R2 */
12823         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12824                 emitcode("push","%s",
12825                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12826                 emitcode("push","%s",
12827                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12828                 emitcode("pop","ar3");
12829                 emitcode("pop","ar2");          
12830         } else {
12831                 emitcode ("mov","r2,%s",
12832                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12833                 emitcode ("mov","r3,%s",
12834                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12835         }
12836         freeAsmop (handle, NULL, ic, FALSE);
12837
12838         /* make the call */
12839         emitcode ("lcall","MM_UnrestrictedPersist");
12840
12841         {
12842                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12843                 if (rsym->liveFrom != rsym->liveTo) {   
12844                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12845                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12846                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12847                 }
12848         }
12849         unsavermask(rsave);
12850 }
12851
12852 /*-----------------------------------------------------------------*/
12853 /* genSystemExecJavaProcess -                                      */
12854 /*-----------------------------------------------------------------*/
12855 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12856 {
12857         bitVect *rsave ;
12858         operand *handle, *pp;
12859
12860         assert (nparms==2);
12861         /* save registers that need to be saved */
12862         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12863                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12864         
12865         pp = parms[0];
12866         handle = parms[1];
12867         
12868         /* put the handle in R3-R2 */
12869         aopOp (handle,ic,FALSE,FALSE);
12870         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12871                 emitcode("push","%s",
12872                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12873                 emitcode("push","%s",
12874                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12875                 emitcode("pop","ar3");
12876                 emitcode("pop","ar2");          
12877         } else {
12878                 emitcode ("mov","r2,%s",
12879                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12880                 emitcode ("mov","r3,%s",
12881                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12882         }
12883         freeAsmop (handle, NULL, ic, FALSE);
12884         
12885         /* put pointer in DPTR */
12886         aopOp (pp,ic,FALSE,FALSE);
12887         if (AOP_TYPE(pp) == AOP_IMMD) {
12888                 emitcode ("mov", "dptr,%s",
12889                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12890         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12891                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12892                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12893                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12894         }
12895         freeAsmop (handle, NULL, ic, FALSE);
12896
12897         /* make the call */
12898         emitcode ("lcall","System_ExecJavaProcess");
12899         
12900         /* put result in place */
12901         {
12902                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12903                 if (rsym->liveFrom != rsym->liveTo) {   
12904                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12905                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12906                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12907                 }
12908         }
12909         
12910         unsavermask(rsave);
12911 }
12912
12913 /*-----------------------------------------------------------------*/
12914 /* genSystemRTCRegisters -                                         */
12915 /*-----------------------------------------------------------------*/
12916 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12917                                   char *name)
12918 {
12919         bitVect *rsave ;
12920         operand *pp;
12921
12922         assert (nparms==1);
12923         /* save registers that need to be saved */
12924         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12925                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12926         
12927         pp=parms[0];
12928         /* put pointer in DPTR */
12929         aopOp (pp,ic,FALSE,FALSE);
12930         if (AOP_TYPE (pp) == AOP_IMMD) {
12931                 emitcode ("mov","dps,#1");
12932                 emitcode ("mov", "dptr,%s", 
12933                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12934                 emitcode ("mov","dps,#0");
12935         } else {
12936                 emitcode ("mov","dpl1,%s",
12937                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12938                 emitcode ("mov","dph1,%s",
12939                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12940                 emitcode ("mov","dpx1,%s",
12941                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12942         }
12943         freeAsmop (pp, NULL, ic, FALSE);
12944
12945         /* make the call */
12946         emitcode ("lcall","System_%sRTCRegisters",name);
12947
12948         unsavermask(rsave);
12949 }
12950
12951 /*-----------------------------------------------------------------*/
12952 /* genSystemThreadSleep -                                          */
12953 /*-----------------------------------------------------------------*/
12954 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12955 {
12956         bitVect *rsave ;
12957         operand *to, *s;
12958
12959         assert (nparms==1);
12960         /* save registers that need to be saved */
12961         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12962                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12963
12964         to = parms[0];
12965         aopOp(to,ic,FALSE,FALSE);
12966         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12967             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12968                 emitcode ("push","%s",
12969                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12970                 emitcode ("push","%s",
12971                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12972                 emitcode ("push","%s",
12973                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12974                 emitcode ("push","%s",
12975                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12976                 emitcode ("pop","ar3");
12977                 emitcode ("pop","ar2");
12978                 emitcode ("pop","ar1");
12979                 emitcode ("pop","ar0");
12980         } else {
12981                 emitcode ("mov","r0,%s",
12982                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12983                 emitcode ("mov","r1,%s",
12984                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12985                 emitcode ("mov","r2,%s",
12986                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12987                 emitcode ("mov","r3,%s",
12988                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12989         }
12990         freeAsmop (to, NULL, ic, FALSE);
12991
12992         /* suspend in acc */
12993         s = parms[1];
12994         aopOp(s,ic,FALSE,FALSE);
12995         emitcode ("mov","a,%s",
12996                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12997         freeAsmop (s, NULL, ic, FALSE);
12998
12999         /* make the call */
13000         emitcode ("lcall","System_%s",name);
13001
13002         unsavermask(rsave);
13003 }
13004
13005 /*-----------------------------------------------------------------*/
13006 /* genSystemThreadResume -                                         */
13007 /*-----------------------------------------------------------------*/
13008 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13009 {
13010         bitVect *rsave ;
13011         operand *tid,*pid;
13012
13013         assert (nparms==2);
13014         /* save registers that need to be saved */
13015         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13016                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13017         
13018         tid = parms[0];
13019         pid = parms[1];
13020         
13021         /* PID in R0 */
13022         aopOp(pid,ic,FALSE,FALSE);
13023         emitcode ("mov","r0,%s",
13024                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13025         freeAsmop (pid, NULL, ic, FALSE);
13026         
13027         /* tid into ACC */
13028         aopOp(tid,ic,FALSE,FALSE);
13029         emitcode ("mov","a,%s",
13030                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13031         freeAsmop (tid, NULL, ic, FALSE);
13032         
13033         emitcode ("lcall","System_ThreadResume");
13034
13035         /* put result into place */
13036         {
13037                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13038                 if (rsym->liveFrom != rsym->liveTo) {   
13039                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13040                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13041                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13042                 }
13043         }
13044         unsavermask(rsave);
13045 }
13046
13047 /*-----------------------------------------------------------------*/
13048 /* genSystemProcessResume -                                        */
13049 /*-----------------------------------------------------------------*/
13050 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13051 {
13052         bitVect *rsave ;
13053         operand *pid;
13054
13055         assert (nparms==1);
13056         /* save registers that need to be saved */
13057         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13058                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13059         
13060         pid = parms[0];
13061         
13062         /* pid into ACC */
13063         aopOp(pid,ic,FALSE,FALSE);
13064         emitcode ("mov","a,%s",
13065                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13066         freeAsmop (pid, NULL, ic, FALSE);
13067         
13068         emitcode ("lcall","System_ProcessResume");
13069
13070         unsavermask(rsave);
13071 }
13072
13073 /*-----------------------------------------------------------------*/
13074 /* genSystem -                                                     */
13075 /*-----------------------------------------------------------------*/
13076 static void genSystem (iCode *ic,int nparms,char *name)
13077 {
13078         assert(nparms == 0);
13079
13080         emitcode ("lcall","System_%s",name);
13081 }
13082
13083 /*-----------------------------------------------------------------*/
13084 /* genSystemPoll -                                                  */
13085 /*-----------------------------------------------------------------*/
13086 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13087 {
13088         bitVect *rsave ;
13089         operand *fp;
13090
13091         assert (nparms==1);
13092         /* save registers that need to be saved */
13093         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13094                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13095
13096         fp = parms[0];
13097         aopOp (fp,ic,FALSE,FALSE);
13098         if (AOP_TYPE (fp) == AOP_IMMD) {
13099                 emitcode ("mov", "dptr,%s", 
13100                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13101         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13102                 emitcode ("mov","dpl,%s",
13103                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13104                 emitcode ("mov","dph,%s",
13105                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13106                 emitcode ("mov","dpx,%s",
13107                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13108         }
13109         freeAsmop (fp, NULL, ic, FALSE);
13110
13111         emitcode ("lcall","System_%sPoll",name);
13112
13113         /* put result into place */
13114         {
13115                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13116                 if (rsym->liveFrom != rsym->liveTo) {   
13117                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13118                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13119                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13120                 }
13121         }
13122         unsavermask(rsave);
13123 }
13124
13125 /*-----------------------------------------------------------------*/
13126 /* genSystemGetCurrentID -                                         */
13127 /*-----------------------------------------------------------------*/
13128 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13129 {
13130         assert (nparms==0);
13131
13132         emitcode ("lcall","System_GetCurrent%sId",name);
13133         /* put result into place */
13134         {
13135                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13136                 if (rsym->liveFrom != rsym->liveTo) {   
13137                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13138                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13139                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13140                 }
13141         }
13142 }
13143
13144 /*-----------------------------------------------------------------*/
13145 /* genDummyRead - generate code for dummy read of volatiles        */
13146 /*-----------------------------------------------------------------*/
13147 static void
13148 genDummyRead (iCode * ic)
13149 {
13150   operand *op;
13151   int size, offset;
13152
13153   D(emitcode(";     genDummyRead",""));
13154
13155   op = IC_RIGHT (ic);
13156   if (op && IS_SYMOP (op))
13157     {
13158       aopOp (op, ic, FALSE, FALSE);
13159
13160       /* if the result is a bit */
13161       if (AOP_TYPE (op) == AOP_CRY)
13162         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13163       else
13164         {
13165           /* bit variables done */
13166           /* general case */
13167           size = AOP_SIZE (op);
13168           offset = 0;
13169           while (size--)
13170           {
13171             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13172             offset++;
13173           }
13174         }
13175
13176       freeAsmop (op, NULL, ic, TRUE);
13177     }
13178
13179   op = IC_LEFT (ic);
13180   if (op && IS_SYMOP (op))
13181     {
13182       aopOp (op, ic, FALSE, FALSE);
13183
13184       /* if the result is a bit */
13185       if (AOP_TYPE (op) == AOP_CRY)
13186         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13187       else
13188         {
13189           /* bit variables done */
13190           /* general case */
13191           size = AOP_SIZE (op);
13192           offset = 0;
13193           while (size--)
13194           {
13195             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13196             offset++;
13197           }
13198         }
13199
13200       freeAsmop (op, NULL, ic, TRUE);
13201     }
13202     
13203 }
13204
13205 /*-----------------------------------------------------------------*/
13206 /* genCritical - generate code for start of a critical sequence    */
13207 /*-----------------------------------------------------------------*/
13208 static void
13209 genCritical (iCode *ic)
13210 {
13211   symbol *tlbl = newiTempLabel (NULL);
13212
13213   D(emitcode(";     genCritical",""));
13214   
13215   if (IC_RESULT (ic))
13216     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13217
13218   emitcode ("setb", "c");
13219   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13220   emitcode ("clr", "c");
13221   emitcode ("", "%05d$:", (tlbl->key + 100));
13222
13223   if (IC_RESULT (ic))
13224     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13225   else
13226     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13227
13228   if (IC_RESULT (ic))
13229     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13230 }
13231
13232 /*-----------------------------------------------------------------*/
13233 /* genEndCritical - generate code for end of a critical sequence   */
13234 /*-----------------------------------------------------------------*/
13235 static void
13236 genEndCritical (iCode *ic)
13237 {
13238   D(emitcode(";     genEndCritical",""));
13239   
13240   if (IC_RIGHT (ic))
13241     {
13242       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13243       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13244         {
13245           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13246           emitcode ("mov", "ea,c");
13247         }
13248       else
13249         {
13250           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13251           emitcode ("rrc", "a");
13252           emitcode ("mov", "ea,c");
13253         }
13254       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13255     }
13256   else
13257     {
13258       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13259       emitcode ("mov", "ea,c");
13260     }
13261 }
13262
13263
13264
13265 /*-----------------------------------------------------------------*/
13266 /* genBuiltIn - calls the appropriate function to  generating code */
13267 /* for a built in function                                         */
13268 /*-----------------------------------------------------------------*/
13269 static void genBuiltIn (iCode *ic)
13270 {
13271         operand *bi_parms[MAX_BUILTIN_ARGS];
13272         int nbi_parms;
13273         iCode *bi_iCode;
13274         symbol *bif;
13275
13276         /* get all the arguments for a built in function */
13277         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13278
13279         /* which function is it */
13280         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13281         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13282                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13283         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13284                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13285         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13286                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13287         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13288                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13289         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13290                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13291         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13292                 genInp(bi_iCode,nbi_parms,bi_parms);
13293         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13294                 genOutp(bi_iCode,nbi_parms,bi_parms);
13295         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13296                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13297                 /* JavaNative builtIns */               
13298         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13299                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13300         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13301                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13302         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13303                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13304         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13305                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13306         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13307                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13308         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13309                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13310         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13311                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13312         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13313                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13314         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13315                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13316         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13317                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13318         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13319                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13320         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13321                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13322         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13323                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13324         } else if (strcmp(bif->name,"MM_Free")==0) {
13325                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13326         } else if (strcmp(bif->name,"MM_Deref")==0) {
13327                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13328         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13329                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13330         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13331                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13332         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13333                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13334         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13335                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13336         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13337                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13338         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13339                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13340         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13341                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13342         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13343                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13344         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13345                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13346         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13347                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13348         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13349                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13350         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13351                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13352         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13353                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13354         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13355                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13356         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13357                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13358         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13359                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13360         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13361                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13362         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13363                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13364         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13365                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13366         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13367                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13368         } else {
13369                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13370                 return ;
13371         }
13372         return ;    
13373 }
13374
13375 /*-----------------------------------------------------------------*/
13376 /* gen390Code - generate code for Dallas 390 based controllers     */
13377 /*-----------------------------------------------------------------*/
13378 void
13379 gen390Code (iCode * lic)
13380 {
13381   iCode *ic;
13382   int cln = 0;
13383
13384   lineHead = lineCurr = NULL;
13385   dptrn[1][0] = "dpl1";
13386   dptrn[1][1] = "dph1";
13387   dptrn[1][2] = "dpx1";
13388   
13389   if (options.model == MODEL_FLAT24) {
13390     fReturnSizeDS390 = 5;
13391     fReturn = fReturn24;
13392   } else {
13393     fReturnSizeDS390 = 4;
13394     fReturn = fReturn16;
13395     options.stack10bit=0;
13396   }
13397 #if 1
13398   /* print the allocation information */
13399   if (allocInfo && currFunc)
13400     printAllocInfo (currFunc, codeOutFile);
13401 #endif
13402   /* if debug information required */
13403   if (options.debug && currFunc)
13404     {
13405       debugFile->writeFunction(currFunc);
13406       _G.debugLine = 1;
13407       if (IS_STATIC (currFunc->etype))
13408         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13409       else
13410         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13411       _G.debugLine = 0;
13412     }
13413   /* stack pointer name */
13414   if (options.useXstack)
13415     spname = "_spx";
13416   else
13417     spname = "sp";
13418
13419
13420   for (ic = lic; ic; ic = ic->next)
13421     {
13422
13423       _G.current_iCode = ic;
13424       
13425       if (ic->lineno && cln != ic->lineno)
13426         {
13427           if (options.debug)
13428             {
13429               _G.debugLine = 1;
13430               emitcode ("", "C$%s$%d$%d$%d ==.",
13431                         FileBaseName (ic->filename), ic->lineno,
13432                         ic->level, ic->block);
13433               _G.debugLine = 0;
13434             }
13435           if (!options.noCcodeInAsm) {
13436             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13437                       printCLine(ic->filename, ic->lineno));
13438           }
13439           cln = ic->lineno;
13440         }
13441       if (options.iCodeInAsm) {
13442         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13443       }
13444       /* if the result is marked as
13445          spilt and rematerializable or code for
13446          this has already been generated then
13447          do nothing */
13448       if (resultRemat (ic) || ic->generated)
13449         continue;
13450
13451       /* depending on the operation */
13452       switch (ic->op)
13453         {
13454         case '!':
13455           genNot (ic);
13456           break;
13457
13458         case '~':
13459           genCpl (ic);
13460           break;
13461
13462         case UNARYMINUS:
13463           genUminus (ic);
13464           break;
13465
13466         case IPUSH:
13467           genIpush (ic);
13468           break;
13469
13470         case IPOP:
13471           /* IPOP happens only when trying to restore a
13472              spilt live range, if there is an ifx statement
13473              following this pop then the if statement might
13474              be using some of the registers being popped which
13475              would destory the contents of the register so
13476              we need to check for this condition and handle it */
13477           if (ic->next &&
13478               ic->next->op == IFX &&
13479               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13480             genIfx (ic->next, ic);
13481           else
13482             genIpop (ic);
13483           break;
13484
13485         case CALL:
13486           genCall (ic);
13487           break;
13488
13489         case PCALL:
13490           genPcall (ic);
13491           break;
13492
13493         case FUNCTION:
13494           genFunction (ic);
13495           break;
13496
13497         case ENDFUNCTION:
13498           genEndFunction (ic);
13499           break;
13500
13501         case RETURN:
13502           genRet (ic);
13503           break;
13504
13505         case LABEL:
13506           genLabel (ic);
13507           break;
13508
13509         case GOTO:
13510           genGoto (ic);
13511           break;
13512
13513         case '+':
13514           genPlus (ic);
13515           break;
13516
13517         case '-':
13518           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13519             genMinus (ic);
13520           break;
13521
13522         case '*':
13523           genMult (ic);
13524           break;
13525
13526         case '/':
13527           genDiv (ic);
13528           break;
13529
13530         case '%':
13531           genMod (ic);
13532           break;
13533
13534         case '>':
13535           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13536           break;
13537
13538         case '<':
13539           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13540           break;
13541
13542         case LE_OP:
13543         case GE_OP:
13544         case NE_OP:
13545
13546           /* note these two are xlated by algebraic equivalence
13547              during parsing SDCC.y */
13548           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13549                   "got '>=' or '<=' shouldn't have come here");
13550           break;
13551
13552         case EQ_OP:
13553           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13554           break;
13555
13556         case AND_OP:
13557           genAndOp (ic);
13558           break;
13559
13560         case OR_OP:
13561           genOrOp (ic);
13562           break;
13563
13564         case '^':
13565           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13566           break;
13567
13568         case '|':
13569           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13570           break;
13571
13572         case BITWISEAND:
13573           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13574           break;
13575
13576         case INLINEASM:
13577           genInline (ic);
13578           break;
13579
13580         case RRC:
13581           genRRC (ic);
13582           break;
13583
13584         case RLC:
13585           genRLC (ic);
13586           break;
13587
13588         case GETHBIT:
13589           genGetHbit (ic);
13590           break;
13591
13592         case LEFT_OP:
13593           genLeftShift (ic);
13594           break;
13595
13596         case RIGHT_OP:
13597           genRightShift (ic);
13598           break;
13599
13600         case GET_VALUE_AT_ADDRESS:
13601           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13602           break;
13603
13604         case '=':
13605           if (POINTER_SET (ic))
13606             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13607           else
13608             genAssign (ic);
13609           break;
13610
13611         case IFX:
13612           genIfx (ic, NULL);
13613           break;
13614
13615         case ADDRESS_OF:
13616           genAddrOf (ic);
13617           break;
13618
13619         case JUMPTABLE:
13620           genJumpTab (ic);
13621           break;
13622
13623         case CAST:
13624           genCast (ic);
13625           break;
13626
13627         case RECEIVE:
13628           genReceive (ic);
13629           break;
13630
13631         case SEND:
13632           if (ic->builtinSEND) genBuiltIn(ic);
13633           else addSet (&_G.sendSet, ic);
13634           break;
13635
13636         case DUMMY_READ_VOLATILE:
13637           genDummyRead (ic);
13638           break;
13639
13640         case CRITICAL:
13641           genCritical (ic);
13642           break;
13643
13644         case ENDCRITICAL:
13645           genEndCritical (ic);
13646           break;
13647         
13648         case SWAP:
13649           genSwap (ic);
13650           break;
13651           
13652 #if 0 // obsolete, and buggy for != xdata
13653         case ARRAYINIT:
13654             genArrayInit(ic);
13655             break;
13656 #endif
13657             
13658         default:
13659           ic = ic;
13660         }
13661     }
13662
13663
13664   /* now we are ready to call the
13665      peep hole optimizer */
13666   if (!options.nopeep)
13667     peepHole (&lineHead);
13668
13669   /* now do the actual printing */
13670   printLine (lineHead, codeOutFile);
13671   return;
13672 }