* src/mcs51/gen.c (genFunction): optimize RECEIVE in reentrant
[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                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3022                     }
3023                 }
3024             }
3025           else
3026             {
3027               /* this function has  a function call cannot
3028                  determines register usage so we will have to push the
3029                  entire bank */
3030               saveRBank (0, ic, FALSE);
3031               if (options.parms_in_bank1) {
3032                   for (i=0; i < 8 ; i++ ) {
3033                       emitcode ("push","%s",rb1regs[i]);
3034                   }
3035               }
3036             }
3037         }
3038         else
3039         {
3040             /* This ISR uses a non-zero bank.
3041              *
3042              * We assume that the bank is available for our
3043              * exclusive use.
3044              *
3045              * However, if this ISR calls a function which uses some
3046              * other bank, we must save that bank entirely.
3047              */
3048             unsigned long banksToSave = 0;
3049             
3050             if (IFFUNC_HASFCALL(sym->type))
3051             {
3052
3053 #define MAX_REGISTER_BANKS 4
3054
3055                 iCode *i;
3056                 int ix;
3057
3058                 for (i = ic; i; i = i->next)
3059                 {
3060                     if (i->op == ENDFUNCTION)
3061                     {
3062                         /* we got to the end OK. */
3063                         break;
3064                     }
3065                     
3066                     if (i->op == CALL)
3067                     {
3068                         sym_link *dtype;
3069                         
3070                         dtype = operandType (IC_LEFT(i));
3071                         if (dtype 
3072                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3073                         {
3074                              /* Mark this bank for saving. */
3075                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3076                              {
3077                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3078                              }
3079                              else
3080                              {
3081                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3082                              }
3083                              
3084                              /* And note that we don't need to do it in 
3085                               * genCall.
3086                               */
3087                              i->bankSaved = 1;
3088                         }
3089                     }
3090                     if (i->op == PCALL)
3091                     {
3092                         /* This is a mess; we have no idea what
3093                          * register bank the called function might
3094                          * use.
3095                          *
3096                          * The only thing I can think of to do is
3097                          * throw a warning and hope.
3098                          */
3099                         werror(W_FUNCPTR_IN_USING_ISR);   
3100                     }
3101                 }
3102
3103                 if (banksToSave && options.useXstack)
3104                 {
3105                     /* Since we aren't passing it an ic, 
3106                      * saveRBank will assume r0 is available to abuse.
3107                      *
3108                      * So switch to our (trashable) bank now, so
3109                      * the caller's R0 isn't trashed.
3110                      */
3111                     emitcode ("push", "psw");
3112                     emitcode ("mov", "psw,#!constbyte", 
3113                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3114                     switchedPSW = TRUE;
3115                 }
3116                 
3117                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3118                 {
3119                      if (banksToSave & (1 << ix))
3120                      {
3121                          saveRBank(ix, NULL, FALSE);
3122                      }
3123                 }
3124             }
3125             // TODO: this needs a closer look
3126             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3127         }
3128     }
3129   else
3130     {
3131       /* if callee-save to be used for this function
3132          then save the registers being used in this function */
3133       if (IFFUNC_CALLEESAVES(sym->type))
3134         {
3135           int i;
3136
3137           /* if any registers used */
3138           if (sym->regsUsed)
3139             {
3140               /* save the registers used */
3141               for (i = 0; i < sym->regsUsed->size; i++)
3142                 {
3143                   if (bitVectBitValue (sym->regsUsed, i))
3144                     {
3145                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3146                       _G.nRegsSaved++;
3147                     }
3148                 }
3149             }
3150         }
3151     }
3152
3153   /* set the register bank to the desired value */
3154   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3155    && !switchedPSW)
3156     {
3157       emitcode ("push", "psw");
3158       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3159     }
3160
3161   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3162        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3163       if (options.stack10bit) {
3164           emitcode ("push","_bpx");
3165           emitcode ("push","_bpx+1");
3166           emitcode ("mov","_bpx,%s",spname);
3167           emitcode ("mov","_bpx+1,esp");
3168           adjustEsp("_bpx+1");
3169       } else {
3170           if (options.useXstack) {
3171               emitcode ("mov", "r0,%s", spname);
3172               emitcode ("mov", "a,_bp");
3173               emitcode ("movx", "@r0,a");
3174               emitcode ("inc", "%s", spname);
3175           } else {
3176               /* set up the stack */
3177               emitcode ("push", "_bp"); /* save the callers stack  */
3178           }
3179           emitcode ("mov", "_bp,%s", spname);
3180       }
3181   }
3182
3183   /* adjust the stack for the function */
3184   if (sym->stack) {
3185       int i = sym->stack;
3186       if (options.stack10bit) {
3187           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3188           assert (sym->recvSize <= 4);
3189           if (sym->stack <= 8) {
3190               while (i--) emitcode ("push","acc");
3191           } else {
3192               PROTECT_SP;
3193               emitcode ("mov","a,sp");
3194               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3195               emitcode ("mov","sp,a");
3196               emitcode ("mov","a,esp");
3197               adjustEsp("a");
3198               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3199               emitcode ("mov","esp,a");
3200               UNPROTECT_SP;
3201           }
3202       } else {
3203           if (i > 256)
3204               werror (W_STACK_OVERFLOW, sym->name);
3205           
3206           if (i > 3 && sym->recvSize < 4) {
3207               
3208               emitcode ("mov", "a,sp");
3209               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3210               emitcode ("mov", "sp,a");
3211               
3212           } else
3213               while (i--)
3214                   emitcode ("inc", "sp");
3215       }
3216   }
3217
3218   if (sym->xstack)
3219     {
3220
3221       emitcode ("mov", "a,_spx");
3222       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3223       emitcode ("mov", "_spx,a");
3224     }
3225   
3226   /* if critical function then turn interrupts off */
3227   if (IFFUNC_ISCRITICAL (ftype))
3228     {
3229       symbol *tlbl = newiTempLabel (NULL);
3230       emitcode ("setb", "c");
3231       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3232       emitcode ("clr", "c");
3233       emitcode ("", "%05d$:", (tlbl->key + 100));
3234       emitcode ("push", "psw"); /* save old ea via c in psw */
3235     }
3236
3237 }
3238
3239 /*-----------------------------------------------------------------*/
3240 /* genEndFunction - generates epilogue for functions               */
3241 /*-----------------------------------------------------------------*/
3242 static void
3243 genEndFunction (iCode * ic)
3244 {
3245   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3246   lineNode *lnp = lineCurr;
3247   bitVect *regsUsed;
3248   bitVect *regsUsedPrologue;
3249   bitVect *regsUnneeded;
3250   int idx;
3251
3252   D (emitcode (";", "genEndFunction "););
3253
3254   if (IFFUNC_ISNAKED(sym->type))
3255   {
3256       emitcode(";", "naked function: no epilogue.");
3257       return;
3258   }
3259
3260   if (IFFUNC_ISCRITICAL (sym->type))
3261     {
3262       emitcode ("pop", "psw"); /* restore ea via c in psw */
3263       emitcode ("mov", "ea,c");
3264     }
3265   
3266   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3267        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3268
3269       if (options.stack10bit) {
3270           PROTECT_SP;     
3271           emitcode ("mov", "sp,_bpx", spname);
3272           emitcode ("mov", "esp,_bpx+1", spname);
3273           UNPROTECT_SP;
3274       } else {
3275           emitcode ("mov", "%s,_bp", spname);
3276       }
3277   }
3278
3279   /* if use external stack but some variables were
3280      added to the local stack then decrement the
3281      local stack */
3282   if (options.useXstack && sym->stack) {
3283       emitcode ("mov", "a,sp");
3284       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3285       emitcode ("mov", "sp,a");
3286   }
3287
3288
3289   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3290        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3291
3292       if (options.useXstack) {
3293           emitcode ("mov", "r0,%s", spname);
3294           emitcode ("movx", "a,@r0");
3295           emitcode ("mov", "_bp,a");
3296           emitcode ("dec", "%s", spname);
3297       } else {
3298           if (options.stack10bit) {
3299               emitcode ("pop", "_bpx+1");
3300               emitcode ("pop", "_bpx");
3301           } else {
3302               emitcode ("pop", "_bp");
3303           }
3304       }
3305   }
3306
3307   /* restore the register bank  */
3308   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3309   {
3310     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3311      || !options.useXstack)
3312     {
3313         /* Special case of ISR using non-zero bank with useXstack
3314          * is handled below.
3315          */
3316         emitcode ("pop", "psw");
3317     }
3318   } 
3319
3320   if (IFFUNC_ISISR (sym->type))
3321       { /* is ISR */  
3322
3323       /* now we need to restore the registers */
3324       /* if this isr has no bank i.e. is going to
3325          run with bank 0 , then we need to save more
3326          registers :-) */
3327       if (!FUNC_REGBANK (sym->type))
3328         {
3329             int i;
3330           /* if this function does not call any other
3331              function then we can be economical and
3332              save only those registers that are used */
3333           if (!IFFUNC_HASFCALL(sym->type))
3334             {
3335
3336               /* if any registers used */
3337               if (sym->regsUsed)
3338                 {
3339                   /* save the registers used */
3340                   for (i = sym->regsUsed->size; i >= 0; i--)
3341                     {
3342                       if (bitVectBitValue (sym->regsUsed, i))
3343                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3344                     }
3345                 }
3346             }
3347           else
3348             {
3349               /* this function has  a function call cannot
3350                  determines register usage so we will have to pop the
3351                  entire bank */
3352               if (options.parms_in_bank1) {
3353                   for (i = 7 ; i >= 0 ; i-- ) {
3354                       emitcode ("pop","%s",rb1regs[i]);
3355                   }
3356               }
3357               unsaveRBank (0, ic, FALSE);
3358             }
3359         }
3360         else
3361         {
3362             /* This ISR uses a non-zero bank.
3363              *
3364              * Restore any register banks saved by genFunction
3365              * in reverse order.
3366              */
3367             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3368             int ix;
3369           
3370             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3371             {
3372                 if (savedBanks & (1 << ix))
3373                 {
3374                     unsaveRBank(ix, NULL, FALSE);
3375                 }
3376             }
3377             
3378             if (options.useXstack)
3379             {
3380                 /* Restore bank AFTER calling unsaveRBank,
3381                  * since it can trash r0.
3382                  */
3383                 emitcode ("pop", "psw");
3384             }
3385         }
3386
3387       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3388         {
3389           if (options.stack10bit)
3390             {
3391               emitcode ("pop", DP2_RESULT_REG);
3392               emitcode ("pop", "dpx1");
3393               emitcode ("pop", "dph1");
3394               emitcode ("pop", "dpl1");
3395             }
3396           emitcode ("pop", "dps");
3397           emitcode ("pop", "dpx");
3398         }
3399       if (!inExcludeList ("dph"))
3400         emitcode ("pop", "dph");
3401       if (!inExcludeList ("dpl"))
3402         emitcode ("pop", "dpl");
3403       if (!inExcludeList ("b"))
3404         emitcode ("pop", "b");
3405       if (!inExcludeList ("acc"))
3406         emitcode ("pop", "acc");
3407
3408       /* if debug then send end of function */
3409       if (options.debug && currFunc) {
3410           _G.debugLine = 1;
3411           emitcode ("", "C$%s$%d$%d$%d ==.",
3412                     FileBaseName (ic->filename), currFunc->lastLine,
3413                     ic->level, ic->block);
3414           if (IS_STATIC (currFunc->etype))
3415             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3416           else
3417             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3418           _G.debugLine = 0;
3419         }
3420
3421       emitcode ("reti", "");
3422     }
3423   else
3424     {
3425       if (IFFUNC_CALLEESAVES(sym->type))
3426         {
3427           int i;
3428
3429           /* if any registers used */
3430           if (sym->regsUsed)
3431             {
3432               /* save the registers used */
3433               for (i = sym->regsUsed->size; i >= 0; i--)
3434                 {
3435                   if (bitVectBitValue (sym->regsUsed, i))
3436                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3437                 }
3438             }
3439         }
3440
3441       /* if debug then send end of function */
3442       if (options.debug && currFunc)
3443         {
3444           _G.debugLine = 1;
3445           emitcode ("", "C$%s$%d$%d$%d ==.",
3446                     FileBaseName (ic->filename), currFunc->lastLine,
3447                     ic->level, ic->block);
3448           if (IS_STATIC (currFunc->etype))
3449             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3450           else
3451             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3452           _G.debugLine = 0;
3453         }
3454
3455       emitcode ("ret", "");
3456     }
3457
3458   if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3459     return;
3460   
3461   /* If this was an interrupt handler using bank 0 that called another */
3462   /* function, then all registers must be saved; nothing to optimized. */
3463   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3464       && !FUNC_REGBANK(sym->type))
3465     return;
3466     
3467   /* There are no push/pops to optimize if not callee-saves or ISR */
3468   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3469     return;
3470   
3471   /* If there were stack parameters, we cannot optimize without also    */
3472   /* fixing all of the stack offsets; this is too dificult to consider. */
3473   if (FUNC_HASSTACKPARM(sym->type))
3474     return;
3475   
3476   /* Compute the registers actually used */
3477   regsUsed = newBitVect (ds390_nRegs);
3478   regsUsedPrologue = newBitVect (ds390_nRegs);
3479   while (lnp)
3480     {
3481       if (lnp->ic && lnp->ic->op == FUNCTION)
3482         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3483       else
3484         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3485       
3486       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3487           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3488         break;
3489       if (!lnp->prev)
3490         break;
3491       lnp = lnp->prev;
3492     }
3493
3494   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3495       && !bitVectBitValue (regsUsed, DPS_IDX))
3496     {
3497       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3498     }
3499     
3500   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3501       && !bitVectBitValue (regsUsed, CND_IDX))
3502     {
3503       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3504       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3505           && !sym->stack)
3506         bitVectUnSetBit (regsUsed, CND_IDX);
3507     }
3508   else
3509     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3510     
3511   /* If this was an interrupt handler that called another function */
3512   /* function, then assume working registers may be modified by it. */
3513   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3514     {
3515       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3516       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3517       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3518       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3519       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3520       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3521       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3522       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3523       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3524       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3525       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3526     }
3527
3528   /* Remove the unneeded push/pops */
3529   regsUnneeded = newBitVect (ds390_nRegs);
3530   while (lnp)
3531     {
3532       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3533         {
3534           if (!strncmp(lnp->line, "push", 4))
3535             {
3536               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3537               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3538                 {
3539                   connectLine (lnp->prev, lnp->next);
3540                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3541                 }
3542             }
3543           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3544             {
3545               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3546               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3547                 {
3548                   connectLine (lnp->prev, lnp->next);
3549                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3550                 }
3551             }
3552         }
3553       lnp = lnp->next;
3554     }  
3555   
3556   for (idx = 0; idx < regsUnneeded->size; idx++)
3557     if (bitVectBitValue (regsUnneeded, idx))
3558       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3559   
3560   freeBitVect (regsUnneeded);
3561   freeBitVect (regsUsed);
3562   freeBitVect (regsUsedPrologue);
3563 }
3564
3565 /*-----------------------------------------------------------------*/
3566 /* genJavaNativeRet - generate code for return JavaNative          */
3567 /*-----------------------------------------------------------------*/
3568 static void genJavaNativeRet(iCode *ic)
3569 {
3570     int i, size;
3571
3572     aopOp (IC_LEFT (ic), ic, FALSE, 
3573            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3574     size = AOP_SIZE (IC_LEFT (ic));
3575
3576     assert (size <= 4);
3577
3578     /* it is assigned to GPR0-R3 then push them */
3579     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3580         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3581         for (i = 0 ; i < size ; i++ ) {
3582             emitcode ("push","%s",
3583                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3584         }
3585         for (i = (size-1) ; i >= 0 ; i--) {
3586             emitcode ("pop","a%s",javaRet[i]);
3587         }
3588     } else {
3589         for (i = 0 ; i < size ; i++) 
3590             emitcode ("mov","%s,%s",javaRet[i],
3591                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3592     }
3593     for (i = size ; i < 4 ; i++ )
3594             emitcode ("mov","%s,#0",javaRet[i]);
3595     return;
3596 }
3597
3598 /*-----------------------------------------------------------------*/
3599 /* genRet - generate code for return statement                     */
3600 /*-----------------------------------------------------------------*/
3601 static void
3602 genRet (iCode * ic)
3603 {
3604   int size, offset = 0, pushed = 0;
3605
3606   D (emitcode (";", "genRet "););
3607
3608   /* if we have no return value then
3609      just generate the "ret" */
3610   if (!IC_LEFT (ic))
3611     goto jumpret;
3612
3613   /* if this is a JavaNative function then return 
3614      value in different register */
3615   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3616       genJavaNativeRet(ic);
3617       goto jumpret;
3618   }
3619   /* we have something to return then
3620      move the return value into place */
3621   aopOp (IC_LEFT (ic), ic, FALSE, 
3622          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3623   size = AOP_SIZE (IC_LEFT (ic));
3624
3625   _startLazyDPSEvaluation ();
3626   while (size--)
3627     {
3628       char *l;
3629       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3630         {
3631           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3632                       FALSE, TRUE, NULL);
3633           emitcode ("push", "%s", l);
3634           pushed++;
3635         }
3636       else
3637         {
3638           /* Since A is the last element of fReturn,
3639            * is is OK to clobber it in the aopGet.
3640            */
3641           l = aopGet (AOP (IC_LEFT (ic)), offset,
3642                       FALSE, FALSE, NULL);
3643           if (strcmp (fReturn[offset], l))
3644             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3645         }
3646     }
3647   _endLazyDPSEvaluation ();
3648
3649   if (pushed)
3650     {
3651       while (pushed)
3652         {
3653           pushed--;
3654           if (strcmp (fReturn[pushed], "a"))
3655             emitcode ("pop", fReturn[pushed]);
3656           else
3657             emitcode ("pop", "acc");
3658         }
3659     }
3660   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3661
3662 jumpret:
3663   /* generate a jump to the return label
3664      if the next is not the return statement */
3665   if (!(ic->next && ic->next->op == LABEL &&
3666         IC_LABEL (ic->next) == returnLabel))
3667
3668     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3669
3670 }
3671
3672 /*-----------------------------------------------------------------*/
3673 /* genLabel - generates a label                                    */
3674 /*-----------------------------------------------------------------*/
3675 static void
3676 genLabel (iCode * ic)
3677 {
3678   /* special case never generate */
3679   if (IC_LABEL (ic) == entryLabel)
3680     return;
3681
3682   D (emitcode (";", "genLabel ");
3683     );
3684
3685   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3686 }
3687
3688 /*-----------------------------------------------------------------*/
3689 /* genGoto - generates a ljmp                                      */
3690 /*-----------------------------------------------------------------*/
3691 static void
3692 genGoto (iCode * ic)
3693 {
3694   D (emitcode (";", "genGoto ");
3695     );
3696   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3697 }
3698
3699 /*-----------------------------------------------------------------*/
3700 /* findLabelBackwards: walks back through the iCode chain looking  */
3701 /* for the given label. Returns number of iCode instructions     */
3702 /* between that label and given ic.          */
3703 /* Returns zero if label not found.          */
3704 /*-----------------------------------------------------------------*/
3705 static int
3706 findLabelBackwards (iCode * ic, int key)
3707 {
3708   int count = 0;
3709
3710   while (ic->prev)
3711     {
3712       ic = ic->prev;
3713       count++;
3714
3715       /* If we have any pushes or pops, we cannot predict the distance.
3716          I don't like this at all, this should be dealt with in the 
3717          back-end */
3718       if (ic->op == IPUSH || ic->op == IPOP) {
3719         return 0;
3720       }
3721
3722       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3723         {
3724           /* printf("findLabelBackwards = %d\n", count); */
3725           return count;
3726         }
3727     }
3728
3729   return 0;
3730 }
3731
3732 /*-----------------------------------------------------------------*/
3733 /* genPlusIncr :- does addition with increment if possible         */
3734 /*-----------------------------------------------------------------*/
3735 static bool
3736 genPlusIncr (iCode * ic)
3737 {
3738   unsigned int icount;
3739   unsigned int size = getDataSize (IC_RESULT (ic));
3740
3741   /* will try to generate an increment */
3742   /* if the right side is not a literal
3743      we cannot */
3744   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3745     return FALSE;
3746
3747   /* if the literal value of the right hand side
3748      is greater than 4 then it is not worth it */
3749   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3750     return FALSE;
3751
3752   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3753       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3754       while (icount--) {
3755           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3756       }
3757       return TRUE;
3758   }
3759   /* if increment 16 bits in register */
3760   if (
3761        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3762        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3763        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3764        (size > 1) &&
3765        (icount == 1))
3766     {
3767       symbol  *tlbl;
3768       int     emitTlbl;
3769       int     labelRange;
3770       char    *l;
3771
3772       /* If the next instruction is a goto and the goto target
3773        * is <= 5 instructions previous to this, we can generate
3774        * jumps straight to that target.
3775        */
3776       if (ic->next && ic->next->op == GOTO
3777           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3778           && labelRange <= 5)
3779         {
3780           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3781           tlbl = IC_LABEL (ic->next);
3782           emitTlbl = 0;
3783         }
3784       else
3785         {
3786           tlbl = newiTempLabel (NULL);
3787           emitTlbl = 1;
3788         }
3789         
3790       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3791       emitcode ("inc", "%s", l);
3792       
3793       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3794           IS_AOP_PREG (IC_RESULT (ic)))
3795       {   
3796         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3797       }
3798       else
3799       {
3800           emitcode ("clr", "a");
3801           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3802       }
3803
3804       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3805       emitcode ("inc", "%s", l);
3806       if (size > 2)
3807         {
3808             if (!strcmp(l, "acc"))
3809             {
3810                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3811             }
3812             else 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 ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3820             }
3821
3822             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3823             emitcode ("inc", "%s", l);
3824         }
3825       if (size > 3)
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)), MSB32, FALSE, FALSE, NULL);
3842             emitcode ("inc", "%s", l);  }
3843
3844       if (emitTlbl)
3845         {
3846           emitcode ("", "!tlabeldef", tlbl->key + 100);
3847         }
3848       return TRUE;
3849     }
3850
3851   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3852       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3853       options.model == MODEL_FLAT24 ) {
3854
3855       switch (size) {
3856       case 3:
3857           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3858       case 2:
3859           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3860       case 1:
3861           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3862           break;
3863       }
3864       while (icount--) emitcode ("inc","dptr");      
3865       return TRUE;
3866   }
3867
3868   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3869       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3870       icount <= 5 ) {
3871       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3872       while (icount--) emitcode ("inc","dptr");
3873       emitcode ("mov","dps,#0");
3874       return TRUE;
3875   }
3876
3877   /* if the sizes are greater than 1 then we cannot */
3878   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3879       AOP_SIZE (IC_LEFT (ic)) > 1)
3880     return FALSE;
3881
3882   /* we can if the aops of the left & result match or
3883      if they are in registers and the registers are the
3884      same */
3885   if (
3886        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3887        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3888        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3889     {
3890
3891       if (icount > 3)
3892         {
3893           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3894           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3895           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3896         }
3897       else
3898         {
3899
3900           _startLazyDPSEvaluation ();
3901           while (icount--)
3902             {
3903               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3904             }
3905           _endLazyDPSEvaluation ();
3906         }
3907
3908       return TRUE;
3909     }
3910
3911   return FALSE;
3912 }
3913
3914 /*-----------------------------------------------------------------*/
3915 /* outBitAcc - output a bit in acc                                 */
3916 /*-----------------------------------------------------------------*/
3917 static void
3918 outBitAcc (operand * result)
3919 {
3920   symbol *tlbl = newiTempLabel (NULL);
3921   /* if the result is a bit */
3922   if (AOP_TYPE (result) == AOP_CRY)
3923     {
3924       aopPut (AOP (result), "a", 0);
3925     }
3926   else
3927     {
3928       emitcode ("jz", "!tlabel", tlbl->key + 100);
3929       emitcode ("mov", "a,%s", one);
3930       emitcode ("", "!tlabeldef", tlbl->key + 100);
3931       outAcc (result);
3932     }
3933 }
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genPlusBits - generates code for addition of two bits           */
3937 /*-----------------------------------------------------------------*/
3938 static void
3939 genPlusBits (iCode * ic)
3940 {
3941   D (emitcode (";", "genPlusBits "););
3942     
3943   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3944     {
3945       symbol *lbl = newiTempLabel (NULL);
3946       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3947       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3948       emitcode ("cpl", "c");
3949       emitcode ("", "!tlabeldef", (lbl->key + 100));
3950       outBitC (IC_RESULT (ic));
3951     }
3952   else
3953     {
3954       emitcode ("clr", "a");
3955       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3956       emitcode ("rlc", "a");
3957       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3958       emitcode ("addc", "a,#0");
3959       outAcc (IC_RESULT (ic));
3960     }
3961 }
3962
3963 static void
3964 adjustArithmeticResult (iCode * ic)
3965 {
3966   if (opIsGptr (IC_RESULT (ic)) &&
3967       opIsGptr (IC_LEFT (ic)) &&
3968       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3969     {
3970       aopPut (AOP (IC_RESULT (ic)),
3971               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3972               GPTRSIZE - 1);
3973     }
3974
3975   if (opIsGptr (IC_RESULT (ic)) &&
3976       opIsGptr (IC_RIGHT (ic)) &&
3977       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3978     {
3979       aopPut (AOP (IC_RESULT (ic)),
3980             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3981               GPTRSIZE - 1);
3982     }
3983
3984   if (opIsGptr (IC_RESULT (ic)) &&
3985       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3986       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3987       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3988       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3989     {
3990       char buff[5];
3991       SNPRINTF (buff, sizeof(buff), 
3992                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3993       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3994     }
3995 }
3996
3997 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3998 // generates the result if possible. If result is generated, returns TRUE; otherwise
3999 // returns false and caller must deal with fact that result isn't aopOp'd.
4000 bool aopOp3(iCode * ic)
4001 {
4002     bool dp1InUse, dp2InUse;
4003     bool useDp2;
4004
4005     // First, generate the right opcode. DPTR may be used if neither left nor result are
4006     // of type AOP_STR.
4007     
4008 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4009 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4010 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4011 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4012 //      );
4013 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4014 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4015 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4016 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4017 //      );
4018     
4019     // Right uses DPTR unless left or result is an AOP_STR; however,
4020     // if right is an AOP_STR, it must use DPTR regardless.
4021     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4022      && !AOP_IS_STR(IC_RIGHT(ic)))
4023     {
4024         useDp2 = TRUE;
4025     }
4026     else
4027     {
4028         useDp2 = FALSE;
4029     }
4030         
4031     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4032     
4033     // if the right used DPTR, left MUST use DPTR2.
4034     // if the right used DPTR2, left MUST use DPTR.
4035     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4036     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4037     // enabling us to assign DPTR to result.
4038      
4039     if (AOP_USESDPTR(IC_RIGHT(ic)))
4040     {
4041         useDp2 = TRUE;
4042     }
4043     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4044     {
4045         useDp2 = FALSE;
4046     }
4047     else
4048     {
4049         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4050         {
4051             useDp2 = TRUE;
4052         }
4053         else
4054         {
4055             useDp2 = FALSE;
4056         }
4057     }
4058
4059     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4060
4061         
4062     // We've op'd the left & right. So, if left or right are the same operand as result, 
4063     // we know aopOp will succeed, and we can just do it & bail.
4064     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4065       {
4066         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4067         return TRUE;
4068       }
4069     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4070       {
4071 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4072         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4073         return TRUE;
4074       }
4075     
4076     // Operands may be equivalent (but not equal) if they share a spill location. If
4077     // so, use the same DPTR or DPTR2.
4078     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4079       {
4080         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4081         return TRUE;
4082       }
4083     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4084       {
4085         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4086         return TRUE;
4087       }
4088     
4089     // Note which dptrs are currently in use.
4090     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4091     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4092     
4093     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
4094     // generate it.
4095     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4096     {
4097         return FALSE;
4098     }
4099     
4100     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4101     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4102     {
4103         return FALSE;
4104     }
4105     
4106     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4107     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4108     {
4109         return FALSE;
4110     }
4111
4112     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4113
4114     // Some sanity checking...
4115     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4116     {
4117         fprintf(stderr,
4118                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4119                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4120         emitcode(";", ">>> unexpected DPTR here.");
4121     }
4122     
4123     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4124     {
4125         fprintf(stderr,
4126                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4127                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4128         emitcode(";", ">>> unexpected DPTR2 here.");
4129     }    
4130     
4131     return TRUE;
4132 }
4133
4134 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4135 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4136 // will be set TRUE. The caller must then handle the case specially, noting
4137 // that the IC_RESULT operand is not aopOp'd.
4138 // 
4139 #define AOP_OP_3_NOFATAL(ic, rc) \
4140             do { rc = !aopOp3(ic); } while (0)
4141
4142 // aopOp the left & right operands of an ic.
4143 #define AOP_OP_2(ic) \
4144     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4145     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4146
4147 // convienience macro.
4148 #define AOP_SET_LOCALS(ic) \
4149     left = IC_LEFT(ic); \
4150     right = IC_RIGHT(ic); \
4151     result = IC_RESULT(ic);
4152
4153
4154 // Given an integer value of pushedSize bytes on the stack,
4155 // adjust it to be resultSize bytes, either by discarding
4156 // the most significant bytes or by zero-padding.
4157 //
4158 // On exit from this macro, pushedSize will have been adjusted to
4159 // equal resultSize, and ACC may be trashed.
4160 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4161       /* If the pushed data is bigger than the result,          \
4162        * simply discard unused bytes. Icky, but works.          \
4163        */                                                       \
4164       while (pushedSize > resultSize)                           \
4165       {                                                         \
4166           D (emitcode (";", "discarding unused result byte."););\
4167           emitcode ("pop", "acc");                              \
4168           pushedSize--;                                         \
4169       }                                                         \
4170       if (pushedSize < resultSize)                              \
4171       {                                                         \
4172           emitcode ("clr", "a");                                \
4173           /* Conversly, we haven't pushed enough here.          \
4174            * just zero-pad, and all is well.                    \
4175            */                                                   \
4176           while (pushedSize < resultSize)                       \
4177           {                                                     \
4178               emitcode("push", "acc");                          \
4179               pushedSize++;                                     \
4180           }                                                     \
4181       }                                                         \
4182       assert(pushedSize == resultSize);
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genPlus - generates code for addition                           */
4186 /*-----------------------------------------------------------------*/
4187 static void
4188 genPlus (iCode * ic)
4189 {
4190   int size, offset = 0;
4191   bool pushResult;
4192   int rSize;
4193
4194   D (emitcode (";", "genPlus "););
4195
4196   /* special cases :- */
4197   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4198       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4199       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4200       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4201       if (size <= 9) {
4202           while (size--) emitcode ("inc","dptr");
4203       } else {
4204           emitcode ("mov","a,dpl");
4205           emitcode ("add","a,#!constbyte",size & 0xff);
4206           emitcode ("mov","dpl,a");
4207           emitcode ("mov","a,dph");
4208           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4209           emitcode ("mov","dph,a");
4210           emitcode ("mov","a,dpx");
4211           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4212           emitcode ("mov","dpx,a");
4213       }
4214       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4215       return ;
4216   }
4217   if ( IS_SYMOP(IC_LEFT(ic)) && 
4218        OP_SYMBOL(IC_LEFT(ic))->remat &&
4219        isOperandInFarSpace(IC_RIGHT(ic))) {
4220       operand *op = IC_RIGHT(ic);
4221       IC_RIGHT(ic) = IC_LEFT(ic);
4222       IC_LEFT(ic) = op;
4223   }
4224                 
4225   AOP_OP_3_NOFATAL (ic, pushResult);
4226     
4227   if (pushResult)
4228     {
4229       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4230     }
4231
4232   if (!pushResult)
4233     {
4234       /* if literal, literal on the right or
4235          if left requires ACC or right is already
4236          in ACC */
4237       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4238        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4239           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4240         {
4241           operand *t = IC_RIGHT (ic);
4242           IC_RIGHT (ic) = IC_LEFT (ic);
4243           IC_LEFT (ic) = t;
4244           emitcode (";", "Swapped plus args.");
4245         }
4246
4247       /* if both left & right are in bit
4248          space */
4249       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4250           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4251         {
4252           genPlusBits (ic);
4253           goto release;
4254         }
4255
4256       /* if left in bit space & right literal */
4257       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4258           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4259         {
4260           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4261           /* if result in bit space */
4262           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4263             {
4264               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4265                 emitcode ("cpl", "c");
4266               outBitC (IC_RESULT (ic));
4267             }
4268           else
4269             {
4270               size = getDataSize (IC_RESULT (ic));
4271               _startLazyDPSEvaluation ();
4272               while (size--)
4273                 {
4274                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4275                   emitcode ("addc", "a,#0");
4276                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4277                 }
4278               _endLazyDPSEvaluation ();
4279             }
4280           goto release;
4281         }
4282
4283       /* if I can do an increment instead
4284          of add then GOOD for ME */
4285       if (genPlusIncr (ic) == TRUE)
4286         {
4287           emitcode (";", "did genPlusIncr");
4288           goto release;
4289         }
4290
4291     }
4292   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4293
4294   _startLazyDPSEvaluation ();
4295   while (size--)
4296     {
4297       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4298         {
4299           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4300           if (offset == 0)
4301             emitcode ("add", "a,%s",
4302                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4303           else
4304             emitcode ("addc", "a,%s",
4305                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4306         }
4307       else
4308         {
4309           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4310           {
4311               /* right is going to use ACC or we would have taken the
4312                * above branch.
4313                */
4314               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4315        TR_AP("#3");
4316               D(emitcode(";", "+ AOP_ACC special case."););
4317               emitcode("xch", "a, %s", DP2_RESULT_REG);
4318           }
4319           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4320           if (offset == 0)
4321           {
4322             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4323             {
4324          TR_AP("#4");
4325                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4326             }
4327             else
4328             {
4329                 emitcode ("add", "a,%s",
4330                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4331                                   DP2_RESULT_REG));
4332             }
4333           }
4334           else
4335           {
4336             emitcode ("addc", "a,%s",
4337                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4338                           DP2_RESULT_REG));
4339           }
4340         }
4341       if (!pushResult)
4342         {
4343           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4344         }
4345       else
4346         {
4347           emitcode ("push", "acc");
4348         }
4349       offset++;
4350     }
4351   _endLazyDPSEvaluation ();
4352
4353   if (pushResult)
4354     {
4355       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4356
4357       size = getDataSize (IC_LEFT (ic));
4358       rSize = getDataSize (IC_RESULT (ic));
4359
4360       ADJUST_PUSHED_RESULT(size, rSize);
4361
4362       _startLazyDPSEvaluation ();
4363       while (size--)
4364         {
4365           emitcode ("pop", "acc");
4366           aopPut (AOP (IC_RESULT (ic)), "a", size);
4367         }
4368       _endLazyDPSEvaluation ();
4369     }
4370
4371   adjustArithmeticResult (ic);
4372
4373 release:
4374   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4376   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4377 }
4378
4379 /*-----------------------------------------------------------------*/
4380 /* genMinusDec :- does subtraction with deccrement if possible     */
4381 /*-----------------------------------------------------------------*/
4382 static bool
4383 genMinusDec (iCode * ic)
4384 {
4385   unsigned int icount;
4386   unsigned int size = getDataSize (IC_RESULT (ic));
4387
4388   /* will try to generate an increment */
4389   /* if the right side is not a literal
4390      we cannot */
4391   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4392     return FALSE;
4393
4394   /* if the literal value of the right hand side
4395      is greater than 4 then it is not worth it */
4396   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4397     return FALSE;
4398
4399   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4400       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4401       while (icount--) {
4402           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4403       }
4404       return TRUE;
4405   }
4406   /* if decrement 16 bits in register */
4407   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4408       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4409       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4410       (size > 1) &&
4411       (icount == 1))
4412     {
4413       symbol *tlbl;
4414       int    emitTlbl;
4415       int    labelRange;
4416       char   *l;
4417
4418       /* If the next instruction is a goto and the goto target
4419          * is <= 5 instructions previous to this, we can generate
4420          * jumps straight to that target.
4421        */
4422       if (ic->next && ic->next->op == GOTO
4423           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4424           && labelRange <= 5)
4425         {
4426           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4427           tlbl = IC_LABEL (ic->next);
4428           emitTlbl = 0;
4429         }
4430       else
4431         {
4432           tlbl = newiTempLabel (NULL);
4433           emitTlbl = 1;
4434         }
4435
4436       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4437       emitcode ("dec", "%s", l);
4438  
4439       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4440           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4441           IS_AOP_PREG (IC_RESULT (ic)))
4442       {     
4443           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4444       }
4445       else
4446       {
4447           emitcode ("mov", "a,#!constbyte",0xff);
4448           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4449       }
4450       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4451       emitcode ("dec", "%s", l);
4452       if (size > 2)
4453         {
4454             if (!strcmp(l, "acc"))
4455             {
4456                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4457             }
4458             else 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)), MSB24, FALSE, FALSE, NULL);
4470             emitcode ("dec", "%s", l);
4471         }
4472       if (size > 3)
4473         {
4474             if (!strcmp(l, "acc"))
4475             {
4476                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4477             }
4478             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4479                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4480                      IS_AOP_PREG (IC_RESULT (ic)))
4481             {       
4482                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4483             }
4484             else
4485             {
4486                 emitcode ("mov", "a,#!constbyte",0xff);
4487                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4488             }       
4489             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4490             emitcode ("dec", "%s", l);
4491         }
4492       if (emitTlbl)
4493         {
4494           emitcode ("", "!tlabeldef", tlbl->key + 100);
4495         }
4496       return TRUE;
4497     }
4498
4499   /* if the sizes are greater than 1 then we cannot */
4500   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4501       AOP_SIZE (IC_LEFT (ic)) > 1)
4502     return FALSE;
4503
4504   /* we can if the aops of the left & result match or
4505      if they are in registers and the registers are the
4506      same */
4507   if (
4508        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4509        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4510        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4511     {
4512
4513       _startLazyDPSEvaluation ();
4514       while (icount--)
4515         {
4516           emitcode ("dec", "%s",
4517                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4518         }
4519       _endLazyDPSEvaluation ();
4520
4521       return TRUE;
4522     }
4523
4524   return FALSE;
4525 }
4526
4527 /*-----------------------------------------------------------------*/
4528 /* addSign - complete with sign                                    */
4529 /*-----------------------------------------------------------------*/
4530 static void
4531 addSign (operand * result, int offset, int sign)
4532 {
4533   int size = (getDataSize (result) - offset);
4534   if (size > 0)
4535     {
4536       _startLazyDPSEvaluation();
4537       if (sign)
4538         {
4539           emitcode ("rlc", "a");
4540           emitcode ("subb", "a,acc");
4541           while (size--)
4542           {
4543             aopPut (AOP (result), "a", offset++);
4544           }
4545         }
4546       else
4547       {
4548         while (size--)
4549         {
4550           aopPut (AOP (result), zero, offset++);
4551         }
4552       }
4553       _endLazyDPSEvaluation();
4554     }
4555 }
4556
4557 /*-----------------------------------------------------------------*/
4558 /* genMinusBits - generates code for subtraction  of two bits      */
4559 /*-----------------------------------------------------------------*/
4560 static void
4561 genMinusBits (iCode * ic)
4562 {
4563   symbol *lbl = newiTempLabel (NULL);
4564
4565   D (emitcode (";", "genMinusBits "););
4566
4567   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4568     {
4569       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4570       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4571       emitcode ("cpl", "c");
4572       emitcode ("", "!tlabeldef", (lbl->key + 100));
4573       outBitC (IC_RESULT (ic));
4574     }
4575   else
4576     {
4577       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4578       emitcode ("subb", "a,acc");
4579       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4580       emitcode ("inc", "a");
4581       emitcode ("", "!tlabeldef", (lbl->key + 100));
4582       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4583       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4584     }
4585 }
4586
4587 /*-----------------------------------------------------------------*/
4588 /* genMinus - generates code for subtraction                       */
4589 /*-----------------------------------------------------------------*/
4590 static void
4591 genMinus (iCode * ic)
4592 {
4593     int size, offset = 0;
4594     int rSize;
4595     long lit = 0L;
4596     bool pushResult;
4597
4598     D (emitcode (";", "genMinus "););
4599
4600     AOP_OP_3_NOFATAL(ic, pushResult);   
4601
4602     if (!pushResult)
4603     {
4604       /* special cases :- */
4605       /* if both left & right are in bit space */
4606       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4607           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4608         {
4609           genMinusBits (ic);
4610           goto release;
4611         }
4612
4613       /* if I can do an decrement instead
4614          of subtract then GOOD for ME */
4615       if (genMinusDec (ic) == TRUE)
4616         goto release;
4617
4618     }
4619
4620   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4621
4622   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4623     {
4624       CLRC;
4625     }
4626   else
4627     {
4628       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4629       lit = -lit;
4630     }
4631
4632
4633   /* if literal, add a,#-lit, else normal subb */
4634   _startLazyDPSEvaluation ();
4635   while (size--) {
4636       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4637           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4638               emitcode ("mov","b,%s",
4639                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4640               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4641               emitcode ("subb","a,b");
4642           } else {
4643               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4644               emitcode ("subb", "a,%s",
4645                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4646                                 DP2_RESULT_REG));
4647           }
4648       } else {
4649           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4650           /* first add without previous c */
4651           if (!offset) {
4652               if (!size && lit==-1) {
4653                   emitcode ("dec", "a");
4654               } else {
4655                   emitcode ("add", "a,#!constbyte",
4656                             (unsigned int) (lit & 0x0FFL));
4657               }
4658           } else {
4659               emitcode ("addc", "a,#!constbyte",
4660                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4661           }
4662       }
4663       
4664       if (pushResult) {
4665           emitcode ("push", "acc");
4666       } else {
4667           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4668       }
4669       offset++;
4670   }
4671   _endLazyDPSEvaluation ();
4672   
4673   if (pushResult)
4674     {
4675       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4676
4677       size = getDataSize (IC_LEFT (ic));
4678       rSize = getDataSize (IC_RESULT (ic));
4679
4680       ADJUST_PUSHED_RESULT(size, rSize);
4681
4682       _startLazyDPSEvaluation ();
4683       while (size--)
4684         {
4685           emitcode ("pop", "acc");
4686           aopPut (AOP (IC_RESULT (ic)), "a", size);
4687         }
4688       _endLazyDPSEvaluation ();
4689     }
4690
4691   adjustArithmeticResult (ic);
4692
4693 release:
4694   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4696   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4697 }
4698
4699
4700 /*-----------------------------------------------------------------*/
4701 /* genMultbits :- multiplication of bits                           */
4702 /*-----------------------------------------------------------------*/
4703 static void
4704 genMultbits (operand * left,
4705              operand * right,
4706              operand * result,
4707              iCode   * ic)
4708 {
4709   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4710   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4711   aopOp(result, ic, TRUE, FALSE);
4712   outBitC (result);
4713 }
4714
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4718 /*-----------------------------------------------------------------*/
4719 static void
4720 genMultOneByte (operand * left,
4721                 operand * right,
4722                 operand * result,
4723                 iCode   * ic)
4724 {
4725   int size;
4726   symbol *lbl;
4727   bool runtimeSign, compiletimeSign;
4728   bool lUnsigned, rUnsigned;
4729   
4730
4731   /* (if two literals: the value is computed before) */
4732   /* if one literal, literal on the right */
4733   if (AOP_TYPE (left) == AOP_LIT)
4734     {
4735       operand *t = right;
4736       right = left;
4737       left = t;
4738       emitcode (";", "swapped left and right");
4739     }
4740
4741   /* (if two literals: the value is computed before) */
4742   /* if one literal, literal on the right */
4743   if (AOP_TYPE (left) == AOP_LIT)
4744     {
4745       operand *t = right;
4746       right = left;
4747       left = t;
4748       /* emitcode (";", "swapped left and right"); */
4749     }
4750   /* if no literal, unsigned on the right: shorter code */
4751   if (   AOP_TYPE (right) != AOP_LIT
4752       && SPEC_USIGN (getSpec (operandType (left))))
4753     {
4754       operand *t = right;
4755       right = left;
4756       left = t;
4757     }
4758
4759   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4760   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4761
4762   if ((lUnsigned && rUnsigned)
4763 /* sorry, I don't know how to get size
4764    without calling aopOp (result,...);
4765    see Feature Request  */
4766       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4767                    no need to take care about the signedness! */
4768     {
4769       /* just an unsigned 8 * 8 = 8 multiply
4770          or 8u * 8u = 16u */
4771       /* emitcode (";","unsigned"); */
4772       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4773       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4774       emitcode ("mul", "ab");
4775     
4776       _G.accInUse++; _G.bInUse++;
4777       aopOp (result, ic, TRUE, FALSE);
4778       size = AOP_SIZE (result);
4779   
4780       if (size < 1 || size > 2)
4781         {
4782           /* this should never happen */
4783           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4784                    size, __FILE__, lineno);
4785           exit (1);
4786         }
4787   
4788       aopPut (AOP (result), "a", 0);
4789       _G.accInUse--; _G.bInUse--;
4790       if (size == 2) 
4791         aopPut (AOP (result), "b", 1);
4792       return;
4793     }
4794
4795   /* we have to do a signed multiply */
4796   /* emitcode (";", "signed"); */
4797   
4798   /* now sign adjust for both left & right */
4799
4800   /* let's see what's needed: */
4801   /* apply negative sign during runtime */
4802   runtimeSign = FALSE;
4803   /* negative sign from literals */
4804   compiletimeSign = FALSE;
4805
4806   if (!lUnsigned)
4807     {
4808       if (AOP_TYPE(left) == AOP_LIT)
4809         {
4810           /* signed literal */
4811           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4812           if (val < 0)
4813             compiletimeSign = TRUE;
4814         }
4815       else
4816         /* signed but not literal */
4817         runtimeSign = TRUE;
4818     }
4819
4820   if (!rUnsigned)
4821     {
4822       if (AOP_TYPE(right) == AOP_LIT)
4823         {
4824           /* signed literal */
4825           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4826           if (val < 0)
4827             compiletimeSign ^= TRUE;
4828         }
4829       else
4830         /* signed but not literal */
4831         runtimeSign = TRUE;
4832     }
4833
4834   /* initialize F0, which stores the runtime sign */
4835   if (runtimeSign)
4836     {
4837       if (compiletimeSign)
4838         emitcode ("setb", "F0"); /* set sign flag */
4839       else
4840         emitcode ("clr", "F0"); /* reset sign flag */
4841     }
4842   
4843   /* save the signs of the operands */
4844   if (AOP_TYPE(right) == AOP_LIT)
4845     {
4846       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4847
4848       if (!rUnsigned && val < 0)
4849         emitcode ("mov", "b,#!constbyte", -val);
4850       else
4851         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4852     }
4853   else /* ! literal */
4854     {
4855       if (rUnsigned)  /* emitcode (";", "signed"); */
4856         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4857       else
4858         {
4859           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4860           lbl = newiTempLabel (NULL);
4861           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4862           emitcode ("cpl", "F0"); /* complement sign flag */
4863           emitcode ("cpl", "a");  /* 2's complement */
4864           emitcode ("inc", "a");
4865           emitcode ("", "!tlabeldef", lbl->key + 100);
4866           emitcode ("mov", "b,a");
4867         }
4868     }
4869
4870   if (AOP_TYPE(left) == AOP_LIT)
4871     {
4872       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4873
4874       if (!lUnsigned && val < 0)
4875         emitcode ("mov", "a,#!constbyte", -val);
4876       else
4877         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4878     }
4879   else /* ! literal */
4880     {
4881       if (lUnsigned)  /* emitcode (";", "signed"); */
4882
4883         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4884       else
4885         {
4886           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4887           lbl = newiTempLabel (NULL);
4888           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4889           emitcode ("cpl", "F0"); /* complement sign flag */
4890           emitcode ("cpl", "a");  /* 2's complement */
4891           emitcode ("inc", "a");
4892           emitcode ("", "!tlabeldef", lbl->key + 100);
4893         }
4894     }
4895
4896   /* now the multiplication */
4897   emitcode ("mul", "ab");
4898   _G.accInUse++;_G.bInUse++;
4899   aopOp(result, ic, TRUE, FALSE);
4900   size = AOP_SIZE (result);
4901
4902   if (size < 1 || size > 2) 
4903     {
4904       /* this should never happen */
4905       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4906                size, __FILE__, lineno);
4907       exit (1);
4908     }    
4909     
4910   if (runtimeSign || compiletimeSign)
4911     {
4912       lbl = newiTempLabel (NULL);
4913       if (runtimeSign)
4914         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4915       emitcode ("cpl", "a"); /* lsb 2's complement */
4916       if (size != 2)
4917         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4918       else
4919         {
4920           emitcode ("add", "a,#1"); /* this sets carry flag */
4921           emitcode ("xch", "a,b");
4922           emitcode ("cpl", "a"); /* msb 2's complement */
4923           emitcode ("addc", "a,#0");
4924           emitcode ("xch", "a,b");
4925         }
4926       emitcode ("", "!tlabeldef", lbl->key + 100);
4927     }
4928   aopPut (AOP (result), "a", 0);
4929   _G.accInUse--;_G.bInUse--;
4930   if (size == 2)
4931     aopPut (AOP (result), "b", 1);
4932 }
4933
4934 /*-----------------------------------------------------------------*/
4935 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4936 /*-----------------------------------------------------------------*/
4937 static void genMultTwoByte (operand *left, operand *right, 
4938                             operand *result, iCode *ic)
4939 {
4940         sym_link *retype = getSpec(operandType(right));
4941         sym_link *letype = getSpec(operandType(left));
4942         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4943         symbol *lbl;
4944
4945         if (AOP_TYPE (left) == AOP_LIT) {
4946                 operand *t = right;
4947                 right = left;
4948                 left = t;
4949         }
4950         /* save EA bit in F1 */
4951         lbl = newiTempLabel(NULL);
4952         emitcode ("setb","F1");
4953         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4954         emitcode ("clr","F1");
4955         emitcode("","!tlabeldef",lbl->key+100);
4956
4957         /* load up MB with right */
4958         if (!umult) {
4959                 emitcode("clr","F0");
4960                 if (AOP_TYPE(right) == AOP_LIT) {
4961                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4962                         if (val < 0) {
4963                                 emitcode("setb","F0");
4964                                 val = -val;
4965                         }
4966                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4967                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4968                 } else {
4969                         lbl = newiTempLabel(NULL);
4970                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4971                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4972                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4973                         emitcode ("xch", "a,b");
4974                         emitcode ("cpl","a");
4975                         emitcode ("add", "a,#1");
4976                         emitcode ("xch", "a,b");
4977                         emitcode ("cpl", "a"); // msb
4978                         emitcode ("addc", "a,#0");
4979                         emitcode ("setb","F0");
4980                         emitcode ("","!tlabeldef",lbl->key+100);
4981                         emitcode ("mov","mb,b");
4982                         emitcode ("mov","mb,a");
4983                 }
4984         } else {
4985                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4986                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4987         }
4988         /* load up MA with left */
4989         if (!umult) {
4990                 lbl = newiTempLabel(NULL);
4991                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4992                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4993                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4994                 emitcode ("xch", "a,b");
4995                 emitcode ("cpl","a");
4996                 emitcode ("add", "a,#1");
4997                 emitcode ("xch", "a,b");
4998                 emitcode ("cpl", "a"); // msb
4999                 emitcode ("addc","a,#0");
5000                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5001                 emitcode ("setb","F0");
5002                 emitcode ("","!tlabeldef",lbl->key+100);
5003                 emitcode ("mov","ma,b");
5004                 emitcode ("mov","ma,a");
5005         } else {
5006                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008         }
5009         /* wait for multiplication to finish */
5010         lbl = newiTempLabel(NULL);
5011         emitcode("","!tlabeldef", lbl->key+100);
5012         emitcode("mov","a,mcnt1");
5013         emitcode("anl","a,#!constbyte",0x80);
5014         emitcode("jnz","!tlabel",lbl->key+100);
5015         
5016         freeAsmop (left, NULL, ic, TRUE);
5017         freeAsmop (right, NULL, ic,TRUE);
5018         aopOp(result, ic, TRUE, FALSE);
5019
5020         /* if unsigned then simple */   
5021         if (umult) {
5022                 emitcode ("mov","a,ma");
5023                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5024                 emitcode ("mov","a,ma");
5025                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5026                 aopPut(AOP(result),"ma",1);
5027                 aopPut(AOP(result),"ma",0);
5028         } else {
5029                 emitcode("push","ma");
5030                 emitcode("push","ma");
5031                 emitcode("push","ma");
5032                 MOVA("ma");
5033                 /* negate result if needed */
5034                 lbl = newiTempLabel(NULL);      
5035                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5036                 emitcode("cpl","a");
5037                 emitcode("add","a,#1");
5038                 emitcode("","!tlabeldef", lbl->key+100);
5039                 if (AOP_TYPE(result) == AOP_ACC)
5040                 {
5041                     D(emitcode(";", "ACC special case."););
5042                     /* We know result is the only live aop, and 
5043                      * it's obviously not a DPTR2, so AP is available.
5044                      */
5045                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5046                 }
5047                 else
5048                 {
5049                     aopPut(AOP(result),"a",0);
5050                 }
5051             
5052                 emitcode("pop","acc");
5053                 lbl = newiTempLabel(NULL);      
5054                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055                 emitcode("cpl","a");
5056                 emitcode("addc","a,#0");
5057                 emitcode("","!tlabeldef", lbl->key+100);
5058                 aopPut(AOP(result),"a",1);
5059                 emitcode("pop","acc");
5060                 if (AOP_SIZE(result) >= 3) {
5061                         lbl = newiTempLabel(NULL);      
5062                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5063                         emitcode("cpl","a");
5064                         emitcode("addc","a,#0");                        
5065                         emitcode("","!tlabeldef", lbl->key+100);
5066                         aopPut(AOP(result),"a",2);
5067                 }
5068                 emitcode("pop","acc");
5069                 if (AOP_SIZE(result) >= 4) {
5070                         lbl = newiTempLabel(NULL);      
5071                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5072                         emitcode("cpl","a");
5073                         emitcode("addc","a,#0");                        
5074                         emitcode("","!tlabeldef", lbl->key+100);
5075                         aopPut(AOP(result),"a",3);
5076                 }
5077                 if (AOP_TYPE(result) == AOP_ACC)
5078                 {
5079                     /* We stashed the result away above. */
5080                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5081                 }           
5082                 
5083         }
5084         freeAsmop (result, NULL, ic, TRUE);
5085
5086         /* restore EA bit in F1 */
5087         lbl = newiTempLabel(NULL);
5088         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5089         emitcode ("setb","EA");
5090         emitcode("","!tlabeldef",lbl->key+100);
5091         return ;
5092 }
5093
5094 /*-----------------------------------------------------------------*/
5095 /* genMult - generates code for multiplication                     */
5096 /*-----------------------------------------------------------------*/
5097 static void
5098 genMult (iCode * ic)
5099 {
5100   operand *left = IC_LEFT (ic);
5101   operand *right = IC_RIGHT (ic);
5102   operand *result = IC_RESULT (ic);
5103
5104   D (emitcode (";", "genMult "););
5105
5106   /* assign the amsops */
5107   AOP_OP_2 (ic);
5108
5109   /* special cases first */
5110   /* both are bits */
5111   if (AOP_TYPE (left) == AOP_CRY &&
5112       AOP_TYPE (right) == AOP_CRY)
5113     {
5114       genMultbits (left, right, result, ic);
5115       goto release;
5116     }
5117
5118   /* if both are of size == 1 */
5119   if (AOP_SIZE (left) == 1 &&
5120       AOP_SIZE (right) == 1)
5121     {
5122       genMultOneByte (left, right, result, ic);
5123       goto release;
5124     }
5125
5126   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5127           /* use the ds390 ARITHMETIC accel UNIT */
5128           genMultTwoByte (left, right, result, ic);
5129           return ;
5130   }
5131   /* should have been converted to function call */
5132   assert (0);
5133
5134 release:
5135   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137   freeAsmop (result, NULL, ic, TRUE);
5138 }
5139
5140 /*-----------------------------------------------------------------*/
5141 /* genDivbits :- division of bits                                  */
5142 /*-----------------------------------------------------------------*/
5143 static void
5144 genDivbits (operand * left,
5145             operand * right,
5146             operand * result,
5147             iCode   * ic)
5148 {
5149
5150   char *l;
5151
5152   /* the result must be bit */
5153   LOAD_AB_FOR_DIV (left, right, l);
5154   emitcode ("div", "ab");
5155   emitcode ("rrc", "a");
5156   aopOp(result, ic, TRUE, FALSE);
5157     
5158   aopPut (AOP (result), "c", 0);
5159 }
5160
5161 /*-----------------------------------------------------------------*/
5162 /* genDivOneByte : 8 bit division                                  */
5163 /*-----------------------------------------------------------------*/
5164 static void
5165 genDivOneByte (operand * left,
5166                operand * right,
5167                operand * result,
5168                iCode   * ic)
5169 {
5170   bool lUnsigned, rUnsigned;
5171   bool runtimeSign, compiletimeSign;
5172   char *l;
5173   symbol *lbl;
5174   int size, offset;
5175
5176   offset = 1;
5177   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5178   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5179   
5180   /* signed or unsigned */
5181   if (lUnsigned && rUnsigned)
5182     {
5183       /* unsigned is easy */
5184       LOAD_AB_FOR_DIV (left, right, l);
5185       emitcode ("div", "ab");
5186
5187       _G.accInUse++;
5188       aopOp (result, ic, TRUE, FALSE);
5189       aopPut (AOP (result), "a", 0);
5190       _G.accInUse--;
5191
5192       size = AOP_SIZE (result) - 1;
5193       
5194       while (size--)
5195         aopPut (AOP (result), zero, offset++);
5196       return;
5197     }
5198
5199   /* signed is a little bit more difficult */
5200
5201   /* now sign adjust for both left & right */
5202
5203   /* let's see what's needed: */
5204   /* apply negative sign during runtime */
5205   runtimeSign = FALSE;
5206   /* negative sign from literals */
5207   compiletimeSign = FALSE;
5208
5209   if (!lUnsigned)
5210     {
5211       if (AOP_TYPE(left) == AOP_LIT)
5212         {
5213           /* signed literal */
5214           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5215           if (val < 0)
5216             compiletimeSign = TRUE;
5217         }
5218       else
5219         /* signed but not literal */
5220         runtimeSign = TRUE;
5221     }
5222
5223   if (!rUnsigned)
5224     {
5225       if (AOP_TYPE(right) == AOP_LIT)
5226         {
5227           /* signed literal */
5228           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5229           if (val < 0)
5230             compiletimeSign ^= TRUE;
5231         }
5232       else
5233         /* signed but not literal */
5234         runtimeSign = TRUE;
5235     }
5236
5237   /* initialize F0, which stores the runtime sign */
5238   if (runtimeSign)
5239     {
5240       if (compiletimeSign)
5241         emitcode ("setb", "F0"); /* set sign flag */
5242       else
5243         emitcode ("clr", "F0"); /* reset sign flag */
5244     }
5245
5246   /* save the signs of the operands */
5247   if (AOP_TYPE(right) == AOP_LIT)
5248     {
5249       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5250
5251       if (!rUnsigned && val < 0)
5252         emitcode ("mov", "b,#0x%02x", -val);
5253       else
5254         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5255     }
5256   else /* ! literal */
5257     {
5258       if (rUnsigned)
5259         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5260       else
5261         {
5262           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5263           lbl = newiTempLabel (NULL);
5264           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5265           emitcode ("cpl", "F0"); /* complement sign flag */
5266           emitcode ("cpl", "a");  /* 2's complement */
5267           emitcode ("inc", "a");
5268           emitcode ("", "!tlabeldef", lbl->key + 100);
5269           emitcode ("mov", "b,a");
5270         }
5271     }
5272
5273   if (AOP_TYPE(left) == AOP_LIT)
5274     {
5275       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5276
5277       if (!lUnsigned && val < 0)
5278         emitcode ("mov", "a,#0x%02x", -val);
5279       else
5280         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5281     }
5282   else /* ! literal */
5283     {
5284       if (lUnsigned)
5285         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5286       else
5287         {
5288           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5289           lbl = newiTempLabel (NULL);
5290           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5291           emitcode ("cpl", "F0"); /* complement sign flag */
5292           emitcode ("cpl", "a");  /* 2's complement */
5293           emitcode ("inc", "a");
5294           emitcode ("", "!tlabeldef", lbl->key + 100);
5295         }
5296     }
5297   
5298   /* now the division */
5299   emitcode ("nop", "; workaround for DS80C390 div bug.");
5300   emitcode ("div", "ab");
5301   
5302   if (runtimeSign || compiletimeSign)
5303     {
5304       lbl = newiTempLabel (NULL);
5305       if (runtimeSign)
5306         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5307       emitcode ("cpl", "a"); /* lsb 2's complement */
5308       emitcode ("inc", "a");
5309       emitcode ("", "!tlabeldef", lbl->key + 100);
5310
5311       _G.accInUse++;     _G.bInUse++;
5312       aopOp (result, ic, TRUE, FALSE);
5313       size = AOP_SIZE (result) - 1;
5314
5315       if (size > 0)
5316         {
5317           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5318              then the result will be in b, a */
5319           emitcode ("mov", "b,a"); /* 1 */
5320           /* msb is 0x00 or 0xff depending on the sign */
5321           if (runtimeSign)
5322             {
5323               emitcode ("mov",  "c,F0");
5324               emitcode ("subb", "a,acc");
5325               emitcode ("xch",  "a,b"); /* 2 */
5326               while (size--)
5327                 aopPut (AOP (result), "b", offset++); /* write msb's */
5328             }
5329           else /* compiletimeSign */
5330             while (size--)
5331               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5332         }
5333       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5334     }
5335   else
5336     {
5337       _G.accInUse++;     _G.bInUse++;
5338       aopOp(result, ic, TRUE, FALSE);
5339       size = AOP_SIZE (result) - 1;
5340       
5341       aopPut (AOP (result), "a", 0);
5342       while (size--)
5343         aopPut (AOP (result), zero, offset++);
5344     }
5345   _G.accInUse--;     _G.bInUse--;
5346
5347 }
5348
5349 /*-----------------------------------------------------------------*/
5350 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5351 /*-----------------------------------------------------------------*/
5352 static void genDivTwoByte (operand *left, operand *right, 
5353                             operand *result, iCode *ic)
5354 {
5355         sym_link *retype = getSpec(operandType(right));
5356         sym_link *letype = getSpec(operandType(left));
5357         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5358         symbol *lbl;
5359
5360         /* save EA bit in F1 */
5361         lbl = newiTempLabel(NULL);
5362         emitcode ("setb","F1");
5363         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5364         emitcode ("clr","F1");
5365         emitcode("","!tlabeldef",lbl->key+100);
5366
5367         /* load up MA with left */
5368         if (!umult) {
5369                 emitcode("clr","F0");
5370                 lbl = newiTempLabel(NULL);
5371                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5372                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5373                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5374                 emitcode ("xch", "a,b");
5375                 emitcode ("cpl","a");
5376                 emitcode ("add", "a,#1");
5377                 emitcode ("xch", "a,b");
5378                 emitcode ("cpl", "a"); // msb
5379                 emitcode ("addc","a,#0");
5380                 emitcode ("setb","F0");
5381                 emitcode ("","!tlabeldef",lbl->key+100);
5382                 emitcode ("mov","ma,b");
5383                 emitcode ("mov","ma,a");
5384         } else {
5385                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5386                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5387         }
5388
5389         /* load up MB with right */
5390         if (!umult) {
5391                 if (AOP_TYPE(right) == AOP_LIT) {
5392                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5393                         if (val < 0) {
5394                                 lbl = newiTempLabel(NULL);
5395                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5396                                 emitcode("setb","F0");
5397                                 emitcode ("","!tlabeldef",lbl->key+100);
5398                                 val = -val;
5399                         } 
5400                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5401                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5402                 } else {
5403                         lbl = newiTempLabel(NULL);
5404                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5405                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5406                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5407                         emitcode ("xch", "a,b");
5408                         emitcode ("cpl","a");
5409                         emitcode ("add", "a,#1");
5410                         emitcode ("xch", "a,b");
5411                         emitcode ("cpl", "a"); // msb
5412                         emitcode ("addc", "a,#0");
5413                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414                         emitcode ("setb","F0");
5415                         emitcode ("","!tlabeldef",lbl->key+100);
5416                         emitcode ("mov","mb,b");
5417                         emitcode ("mov","mb,a");
5418                 }
5419         } else {
5420                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5421                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5422         }
5423
5424         /* wait for multiplication to finish */
5425         lbl = newiTempLabel(NULL);
5426         emitcode("","!tlabeldef", lbl->key+100);
5427         emitcode("mov","a,mcnt1");
5428         emitcode("anl","a,#!constbyte",0x80);
5429         emitcode("jnz","!tlabel",lbl->key+100);
5430         
5431         freeAsmop (left, NULL, ic, TRUE);
5432         freeAsmop (right, NULL, ic,TRUE);
5433         aopOp(result, ic, TRUE, FALSE);
5434
5435         /* if unsigned then simple */   
5436         if (umult) {
5437                 aopPut(AOP(result),"ma",1);
5438                 aopPut(AOP(result),"ma",0);
5439         } else {
5440                 emitcode("push","ma");
5441                 MOVA("ma");
5442                 /* negate result if needed */
5443                 lbl = newiTempLabel(NULL);      
5444                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5445                 emitcode("cpl","a");
5446                 emitcode("add","a,#1");
5447                 emitcode("","!tlabeldef", lbl->key+100);
5448                 aopPut(AOP(result),"a",0);
5449                 emitcode("pop","acc");
5450                 lbl = newiTempLabel(NULL);      
5451                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5452                 emitcode("cpl","a");
5453                 emitcode("addc","a,#0");
5454                 emitcode("","!tlabeldef", lbl->key+100);
5455                 aopPut(AOP(result),"a",1);
5456         }
5457         freeAsmop (result, NULL, ic, TRUE);
5458         /* restore EA bit in F1 */
5459         lbl = newiTempLabel(NULL);
5460         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5461         emitcode ("setb","EA");
5462         emitcode("","!tlabeldef",lbl->key+100);
5463         return ;
5464 }
5465
5466 /*-----------------------------------------------------------------*/
5467 /* genDiv - generates code for division                            */
5468 /*-----------------------------------------------------------------*/
5469 static void
5470 genDiv (iCode * ic)
5471 {
5472   operand *left = IC_LEFT (ic);
5473   operand *right = IC_RIGHT (ic);
5474   operand *result = IC_RESULT (ic);
5475
5476   D (emitcode (";", "genDiv "););
5477
5478   /* assign the amsops */
5479   AOP_OP_2 (ic);
5480
5481   /* special cases first */
5482   /* both are bits */
5483   if (AOP_TYPE (left) == AOP_CRY &&
5484       AOP_TYPE (right) == AOP_CRY)
5485     {
5486       genDivbits (left, right, result, ic);
5487       goto release;
5488     }
5489
5490   /* if both are of size == 1 */
5491   if (AOP_SIZE (left) == 1 &&
5492       AOP_SIZE (right) == 1)
5493     {
5494       genDivOneByte (left, right, result, ic);
5495       goto release;
5496     }
5497
5498   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5499           /* use the ds390 ARITHMETIC accel UNIT */
5500           genDivTwoByte (left, right, result, ic);
5501           return ;
5502   }
5503   /* should have been converted to function call */
5504   assert (0);
5505 release:
5506   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508   freeAsmop (result, NULL, ic, TRUE);
5509 }
5510
5511 /*-----------------------------------------------------------------*/
5512 /* genModbits :- modulus of bits                                   */
5513 /*-----------------------------------------------------------------*/
5514 static void
5515 genModbits (operand * left,
5516             operand * right,
5517             operand * result,
5518             iCode   * ic)
5519 {
5520
5521   char *l;
5522
5523   /* the result must be bit */
5524   LOAD_AB_FOR_DIV (left, right, l);
5525   emitcode ("div", "ab");
5526   emitcode ("mov", "a,b");
5527   emitcode ("rrc", "a");
5528   aopOp(result, ic, TRUE, FALSE);
5529   aopPut (AOP (result), "c", 0);
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* genModOneByte : 8 bit modulus                                   */
5534 /*-----------------------------------------------------------------*/
5535 static void
5536 genModOneByte (operand * left,
5537                operand * right,
5538                operand * result,
5539                iCode   * ic)
5540 {
5541   bool lUnsigned, rUnsigned;
5542   bool runtimeSign, compiletimeSign;
5543   char *l;
5544   symbol *lbl;
5545   int size, offset;
5546
5547   offset = 1;
5548   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5549   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5550   
5551   /* signed or unsigned */
5552   if (lUnsigned && rUnsigned)
5553     {
5554       /* unsigned is easy */
5555       LOAD_AB_FOR_DIV (left, right, l);
5556       emitcode ("div", "ab");
5557       aopOp (result, ic, TRUE, FALSE);  
5558       aopPut (AOP (result), "b", 0);
5559
5560       for (size = AOP_SIZE (result) - 1; size--;)
5561         aopPut (AOP (result), zero, offset++);
5562       return;
5563     }
5564
5565   /* signed is a little bit more difficult */
5566
5567   /* now sign adjust for both left & right */
5568
5569   /* modulus: sign of the right operand has no influence on the result! */
5570   if (AOP_TYPE(right) == AOP_LIT)
5571     {
5572       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5573
5574       if (!rUnsigned && val < 0)
5575         emitcode ("mov", "b,#0x%02x", -val);
5576       else
5577         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5578     }
5579   else /* ! literal */
5580     {
5581       if (rUnsigned)
5582         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5583       else
5584         {
5585           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5586           lbl = newiTempLabel (NULL);
5587           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5588           emitcode ("cpl", "a");  /* 2's complement */
5589           emitcode ("inc", "a");
5590           emitcode ("", "!tlabeldef", lbl->key + 100);
5591           emitcode ("mov", "b,a");
5592         }
5593     }
5594   
5595   /* let's see what's needed: */
5596   /* apply negative sign during runtime */
5597   runtimeSign = FALSE;
5598   /* negative sign from literals */
5599   compiletimeSign = FALSE;
5600
5601   /* sign adjust left side */
5602   if (AOP_TYPE(left) == AOP_LIT)
5603     {
5604       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5605
5606       if (!lUnsigned && val < 0)
5607         {
5608           compiletimeSign = TRUE; /* set sign flag */
5609           emitcode ("mov", "a,#0x%02x", -val);
5610         }
5611       else
5612         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5613     }
5614   else /* ! literal */
5615     {
5616       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5617       
5618       if (!lUnsigned)
5619         {
5620           runtimeSign = TRUE;
5621           emitcode ("clr", "F0"); /* clear sign flag */
5622           
5623           lbl = newiTempLabel (NULL);
5624           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5625           emitcode ("setb", "F0"); /* set sign flag */
5626           emitcode ("cpl", "a");   /* 2's complement */
5627           emitcode ("inc", "a");
5628           emitcode ("", "!tlabeldef", lbl->key + 100);
5629         }
5630     }
5631   
5632   /* now the modulus */
5633   emitcode ("nop", "; workaround for DS80C390 div bug.");
5634   emitcode ("div", "ab");
5635   
5636   if (runtimeSign || compiletimeSign)
5637     {
5638       emitcode ("mov", "a,b");
5639       lbl = newiTempLabel (NULL);
5640       if (runtimeSign)
5641         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5642       emitcode ("cpl", "a"); /* lsb 2's complement */
5643       emitcode ("inc", "a");
5644       emitcode ("", "!tlabeldef", lbl->key + 100);
5645
5646       _G.accInUse++;     _G.bInUse++;
5647       aopOp (result, ic, TRUE, FALSE);
5648       size = AOP_SIZE (result) - 1;
5649       
5650       if (size > 0)
5651         {
5652           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5653              then the result will be in b, a */
5654           emitcode ("mov", "b,a"); /* 1 */
5655           /* msb is 0x00 or 0xff depending on the sign */
5656           if (runtimeSign)
5657             {
5658               emitcode ("mov",  "c,F0");
5659               emitcode ("subb", "a,acc");
5660               emitcode ("xch",  "a,b"); /* 2 */
5661               while (size--)
5662                 aopPut (AOP (result), "b", offset++); /* write msb's */
5663             }
5664           else /* compiletimeSign */
5665             while (size--)
5666               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5667         }
5668       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5669     }
5670   else
5671     {
5672       _G.accInUse++;     _G.bInUse++;
5673       aopOp(result, ic, TRUE, FALSE);
5674       size = AOP_SIZE (result) - 1;
5675       
5676       aopPut (AOP (result), "b", 0);
5677       while (size--)
5678         aopPut (AOP (result), zero, offset++);
5679     }
5680   _G.accInUse--;     _G.bInUse--;
5681
5682 }
5683
5684 /*-----------------------------------------------------------------*/
5685 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5686 /*-----------------------------------------------------------------*/
5687 static void genModTwoByte (operand *left, operand *right, 
5688                             operand *result, iCode *ic)
5689 {
5690         sym_link *retype = getSpec(operandType(right));
5691         sym_link *letype = getSpec(operandType(left));
5692         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5693         symbol *lbl;
5694
5695         /* load up MA with left */
5696         /* save EA bit in F1 */
5697         lbl = newiTempLabel(NULL);
5698         emitcode ("setb","F1");
5699         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5700         emitcode ("clr","F1");
5701         emitcode("","!tlabeldef",lbl->key+100);
5702
5703         if (!umult) {
5704                 lbl = newiTempLabel(NULL);
5705                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5706                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5707                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5708                 emitcode ("xch", "a,b");
5709                 emitcode ("cpl","a");
5710                 emitcode ("add", "a,#1");
5711                 emitcode ("xch", "a,b");
5712                 emitcode ("cpl", "a"); // msb
5713                 emitcode ("addc","a,#0");
5714                 emitcode ("","!tlabeldef",lbl->key+100);
5715                 emitcode ("mov","ma,b");
5716                 emitcode ("mov","ma,a");
5717         } else {
5718                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5719                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5720         }
5721
5722         /* load up MB with right */
5723         if (!umult) {
5724                 if (AOP_TYPE(right) == AOP_LIT) {
5725                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5726                         if (val < 0) {
5727                                 val = -val;
5728                         } 
5729                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5730                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5731                 } else {
5732                         lbl = newiTempLabel(NULL);
5733                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5734                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5735                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5736                         emitcode ("xch", "a,b");
5737                         emitcode ("cpl","a");
5738                         emitcode ("add", "a,#1");
5739                         emitcode ("xch", "a,b");
5740                         emitcode ("cpl", "a"); // msb
5741                         emitcode ("addc", "a,#0");
5742                         emitcode ("","!tlabeldef",lbl->key+100);
5743                         emitcode ("mov","mb,b");
5744                         emitcode ("mov","mb,a");
5745                 }
5746         } else {
5747                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5748                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5749         }
5750
5751         /* wait for multiplication to finish */
5752         lbl = newiTempLabel(NULL);
5753         emitcode("","!tlabeldef", lbl->key+100);
5754         emitcode("mov","a,mcnt1");
5755         emitcode("anl","a,#!constbyte",0x80);
5756         emitcode("jnz","!tlabel",lbl->key+100);
5757         
5758         freeAsmop (left, NULL, ic, TRUE);
5759         freeAsmop (right, NULL, ic,TRUE);
5760         aopOp(result, ic, TRUE, FALSE);
5761
5762         aopPut(AOP(result),"mb",1);
5763         aopPut(AOP(result),"mb",0);
5764         freeAsmop (result, NULL, ic, TRUE);
5765
5766         /* restore EA bit in F1 */
5767         lbl = newiTempLabel(NULL);
5768         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5769         emitcode ("setb","EA");
5770         emitcode("","!tlabeldef",lbl->key+100);
5771         return ;
5772 }
5773
5774 /*-----------------------------------------------------------------*/
5775 /* genMod - generates code for division                            */
5776 /*-----------------------------------------------------------------*/
5777 static void
5778 genMod (iCode * ic)
5779 {
5780   operand *left = IC_LEFT (ic);
5781   operand *right = IC_RIGHT (ic);
5782   operand *result = IC_RESULT (ic);
5783
5784   D (emitcode (";", "genMod "); );
5785
5786   /* assign the amsops */
5787   AOP_OP_2 (ic);
5788
5789   /* special cases first */
5790   /* both are bits */
5791   if (AOP_TYPE (left) == AOP_CRY &&
5792       AOP_TYPE (right) == AOP_CRY)
5793     {
5794       genModbits (left, right, result, ic);
5795       goto release;
5796     }
5797
5798   /* if both are of size == 1 */
5799   if (AOP_SIZE (left) == 1 &&
5800       AOP_SIZE (right) == 1)
5801     {
5802       genModOneByte (left, right, result, ic);
5803       goto release;
5804     }
5805
5806   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5807           /* use the ds390 ARITHMETIC accel UNIT */
5808           genModTwoByte (left, right, result, ic);
5809           return ;
5810   }
5811
5812   /* should have been converted to function call */
5813   assert (0);
5814
5815 release:
5816   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818   freeAsmop (result, NULL, ic, TRUE);
5819 }
5820
5821 /*-----------------------------------------------------------------*/
5822 /* genIfxJump :- will create a jump depending on the ifx           */
5823 /*-----------------------------------------------------------------*/
5824 static void
5825 genIfxJump (iCode * ic, char *jval)
5826 {
5827   symbol *jlbl;
5828   symbol *tlbl = newiTempLabel (NULL);
5829   char *inst;
5830
5831   D (emitcode (";", "genIfxJump"););
5832
5833   /* if true label then we jump if condition
5834      supplied is true */
5835   if (IC_TRUE (ic))
5836     {
5837       jlbl = IC_TRUE (ic);
5838       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5839                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5840     }
5841   else
5842     {
5843       /* false label is present */
5844       jlbl = IC_FALSE (ic);
5845       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5846                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5847     }
5848   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5849     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5850   else
5851     emitcode (inst, "!tlabel", tlbl->key + 100);
5852   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5853   emitcode ("", "!tlabeldef", tlbl->key + 100);
5854
5855   /* mark the icode as generated */
5856   ic->generated = 1;
5857 }
5858
5859 /*-----------------------------------------------------------------*/
5860 /* genCmp :- greater or less than comparison                       */
5861 /*-----------------------------------------------------------------*/
5862 static void
5863 genCmp (operand * left, operand * right,
5864         iCode * ic, iCode * ifx, int sign)
5865 {
5866   int size, offset = 0;
5867   unsigned long lit = 0L;
5868   operand *result;
5869
5870   D (emitcode (";", "genCmp"););
5871
5872   result = IC_RESULT (ic);
5873
5874   /* if left & right are bit variables */
5875   if (AOP_TYPE (left) == AOP_CRY &&
5876       AOP_TYPE (right) == AOP_CRY)
5877     {
5878       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5879       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5880     }
5881   else
5882     {
5883       /* subtract right from left if at the
5884          end the carry flag is set then we know that
5885          left is greater than right */
5886       size = max (AOP_SIZE (left), AOP_SIZE (right));
5887
5888       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5889       if ((size == 1) && !sign 
5890           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5891         {
5892           symbol *lbl = newiTempLabel (NULL);
5893           emitcode ("cjne", "%s,%s,!tlabel",
5894                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5895                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5896                     lbl->key + 100);
5897           emitcode ("", "!tlabeldef", lbl->key + 100);
5898         }
5899       else
5900         {
5901           if (AOP_TYPE (right) == AOP_LIT)
5902             {
5903               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5904               /* optimize if(x < 0) or if(x >= 0) */
5905               if (lit == 0L)
5906                 {
5907                   if (!sign)
5908                     {
5909                       CLRC;
5910                     }
5911                   else
5912                     {
5913                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5914
5915                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5916                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5917
5918                       aopOp (result, ic, FALSE, FALSE);
5919
5920                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5921                         {
5922                           freeAsmop (result, NULL, ic, TRUE);
5923                           genIfxJump (ifx, "acc.7");
5924                           return;
5925                         }
5926                       else
5927                         {
5928                           emitcode ("rlc", "a");
5929                         }
5930                       goto release_freedLR;
5931                     }
5932                   goto release;
5933                 }
5934             }
5935           CLRC;
5936           while (size--)
5937             {
5938               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5939               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5940               // emitcode (";", "genCmp #2");
5941               if (sign && (size == 0))
5942                 {
5943                   // emitcode (";", "genCmp #3");
5944                   emitcode ("xrl", "a,#!constbyte",0x80);
5945                   if (AOP_TYPE (right) == AOP_LIT)
5946                     {
5947                       unsigned long lit = (unsigned long)
5948                       floatFromVal (AOP (right)->aopu.aop_lit);
5949                       // emitcode (";", "genCmp #3.1");
5950                       emitcode ("subb", "a,#!constbyte",
5951                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5952                     }
5953                   else
5954                     {
5955                       // emitcode (";", "genCmp #3.2");
5956                       saveAccWarn = 0;  
5957                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5958                       saveAccWarn = DEFAULT_ACC_WARNING;
5959                       emitcode ("xrl", "b,#!constbyte",0x80);
5960                       emitcode ("subb", "a,b");
5961                     }
5962                 }
5963               else
5964                 {
5965                   const char *s;
5966
5967                   // emitcode (";", "genCmp #4");
5968                   saveAccWarn = 0;
5969                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5970                   saveAccWarn = DEFAULT_ACC_WARNING;
5971
5972                   emitcode ("subb", "a,%s", s);
5973                 }
5974             }
5975         }
5976     }
5977
5978 release:
5979 /* Don't need the left & right operands any more; do need the result. */
5980   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5982
5983   aopOp (result, ic, FALSE, FALSE);
5984
5985 release_freedLR:
5986
5987   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5988     {
5989       outBitC (result);
5990     }
5991   else
5992     {
5993       /* if the result is used in the next
5994          ifx conditional branch then generate
5995          code a little differently */
5996       if (ifx)
5997         {
5998           genIfxJump (ifx, "c");
5999         }
6000       else
6001         {
6002           outBitC (result);
6003         }
6004       /* leave the result in acc */
6005     }
6006   freeAsmop (result, NULL, ic, TRUE);
6007 }
6008
6009 /*-----------------------------------------------------------------*/
6010 /* genCmpGt :- greater than comparison                             */
6011 /*-----------------------------------------------------------------*/
6012 static void
6013 genCmpGt (iCode * ic, iCode * ifx)
6014 {
6015   operand *left, *right;
6016   sym_link *letype, *retype;
6017   int sign;
6018
6019   D (emitcode (";", "genCmpGt ");
6020     );
6021
6022   left = IC_LEFT (ic);
6023   right = IC_RIGHT (ic);
6024
6025   letype = getSpec (operandType (left));
6026   retype = getSpec (operandType (right));
6027   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6028
6029   /* assign the left & right amsops */
6030   AOP_OP_2 (ic);
6031
6032   genCmp (right, left, ic, ifx, sign);
6033 }
6034
6035 /*-----------------------------------------------------------------*/
6036 /* genCmpLt - less than comparisons                                */
6037 /*-----------------------------------------------------------------*/
6038 static void
6039 genCmpLt (iCode * ic, iCode * ifx)
6040 {
6041   operand *left, *right;
6042   sym_link *letype, *retype;
6043   int sign;
6044
6045   D (emitcode (";", "genCmpLt "););
6046
6047   left = IC_LEFT (ic);
6048   right = IC_RIGHT (ic);
6049
6050   letype = getSpec (operandType (left));
6051   retype = getSpec (operandType (right));
6052   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6053
6054   /* assign the left & right amsops */
6055   AOP_OP_2 (ic);
6056
6057   genCmp (left, right, ic, ifx, sign);
6058 }
6059
6060 /*-----------------------------------------------------------------*/
6061 /* gencjneshort - compare and jump if not equal                    */
6062 /*-----------------------------------------------------------------*/
6063 static void
6064 gencjneshort (operand * left, operand * right, symbol * lbl)
6065 {
6066   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6067   int offset = 0;
6068   unsigned long lit = 0L;
6069
6070   D (emitcode (";", "gencjneshort");
6071     );
6072
6073   /* if the left side is a literal or
6074      if the right is in a pointer register and left
6075      is not */
6076   if ((AOP_TYPE (left) == AOP_LIT) ||
6077       (AOP_TYPE (left) == AOP_IMMD) ||
6078       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6079     {
6080       operand *t = right;
6081       right = left;
6082       left = t;
6083     }
6084
6085   if (AOP_TYPE (right) == AOP_LIT)
6086     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6087
6088   if (opIsGptr (left) || opIsGptr (right))
6089     {
6090       /* We are comparing a generic pointer to something.
6091        * Exclude the generic type byte from the comparison.
6092        */
6093       size--;
6094       D (emitcode (";", "cjneshort: generic ptr special case."););
6095     }
6096
6097
6098   /* if the right side is a literal then anything goes */
6099   if (AOP_TYPE (right) == AOP_LIT &&
6100       AOP_TYPE (left) != AOP_DIR)
6101     {
6102       while (size--)
6103         {
6104           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6105           emitcode ("cjne", "a,%s,!tlabel",
6106                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6107                     lbl->key + 100);
6108           offset++;
6109         }
6110     }
6111
6112   /* if the right side is in a register or in direct space or
6113      if the left is a pointer register & right is not */
6114   else if (AOP_TYPE (right) == AOP_REG ||
6115            AOP_TYPE (right) == AOP_DIR ||
6116            AOP_TYPE (right) == AOP_LIT ||
6117            AOP_TYPE (right) == AOP_IMMD ||
6118            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6119            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6120     {
6121       while (size--)
6122         {
6123           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6124           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6125               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6126             emitcode ("jnz", "!tlabel", lbl->key + 100);
6127           else
6128             emitcode ("cjne", "a,%s,!tlabel",
6129                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6130                       lbl->key + 100);
6131           offset++;
6132         }
6133     }
6134   else
6135     {
6136       /* right is a pointer reg need both a & b */
6137       while (size--)
6138         {
6139           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6140           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6141           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6142           offset++;
6143         }
6144     }
6145 }
6146
6147 /*-----------------------------------------------------------------*/
6148 /* gencjne - compare and jump if not equal                         */
6149 /*-----------------------------------------------------------------*/
6150 static void
6151 gencjne (operand * left, operand * right, symbol * lbl)
6152 {
6153   symbol *tlbl = newiTempLabel (NULL);
6154
6155   D (emitcode (";", "gencjne");
6156     );
6157
6158   gencjneshort (left, right, lbl);
6159
6160   emitcode ("mov", "a,%s", one);
6161   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6162   emitcode ("", "!tlabeldef", lbl->key + 100);
6163   emitcode ("clr", "a");
6164   emitcode ("", "!tlabeldef", tlbl->key + 100);
6165 }
6166
6167 /*-----------------------------------------------------------------*/
6168 /* genCmpEq - generates code for equal to                          */
6169 /*-----------------------------------------------------------------*/
6170 static void
6171 genCmpEq (iCode * ic, iCode * ifx)
6172 {
6173   operand *left, *right, *result;
6174
6175   D (emitcode (";", "genCmpEq ");
6176     );
6177
6178   AOP_OP_2 (ic);
6179   AOP_SET_LOCALS (ic);
6180
6181   /* if literal, literal on the right or
6182      if the right is in a pointer register and left
6183      is not */
6184   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6185       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6186     {
6187       operand *t = IC_RIGHT (ic);
6188       IC_RIGHT (ic) = IC_LEFT (ic);
6189       IC_LEFT (ic) = t;
6190     }
6191
6192   if (ifx &&                    /* !AOP_SIZE(result) */
6193       OP_SYMBOL (result) &&
6194       OP_SYMBOL (result)->regType == REG_CND)
6195     {
6196       symbol *tlbl;
6197       /* if they are both bit variables */
6198       if (AOP_TYPE (left) == AOP_CRY &&
6199           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6200         {
6201           if (AOP_TYPE (right) == AOP_LIT)
6202             {
6203               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6204               if (lit == 0L)
6205                 {
6206                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207                   emitcode ("cpl", "c");
6208                 }
6209               else if (lit == 1L)
6210                 {
6211                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6212                 }
6213               else
6214                 {
6215                   emitcode ("clr", "c");
6216                 }
6217               /* AOP_TYPE(right) == AOP_CRY */
6218             }
6219           else
6220             {
6221               symbol *lbl = newiTempLabel (NULL);
6222               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6223               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6224               emitcode ("cpl", "c");
6225               emitcode ("", "!tlabeldef", (lbl->key + 100));
6226             }
6227           /* if true label then we jump if condition
6228              supplied is true */
6229           tlbl = newiTempLabel (NULL);
6230           if (IC_TRUE (ifx))
6231             {
6232               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6233               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6234             }
6235           else
6236             {
6237               emitcode ("jc", "!tlabel", tlbl->key + 100);
6238               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6239             }
6240           emitcode ("", "!tlabeldef", tlbl->key + 100);
6241         }
6242       else
6243         {
6244           tlbl = newiTempLabel (NULL);
6245           gencjneshort (left, right, tlbl);
6246           if (IC_TRUE (ifx))
6247             {
6248               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6249               emitcode ("", "!tlabeldef", tlbl->key + 100);
6250             }
6251           else
6252             {
6253               symbol *lbl = newiTempLabel (NULL);
6254               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6255               emitcode ("", "!tlabeldef", tlbl->key + 100);
6256               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6257               emitcode ("", "!tlabeldef", lbl->key + 100);
6258             }
6259         }
6260       /* mark the icode as generated */
6261       ifx->generated = 1;
6262
6263       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6264       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6265       return;
6266     }
6267
6268   /* if they are both bit variables */
6269   if (AOP_TYPE (left) == AOP_CRY &&
6270       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6271     {
6272       if (AOP_TYPE (right) == AOP_LIT)
6273         {
6274           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6275           if (lit == 0L)
6276             {
6277               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278               emitcode ("cpl", "c");
6279             }
6280           else if (lit == 1L)
6281             {
6282               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6283             }
6284           else
6285             {
6286               emitcode ("clr", "c");
6287             }
6288           /* AOP_TYPE(right) == AOP_CRY */
6289         }
6290       else
6291         {
6292           symbol *lbl = newiTempLabel (NULL);
6293           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6294           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6295           emitcode ("cpl", "c");
6296           emitcode ("", "!tlabeldef", (lbl->key + 100));
6297         }
6298
6299       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6301
6302       aopOp (result, ic, TRUE, FALSE);
6303
6304       /* c = 1 if egal */
6305       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6306         {
6307           outBitC (result);
6308           goto release;
6309         }
6310       if (ifx)
6311         {
6312           genIfxJump (ifx, "c");
6313           goto release;
6314         }
6315       /* if the result is used in an arithmetic operation
6316          then put the result in place */
6317       outBitC (result);
6318     }
6319   else
6320     {
6321       gencjne (left, right, newiTempLabel (NULL));
6322
6323       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325
6326       aopOp (result, ic, TRUE, FALSE);
6327
6328       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6329         {
6330           aopPut (AOP (result), "a", 0);
6331           goto release;
6332         }
6333       if (ifx)
6334         {
6335           genIfxJump (ifx, "a");
6336           goto release;
6337         }
6338       /* if the result is used in an arithmetic operation
6339          then put the result in place */
6340       if (AOP_TYPE (result) != AOP_CRY)
6341         outAcc (result);
6342       /* leave the result in acc */
6343     }
6344
6345 release:
6346   freeAsmop (result, NULL, ic, TRUE);
6347 }
6348
6349 /*-----------------------------------------------------------------*/
6350 /* ifxForOp - returns the icode containing the ifx for operand     */
6351 /*-----------------------------------------------------------------*/
6352 static iCode *
6353 ifxForOp (operand * op, iCode * ic)
6354 {
6355   /* if true symbol then needs to be assigned */
6356   if (IS_TRUE_SYMOP (op))
6357     return NULL;
6358
6359   /* if this has register type condition and
6360      the next instruction is ifx with the same operand
6361      and live to of the operand is upto the ifx only then */
6362   if (ic->next &&
6363       ic->next->op == IFX &&
6364       IC_COND (ic->next)->key == op->key &&
6365       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6366     return ic->next;
6367
6368   return NULL;
6369 }
6370 /*-----------------------------------------------------------------*/
6371 /* hasInc - operand is incremented before any other use            */
6372 /*-----------------------------------------------------------------*/
6373 static iCode *
6374 hasInc (operand *op, iCode *ic, int osize)
6375 {
6376   sym_link *type = operandType(op);
6377   sym_link *retype = getSpec (type);
6378   iCode *lic = ic->next;
6379   int isize ;
6380   
6381   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6382   if (!IS_SYMOP(op)) return NULL;
6383
6384   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6385   if (IS_AGGREGATE(type->next)) return NULL;
6386   if (osize != (isize = getSize(type->next))) return NULL;
6387
6388   while (lic) {
6389       /* if operand of the form op = op + <sizeof *op> */
6390       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6391           isOperandEqual(IC_RESULT(lic),op) && 
6392           isOperandLiteral(IC_RIGHT(lic)) &&
6393           operandLitValue(IC_RIGHT(lic)) == isize) {
6394           return lic;
6395       }
6396       /* if the operand used or deffed */
6397       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6398           return NULL;
6399       }
6400       /* if GOTO or IFX */
6401       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6402       lic = lic->next;
6403   }
6404   return NULL;
6405 }
6406
6407 /*-----------------------------------------------------------------*/
6408 /* genAndOp - for && operation                                     */
6409 /*-----------------------------------------------------------------*/
6410 static void
6411 genAndOp (iCode * ic)
6412 {
6413   operand *left, *right, *result;
6414   symbol *tlbl;
6415
6416   D (emitcode (";", "genAndOp "););
6417
6418   /* note here that && operations that are in an
6419      if statement are taken away by backPatchLabels
6420      only those used in arthmetic operations remain */
6421   AOP_OP_2 (ic);
6422   AOP_SET_LOCALS (ic);
6423
6424   /* if both are bit variables */
6425   if (AOP_TYPE (left) == AOP_CRY &&
6426       AOP_TYPE (right) == AOP_CRY)
6427     {
6428       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6429       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6430       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6432   
6433       aopOp (result,ic,FALSE, FALSE);
6434       outBitC (result);
6435     }
6436   else
6437     {
6438       tlbl = newiTempLabel (NULL);
6439       toBoolean (left);
6440       emitcode ("jz", "!tlabel", tlbl->key + 100);
6441       toBoolean (right);
6442       emitcode ("", "!tlabeldef", tlbl->key + 100);
6443       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445   
6446       aopOp (result,ic,FALSE, FALSE);
6447       outBitAcc (result);
6448     }
6449     freeAsmop (result, NULL, ic, TRUE);
6450 }
6451
6452
6453 /*-----------------------------------------------------------------*/
6454 /* genOrOp - for || operation                                      */
6455 /*-----------------------------------------------------------------*/
6456 static void
6457 genOrOp (iCode * ic)
6458 {
6459   operand *left, *right, *result;
6460   symbol *tlbl;
6461
6462   D (emitcode (";", "genOrOp "););
6463
6464   /* note here that || operations that are in an
6465      if statement are taken away by backPatchLabels
6466      only those used in arthmetic operations remain */
6467   AOP_OP_2 (ic);
6468   AOP_SET_LOCALS (ic);
6469
6470   /* if both are bit variables */
6471   if (AOP_TYPE (left) == AOP_CRY &&
6472       AOP_TYPE (right) == AOP_CRY)
6473     {
6474       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6475       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6476       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6478   
6479       aopOp (result,ic,FALSE, FALSE);
6480       
6481       outBitC (result);
6482     }
6483   else
6484     {
6485       tlbl = newiTempLabel (NULL);
6486       toBoolean (left);
6487       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6488       toBoolean (right);
6489       emitcode ("", "!tlabeldef", tlbl->key + 100);
6490       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492   
6493       aopOp (result,ic,FALSE, FALSE);
6494       
6495       outBitAcc (result);
6496     }
6497
6498   freeAsmop (result, NULL, ic, TRUE);
6499 }
6500
6501 /*-----------------------------------------------------------------*/
6502 /* isLiteralBit - test if lit == 2^n                               */
6503 /*-----------------------------------------------------------------*/
6504 static int
6505 isLiteralBit (unsigned long lit)
6506 {
6507   unsigned long pw[32] =
6508   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6509    0x100L, 0x200L, 0x400L, 0x800L,
6510    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6511    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6512    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6513    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6514    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6515   int idx;
6516
6517   for (idx = 0; idx < 32; idx++)
6518     if (lit == pw[idx])
6519       return idx + 1;
6520   return 0;
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* continueIfTrue -                                                */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 continueIfTrue (iCode * ic)
6528 {
6529   if (IC_TRUE (ic))
6530     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6531   ic->generated = 1;
6532 }
6533
6534 /*-----------------------------------------------------------------*/
6535 /* jmpIfTrue -                                                     */
6536 /*-----------------------------------------------------------------*/
6537 static void
6538 jumpIfTrue (iCode * ic)
6539 {
6540   if (!IC_TRUE (ic))
6541     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6542   ic->generated = 1;
6543 }
6544
6545 /*-----------------------------------------------------------------*/
6546 /* jmpTrueOrFalse -                                                */
6547 /*-----------------------------------------------------------------*/
6548 static void
6549 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6550 {
6551   // ugly but optimized by peephole
6552   if (IC_TRUE (ic))
6553     {
6554       symbol *nlbl = newiTempLabel (NULL);
6555       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6556       emitcode ("", "!tlabeldef", tlbl->key + 100);
6557       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6558       emitcode ("", "!tlabeldef", nlbl->key + 100);
6559     }
6560   else
6561     {
6562       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6563       emitcode ("", "!tlabeldef", tlbl->key + 100);
6564     }
6565   ic->generated = 1;
6566 }
6567
6568 // Generate code to perform a bit-wise logic operation
6569 // on two operands in far space (assumed to already have been 
6570 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6571 // in far space. This requires pushing the result on the stack
6572 // then popping it into the result.
6573 static void
6574 genFarFarLogicOp(iCode *ic, char *logicOp)
6575 {
6576       int size, resultSize, compSize;
6577       int offset = 0;
6578       
6579       TR_AP("#5");
6580       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6581       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6582                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6583       
6584       _startLazyDPSEvaluation();
6585       for (size = compSize; (size--); offset++)
6586       {
6587           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6588           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6589           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6590           
6591           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6592           emitcode ("push", "acc");
6593       }
6594       _endLazyDPSEvaluation();
6595      
6596       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6598       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6599      
6600       resultSize = AOP_SIZE(IC_RESULT(ic));
6601
6602       ADJUST_PUSHED_RESULT(compSize, resultSize);
6603
6604       _startLazyDPSEvaluation();
6605       while (compSize--)
6606       {
6607           emitcode ("pop", "acc");
6608           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6609       }
6610       _endLazyDPSEvaluation();
6611       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6612 }
6613
6614
6615 /*-----------------------------------------------------------------*/
6616 /* genAnd  - code for and                                          */
6617 /*-----------------------------------------------------------------*/
6618 static void
6619 genAnd (iCode * ic, iCode * ifx)
6620 {
6621   operand *left, *right, *result;
6622   int size, offset = 0;
6623   unsigned long lit = 0L;
6624   int bytelit;
6625   char buff[10];
6626   bool pushResult;
6627
6628   D (emitcode (";", "genAnd "););
6629
6630   AOP_OP_3_NOFATAL (ic, pushResult);
6631   AOP_SET_LOCALS (ic);
6632
6633   if (pushResult)
6634   {
6635       genFarFarLogicOp(ic, "anl");
6636       return;
6637   }  
6638
6639 #ifdef DEBUG_TYPE
6640   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6641             AOP_TYPE (result),
6642             AOP_TYPE (left), AOP_TYPE (right));
6643   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6644             AOP_SIZE (result),
6645             AOP_SIZE (left), AOP_SIZE (right));
6646 #endif
6647
6648   /* if left is a literal & right is not then exchange them */
6649   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6650 #ifdef LOGIC_OPS_BROKEN      
6651     ||  AOP_NEEDSACC (left)
6652 #endif
6653     )
6654     {
6655       operand *tmp = right;
6656       right = left;
6657       left = tmp;
6658     }
6659
6660   /* if result = right then exchange them */
6661   if (sameRegs (AOP (result), AOP (right)))
6662     {
6663       operand *tmp = right;
6664       right = left;
6665       left = tmp;
6666     }
6667
6668   /* if right is bit then exchange them */
6669   if (AOP_TYPE (right) == AOP_CRY &&
6670       AOP_TYPE (left) != AOP_CRY)
6671     {
6672       operand *tmp = right;
6673       right = left;
6674       left = tmp;
6675     }
6676   if (AOP_TYPE (right) == AOP_LIT)
6677     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6678
6679   size = AOP_SIZE (result);
6680
6681   // if(bit & yy)
6682   // result = bit & yy;
6683   if (AOP_TYPE (left) == AOP_CRY)
6684     {
6685       // c = bit & literal;
6686       if (AOP_TYPE (right) == AOP_LIT)
6687         {
6688           if (lit & 1)
6689             {
6690               if (size && sameRegs (AOP (result), AOP (left)))
6691                 // no change
6692                 goto release;
6693               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6694             }
6695           else
6696             {
6697               // bit(result) = 0;
6698               if (size && (AOP_TYPE (result) == AOP_CRY))
6699                 {
6700                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6701                   goto release;
6702                 }
6703               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6704                 {
6705                   jumpIfTrue (ifx);
6706                   goto release;
6707                 }
6708               emitcode ("clr", "c");
6709             }
6710         }
6711       else
6712         {
6713           if (AOP_TYPE (right) == AOP_CRY)
6714             {
6715               // c = bit & bit;
6716               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6717               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6718             }
6719           else
6720             {
6721               // c = bit & val;
6722               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6723               // c = lsb
6724               emitcode ("rrc", "a");
6725               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6726             }
6727         }
6728       // bit = c
6729       // val = c
6730       if (size)
6731         outBitC (result);
6732       // if(bit & ...)
6733       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6734         genIfxJump (ifx, "c");
6735       goto release;
6736     }
6737
6738   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6739   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6740   if ((AOP_TYPE (right) == AOP_LIT) &&
6741       (AOP_TYPE (result) == AOP_CRY) &&
6742       (AOP_TYPE (left) != AOP_CRY))
6743     {
6744       int posbit = isLiteralBit (lit);
6745       /* left &  2^n */
6746       if (posbit)
6747         {
6748           posbit--;
6749           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6750           // bit = left & 2^n
6751           if (size)
6752             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6753           // if(left &  2^n)
6754           else
6755             {
6756               if (ifx)
6757                 {
6758                   SNPRINTF (buff, sizeof(buff), 
6759                             "acc.%d", posbit & 0x07);
6760                   genIfxJump (ifx, buff);
6761                 }
6762               else 
6763                   {
6764                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6765                   }
6766               goto release;
6767             }
6768         }
6769       else
6770         {
6771           symbol *tlbl = newiTempLabel (NULL);
6772           int sizel = AOP_SIZE (left);
6773           if (size)
6774             emitcode ("setb", "c");
6775           while (sizel--)
6776             {
6777               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6778                 {
6779                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6780                   // byte ==  2^n ?
6781                   if ((posbit = isLiteralBit (bytelit)) != 0)
6782                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6783                   else
6784                     {
6785                       if (bytelit != 0x0FFL)
6786                         emitcode ("anl", "a,%s",
6787                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6788                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6789                     }
6790                 }
6791               offset++;
6792             }
6793           // bit = left & literal
6794           if (size)
6795             {
6796               emitcode ("clr", "c");
6797               emitcode ("", "!tlabeldef", tlbl->key + 100);
6798             }
6799           // if(left & literal)
6800           else
6801             {
6802               if (ifx)
6803                 jmpTrueOrFalse (ifx, tlbl);
6804               else
6805                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6806               goto release;
6807             }
6808         }
6809       outBitC (result);
6810       goto release;
6811     }
6812
6813   /* if left is same as result */
6814   if (sameRegs (AOP (result), AOP (left)))
6815     {
6816       for (; size--; offset++)
6817         {
6818           if (AOP_TYPE (right) == AOP_LIT)
6819             {
6820               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6821                 continue;
6822               else if (bytelit == 0)
6823                 aopPut (AOP (result), zero, offset);
6824               else if (IS_AOP_PREG (result))
6825                 {
6826                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6827                   emitcode ("anl", "a,%s",
6828                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6829                   aopPut (AOP (result), "a", offset);
6830                 }
6831               else
6832                 emitcode ("anl", "%s,%s",
6833                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6834                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6835             }
6836           else
6837             {
6838               if (AOP_TYPE (left) == AOP_ACC)
6839                 emitcode ("anl", "a,%s",
6840                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6841               else
6842                 {
6843                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6844                   if (IS_AOP_PREG (result))
6845                     {
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,a",
6852                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6853                 }
6854             }
6855         }
6856     }
6857   else
6858     {
6859       // left & result in different registers
6860       if (AOP_TYPE (result) == AOP_CRY)
6861         {
6862           // result = bit
6863           // if(size), result in bit
6864           // if(!size && ifx), conditional oper: if(left & right)
6865           symbol *tlbl = newiTempLabel (NULL);
6866           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6867           if (size)
6868             emitcode ("setb", "c");
6869           while (sizer--)
6870             {
6871               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6872                 emitcode ("anl", "a,%s",
6873                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6874               } else {
6875                 if (AOP_TYPE(left)==AOP_ACC) {
6876                   emitcode("mov", "b,a");
6877                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6878                   emitcode("anl", "a,b");
6879                 }else {
6880                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6881                   emitcode ("anl", "a,%s",
6882                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6883                 }
6884               }
6885               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6886               offset++;
6887             }
6888           if (size)
6889             {
6890               CLRC;
6891               emitcode ("", "!tlabeldef", tlbl->key + 100);
6892               outBitC (result);
6893             }
6894           else if (ifx)
6895             jmpTrueOrFalse (ifx, tlbl);
6896           else
6897             emitcode ("", "!tlabeldef", tlbl->key + 100);
6898         }
6899       else
6900         {
6901           for (; (size--); offset++)
6902             {
6903               // normal case
6904               // result = left & right
6905               if (AOP_TYPE (right) == AOP_LIT)
6906                 {
6907                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6908                     {
6909                       aopPut (AOP (result),
6910                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6911                               offset);
6912                       continue;
6913                     }
6914                   else if (bytelit == 0)
6915                     {
6916                       aopPut (AOP (result), zero, offset);
6917                       continue;
6918                     }
6919                   D (emitcode (";", "better literal AND."););
6920                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6921                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6922                                                     FALSE, FALSE, DP2_RESULT_REG));
6923
6924                 }
6925               else
6926                 {
6927                   // faster than result <- left, anl result,right
6928                   // and better if result is SFR
6929                   if (AOP_TYPE (left) == AOP_ACC)
6930                     {
6931                       emitcode ("anl", "a,%s", 
6932                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6933                     }
6934                   else
6935                     {
6936                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6937                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6938                       {
6939                           emitcode("mov", "b,a");
6940                           rOp = "b";
6941                       }
6942                         
6943                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6944                       emitcode ("anl", "a,%s", rOp);
6945                     }                   
6946                 }
6947               aopPut (AOP (result), "a", offset);
6948             }
6949         }
6950     }
6951
6952 release:
6953   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6955   freeAsmop (result, NULL, ic, TRUE);
6956 }
6957
6958
6959 /*-----------------------------------------------------------------*/
6960 /* genOr  - code for or                                            */
6961 /*-----------------------------------------------------------------*/
6962 static void
6963 genOr (iCode * ic, iCode * ifx)
6964 {
6965   operand *left, *right, *result;
6966   int size, offset = 0;
6967   unsigned long lit = 0L;
6968   bool     pushResult;
6969
6970   D (emitcode (";", "genOr "););
6971
6972   AOP_OP_3_NOFATAL (ic, pushResult);
6973   AOP_SET_LOCALS (ic);
6974
6975   if (pushResult)
6976   {
6977       genFarFarLogicOp(ic, "orl");
6978       return;
6979   }
6980
6981
6982 #ifdef DEBUG_TYPE
6983   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6984             AOP_TYPE (result),
6985             AOP_TYPE (left), AOP_TYPE (right));
6986   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6987             AOP_SIZE (result),
6988             AOP_SIZE (left), AOP_SIZE (right));
6989 #endif
6990
6991   /* if left is a literal & right is not then exchange them */
6992   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6993 #ifdef LOGIC_OPS_BROKEN
6994    || AOP_NEEDSACC (left) // I think this is a net loss now.
6995 #endif      
6996       )
6997     {
6998       operand *tmp = right;
6999       right = left;
7000       left = tmp;
7001     }
7002
7003   /* if result = right then exchange them */
7004   if (sameRegs (AOP (result), AOP (right)))
7005     {
7006       operand *tmp = right;
7007       right = left;
7008       left = tmp;
7009     }
7010
7011   /* if right is bit then exchange them */
7012   if (AOP_TYPE (right) == AOP_CRY &&
7013       AOP_TYPE (left) != AOP_CRY)
7014     {
7015       operand *tmp = right;
7016       right = left;
7017       left = tmp;
7018     }
7019   if (AOP_TYPE (right) == AOP_LIT)
7020     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7021
7022   size = AOP_SIZE (result);
7023
7024   // if(bit | yy)
7025   // xx = bit | yy;
7026   if (AOP_TYPE (left) == AOP_CRY)
7027     {
7028       if (AOP_TYPE (right) == AOP_LIT)
7029         {
7030           // c = bit & literal;
7031           if (lit)
7032             {
7033               // lit != 0 => result = 1
7034               if (AOP_TYPE (result) == AOP_CRY)
7035                 {
7036                   if (size)
7037                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7038                   else if (ifx)
7039                     continueIfTrue (ifx);
7040                   goto release;
7041                 }
7042               emitcode ("setb", "c");
7043             }
7044           else
7045             {
7046               // lit == 0 => result = left
7047               if (size && sameRegs (AOP (result), AOP (left)))
7048                 goto release;
7049               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7050             }
7051         }
7052       else
7053         {
7054           if (AOP_TYPE (right) == AOP_CRY)
7055             {
7056               // c = bit | bit;
7057               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7058               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7059             }
7060           else
7061             {
7062               // c = bit | val;
7063               symbol *tlbl = newiTempLabel (NULL);
7064               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7065                 emitcode ("setb", "c");
7066               emitcode ("jb", "%s,!tlabel",
7067                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7068               toBoolean (right);
7069               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7070               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7071                 {
7072                   jmpTrueOrFalse (ifx, tlbl);
7073                   goto release;
7074                 }
7075               else
7076                 {
7077                   CLRC;
7078                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7079                 }
7080             }
7081         }
7082       // bit = c
7083       // val = c
7084       if (size)
7085         outBitC (result);
7086       // if(bit | ...)
7087       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7088            genIfxJump (ifx, "c");
7089       goto release;
7090     }
7091
7092   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7093   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7094   if ((AOP_TYPE (right) == AOP_LIT) &&
7095       (AOP_TYPE (result) == AOP_CRY) &&
7096       (AOP_TYPE (left) != AOP_CRY))
7097     {
7098       if (lit)
7099         {
7100           // result = 1
7101           if (size)
7102             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7103           else
7104             continueIfTrue (ifx);
7105           goto release;
7106         }
7107       else
7108         {
7109           // lit = 0, result = boolean(left)
7110           if (size)
7111             emitcode ("setb", "c");
7112           toBoolean (right);
7113           if (size)
7114             {
7115               symbol *tlbl = newiTempLabel (NULL);
7116               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7117               CLRC;
7118               emitcode ("", "!tlabeldef", tlbl->key + 100);
7119             }
7120           else
7121             {
7122               genIfxJump (ifx, "a");
7123               goto release;
7124             }
7125         }
7126       outBitC (result);
7127       goto release;
7128     }
7129
7130   /* if left is same as result */
7131   if (sameRegs (AOP (result), AOP (left)))
7132     {
7133       for (; size--; offset++)
7134         {
7135           if (AOP_TYPE (right) == AOP_LIT)
7136             {
7137               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7138                 {
7139                   continue;
7140                 }
7141               else
7142                 {
7143                   if (IS_AOP_PREG (left))
7144                     {
7145                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7146                       emitcode ("orl", "a,%s",
7147                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7148                       aopPut (AOP (result), "a", offset);
7149                     }
7150                   else
7151                     {
7152                       emitcode ("orl", "%s,%s",
7153                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7154                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7155                     }
7156                 }
7157             }
7158           else
7159             {
7160               if (AOP_TYPE (left) == AOP_ACC)
7161                 {
7162                   emitcode ("orl", "a,%s",
7163                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7164                 }
7165               else
7166                 {
7167                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7168                   if (IS_AOP_PREG (left))
7169                     {
7170                       emitcode ("orl", "a,%s", 
7171                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7172                       aopPut (AOP (result), "a", offset);
7173                     }
7174                   else
7175                     {
7176                       emitcode ("orl", "%s,a",
7177                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7178                     }
7179                 }
7180             }
7181         }
7182     }
7183   else
7184     {
7185       // left & result in different registers
7186       if (AOP_TYPE (result) == AOP_CRY)
7187         {
7188           // result = bit
7189           // if(size), result in bit
7190           // if(!size && ifx), conditional oper: if(left | right)
7191           symbol *tlbl = newiTempLabel (NULL);
7192           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7193           if (size)
7194             emitcode ("setb", "c");
7195           while (sizer--)
7196             {
7197               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7198                 emitcode ("orl", "a,%s",
7199                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7200               } else {
7201                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7202                 emitcode ("orl", "a,%s",
7203                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7204               }
7205               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7206               offset++;
7207             }
7208           if (size)
7209             {
7210               CLRC;
7211               emitcode ("", "!tlabeldef", tlbl->key + 100);
7212               outBitC (result);
7213             }
7214           else if (ifx)
7215             jmpTrueOrFalse (ifx, tlbl);
7216           else
7217             emitcode ("", "!tlabeldef", tlbl->key + 100);
7218         }
7219       else
7220         {
7221             _startLazyDPSEvaluation();
7222           for (; (size--); offset++)
7223             {
7224               // normal case
7225               // result = left & right
7226               if (AOP_TYPE (right) == AOP_LIT)
7227                 {
7228                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7229                     {
7230                       aopPut (AOP (result),
7231                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7232                               offset);
7233                       continue;
7234                     }
7235                   D (emitcode (";", "better literal OR."););
7236                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7237                   emitcode ("orl", "a, %s",
7238                             aopGet (AOP (right), offset,
7239                                     FALSE, FALSE, DP2_RESULT_REG));
7240
7241                 }
7242               else
7243                 {
7244                   // faster than result <- left, anl result,right
7245                   // and better if result is SFR
7246                   if (AOP_TYPE (left) == AOP_ACC)
7247                     {
7248                       emitcode ("orl", "a,%s",
7249                                 aopGet (AOP (right), offset,
7250                                         FALSE, FALSE, DP2_RESULT_REG));
7251                     }
7252                   else
7253                     {
7254                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7255                         
7256                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7257                       {
7258                           emitcode("mov", "b,a");
7259                           rOp = "b";
7260                       }
7261                         
7262                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7263                       emitcode ("orl", "a,%s", rOp);
7264                     }
7265                 }
7266               aopPut (AOP (result), "a", offset);
7267             }
7268             _endLazyDPSEvaluation();
7269         }
7270     }
7271
7272 release:
7273   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7274   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7275   freeAsmop (result, NULL, ic, TRUE);
7276 }
7277
7278 /*-----------------------------------------------------------------*/
7279 /* genXor - code for xclusive or                                   */
7280 /*-----------------------------------------------------------------*/
7281 static void
7282 genXor (iCode * ic, iCode * ifx)
7283 {
7284   operand *left, *right, *result;
7285   int size, offset = 0;
7286   unsigned long lit = 0L;
7287   bool pushResult;
7288
7289   D (emitcode (";", "genXor "););
7290
7291   AOP_OP_3_NOFATAL (ic, pushResult);
7292   AOP_SET_LOCALS (ic);
7293
7294   if (pushResult)
7295   {
7296       genFarFarLogicOp(ic, "xrl");
7297       return;
7298   }  
7299
7300 #ifdef DEBUG_TYPE
7301   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7302             AOP_TYPE (result),
7303             AOP_TYPE (left), AOP_TYPE (right));
7304   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7305             AOP_SIZE (result),
7306             AOP_SIZE (left), AOP_SIZE (right));
7307 #endif
7308
7309   /* if left is a literal & right is not ||
7310      if left needs acc & right does not */
7311   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
7312 #ifdef LOGIC_OPS_BROKEN      
7313       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7314 #endif
7315      )
7316     {
7317       operand *tmp = right;
7318       right = left;
7319       left = tmp;
7320     }
7321
7322   /* if result = right then exchange them */
7323   if (sameRegs (AOP (result), AOP (right)))
7324     {
7325       operand *tmp = right;
7326       right = left;
7327       left = tmp;
7328     }
7329
7330   /* if right is bit then exchange them */
7331   if (AOP_TYPE (right) == AOP_CRY &&
7332       AOP_TYPE (left) != AOP_CRY)
7333     {
7334       operand *tmp = right;
7335       right = left;
7336       left = tmp;
7337     }
7338   if (AOP_TYPE (right) == AOP_LIT)
7339     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7340
7341   size = AOP_SIZE (result);
7342
7343   // if(bit ^ yy)
7344   // xx = bit ^ yy;
7345   if (AOP_TYPE (left) == AOP_CRY)
7346     {
7347       if (AOP_TYPE (right) == AOP_LIT)
7348         {
7349           // c = bit & literal;
7350           if (lit >> 1)
7351             {
7352               // lit>>1  != 0 => result = 1
7353               if (AOP_TYPE (result) == AOP_CRY)
7354                 {
7355                   if (size)
7356                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7357                   else if (ifx)
7358                     continueIfTrue (ifx);
7359                   goto release;
7360                 }
7361               emitcode ("setb", "c");
7362             }
7363           else
7364             {
7365               // lit == (0 or 1)
7366               if (lit == 0)
7367                 {
7368                   // lit == 0, result = left
7369                   if (size && sameRegs (AOP (result), AOP (left)))
7370                     goto release;
7371                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7372                 }
7373               else
7374                 {
7375                   // lit == 1, result = not(left)
7376                   if (size && sameRegs (AOP (result), AOP (left)))
7377                     {
7378                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7379                       goto release;
7380                     }
7381                   else
7382                     {
7383                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7384                       emitcode ("cpl", "c");
7385                     }
7386                 }
7387             }
7388
7389         }
7390       else
7391         {
7392           // right != literal
7393           symbol *tlbl = newiTempLabel (NULL);
7394           if (AOP_TYPE (right) == AOP_CRY)
7395             {
7396               // c = bit ^ bit;
7397               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7398             }
7399           else
7400             {
7401               int sizer = AOP_SIZE (right);
7402               // c = bit ^ val
7403               // if val>>1 != 0, result = 1
7404               emitcode ("setb", "c");
7405               while (sizer)
7406                 {
7407                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7408                   if (sizer == 1)
7409                     // test the msb of the lsb
7410                     emitcode ("anl", "a,#!constbyte",0xfe);
7411                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7412                   sizer--;
7413                 }
7414               // val = (0,1)
7415               emitcode ("rrc", "a");
7416             }
7417           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7418           emitcode ("cpl", "c");
7419           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7420         }
7421       // bit = c
7422       // val = c
7423       if (size)
7424         outBitC (result);
7425       // if(bit | ...)
7426       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7427         genIfxJump (ifx, "c");
7428       goto release;
7429     }
7430
7431   if (sameRegs (AOP (result), AOP (left)))
7432     {
7433       /* if left is same as result */
7434       for (; size--; offset++)
7435         {
7436           if (AOP_TYPE (right) == AOP_LIT)
7437             {
7438               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7439                 continue;
7440               else if (IS_AOP_PREG (left))
7441                 {
7442                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7443                   emitcode ("xrl", "a,%s",
7444                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7445                   aopPut (AOP (result), "a", offset);
7446                 }
7447               else
7448                 emitcode ("xrl", "%s,%s",
7449                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7450                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7451             }
7452           else
7453             {
7454               if (AOP_TYPE (left) == AOP_ACC)
7455                 emitcode ("xrl", "a,%s",
7456                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7457               else
7458                 {
7459                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7460                   if (IS_AOP_PREG (left))
7461                     {
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,a",
7468                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7469                 }
7470             }
7471         }
7472     }
7473   else
7474     {
7475       // left & result in different registers
7476       if (AOP_TYPE (result) == AOP_CRY)
7477         {
7478           // result = bit
7479           // if(size), result in bit
7480           // if(!size && ifx), conditional oper: if(left ^ right)
7481           symbol *tlbl = newiTempLabel (NULL);
7482           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7483                   
7484           if (size)
7485             emitcode ("setb", "c");
7486           while (sizer--)
7487             {
7488               if ((AOP_TYPE (right) == AOP_LIT) &&
7489                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7490                 {
7491                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7492                 }
7493               else
7494                 {
7495                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7496                     emitcode ("xrl", "a,%s",
7497                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7498                   } else {
7499                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7500                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7501                       {
7502                           emitcode("mov", "b,a");
7503                           rOp = "b";
7504                       }
7505                         
7506                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7507                       emitcode ("xrl", "a,%s", rOp);                  
7508                   }
7509                 }
7510               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7511               offset++;
7512             }
7513           if (size)
7514             {
7515               CLRC;
7516               emitcode ("", "!tlabeldef", tlbl->key + 100);
7517               outBitC (result);
7518             }
7519           else if (ifx)
7520             jmpTrueOrFalse (ifx, tlbl);
7521         }
7522       else
7523         {
7524         for (; (size--); offset++)
7525           {
7526             // normal case
7527             // result = left & right
7528             if (AOP_TYPE (right) == AOP_LIT)
7529               {
7530                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7531                   {
7532                     aopPut (AOP (result),
7533                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7534                             offset);
7535                     continue;
7536                   }
7537                 D (emitcode (";", "better literal XOR."););
7538                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7539                 emitcode ("xrl", "a, %s",
7540                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7541               }
7542             else
7543               {
7544                 // faster than result <- left, anl result,right
7545                 // and better if result is SFR
7546                 if (AOP_TYPE (left) == AOP_ACC)
7547                   {
7548                     emitcode ("xrl", "a,%s",
7549                               aopGet (AOP (right), offset,
7550                                       FALSE, FALSE, DP2_RESULT_REG));
7551                   }
7552                 else
7553                   {
7554                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7555                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7556                       {
7557                           emitcode("mov", "b,a");
7558                           rOp = "b";
7559                       }
7560                         
7561                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7562                       emitcode ("xrl", "a,%s", rOp);
7563                   }
7564               }
7565             aopPut (AOP (result), "a", offset);
7566           }
7567         }
7568         
7569     }
7570
7571 release:
7572   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7573   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7574   freeAsmop (result, NULL, ic, TRUE);
7575 }
7576
7577 /*-----------------------------------------------------------------*/
7578 /* genInline - write the inline code out                           */
7579 /*-----------------------------------------------------------------*/
7580 static void
7581 genInline (iCode * ic)
7582 {
7583   char *buffer, *bp, *bp1;
7584
7585   D (emitcode (";", "genInline "); );
7586
7587   _G.inLine += (!options.asmpeep);
7588
7589   buffer = Safe_strdup(IC_INLINE(ic));
7590   bp = buffer;
7591   bp1 = buffer;
7592
7593   /* emit each line as a code */
7594   while (*bp)
7595     {
7596       if (*bp == '\n')
7597         {
7598           *bp++ = '\0';
7599           emitcode (bp1, "");
7600           bp1 = bp;
7601         }
7602       else
7603         {
7604           if (*bp == ':')
7605             {
7606               bp++;
7607               *bp = '\0';
7608               bp++;
7609               emitcode (bp1, "");
7610               bp1 = bp;
7611             }
7612           else
7613             bp++;
7614         }
7615     }
7616   if (bp1 != bp)
7617     emitcode (bp1, "");
7618   /*     emitcode("",buffer); */
7619   _G.inLine -= (!options.asmpeep);
7620 }
7621
7622 /*-----------------------------------------------------------------*/
7623 /* genRRC - rotate right with carry                                */
7624 /*-----------------------------------------------------------------*/
7625 static void
7626 genRRC (iCode * ic)
7627 {
7628   operand *left, *result;
7629   int     size, offset;
7630
7631   D (emitcode (";", "genRRC "););
7632
7633   /* rotate right with carry */
7634   left = IC_LEFT (ic);
7635   result = IC_RESULT (ic);
7636   aopOp (left, ic, FALSE, FALSE);
7637   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7638
7639   /* move it to the result */
7640   size = AOP_SIZE (result);
7641   offset = size - 1;
7642   CLRC;
7643
7644   _startLazyDPSEvaluation ();
7645   while (size--)
7646     {
7647       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7648       emitcode ("rrc", "a");
7649       if (AOP_SIZE (result) > 1)
7650         aopPut (AOP (result), "a", offset--);
7651     }
7652   _endLazyDPSEvaluation ();
7653
7654   /* now we need to put the carry into the
7655      highest order byte of the result */
7656   if (AOP_SIZE (result) > 1)
7657     {
7658       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7659     }
7660   emitcode ("mov", "acc.7,c");
7661   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7662   freeAsmop (left, NULL, ic, TRUE);
7663   freeAsmop (result, NULL, ic, TRUE);
7664 }
7665
7666 /*-----------------------------------------------------------------*/
7667 /* genRLC - generate code for rotate left with carry               */
7668 /*-----------------------------------------------------------------*/
7669 static void
7670 genRLC (iCode * ic)
7671 {
7672   operand *left, *result;
7673   int size, offset;
7674   char *l;
7675
7676   D (emitcode (";", "genRLC "););
7677
7678   /* rotate right with carry */
7679   left = IC_LEFT (ic);
7680   result = IC_RESULT (ic);
7681   aopOp (left, ic, FALSE, FALSE);
7682   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7683
7684   /* move it to the result */
7685   size = AOP_SIZE (result);
7686   offset = 0;
7687   if (size--)
7688     {
7689       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7690       MOVA (l);
7691       emitcode ("add", "a,acc");
7692       if (AOP_SIZE (result) > 1)
7693         {
7694           aopPut (AOP (result), "a", offset++);
7695         }
7696
7697       _startLazyDPSEvaluation ();
7698       while (size--)
7699         {
7700           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7701           MOVA (l);
7702           emitcode ("rlc", "a");
7703           if (AOP_SIZE (result) > 1)
7704             aopPut (AOP (result), "a", offset++);
7705         }
7706       _endLazyDPSEvaluation ();
7707     }
7708   /* now we need to put the carry into the
7709      highest order byte of the result */
7710   if (AOP_SIZE (result) > 1)
7711     {
7712       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7713       MOVA (l);
7714     }
7715   emitcode ("mov", "acc.0,c");
7716   aopPut (AOP (result), "a", 0);
7717   freeAsmop (left, NULL, ic, TRUE);
7718   freeAsmop (result, NULL, ic, TRUE);
7719 }
7720
7721 /*-----------------------------------------------------------------*/
7722 /* genGetHbit - generates code get highest order bit               */
7723 /*-----------------------------------------------------------------*/
7724 static void
7725 genGetHbit (iCode * ic)
7726 {
7727   operand *left, *result;
7728   left = IC_LEFT (ic);
7729   result = IC_RESULT (ic);
7730   aopOp (left, ic, FALSE, FALSE);
7731   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7732
7733   D (emitcode (";", "genGetHbit "););
7734
7735   /* get the highest order byte into a */
7736   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7737   if (AOP_TYPE (result) == AOP_CRY)
7738     {
7739       emitcode ("rlc", "a");
7740       outBitC (result);
7741     }
7742   else
7743     {
7744       emitcode ("rl", "a");
7745       emitcode ("anl", "a,#1");
7746       outAcc (result);
7747     }
7748
7749
7750   freeAsmop (left, NULL, ic, TRUE);
7751   freeAsmop (result, NULL, ic, TRUE);
7752 }
7753
7754 /*-----------------------------------------------------------------*/
7755 /* genSwap - generates code to swap nibbles or bytes               */
7756 /*-----------------------------------------------------------------*/
7757 static void
7758 genSwap (iCode * ic)
7759 {
7760   operand *left, *result;
7761
7762   D(emitcode (";     genSwap",""));
7763
7764   left = IC_LEFT (ic);
7765   result = IC_RESULT (ic);
7766   aopOp (left, ic, FALSE, FALSE);
7767   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7768   
7769   _startLazyDPSEvaluation ();
7770   switch (AOP_SIZE (left))
7771     {
7772     case 1: /* swap nibbles in byte */
7773       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7774       emitcode ("swap", "a");
7775       aopPut (AOP (result), "a", 0);
7776       break;
7777     case 2: /* swap bytes in word */
7778       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7779         {
7780           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7781           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7782           aopPut (AOP (result), "a", 1);
7783         }
7784       else if (operandsEqu (left, result))
7785         {
7786           char * reg = "a";
7787           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7788           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7789             {
7790               emitcode ("mov", "b,a");
7791               reg = "b";
7792               _G.bInUse=1;
7793             }
7794           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7795           aopPut (AOP (result), reg, 1);
7796           _G.bInUse=0;
7797         }
7798       else
7799         {
7800           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7801           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7802         }
7803       break;
7804     default:
7805       wassertl(FALSE, "unsupported SWAP operand size");
7806     }
7807   _endLazyDPSEvaluation ();
7808   
7809   freeAsmop (left, NULL, ic, TRUE);
7810   freeAsmop (result, NULL, ic, TRUE);
7811 }
7812
7813 /*-----------------------------------------------------------------*/
7814 /* AccRol - rotate left accumulator by known count                 */
7815 /*-----------------------------------------------------------------*/
7816 static void
7817 AccRol (int shCount)
7818 {
7819   shCount &= 0x0007;            // shCount : 0..7
7820
7821   switch (shCount)
7822     {
7823     case 0:
7824       break;
7825     case 1:
7826       emitcode ("rl", "a");
7827       break;
7828     case 2:
7829       emitcode ("rl", "a");
7830       emitcode ("rl", "a");
7831       break;
7832     case 3:
7833       emitcode ("swap", "a");
7834       emitcode ("rr", "a");
7835       break;
7836     case 4:
7837       emitcode ("swap", "a");
7838       break;
7839     case 5:
7840       emitcode ("swap", "a");
7841       emitcode ("rl", "a");
7842       break;
7843     case 6:
7844       emitcode ("rr", "a");
7845       emitcode ("rr", "a");
7846       break;
7847     case 7:
7848       emitcode ("rr", "a");
7849       break;
7850     }
7851 }
7852
7853 /*-----------------------------------------------------------------*/
7854 /* AccLsh - left shift accumulator by known count                  */
7855 /*-----------------------------------------------------------------*/
7856 static void
7857 AccLsh (int shCount)
7858 {
7859   if (shCount != 0)
7860     {
7861       if (shCount == 1)
7862         emitcode ("add", "a,acc");
7863       else if (shCount == 2)
7864         {
7865           emitcode ("add", "a,acc");
7866           emitcode ("add", "a,acc");
7867         }
7868       else
7869         {
7870           /* rotate left accumulator */
7871           AccRol (shCount);
7872           /* and kill the lower order bits */
7873           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7874         }
7875     }
7876 }
7877
7878 /*-----------------------------------------------------------------*/
7879 /* AccRsh - right shift accumulator by known count                 */
7880 /*-----------------------------------------------------------------*/
7881 static void
7882 AccRsh (int shCount)
7883 {
7884   if (shCount != 0)
7885     {
7886       if (shCount == 1)
7887         {
7888           CLRC;
7889           emitcode ("rrc", "a");
7890         }
7891       else
7892         {
7893           /* rotate right accumulator */
7894           AccRol (8 - shCount);
7895           /* and kill the higher order bits */
7896           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7897         }
7898     }
7899 }
7900
7901 #ifdef BETTER_LITERAL_SHIFT
7902 /*-----------------------------------------------------------------*/
7903 /* AccSRsh - signed right shift accumulator by known count                 */
7904 /*-----------------------------------------------------------------*/
7905 static void
7906 AccSRsh (int shCount)
7907 {
7908   symbol *tlbl;
7909   if (shCount != 0)
7910     {
7911       if (shCount == 1)
7912         {
7913           emitcode ("mov", "c,acc.7");
7914           emitcode ("rrc", "a");
7915         }
7916       else if (shCount == 2)
7917         {
7918           emitcode ("mov", "c,acc.7");
7919           emitcode ("rrc", "a");
7920           emitcode ("mov", "c,acc.7");
7921           emitcode ("rrc", "a");
7922         }
7923       else
7924         {
7925           tlbl = newiTempLabel (NULL);
7926           /* rotate right accumulator */
7927           AccRol (8 - shCount);
7928           /* and kill the higher order bits */
7929           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7930           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7931           emitcode ("orl", "a,#!constbyte",
7932                     (unsigned char) ~SRMask[shCount]);
7933           emitcode ("", "!tlabeldef", tlbl->key + 100);
7934         }
7935     }
7936 }
7937 #endif
7938
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* shiftR1Left2Result - shift right one byte from left to result   */
7942 /*-----------------------------------------------------------------*/
7943 static void
7944 shiftR1Left2Result (operand * left, int offl,
7945                     operand * result, int offr,
7946                     int shCount, int sign)
7947 {
7948   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7949   /* shift right accumulator */
7950   if (sign)
7951     AccSRsh (shCount);
7952   else
7953     AccRsh (shCount);
7954   aopPut (AOP (result), "a", offr);
7955 }
7956 #endif
7957
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* shiftL1Left2Result - shift left one byte from left to result    */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 shiftL1Left2Result (operand * left, int offl,
7964                     operand * result, int offr, int shCount)
7965 {
7966   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7967   /* shift left accumulator */
7968   AccLsh (shCount);
7969   aopPut (AOP (result), "a", offr);
7970 }
7971 #endif
7972
7973 #ifdef BETTER_LITERAL_SHIFT
7974 /*-----------------------------------------------------------------*/
7975 /* movLeft2Result - move byte from left to result                  */
7976 /*-----------------------------------------------------------------*/
7977 static void
7978 movLeft2Result (operand * left, int offl,
7979                 operand * result, int offr, int sign)
7980 {
7981   char *l;
7982   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7983   {
7984       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7985
7986       if (*l == '@' && (IS_AOP_PREG (result)))
7987       {
7988           emitcode ("mov", "a,%s", l);
7989           aopPut (AOP (result), "a", offr);
7990       }
7991       else
7992       {
7993           if (!sign)
7994           {
7995             aopPut (AOP (result), l, offr);
7996           }
7997           else
7998             {
7999               /* MSB sign in acc.7 ! */
8000               if (getDataSize (left) == offl + 1)
8001                 {
8002                   emitcode ("mov", "a,%s", l);
8003                   aopPut (AOP (result), "a", offr);
8004                 }
8005             }
8006       }
8007   }
8008 }
8009 #endif
8010
8011 #ifdef BETTER_LITERAL_SHIFT
8012 /*-----------------------------------------------------------------*/
8013 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8014 /*-----------------------------------------------------------------*/
8015 static void
8016 AccAXRrl1 (char *x)
8017 {
8018   emitcode ("rrc", "a");
8019   emitcode ("xch", "a,%s", x);
8020   emitcode ("rrc", "a");
8021   emitcode ("xch", "a,%s", x);
8022 }
8023 #endif
8024
8025 #ifdef BETTER_LITERAL_SHIFT
8026 //REMOVE ME!!!
8027 /*-----------------------------------------------------------------*/
8028 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8029 /*-----------------------------------------------------------------*/
8030 static void
8031 AccAXLrl1 (char *x)
8032 {
8033   emitcode ("xch", "a,%s", x);
8034   emitcode ("rlc", "a");
8035   emitcode ("xch", "a,%s", x);
8036   emitcode ("rlc", "a");
8037 }
8038 #endif
8039
8040 #ifdef BETTER_LITERAL_SHIFT
8041 /*-----------------------------------------------------------------*/
8042 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 AccAXLsh1 (char *x)
8046 {
8047   emitcode ("xch", "a,%s", x);
8048   emitcode ("add", "a,acc");
8049   emitcode ("xch", "a,%s", x);
8050   emitcode ("rlc", "a");
8051 }
8052 #endif
8053
8054 #ifdef BETTER_LITERAL_SHIFT
8055 /*-----------------------------------------------------------------*/
8056 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8057 /*-----------------------------------------------------------------*/
8058 static void
8059 AccAXLsh (char *x, int shCount)
8060 {
8061   switch (shCount)
8062     {
8063     case 0:
8064       break;
8065     case 1:
8066       AccAXLsh1 (x);
8067       break;
8068     case 2:
8069       AccAXLsh1 (x);
8070       AccAXLsh1 (x);
8071       break;
8072     case 3:
8073     case 4:
8074     case 5:                     // AAAAABBB:CCCCCDDD
8075
8076       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8077
8078       emitcode ("anl", "a,#!constbyte",
8079                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8080
8081       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8082
8083       AccRol (shCount);         // DDDCCCCC:BBB00000
8084
8085       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8086
8087       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8088
8089       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8090
8091       emitcode ("anl", "a,#!constbyte",
8092                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8093
8094       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8095
8096       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8097
8098       break;
8099     case 6:                     // AAAAAABB:CCCCCCDD
8100       emitcode ("anl", "a,#!constbyte",
8101                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8102       emitcode ("mov", "c,acc.0");      // c = B
8103       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8104 #if 0
8105       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8106       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8107 #else
8108       emitcode("rrc","a"); 
8109       emitcode("xch","a,%s", x); 
8110       emitcode("rrc","a"); 
8111       emitcode("mov","c,acc.0"); //<< get correct bit 
8112       emitcode("xch","a,%s", x); 
8113
8114       emitcode("rrc","a"); 
8115       emitcode("xch","a,%s", x); 
8116       emitcode("rrc","a"); 
8117       emitcode("xch","a,%s", x); 
8118 #endif
8119       break;
8120     case 7:                     // a:x <<= 7
8121
8122       emitcode ("anl", "a,#!constbyte",
8123                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8124
8125       emitcode ("mov", "c,acc.0");      // c = B
8126
8127       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8128
8129       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8130
8131       break;
8132     default:
8133       break;
8134     }
8135 }
8136 #endif
8137
8138 #ifdef BETTER_LITERAL_SHIFT
8139 //REMOVE ME!!!
8140 /*-----------------------------------------------------------------*/
8141 /* AccAXRsh - right shift a:x known count (0..7)                   */
8142 /*-----------------------------------------------------------------*/
8143 static void
8144 AccAXRsh (char *x, int shCount)
8145 {
8146   switch (shCount)
8147     {
8148     case 0:
8149       break;
8150     case 1:
8151       CLRC;
8152       AccAXRrl1 (x);            // 0->a:x
8153
8154       break;
8155     case 2:
8156       CLRC;
8157       AccAXRrl1 (x);            // 0->a:x
8158
8159       CLRC;
8160       AccAXRrl1 (x);            // 0->a:x
8161
8162       break;
8163     case 3:
8164     case 4:
8165     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8166
8167       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8168
8169       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8170
8171       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8172
8173       emitcode ("anl", "a,#!constbyte",
8174                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8175
8176       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8177
8178       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8179
8180       emitcode ("anl", "a,#!constbyte",
8181                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8182
8183       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8184
8185       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8186
8187       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8188
8189       break;
8190     case 6:                     // AABBBBBB:CCDDDDDD
8191
8192       emitcode ("mov", "c,acc.7");
8193       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8194
8195       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8196
8197       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8198
8199       emitcode ("anl", "a,#!constbyte",
8200                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8201
8202       break;
8203     case 7:                     // ABBBBBBB:CDDDDDDD
8204
8205       emitcode ("mov", "c,acc.7");      // c = A
8206
8207       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8208
8209       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8210
8211       emitcode ("anl", "a,#!constbyte",
8212                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8213
8214       break;
8215     default:
8216       break;
8217     }
8218 }
8219 #endif
8220
8221 #ifdef BETTER_LITERAL_SHIFT
8222 /*-----------------------------------------------------------------*/
8223 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8224 /*-----------------------------------------------------------------*/
8225 static void
8226 AccAXRshS (char *x, int shCount)
8227 {
8228   symbol *tlbl;
8229   switch (shCount)
8230     {
8231     case 0:
8232       break;
8233     case 1:
8234       emitcode ("mov", "c,acc.7");
8235       AccAXRrl1 (x);            // s->a:x
8236
8237       break;
8238     case 2:
8239       emitcode ("mov", "c,acc.7");
8240       AccAXRrl1 (x);            // s->a:x
8241
8242       emitcode ("mov", "c,acc.7");
8243       AccAXRrl1 (x);            // s->a:x
8244
8245       break;
8246     case 3:
8247     case 4:
8248     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8249
8250       tlbl = newiTempLabel (NULL);
8251       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8252
8253       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8254
8255       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8256
8257       emitcode ("anl", "a,#!constbyte",
8258                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8259
8260       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8261
8262       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8263
8264       emitcode ("anl", "a,#!constbyte",
8265                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8266
8267       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8268
8269       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8270
8271       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8272
8273       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8274       emitcode ("orl", "a,#!constbyte",
8275                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8276
8277       emitcode ("", "!tlabeldef", tlbl->key + 100);
8278       break;                    // SSSSAAAA:BBBCCCCC
8279
8280     case 6:                     // AABBBBBB:CCDDDDDD
8281
8282       tlbl = newiTempLabel (NULL);
8283       emitcode ("mov", "c,acc.7");
8284       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8285
8286       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8287
8288       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8289
8290       emitcode ("anl", "a,#!constbyte",
8291                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8292
8293       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8294       emitcode ("orl", "a,#!constbyte",
8295                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8296
8297       emitcode ("", "!tlabeldef", tlbl->key + 100);
8298       break;
8299     case 7:                     // ABBBBBBB:CDDDDDDD
8300
8301       tlbl = newiTempLabel (NULL);
8302       emitcode ("mov", "c,acc.7");      // c = A
8303
8304       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8305
8306       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8307
8308       emitcode ("anl", "a,#!constbyte",
8309                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8310
8311       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8312       emitcode ("orl", "a,#!constbyte",
8313                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8314
8315       emitcode ("", "!tlabeldef", tlbl->key + 100);
8316       break;
8317     default:
8318       break;
8319     }
8320 }
8321 #endif
8322
8323 #ifdef BETTER_LITERAL_SHIFT
8324 static void
8325 _loadLeftIntoAx(char    **lsb, 
8326                 operand *left, 
8327                 operand *result,
8328                 int     offl,
8329                 int     offr)
8330 {
8331   // Get the initial value from left into a pair of registers.
8332   // MSB must be in A, LSB can be any register.
8333   //
8334   // If the result is held in registers, it is an optimization
8335   // if the LSB can be held in the register which will hold the,
8336   // result LSB since this saves us from having to copy it into
8337   // the result following AccAXLsh.
8338   //
8339   // If the result is addressed indirectly, this is not a gain.
8340   if (AOP_NEEDSACC(result))
8341   {
8342        char *leftByte;
8343        
8344        _startLazyDPSEvaluation();
8345       if (AOP_TYPE(left) == AOP_DPTR2)
8346        {
8347            // Get MSB in A.
8348            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8349            // get LSB in DP2_RESULT_REG.
8350            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8351            assert(!strcmp(leftByte, DP2_RESULT_REG));
8352        }
8353        else
8354        {
8355            // get LSB into DP2_RESULT_REG
8356            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8357            if (strcmp(leftByte, DP2_RESULT_REG))
8358            {
8359                TR_AP("#7");
8360                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8361            }
8362            // And MSB in A.
8363            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8364            assert(strcmp(leftByte, DP2_RESULT_REG));
8365            MOVA(leftByte);
8366        }
8367        _endLazyDPSEvaluation();
8368        *lsb = DP2_RESULT_REG;
8369   }
8370   else
8371   {
8372       if (sameRegs (AOP (result), AOP (left)) &&
8373         ((offl + MSB16) == offr))
8374       {
8375           /* don't crash result[offr] */
8376           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8377           emitcode ("xch", "a,%s", 
8378                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8379       }
8380       else
8381       {
8382           movLeft2Result (left, offl, result, offr, 0);
8383           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8384       }
8385       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8386       assert(strcmp(*lsb,"a"));      
8387   }
8388 }
8389
8390 static void
8391 _storeAxResults(char    *lsb,
8392                 operand *result,
8393                 int     offr)
8394 {
8395   _startLazyDPSEvaluation();
8396   if (AOP_NEEDSACC(result))
8397   {
8398       /* We have to explicitly update the result LSB.
8399        */
8400       emitcode("xch","a,%s", lsb);
8401       aopPut(AOP(result), "a", offr);
8402       emitcode("mov","a,%s", lsb);
8403   }
8404   if (getDataSize (result) > 1)
8405   {
8406       aopPut (AOP (result), "a", offr + MSB16);
8407   }
8408   _endLazyDPSEvaluation();
8409 }
8410
8411 /*-----------------------------------------------------------------*/
8412 /* shiftL2Left2Result - shift left two bytes from left to result   */
8413 /*-----------------------------------------------------------------*/
8414 static void
8415 shiftL2Left2Result (operand * left, int offl,
8416                     operand * result, int offr, int shCount)
8417 {
8418   char *lsb;
8419
8420   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8421   
8422   AccAXLsh (lsb, shCount);
8423   
8424   _storeAxResults(lsb, result, offr);
8425 }
8426 #endif
8427
8428 #ifdef BETTER_LITERAL_SHIFT
8429 /*-----------------------------------------------------------------*/
8430 /* shiftR2Left2Result - shift right two bytes from left to result  */
8431 /*-----------------------------------------------------------------*/
8432 static void
8433 shiftR2Left2Result (operand * left, int offl,
8434                     operand * result, int offr,
8435                     int shCount, int sign)
8436 {
8437   char *lsb;
8438   
8439   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8440   
8441   /* a:x >> shCount (x = lsb(result)) */
8442   if (sign)
8443   {
8444      AccAXRshS(lsb, shCount);
8445   }
8446   else
8447   {
8448     AccAXRsh(lsb, shCount);
8449   }
8450   
8451   _storeAxResults(lsb, result, offr);
8452 }
8453 #endif
8454
8455 /*-----------------------------------------------------------------*/
8456 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8457 /*-----------------------------------------------------------------*/
8458 static void
8459 shiftLLeftOrResult (operand * left, int offl,
8460                     operand * result, int offr, int shCount)
8461 {
8462   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8463   /* shift left accumulator */
8464   AccLsh (shCount);
8465   /* or with result */
8466   emitcode ("orl", "a,%s",
8467             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8468   /* back to result */
8469   aopPut (AOP (result), "a", offr);
8470 }
8471
8472 #if 0
8473 //REMOVE ME!!!
8474 /*-----------------------------------------------------------------*/
8475 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8476 /*-----------------------------------------------------------------*/
8477 static void
8478 shiftRLeftOrResult (operand * left, int offl,
8479                     operand * result, int offr, int shCount)
8480 {
8481   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8482   /* shift right accumulator */
8483   AccRsh (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 #endif
8491
8492 #ifdef BETTER_LITERAL_SHIFT
8493 /*-----------------------------------------------------------------*/
8494 /* genlshOne - left shift a one byte quantity by known count       */
8495 /*-----------------------------------------------------------------*/
8496 static void
8497 genlshOne (operand * result, operand * left, int shCount)
8498 {
8499   D (emitcode (";", "genlshOne "););
8500   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8501 }
8502 #endif
8503
8504 #ifdef BETTER_LITERAL_SHIFT
8505 /*-----------------------------------------------------------------*/
8506 /* genlshTwo - left shift two bytes by known amount != 0           */
8507 /*-----------------------------------------------------------------*/
8508 static void
8509 genlshTwo (operand * result, operand * left, int shCount)
8510 {
8511   int size;
8512
8513   D (emitcode (";", "genlshTwo "););
8514
8515   size = getDataSize (result);
8516
8517   /* if shCount >= 8 */
8518   if (shCount >= 8)
8519   {
8520       shCount -= 8;
8521
8522       _startLazyDPSEvaluation();
8523
8524       if (size > 1)
8525         {
8526           if (shCount)
8527           {
8528             _endLazyDPSEvaluation();
8529             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8530             aopPut (AOP (result), zero, LSB);       
8531           }
8532           else
8533           {
8534             movLeft2Result (left, LSB, result, MSB16, 0);
8535             aopPut (AOP (result), zero, LSB);
8536             _endLazyDPSEvaluation();
8537           }
8538         }
8539         else
8540         {
8541           aopPut (AOP (result), zero, LSB);
8542           _endLazyDPSEvaluation();
8543         }
8544   }
8545
8546   /*  1 <= shCount <= 7 */
8547   else
8548     {
8549       if (size == 1)
8550       {
8551         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8552       }
8553       else
8554       {
8555         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8556       }
8557     }
8558 }
8559 #endif
8560
8561 #if 0
8562 //REMOVE ME!!!
8563 /*-----------------------------------------------------------------*/
8564 /* shiftLLong - shift left one long from left to result            */
8565 /* offl = LSB or MSB16                                             */
8566 /*-----------------------------------------------------------------*/
8567 static void
8568 shiftLLong (operand * left, operand * result, int offr)
8569 {
8570   char *l;
8571   int size = AOP_SIZE (result);
8572
8573   if (size >= LSB + offr)
8574     {
8575       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8576       MOVA (l);
8577       emitcode ("add", "a,acc");
8578       if (sameRegs (AOP (left), AOP (result)) &&
8579           size >= MSB16 + offr && offr != LSB)
8580         emitcode ("xch", "a,%s",
8581                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8582       else
8583         aopPut (AOP (result), "a", LSB + offr);
8584     }
8585
8586   if (size >= MSB16 + offr)
8587     {
8588       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8589         {
8590           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8591         }
8592       emitcode ("rlc", "a");
8593       if (sameRegs (AOP (left), AOP (result)) &&
8594           size >= MSB24 + offr && offr != LSB)
8595         emitcode ("xch", "a,%s",
8596                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8597       else
8598         aopPut (AOP (result), "a", MSB16 + offr);
8599     }
8600
8601   if (size >= MSB24 + offr)
8602     {
8603       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8604         {
8605           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8606         }
8607       emitcode ("rlc", "a");
8608       if (sameRegs (AOP (left), AOP (result)) &&
8609           size >= MSB32 + offr && offr != LSB)
8610         emitcode ("xch", "a,%s",
8611                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8612       else
8613         aopPut (AOP (result), "a", MSB24 + offr);
8614     }
8615
8616   if (size > MSB32 + offr)
8617     {
8618       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8619         {
8620           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8621         }
8622       emitcode ("rlc", "a");
8623       aopPut (AOP (result), "a", MSB32 + offr);
8624     }
8625   if (offr != LSB)
8626     aopPut (AOP (result), zero, LSB);
8627 }
8628 #endif
8629
8630 #if 0
8631 //REMOVE ME!!!
8632 /*-----------------------------------------------------------------*/
8633 /* genlshFour - shift four byte by a known amount != 0             */
8634 /*-----------------------------------------------------------------*/
8635 static void
8636 genlshFour (operand * result, operand * left, int shCount)
8637 {
8638   int size;
8639
8640   D (emitcode (";", "genlshFour ");
8641     );
8642
8643   size = AOP_SIZE (result);
8644
8645   /* if shifting more that 3 bytes */
8646   if (shCount >= 24)
8647     {
8648       shCount -= 24;
8649       if (shCount)
8650         /* lowest order of left goes to the highest
8651            order of the destination */
8652         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8653       else
8654         movLeft2Result (left, LSB, result, MSB32, 0);
8655       aopPut (AOP (result), zero, LSB);
8656       aopPut (AOP (result), zero, MSB16);
8657       aopPut (AOP (result), zero, MSB24);
8658       return;
8659     }
8660
8661   /* more than two bytes */
8662   else if (shCount >= 16)
8663     {
8664       /* lower order two bytes goes to higher order two bytes */
8665       shCount -= 16;
8666       /* if some more remaining */
8667       if (shCount)
8668         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8669       else
8670         {
8671           movLeft2Result (left, MSB16, result, MSB32, 0);
8672           movLeft2Result (left, LSB, result, MSB24, 0);
8673         }
8674       aopPut (AOP (result), zero, MSB16);
8675       aopPut (AOP (result), zero, LSB);
8676       return;
8677     }
8678
8679   /* if more than 1 byte */
8680   else if (shCount >= 8)
8681     {
8682       /* lower order three bytes goes to higher order  three bytes */
8683       shCount -= 8;
8684       if (size == 2)
8685         {
8686           if (shCount)
8687             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8688           else
8689             movLeft2Result (left, LSB, result, MSB16, 0);
8690         }
8691       else
8692         {                       /* size = 4 */
8693           if (shCount == 0)
8694             {
8695               movLeft2Result (left, MSB24, result, MSB32, 0);
8696               movLeft2Result (left, MSB16, result, MSB24, 0);
8697               movLeft2Result (left, LSB, result, MSB16, 0);
8698               aopPut (AOP (result), zero, LSB);
8699             }
8700           else if (shCount == 1)
8701             shiftLLong (left, result, MSB16);
8702           else
8703             {
8704               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8705               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8706               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8707               aopPut (AOP (result), zero, LSB);
8708             }
8709         }
8710     }
8711
8712   /* 1 <= shCount <= 7 */
8713   else if (shCount <= 2)
8714     {
8715       shiftLLong (left, result, LSB);
8716       if (shCount == 2)
8717         shiftLLong (result, result, LSB);
8718     }
8719   /* 3 <= shCount <= 7, optimize */
8720   else
8721     {
8722       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8723       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8724       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8725     }
8726 }
8727 #endif
8728
8729 #ifdef BETTER_LITERAL_SHIFT
8730 /*-----------------------------------------------------------------*/
8731 /* genLeftShiftLiteral - left shifting by known count              */
8732 /*-----------------------------------------------------------------*/
8733 static bool
8734 genLeftShiftLiteral (operand * left,
8735                      operand * right,
8736                      operand * result,
8737                      iCode * ic)
8738 {
8739   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8740   int size;
8741
8742   size = getSize (operandType (result));
8743
8744   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8745
8746   /* We only handle certain easy cases so far. */
8747   if ((shCount != 0)
8748    && (shCount < (size * 8))
8749    && (size != 1)
8750    && (size != 2))
8751   {
8752       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8753       return FALSE;
8754   }
8755
8756   freeAsmop (right, NULL, ic, TRUE);
8757
8758   aopOp(left, ic, FALSE, FALSE);
8759   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8760
8761 #if 0 // debug spew
8762   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8763   {
8764         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8765         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8766         {
8767            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8768         }
8769   }
8770   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8771   {
8772         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8773         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8774         {
8775            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8776         }       
8777   }  
8778 #endif
8779   
8780 #if VIEW_SIZE
8781   emitcode ("; shift left ", "result %d, left %d", size,
8782             AOP_SIZE (left));
8783 #endif
8784
8785   /* I suppose that the left size >= result size */
8786   if (shCount == 0)
8787   {
8788         _startLazyDPSEvaluation();
8789         while (size--)
8790         {
8791           movLeft2Result (left, size, result, size, 0);
8792         }
8793         _endLazyDPSEvaluation();
8794   }
8795   else if (shCount >= (size * 8))
8796   {
8797     _startLazyDPSEvaluation();
8798     while (size--)
8799     {
8800       aopPut (AOP (result), zero, size);
8801     }
8802     _endLazyDPSEvaluation();
8803   }
8804   else
8805   {
8806       switch (size)
8807         {
8808         case 1:
8809           genlshOne (result, left, shCount);
8810           break;
8811
8812         case 2:
8813           genlshTwo (result, left, shCount);
8814           break;
8815 #if 0
8816         case 4:
8817           genlshFour (result, left, shCount);
8818           break;
8819 #endif
8820         default:
8821           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8822           break;
8823         }
8824     }
8825   freeAsmop (left, NULL, ic, TRUE);
8826   freeAsmop (result, NULL, ic, TRUE);
8827   return TRUE;
8828 }
8829 #endif
8830
8831 /*-----------------------------------------------------------------*/
8832 /* genLeftShift - generates code for left shifting                 */
8833 /*-----------------------------------------------------------------*/
8834 static void
8835 genLeftShift (iCode * ic)
8836 {
8837   operand *left, *right, *result;
8838   int size, offset;
8839   char *l;
8840   symbol *tlbl, *tlbl1;
8841
8842   D (emitcode (";", "genLeftShift "););
8843
8844   right = IC_RIGHT (ic);
8845   left = IC_LEFT (ic);
8846   result = IC_RESULT (ic);
8847
8848   aopOp (right, ic, FALSE, FALSE);
8849
8850
8851 #ifdef BETTER_LITERAL_SHIFT
8852   /* if the shift count is known then do it
8853      as efficiently as possible */
8854   if (AOP_TYPE (right) == AOP_LIT)
8855     {
8856       if (genLeftShiftLiteral (left, right, result, ic))
8857       {
8858         return;
8859       }
8860     }
8861 #endif
8862
8863   /* shift count is unknown then we have to form
8864      a loop get the loop count in B : Note: we take
8865      only the lower order byte since shifting
8866      more that 32 bits make no sense anyway, ( the
8867      largest size of an object can be only 32 bits ) */
8868
8869   if (AOP_TYPE (right) == AOP_LIT)
8870   {
8871       /* Really should be handled by genLeftShiftLiteral,
8872        * but since I'm too lazy to fix that today, at least we can make
8873        * some small improvement.
8874        */
8875        emitcode("mov", "b,#!constbyte",
8876                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8877   }
8878   else
8879   {
8880       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8881       emitcode ("inc", "b");
8882   }
8883   freeAsmop (right, NULL, ic, TRUE);
8884   aopOp (left, ic, FALSE, FALSE);
8885   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8886
8887   /* now move the left to the result if they are not the
8888      same */
8889   if (!sameRegs (AOP (left), AOP (result)) &&
8890       AOP_SIZE (result) > 1)
8891     {
8892
8893       size = AOP_SIZE (result);
8894       offset = 0;
8895       _startLazyDPSEvaluation ();
8896       while (size--)
8897         {
8898           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8899           if (*l == '@' && (IS_AOP_PREG (result)))
8900             {
8901
8902               emitcode ("mov", "a,%s", l);
8903               aopPut (AOP (result), "a", offset);
8904             }
8905           else
8906             aopPut (AOP (result), l, offset);
8907           offset++;
8908         }
8909       _endLazyDPSEvaluation ();
8910     }
8911
8912   tlbl = newiTempLabel (NULL);
8913   size = AOP_SIZE (result);
8914   offset = 0;
8915   tlbl1 = newiTempLabel (NULL);
8916
8917   /* if it is only one byte then */
8918   if (size == 1)
8919     {
8920       symbol *tlbl1 = newiTempLabel (NULL);
8921
8922       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8923       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8924       emitcode ("", "!tlabeldef", tlbl->key + 100);
8925       emitcode ("add", "a,acc");
8926       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8927       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8928       aopPut (AOP (result), "a", 0);
8929       goto release;
8930     }
8931
8932   reAdjustPreg (AOP (result));
8933
8934   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8935   emitcode ("", "!tlabeldef", tlbl->key + 100);
8936   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8937   emitcode ("add", "a,acc");
8938   aopPut (AOP (result), "a", offset++);
8939   _startLazyDPSEvaluation ();
8940   while (--size)
8941     {
8942       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8943       emitcode ("rlc", "a");
8944       aopPut (AOP (result), "a", offset++);
8945     }
8946   _endLazyDPSEvaluation ();
8947   reAdjustPreg (AOP (result));
8948
8949   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8950   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8951 release:
8952   freeAsmop (left, NULL, ic, TRUE);
8953   freeAsmop (result, NULL, ic, TRUE);
8954 }
8955
8956 #ifdef BETTER_LITERAL_SHIFT
8957 /*-----------------------------------------------------------------*/
8958 /* genrshOne - right shift a one byte quantity by known count      */
8959 /*-----------------------------------------------------------------*/
8960 static void
8961 genrshOne (operand * result, operand * left,
8962            int shCount, int sign)
8963 {
8964   D (emitcode (";", "genrshOne"););
8965   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8966 }
8967 #endif
8968
8969 #ifdef BETTER_LITERAL_SHIFT
8970 /*-----------------------------------------------------------------*/
8971 /* genrshTwo - right shift two bytes by known amount != 0          */
8972 /*-----------------------------------------------------------------*/
8973 static void
8974 genrshTwo (operand * result, operand * left,
8975            int shCount, int sign)
8976 {
8977   D (emitcode (";", "genrshTwo"););
8978
8979   /* if shCount >= 8 */
8980   if (shCount >= 8)
8981     {
8982       shCount -= 8;
8983       _startLazyDPSEvaluation();
8984       if (shCount)
8985       {
8986         shiftR1Left2Result (left, MSB16, result, LSB,
8987                             shCount, sign);
8988       }                     
8989       else
8990       {
8991         movLeft2Result (left, MSB16, result, LSB, sign);
8992       }
8993       addSign (result, MSB16, sign);
8994       _endLazyDPSEvaluation();
8995     }
8996
8997   /*  1 <= shCount <= 7 */
8998   else
8999   {
9000     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9001   }
9002 }
9003 #endif
9004
9005 /*-----------------------------------------------------------------*/
9006 /* shiftRLong - shift right one long from left to result           */
9007 /* offl = LSB or MSB16                                             */
9008 /*-----------------------------------------------------------------*/
9009 static void
9010 shiftRLong (operand * left, int offl,
9011             operand * result, int sign)
9012 {
9013   int isSameRegs=sameRegs(AOP(left),AOP(result));
9014
9015   if (isSameRegs && offl>1) {
9016     // we are in big trouble, but this shouldn't happen
9017     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9018   }
9019
9020   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9021   
9022   if (offl==MSB16) {
9023     // shift is > 8
9024     if (sign) {
9025       emitcode ("rlc", "a");
9026       emitcode ("subb", "a,acc");
9027       emitcode ("xch", "a,%s",
9028                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9029     } else {
9030       aopPut (AOP(result), zero, MSB32);
9031     }
9032   }
9033
9034   if (!sign) {
9035     emitcode ("clr", "c");
9036   } else {
9037     emitcode ("mov", "c,acc.7");
9038   }
9039
9040   emitcode ("rrc", "a");
9041
9042   if (isSameRegs && offl==MSB16) {
9043     emitcode ("xch",
9044               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9045   } else {
9046     aopPut (AOP (result), "a", MSB32);
9047     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9048   }
9049
9050   emitcode ("rrc", "a");
9051   if (isSameRegs && offl==1) {
9052     emitcode ("xch", "a,%s",
9053               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9054   } else {
9055     aopPut (AOP (result), "a", MSB24);
9056     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9057   }
9058   emitcode ("rrc", "a");
9059   aopPut (AOP (result), "a", MSB16 - offl);
9060
9061   if (offl == LSB)
9062     {
9063       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9064       emitcode ("rrc", "a");
9065       aopPut (AOP (result), "a", LSB);
9066     }
9067 }
9068
9069 /*-----------------------------------------------------------------*/
9070 /* genrshFour - shift four byte by a known amount != 0             */
9071 /*-----------------------------------------------------------------*/
9072 static void
9073 genrshFour (operand * result, operand * left,
9074             int shCount, int sign)
9075 {
9076   D (emitcode (";", "genrshFour"););
9077
9078   /* if shifting more that 3 bytes */
9079   if (shCount >= 24)
9080     {
9081       shCount -= 24;
9082       _startLazyDPSEvaluation();
9083       if (shCount)
9084         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9085       else
9086         movLeft2Result (left, MSB32, result, LSB, sign);
9087       addSign (result, MSB16, sign);
9088       _endLazyDPSEvaluation();
9089     }
9090   else if (shCount >= 16)
9091     {
9092       shCount -= 16;
9093       _startLazyDPSEvaluation();
9094       if (shCount)
9095         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9096       else
9097         {
9098           movLeft2Result (left, MSB24, result, LSB, 0);
9099           movLeft2Result (left, MSB32, result, MSB16, sign);
9100         }
9101       addSign (result, MSB24, sign);
9102       _endLazyDPSEvaluation();
9103     }
9104   else if (shCount >= 8)
9105     {
9106       shCount -= 8;
9107       _startLazyDPSEvaluation();
9108       if (shCount == 1)
9109         {
9110             shiftRLong (left, MSB16, result, sign);
9111         }
9112       else if (shCount == 0)
9113         {
9114           movLeft2Result (left, MSB16, result, LSB, 0);
9115           movLeft2Result (left, MSB24, result, MSB16, 0);
9116           movLeft2Result (left, MSB32, result, MSB24, sign);
9117           addSign (result, MSB32, sign);
9118         }
9119       else
9120         {
9121           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9122           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9123           /* the last shift is signed */
9124           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9125           addSign (result, MSB32, sign);
9126         }
9127         _endLazyDPSEvaluation();
9128     }
9129   else
9130     {   
9131         /* 1 <= shCount <= 7 */
9132       if (shCount <= 2)
9133         {
9134           shiftRLong (left, LSB, result, sign);
9135           if (shCount == 2)
9136             shiftRLong (result, LSB, result, sign);
9137         }
9138       else
9139         {
9140           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9141           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9142           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9143         }
9144     }
9145 }
9146
9147 #ifdef BETTER_LITERAL_SHIFT
9148 /*-----------------------------------------------------------------*/
9149 /* genRightShiftLiteral - right shifting by known count            */
9150 /*-----------------------------------------------------------------*/
9151 static bool
9152 genRightShiftLiteral (operand * left,
9153                       operand * right,
9154                       operand * result,
9155                       iCode * ic,
9156                       int sign)
9157 {
9158   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9159   int size;
9160
9161   size = getSize (operandType (result));
9162
9163   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9164
9165   /* We only handle certain easy cases so far. */
9166   if ((shCount != 0)
9167    && (shCount < (size * 8))
9168    && (size != 1)
9169    && (size != 2)
9170    && (size != 4))
9171   {
9172       D(emitcode (";", "genRightShiftLiteral wimping out"););
9173       return FALSE;
9174   }
9175
9176   freeAsmop (right, NULL, ic, TRUE);
9177
9178   aopOp (left, ic, FALSE, FALSE);
9179   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9180
9181 #if VIEW_SIZE
9182   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9183             AOP_SIZE (left));
9184 #endif
9185
9186   /* test the LEFT size !!! */
9187
9188   /* I suppose that the left size >= result size */
9189   if (shCount == 0)
9190   {
9191       size = getDataSize (result);
9192       _startLazyDPSEvaluation();
9193       while (size--)
9194       {
9195         movLeft2Result (left, size, result, size, 0);
9196       }
9197       _endLazyDPSEvaluation();
9198   }
9199   else if (shCount >= (size * 8))
9200     {
9201       if (sign)
9202       {
9203         /* get sign in acc.7 */
9204         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9205       }
9206       addSign (result, LSB, sign);
9207     }
9208   else
9209     {
9210       switch (size)
9211         {
9212         case 1:
9213           genrshOne (result, left, shCount, sign);
9214           break;
9215
9216         case 2:
9217           genrshTwo (result, left, shCount, sign);
9218           break;
9219 #if 1
9220         case 4:
9221           genrshFour (result, left, shCount, sign);
9222           break;
9223 #endif    
9224         default:
9225           break;
9226         }
9227     }
9228   freeAsmop (left, NULL, ic, TRUE);
9229   freeAsmop (result, NULL, ic, TRUE);
9230   
9231   return TRUE;
9232 }
9233 #endif
9234
9235 /*-----------------------------------------------------------------*/
9236 /* genSignedRightShift - right shift of signed number              */
9237 /*-----------------------------------------------------------------*/
9238 static void
9239 genSignedRightShift (iCode * ic)
9240 {
9241   operand *right, *left, *result;
9242   int size, offset;
9243   char *l;
9244   symbol *tlbl, *tlbl1;
9245
9246   D (emitcode (";", "genSignedRightShift "););
9247
9248   /* we do it the hard way put the shift count in b
9249      and loop thru preserving the sign */
9250
9251   right = IC_RIGHT (ic);
9252   left = IC_LEFT (ic);
9253   result = IC_RESULT (ic);
9254
9255   aopOp (right, ic, FALSE, FALSE);
9256
9257 #ifdef BETTER_LITERAL_SHIFT
9258   if (AOP_TYPE (right) == AOP_LIT)
9259     {
9260       if (genRightShiftLiteral (left, right, result, ic, 1))
9261       {
9262         return;
9263       }
9264     }
9265 #endif
9266   /* shift count is unknown then we have to form
9267      a loop get the loop count in B : Note: we take
9268      only the lower order byte since shifting
9269      more that 32 bits make no sense anyway, ( the
9270      largest size of an object can be only 32 bits ) */
9271
9272   if (AOP_TYPE (right) == AOP_LIT)
9273   {
9274       /* Really should be handled by genRightShiftLiteral,
9275        * but since I'm too lazy to fix that today, at least we can make
9276        * some small improvement.
9277        */
9278        emitcode("mov", "b,#!constbyte",
9279                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9280   }
9281   else
9282   {
9283         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9284         emitcode ("inc", "b");
9285   }
9286   freeAsmop (right, NULL, ic, TRUE);
9287   aopOp (left, ic, FALSE, FALSE);
9288   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
9289
9290   /* now move the left to the result if they are not the
9291      same */
9292   if (!sameRegs (AOP (left), AOP (result)) &&
9293       AOP_SIZE (result) > 1)
9294     {
9295
9296       size = AOP_SIZE (result);
9297       offset = 0;
9298       _startLazyDPSEvaluation ();
9299       while (size--)
9300         {
9301           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9302           if (*l == '@' && IS_AOP_PREG (result))
9303             {
9304
9305               emitcode ("mov", "a,%s", l);
9306               aopPut (AOP (result), "a", offset);
9307             }
9308           else
9309             aopPut (AOP (result), l, offset);
9310           offset++;
9311         }
9312       _endLazyDPSEvaluation ();
9313     }
9314
9315   /* mov the highest order bit to OVR */
9316   tlbl = newiTempLabel (NULL);
9317   tlbl1 = newiTempLabel (NULL);
9318
9319   size = AOP_SIZE (result);
9320   offset = size - 1;
9321   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9322   emitcode ("rlc", "a");
9323   emitcode ("mov", "ov,c");
9324   /* if it is only one byte then */
9325   if (size == 1)
9326     {
9327       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9328       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9329       emitcode ("", "!tlabeldef", tlbl->key + 100);
9330       emitcode ("mov", "c,ov");
9331       emitcode ("rrc", "a");
9332       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9333       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9334       aopPut (AOP (result), "a", 0);
9335       goto release;
9336     }
9337
9338   reAdjustPreg (AOP (result));
9339   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9340   emitcode ("", "!tlabeldef", tlbl->key + 100);
9341   emitcode ("mov", "c,ov");
9342   _startLazyDPSEvaluation ();
9343   while (size--)
9344     {
9345       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9346       emitcode ("rrc", "a");
9347       aopPut (AOP (result), "a", offset--);
9348     }
9349   _endLazyDPSEvaluation ();
9350   reAdjustPreg (AOP (result));
9351   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9352   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9353
9354 release:
9355   freeAsmop (left, NULL, ic, TRUE);
9356   freeAsmop (result, NULL, ic, TRUE);
9357 }
9358
9359 /*-----------------------------------------------------------------*/
9360 /* genRightShift - generate code for right shifting                */
9361 /*-----------------------------------------------------------------*/
9362 static void
9363 genRightShift (iCode * ic)
9364 {
9365   operand *right, *left, *result;
9366   sym_link *letype;
9367   int size, offset;
9368   char *l;
9369   symbol *tlbl, *tlbl1;
9370
9371   D (emitcode (";", "genRightShift "););
9372
9373   /* if signed then we do it the hard way preserve the
9374      sign bit moving it inwards */
9375   letype = getSpec (operandType (IC_LEFT (ic)));
9376
9377   if (!SPEC_USIGN (letype))
9378     {
9379       genSignedRightShift (ic);
9380       return;
9381     }
9382
9383   /* signed & unsigned types are treated the same : i.e. the
9384      signed is NOT propagated inwards : quoting from the
9385      ANSI - standard : "for E1 >> E2, is equivalent to division
9386      by 2**E2 if unsigned or if it has a non-negative value,
9387      otherwise the result is implementation defined ", MY definition
9388      is that the sign does not get propagated */
9389
9390   right = IC_RIGHT (ic);
9391   left = IC_LEFT (ic);
9392   result = IC_RESULT (ic);
9393
9394   aopOp (right, ic, FALSE, FALSE);
9395
9396 #ifdef BETTER_LITERAL_SHIFT
9397   /* if the shift count is known then do it
9398      as efficiently as possible */
9399   if (AOP_TYPE (right) == AOP_LIT)
9400     {
9401       if (genRightShiftLiteral (left, right, result, ic, 0))
9402       {
9403         return;
9404       }
9405     }
9406 #endif
9407
9408   /* shift count is unknown then we have to form
9409      a loop get the loop count in B : Note: we take
9410      only the lower order byte since shifting
9411      more that 32 bits make no sense anyway, ( the
9412      largest size of an object can be only 32 bits ) */
9413   
9414   if (AOP_TYPE (right) == AOP_LIT)
9415   {
9416       /* Really should be handled by genRightShiftLiteral,
9417        * but since I'm too lazy to fix that today, at least we can make
9418        * some small improvement.
9419        */
9420        emitcode("mov", "b,#!constbyte",
9421                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9422   }
9423   else
9424   {
9425       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9426       emitcode ("inc", "b");
9427   }
9428   freeAsmop (right, NULL, ic, TRUE);
9429   aopOp (left, ic, FALSE, FALSE);
9430   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9431
9432   /* now move the left to the result if they are not the
9433      same */
9434   if (!sameRegs (AOP (left), AOP (result)) &&
9435       AOP_SIZE (result) > 1)
9436     {
9437
9438       size = AOP_SIZE (result);
9439       offset = 0;
9440       _startLazyDPSEvaluation ();
9441       while (size--)
9442         {
9443           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9444           if (*l == '@' && IS_AOP_PREG (result))
9445             {
9446
9447               emitcode ("mov", "a,%s", l);
9448               aopPut (AOP (result), "a", offset);
9449             }
9450           else
9451             aopPut (AOP (result), l, offset);
9452           offset++;
9453         }
9454       _endLazyDPSEvaluation ();
9455     }
9456
9457   tlbl = newiTempLabel (NULL);
9458   tlbl1 = newiTempLabel (NULL);
9459   size = AOP_SIZE (result);
9460   offset = size - 1;
9461
9462   /* if it is only one byte then */
9463   if (size == 1)
9464     {
9465       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9466       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9467       emitcode ("", "!tlabeldef", tlbl->key + 100);
9468       CLRC;
9469       emitcode ("rrc", "a");
9470       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9471       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9472       aopPut (AOP (result), "a", 0);
9473       goto release;
9474     }
9475
9476   reAdjustPreg (AOP (result));
9477   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9478   emitcode ("", "!tlabeldef", tlbl->key + 100);
9479   CLRC;
9480   _startLazyDPSEvaluation ();
9481   while (size--)
9482     {
9483       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9484       emitcode ("rrc", "a");
9485       aopPut (AOP (result), "a", offset--);
9486     }
9487   _endLazyDPSEvaluation ();
9488   reAdjustPreg (AOP (result));
9489
9490   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9491   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9492
9493 release:
9494   freeAsmop (left, NULL, ic, TRUE);
9495   freeAsmop (result, NULL, ic, TRUE);
9496 }
9497
9498
9499 /*-----------------------------------------------------------------*/
9500 /* emitPtrByteGet - emits code to get a byte into A through a      */
9501 /*                  pointer register (R0, R1, or DPTR). The        */
9502 /*                  original value of A can be preserved in B.     */
9503 /*-----------------------------------------------------------------*/
9504 static void
9505 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9506 {
9507   switch (p_type)
9508     {
9509     case IPOINTER:
9510     case POINTER:
9511       if (preserveAinB)
9512         emitcode ("mov", "b,a");
9513       emitcode ("mov", "a,@%s", rname);
9514       break;
9515
9516     case PPOINTER:
9517       if (preserveAinB)
9518         emitcode ("mov", "b,a");
9519       emitcode ("movx", "a,@%s", rname);
9520       break;
9521       
9522     case FPOINTER:
9523       if (preserveAinB)
9524         emitcode ("mov", "b,a");
9525       emitcode ("movx", "a,@dptr");
9526       break;
9527
9528     case CPOINTER:
9529       if (preserveAinB)
9530         emitcode ("mov", "b,a");
9531       emitcode ("clr", "a");
9532       emitcode ("movc", "a,@a+dptr");
9533       break;
9534
9535     case GPOINTER:
9536       if (preserveAinB)
9537         {
9538           emitcode ("push", "b");
9539           emitcode ("push", "acc");
9540         }
9541       emitcode ("lcall", "__gptrget");
9542       if (preserveAinB)
9543         emitcode ("pop", "b");
9544       break;
9545     }
9546 }
9547
9548 /*-----------------------------------------------------------------*/
9549 /* emitPtrByteSet - emits code to set a byte from src through a    */
9550 /*                  pointer register (R0, R1, or DPTR).            */
9551 /*-----------------------------------------------------------------*/
9552 static void
9553 emitPtrByteSet (char *rname, int p_type, char *src)
9554 {
9555   switch (p_type)
9556     {
9557     case IPOINTER:
9558     case POINTER:
9559       if (*src=='@')
9560         {
9561           MOVA (src);
9562           emitcode ("mov", "@%s,a", rname);
9563         }
9564       else
9565         emitcode ("mov", "@%s,%s", rname, src);
9566       break;
9567
9568     case PPOINTER:
9569       MOVA (src);
9570       emitcode ("movx", "@%s,a", rname);
9571       break;
9572       
9573     case FPOINTER:
9574       MOVA (src);
9575       emitcode ("movx", "@dptr,a");
9576       break;
9577
9578     case GPOINTER:
9579       MOVA (src);
9580       emitcode ("lcall", "__gptrput");
9581       break;
9582     }
9583 }
9584
9585 /*-----------------------------------------------------------------*/
9586 /* genUnpackBits - generates code for unpacking bits               */
9587 /*-----------------------------------------------------------------*/
9588 static void
9589 genUnpackBits (operand * result, char *rname, int ptype)
9590 {
9591   int offset = 0;       /* result byte offset */
9592   int rsize;            /* result size */
9593   int rlen = 0;         /* remaining bitfield length */
9594   sym_link *etype;      /* bitfield type information */
9595   int blen;             /* bitfield length */
9596   int bstr;             /* bitfield starting bit within byte */
9597
9598   D(emitcode (";     genUnpackBits",""));
9599
9600   etype = getSpec (operandType (result));
9601   rsize = getSize (operandType (result));
9602   blen = SPEC_BLEN (etype);
9603   bstr = SPEC_BSTR (etype);
9604
9605   /* If the bitfield length is less than a byte */
9606   if (blen < 8)
9607     {
9608       emitPtrByteGet (rname, ptype, FALSE);
9609       AccRsh (bstr);
9610       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9611       aopPut (AOP (result), "a", offset++);
9612       goto finish;
9613     }
9614
9615   /* Bit field did not fit in a byte. Copy all
9616      but the partial byte at the end.  */
9617   for (rlen=blen;rlen>=8;rlen-=8)
9618     {
9619       emitPtrByteGet (rname, ptype, FALSE);
9620       aopPut (AOP (result), "a", offset++);
9621       if (rlen>8)
9622         emitcode ("inc", "%s", rname);
9623     }
9624
9625   /* Handle the partial byte at the end */
9626   if (rlen)
9627     {
9628       emitPtrByteGet (rname, ptype, FALSE);
9629       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9630       aopPut (AOP (result), "a", offset++);
9631     }
9632
9633 finish:
9634   if (offset < rsize)
9635     {
9636       rsize -= offset;
9637       while (rsize--)
9638         aopPut (AOP (result), zero, offset++);
9639     }
9640 }
9641
9642
9643 /*-----------------------------------------------------------------*/
9644 /* genDataPointerGet - generates code when ptr offset is known     */
9645 /*-----------------------------------------------------------------*/
9646 static void
9647 genDataPointerGet (operand * left,
9648                    operand * result,
9649                    iCode * ic)
9650 {
9651   char *l;
9652   char buff[256];
9653   int size, offset = 0;
9654   aopOp (result, ic, TRUE, FALSE);
9655
9656   /* get the string representation of the name */
9657   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9658   size = AOP_SIZE (result);
9659   _startLazyDPSEvaluation ();
9660   while (size--)
9661     {
9662         if (offset)
9663         {
9664             SNPRINTF (buff, sizeof(buff), 
9665                       "(%s + %d)", l + 1, offset);
9666         }
9667         else
9668         {
9669             SNPRINTF (buff, sizeof(buff), 
9670                       "%s", l + 1);
9671         }
9672       aopPut (AOP (result), buff, offset++);
9673     }
9674   _endLazyDPSEvaluation ();
9675
9676   freeAsmop (left, NULL, ic, TRUE);
9677   freeAsmop (result, NULL, ic, TRUE);
9678 }
9679
9680 /*-----------------------------------------------------------------*/
9681 /* genNearPointerGet - emitcode for near pointer fetch             */
9682 /*-----------------------------------------------------------------*/
9683 static void
9684 genNearPointerGet (operand * left,
9685                    operand * result,
9686                    iCode * ic,
9687                    iCode *pi)
9688 {
9689   asmop *aop = NULL;
9690   regs *preg;
9691   char *rname;
9692   sym_link *rtype, *retype, *letype;
9693   sym_link *ltype = operandType (left);
9694   char buff[80];
9695
9696   rtype = operandType (result);
9697   retype = getSpec (rtype);
9698   letype = getSpec (ltype);
9699
9700   aopOp (left, ic, FALSE, FALSE);
9701
9702   /* if left is rematerialisable and
9703      result is not bitfield variable type and
9704      the left is pointer to data space i.e
9705      lower 128 bytes of space */
9706   if (AOP_TYPE (left) == AOP_IMMD &&
9707       !IS_BITFIELD (retype) &&
9708       !IS_BITFIELD (letype) &&
9709       DCL_TYPE (ltype) == POINTER)
9710     {
9711       genDataPointerGet (left, result, ic);
9712       return;
9713     }
9714
9715   /* if the value is already in a pointer register
9716      then don't need anything more */
9717   if (!AOP_INPREG (AOP (left)))
9718     {
9719       /* otherwise get a free pointer register */
9720       aop = newAsmop (0);
9721       preg = getFreePtr (ic, &aop, FALSE);
9722       emitcode ("mov", "%s,%s",
9723                 preg->name,
9724                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9725       rname = preg->name;
9726     }
9727   else
9728     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9729
9730   freeAsmop (left, NULL, ic, TRUE);
9731   aopOp (result, ic, FALSE, FALSE);
9732
9733   /* if bitfield then unpack the bits */
9734   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9735     genUnpackBits (result, rname, POINTER);
9736   else
9737     {
9738       /* we have can just get the values */
9739       int size = AOP_SIZE (result);
9740       int offset = 0;
9741
9742       while (size--)
9743         {
9744           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9745             {
9746
9747               emitcode ("mov", "a,@%s", rname);
9748               aopPut (AOP (result), "a", offset);
9749             }
9750           else
9751             {
9752               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9753               aopPut (AOP (result), buff, offset);
9754             }
9755           offset++;
9756           if (size || pi)
9757             {
9758                 emitcode ("inc", "%s", rname);
9759             }
9760         }
9761     }
9762
9763   /* now some housekeeping stuff */
9764   if (aop)
9765     {
9766       /* we had to allocate for this iCode */
9767       if (pi) { /* post increment present */
9768         aopPut(AOP ( left ),rname,0);
9769       }
9770       freeAsmop (NULL, aop, ic, TRUE);
9771     }
9772   else
9773     {
9774       /* we did not allocate which means left
9775          already in a pointer register, then
9776          if size > 0 && this could be used again
9777          we have to point it back to where it
9778          belongs */
9779       if (AOP_SIZE (result) > 1 &&
9780           !OP_SYMBOL (left)->remat &&
9781           (OP_SYMBOL (left)->liveTo > ic->seq ||
9782            ic->depth) &&
9783           !pi)
9784         {
9785           int size = AOP_SIZE (result) - 1;
9786           while (size--)
9787             emitcode ("dec", "%s", rname);
9788         }
9789     }
9790
9791   /* done */
9792   freeAsmop (result, NULL, ic, TRUE);
9793   if (pi) pi->generated = 1;
9794 }
9795
9796 /*-----------------------------------------------------------------*/
9797 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9798 /*-----------------------------------------------------------------*/
9799 static void
9800 genPagedPointerGet (operand * left,
9801                     operand * result,
9802                     iCode * ic,
9803                     iCode * pi)
9804 {
9805   asmop *aop = NULL;
9806   regs *preg;
9807   char *rname;
9808   sym_link *rtype, *retype, *letype;
9809
9810   rtype = operandType (result);
9811   retype = getSpec (rtype);
9812   letype = getSpec (operandType (left));
9813   aopOp (left, ic, FALSE, FALSE);
9814
9815   /* if the value is already in a pointer register
9816      then don't need anything more */
9817   if (!AOP_INPREG (AOP (left)))
9818     {
9819       /* otherwise get a free pointer register */
9820       aop = newAsmop (0);
9821       preg = getFreePtr (ic, &aop, FALSE);
9822       emitcode ("mov", "%s,%s",
9823                 preg->name,
9824                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9825       rname = preg->name;
9826     }
9827   else
9828     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9829
9830   freeAsmop (left, NULL, ic, TRUE);
9831   aopOp (result, ic, FALSE, FALSE);
9832
9833   /* if bitfield then unpack the bits */
9834   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9835     genUnpackBits (result, rname, PPOINTER);
9836   else
9837     {
9838       /* we have can just get the values */
9839       int size = AOP_SIZE (result);
9840       int offset = 0;
9841
9842       while (size--)
9843         {
9844
9845           emitcode ("movx", "a,@%s", rname);
9846           aopPut (AOP (result), "a", offset);
9847
9848           offset++;
9849
9850           if (size || pi)
9851             emitcode ("inc", "%s", rname);
9852         }
9853     }
9854
9855   /* now some housekeeping stuff */
9856   if (aop)
9857     {
9858       /* we had to allocate for this iCode */
9859       if (pi) aopPut ( AOP (left), rname, 0);
9860       freeAsmop (NULL, aop, ic, TRUE);
9861     }
9862   else
9863     {
9864       /* we did not allocate which means left
9865          already in a pointer register, then
9866          if size > 0 && this could be used again
9867          we have to point it back to where it
9868          belongs */
9869       if (AOP_SIZE (result) > 1 &&
9870           !OP_SYMBOL (left)->remat &&
9871           (OP_SYMBOL (left)->liveTo > ic->seq ||
9872            ic->depth) &&
9873           !pi)
9874         {
9875           int size = AOP_SIZE (result) - 1;
9876           while (size--)
9877             emitcode ("dec", "%s", rname);
9878         }
9879     }
9880
9881   /* done */
9882   freeAsmop (result, NULL, ic, TRUE);
9883   if (pi) pi->generated = 1;
9884 }
9885
9886 /*-----------------------------------------------------------------*/
9887 /* genFarPointerGet - gget value from far space                    */
9888 /*-----------------------------------------------------------------*/
9889 static void
9890 genFarPointerGet (operand * left,
9891                   operand * result, iCode * ic, iCode *pi)
9892 {
9893     int size, offset, dopi=1;
9894   sym_link *retype = getSpec (operandType (result));
9895   sym_link *letype = getSpec (operandType (left));
9896   D (emitcode (";", "genFarPointerGet"););
9897
9898   aopOp (left, ic, FALSE, FALSE);
9899
9900   /* if the operand is already in dptr
9901      then we do nothing else we move the value to dptr */
9902   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9903     {
9904       /* if this is remateriazable */
9905       if (AOP_TYPE (left) == AOP_IMMD)
9906         {
9907           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9908         }
9909       else
9910         {
9911           /* we need to get it byte by byte */
9912           _startLazyDPSEvaluation ();
9913           if (AOP_TYPE (left) != AOP_DPTR)
9914             {
9915               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9916               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9917               if (options.model == MODEL_FLAT24)
9918                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9919             }
9920           else
9921             {
9922               /* We need to generate a load to DPTR indirect through DPTR. */
9923               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9924               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9925               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9926               if (options.model == MODEL_FLAT24)
9927                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9928               emitcode ("pop", "dph");
9929               emitcode ("pop", "dpl");
9930               dopi =0;
9931             }
9932           _endLazyDPSEvaluation ();
9933         }
9934     }
9935   /* so dptr know contains the address */
9936   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9937
9938   /* if bit then unpack */
9939   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9940       if (AOP_INDPTRn(left)) {
9941           genSetDPTR(AOP(left)->aopu.dptr);
9942       }
9943       genUnpackBits (result, "dptr", FPOINTER);
9944       if (AOP_INDPTRn(left)) {
9945           genSetDPTR(0);
9946       }
9947   } else
9948     {
9949       size = AOP_SIZE (result);
9950       offset = 0;
9951
9952       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9953           while (size--) {
9954               genSetDPTR(AOP(left)->aopu.dptr);
9955               emitcode ("movx", "a,@dptr");
9956               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9957                   emitcode ("inc", "dptr");
9958               genSetDPTR (0);
9959               aopPut (AOP (result), "a", offset++);
9960           }
9961       } else {
9962           _startLazyDPSEvaluation ();
9963           while (size--) {
9964               if (AOP_INDPTRn(left)) {
9965                   genSetDPTR(AOP(left)->aopu.dptr);
9966               } else {
9967                   genSetDPTR (0);
9968               }
9969               _flushLazyDPS ();
9970               
9971               emitcode ("movx", "a,@dptr");
9972               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9973                   emitcode ("inc", "dptr");
9974               
9975               aopPut (AOP (result), "a", offset++);
9976           }
9977           _endLazyDPSEvaluation ();
9978       }
9979     }
9980   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9981       if (!AOP_INDPTRn(left)) {
9982           _startLazyDPSEvaluation ();
9983           aopPut ( AOP (left), "dpl", 0);
9984           aopPut ( AOP (left), "dph", 1);
9985           if (options.model == MODEL_FLAT24)
9986               aopPut ( AOP (left), "dpx", 2);
9987           _endLazyDPSEvaluation ();
9988       }
9989     pi->generated = 1;
9990   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9991              AOP_SIZE(result) > 1 &&
9992              IS_SYMOP(left) &&
9993              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9994       
9995       size = AOP_SIZE (result) - 1;
9996       if (AOP_INDPTRn(left)) {
9997           genSetDPTR(AOP(left)->aopu.dptr);
9998       }
9999       while (size--) emitcode ("lcall","__decdptr");
10000       if (AOP_INDPTRn(left)) {
10001           genSetDPTR(0);
10002       }
10003   }
10004
10005   freeAsmop (left, NULL, ic, TRUE);
10006   freeAsmop (result, NULL, ic, TRUE);
10007 }
10008
10009 /*-----------------------------------------------------------------*/
10010 /* genCodePointerGet - get value from code space                  */
10011 /*-----------------------------------------------------------------*/
10012 static void
10013 genCodePointerGet (operand * left,
10014                     operand * result, iCode * ic, iCode *pi)
10015 {
10016   int size, offset, dopi=1;
10017   sym_link *retype = getSpec (operandType (result));
10018
10019   aopOp (left, ic, FALSE, FALSE);
10020
10021   /* if the operand is already in dptr
10022      then we do nothing else we move the value to dptr */
10023   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10024     {
10025       /* if this is remateriazable */
10026       if (AOP_TYPE (left) == AOP_IMMD)
10027         {
10028           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10029         }
10030       else
10031         {                       /* we need to get it byte by byte */
10032           _startLazyDPSEvaluation ();
10033           if (AOP_TYPE (left) != AOP_DPTR)
10034             {
10035               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10036               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10037               if (options.model == MODEL_FLAT24)
10038                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10039             }
10040           else
10041             {
10042               /* We need to generate a load to DPTR indirect through DPTR. */
10043               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10044               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10045               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10046               if (options.model == MODEL_FLAT24)
10047                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10048               emitcode ("pop", "dph");
10049               emitcode ("pop", "dpl");
10050               dopi=0;
10051             }
10052           _endLazyDPSEvaluation ();
10053         }
10054     }
10055   /* so dptr know contains the address */
10056   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10057
10058   /* if bit then unpack */
10059   if (IS_BITFIELD (retype)) {
10060       if (AOP_INDPTRn(left)) {
10061           genSetDPTR(AOP(left)->aopu.dptr);
10062       }
10063       genUnpackBits (result, "dptr", CPOINTER);
10064       if (AOP_INDPTRn(left)) {
10065           genSetDPTR(0);
10066       }
10067   } else
10068     {
10069       size = AOP_SIZE (result);
10070       offset = 0;
10071       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10072           while (size--) {
10073               genSetDPTR(AOP(left)->aopu.dptr);
10074               emitcode ("clr", "a");
10075               emitcode ("movc", "a,@a+dptr");
10076               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10077                   emitcode ("inc", "dptr");
10078               genSetDPTR (0);
10079               aopPut (AOP (result), "a", offset++);
10080           }
10081       } else {
10082           _startLazyDPSEvaluation ();
10083           while (size--)
10084               {
10085                   if (AOP_INDPTRn(left)) {
10086                       genSetDPTR(AOP(left)->aopu.dptr);
10087                   } else {
10088                       genSetDPTR (0);
10089                   }
10090                   _flushLazyDPS ();
10091                   
10092                   emitcode ("clr", "a");
10093                   emitcode ("movc", "a,@a+dptr");
10094                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10095                       emitcode ("inc", "dptr");
10096                   aopPut (AOP (result), "a", offset++);
10097               }
10098           _endLazyDPSEvaluation ();
10099       }
10100     }
10101   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10102       if (!AOP_INDPTRn(left)) {
10103           _startLazyDPSEvaluation ();
10104           
10105           aopPut ( AOP (left), "dpl", 0);
10106           aopPut ( AOP (left), "dph", 1);
10107           if (options.model == MODEL_FLAT24)
10108               aopPut ( AOP (left), "dpx", 2);
10109
10110           _endLazyDPSEvaluation ();
10111       }
10112       pi->generated = 1;
10113   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
10114              AOP_SIZE(result) > 1 &&
10115              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10116       
10117       size = AOP_SIZE (result) - 1;
10118       if (AOP_INDPTRn(left)) {
10119           genSetDPTR(AOP(left)->aopu.dptr);
10120       }
10121       while (size--) emitcode ("lcall","__decdptr");
10122       if (AOP_INDPTRn(left)) {
10123           genSetDPTR(0);
10124       }
10125   }
10126   
10127   freeAsmop (left, NULL, ic, TRUE);
10128   freeAsmop (result, NULL, ic, TRUE);
10129 }
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genGenPointerGet - gget value from generic pointer space        */
10133 /*-----------------------------------------------------------------*/
10134 static void
10135 genGenPointerGet (operand * left,
10136                   operand * result, iCode * ic, iCode * pi)
10137 {
10138   int size, offset;
10139   sym_link *retype = getSpec (operandType (result));
10140   sym_link *letype = getSpec (operandType (left));
10141
10142   D (emitcode (";", "genGenPointerGet "); );
10143
10144   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10145
10146   /* if the operand is already in dptr
10147      then we do nothing else we move the value to dptr */
10148   if (AOP_TYPE (left) != AOP_STR)
10149     {
10150       /* if this is remateriazable */
10151       if (AOP_TYPE (left) == AOP_IMMD)
10152         {
10153           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10154           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
10155             {
10156                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10157             }
10158             else
10159             {
10160                 emitcode ("mov", "b,#%d", pointerCode (retype));
10161             }
10162         }
10163       else
10164         {                       /* we need to get it byte by byte */
10165             _startLazyDPSEvaluation ();
10166             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10167             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10168             if (options.model == MODEL_FLAT24) {
10169                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10170                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10171             } else {
10172                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10173             }
10174             _endLazyDPSEvaluation ();
10175         }
10176     }
10177
10178   /* so dptr-b now contains the address */
10179   _G.bInUse++;
10180   aopOp (result, ic, FALSE, TRUE);
10181   _G.bInUse--;
10182
10183   /* if bit then unpack */
10184   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10185   {
10186     genUnpackBits (result, "dptr", GPOINTER);
10187   }
10188   else
10189     {
10190         size = AOP_SIZE (result);
10191         offset = 0;
10192
10193         while (size--)
10194         {
10195             if (size)
10196             {
10197                 // Get two bytes at a time, results in _AP & A.
10198                 // dptr will be incremented ONCE by __gptrgetWord.
10199                 //
10200                 // Note: any change here must be coordinated
10201                 // with the implementation of __gptrgetWord
10202                 // in device/lib/_gptrget.c
10203                 emitcode ("lcall", "__gptrgetWord");
10204                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10205                 aopPut (AOP (result), "a", offset++);
10206                 size--;
10207             }
10208             else
10209             {
10210                 // Only one byte to get.
10211                 emitcode ("lcall", "__gptrget");
10212                 aopPut (AOP (result), "a", offset++);
10213             }
10214             
10215             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10216             {
10217                 emitcode ("inc", "dptr");
10218             }
10219         }
10220     }
10221
10222   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10223     _startLazyDPSEvaluation ();
10224       
10225     aopPut ( AOP (left), "dpl", 0);
10226     aopPut ( AOP (left), "dph", 1);
10227     if (options.model == MODEL_FLAT24) {
10228         aopPut ( AOP (left), "dpx", 2);
10229         aopPut ( AOP (left), "b", 3);   
10230     } else  aopPut ( AOP (left), "b", 2);       
10231     
10232     _endLazyDPSEvaluation ();
10233       
10234     pi->generated = 1;
10235   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10236              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10237       
10238       size = AOP_SIZE (result) - 1;
10239       while (size--) emitcode ("lcall","__decdptr");
10240   }
10241
10242   freeAsmop (left, NULL, ic, TRUE);
10243   freeAsmop (result, NULL, ic, TRUE);
10244 }
10245
10246 /*-----------------------------------------------------------------*/
10247 /* genPointerGet - generate code for pointer get                   */
10248 /*-----------------------------------------------------------------*/
10249 static void
10250 genPointerGet (iCode * ic, iCode *pi)
10251 {
10252   operand *left, *result;
10253   sym_link *type, *etype;
10254   int p_type;
10255
10256   D (emitcode (";", "genPointerGet ");
10257     );
10258
10259   left = IC_LEFT (ic);
10260   result = IC_RESULT (ic);
10261
10262   /* depending on the type of pointer we need to
10263      move it to the correct pointer register */
10264   type = operandType (left);
10265   etype = getSpec (type);
10266   /* if left is of type of pointer then it is simple */
10267   if (IS_PTR (type) && !IS_FUNC (type->next))
10268     p_type = DCL_TYPE (type);
10269   else
10270     {
10271       /* we have to go by the storage class */
10272       p_type = PTR_TYPE (SPEC_OCLS (etype));
10273     }
10274   /* special case when cast remat */
10275   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10276       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10277           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10278           type = operandType (left);
10279           p_type = DCL_TYPE (type);
10280   }
10281   /* now that we have the pointer type we assign
10282      the pointer values */
10283   switch (p_type)
10284     {
10285
10286     case POINTER:
10287     case IPOINTER:
10288       genNearPointerGet (left, result, ic, pi);
10289       break;
10290
10291     case PPOINTER:
10292       genPagedPointerGet (left, result, ic, pi);
10293       break;
10294
10295     case FPOINTER:
10296       genFarPointerGet (left, result, ic, pi);
10297       break;
10298
10299     case CPOINTER:
10300       genCodePointerGet (left, result, ic, pi);
10301       break;
10302
10303     case GPOINTER:
10304       genGenPointerGet (left, result, ic, pi);
10305       break;
10306     }
10307
10308 }
10309
10310 /*-----------------------------------------------------------------*/
10311 /* genPackBits - generates code for packed bit storage             */
10312 /*-----------------------------------------------------------------*/
10313 static void
10314 genPackBits (sym_link * etype,
10315              operand * right,
10316              char *rname, int p_type)
10317 {
10318   int offset = 0;       /* source byte offset */
10319   int rlen = 0;         /* remaining bitfield length */
10320   int blen;             /* bitfield length */
10321   int bstr;             /* bitfield starting bit within byte */
10322   int litval;           /* source literal value (if AOP_LIT) */
10323   unsigned char mask;   /* bitmask within current byte */
10324
10325   D(emitcode (";     genPackBits",""));
10326
10327   blen = SPEC_BLEN (etype);
10328   bstr = SPEC_BSTR (etype);
10329
10330   /* If the bitfield length is less than a byte */
10331   if (blen < 8)
10332     {
10333       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10334               (unsigned char) (0xFF >> (8 - bstr)));
10335
10336       if (AOP_TYPE (right) == AOP_LIT)
10337         {
10338           /* Case with a bitfield length <8 and literal source
10339           */
10340           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10341           litval <<= bstr;
10342           litval &= (~mask) & 0xff;
10343           emitPtrByteGet (rname, p_type, FALSE);
10344           if ((mask|litval)!=0xff)
10345             emitcode ("anl","a,#!constbyte", mask);
10346           if (litval)
10347             emitcode ("orl","a,#!constbyte", litval);
10348         }
10349       else
10350         {
10351           if ((blen==1) && (p_type!=GPOINTER))
10352             {
10353               /* Case with a bitfield length == 1 and no generic pointer
10354               */
10355               if (AOP_TYPE (right) == AOP_CRY)
10356                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10357               else
10358                 {
10359                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10360                   emitcode ("rrc","a");
10361                 }
10362               emitPtrByteGet (rname, p_type, FALSE);
10363               emitcode ("mov","acc.%d,c",bstr);
10364             }
10365           else
10366             {
10367               /* Case with a bitfield length < 8 and arbitrary source
10368               */
10369               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10370               /* shift and mask source value */
10371               AccLsh (bstr);
10372               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10373
10374               /* transfer A to B and get next byte */
10375               emitPtrByteGet (rname, p_type, TRUE);
10376
10377               emitcode ("anl", "a,#!constbyte", mask);
10378               emitcode ("orl", "a,b");
10379               if (p_type == GPOINTER)
10380                 emitcode ("pop", "b");
10381            }
10382         }
10383
10384       emitPtrByteSet (rname, p_type, "a");
10385       return;
10386     }
10387
10388   /* Bit length is greater than 7 bits. In this case, copy  */
10389   /* all except the partial byte at the end                 */
10390   for (rlen=blen;rlen>=8;rlen-=8)
10391     {
10392       emitPtrByteSet (rname, p_type, 
10393                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10394       if (rlen>8)
10395         emitcode ("inc", "%s", rname);
10396     }
10397
10398   /* If there was a partial byte at the end */
10399   if (rlen)
10400     {
10401       mask = (((unsigned char) -1 << rlen) & 0xff);
10402       
10403       if (AOP_TYPE (right) == AOP_LIT)
10404         {
10405           /* Case with partial byte and literal source
10406           */
10407           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10408           litval >>= (blen-rlen);
10409           litval &= (~mask) & 0xff;
10410           emitPtrByteGet (rname, p_type, FALSE);
10411           if ((mask|litval)!=0xff)
10412             emitcode ("anl","a,#!constbyte", mask);
10413           if (litval)
10414             emitcode ("orl","a,#!constbyte", litval);
10415         }
10416       else
10417         {
10418           /* Case with partial byte and arbitrary source
10419           */
10420           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10421           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10422
10423           /* transfer A to B and get next byte */
10424           emitPtrByteGet (rname, p_type, TRUE);
10425
10426           emitcode ("anl", "a,#!constbyte", mask);
10427           emitcode ("orl", "a,b");
10428           if (p_type == GPOINTER)
10429             emitcode ("pop", "b");
10430         }
10431       emitPtrByteSet (rname, p_type, "a");
10432     }
10433
10434 }
10435
10436
10437 /*-----------------------------------------------------------------*/
10438 /* genDataPointerSet - remat pointer to data space                 */
10439 /*-----------------------------------------------------------------*/
10440 static void
10441 genDataPointerSet (operand * right,
10442                    operand * result,
10443                    iCode * ic)
10444 {
10445   int size, offset = 0;
10446   char *l, buff[256];
10447
10448   aopOp (right, ic, FALSE, FALSE);
10449
10450   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10451   size = AOP_SIZE (right);
10452   while (size--)
10453     {
10454       if (offset)
10455         {
10456             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10457         }
10458       else
10459         {
10460             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10461         }
10462         
10463       emitcode ("mov", "%s,%s", buff,
10464                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10465     }
10466
10467   freeAsmop (right, NULL, ic, TRUE);
10468   freeAsmop (result, NULL, ic, TRUE);
10469 }
10470
10471 /*-----------------------------------------------------------------*/
10472 /* genNearPointerSet - emitcode for near pointer put                */
10473 /*-----------------------------------------------------------------*/
10474 static void
10475 genNearPointerSet (operand * right,
10476                    operand * result,
10477                    iCode * ic,
10478                    iCode * pi)
10479 {
10480   asmop *aop = NULL;
10481   char *rname, *l;
10482   sym_link *retype, *letype;
10483   sym_link *ptype = operandType (result);
10484
10485   retype = getSpec (operandType (right));
10486   letype = getSpec (ptype);
10487
10488   aopOp (result, ic, FALSE, FALSE);
10489
10490   /* if the result is rematerializable &
10491      in data space & not a bit variable */
10492   if (AOP_TYPE (result) == AOP_IMMD &&
10493       DCL_TYPE (ptype) == POINTER &&
10494       !IS_BITVAR (retype) &&
10495       !IS_BITVAR (letype))
10496     {
10497       genDataPointerSet (right, result, ic);
10498       return;
10499     }
10500
10501   /* if the value is already in a pointer register
10502      then don't need anything more */
10503   if (!AOP_INPREG (AOP (result)))
10504     {
10505       /* otherwise get a free pointer register */
10506       regs *preg;
10507         
10508       aop = newAsmop (0);
10509       preg = getFreePtr (ic, &aop, FALSE);
10510       emitcode ("mov", "%s,%s",
10511                 preg->name,
10512                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10513       rname = preg->name;
10514     }
10515   else
10516     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10517
10518   aopOp (right, ic, FALSE, FALSE);
10519
10520   /* if bitfield then unpack the bits */
10521   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10522     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10523   else
10524     {
10525       /* we have can just get the values */
10526       int size = AOP_SIZE (right);
10527       int offset = 0;
10528
10529       while (size--)
10530         {
10531           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10532           if (*l == '@')
10533             {
10534               MOVA (l);
10535               emitcode ("mov", "@%s,a", rname);
10536             }
10537           else
10538             emitcode ("mov", "@%s,%s", rname, l);
10539           if (size || pi)
10540             emitcode ("inc", "%s", rname);
10541           offset++;
10542         }
10543     }
10544
10545   /* now some housekeeping stuff */
10546   if (aop)
10547     {
10548       /* we had to allocate for this iCode */
10549       if (pi) aopPut (AOP (result),rname,0);
10550       freeAsmop (NULL, aop, ic, TRUE);
10551     }
10552   else
10553     {
10554       /* we did not allocate which means left
10555          already in a pointer register, then
10556          if size > 0 && this could be used again
10557          we have to point it back to where it
10558          belongs */
10559       if (AOP_SIZE (right) > 1 &&
10560           !OP_SYMBOL (result)->remat &&
10561           (OP_SYMBOL (result)->liveTo > ic->seq ||
10562            ic->depth) &&
10563           !pi)
10564         {
10565           int size = AOP_SIZE (right) - 1;
10566           while (size--)
10567             emitcode ("dec", "%s", rname);
10568         }
10569     }
10570
10571   /* done */
10572   if (pi) pi->generated = 1;
10573   freeAsmop (result, NULL, ic, TRUE);
10574   freeAsmop (right, NULL, ic, TRUE);
10575
10576
10577 }
10578
10579 /*-----------------------------------------------------------------*/
10580 /* genPagedPointerSet - emitcode for Paged pointer put             */
10581 /*-----------------------------------------------------------------*/
10582 static void
10583 genPagedPointerSet (operand * right,
10584                     operand * result,
10585                     iCode * ic,
10586                     iCode *pi)
10587 {
10588   asmop *aop = NULL;
10589   char *rname;
10590   sym_link *retype, *letype;
10591
10592   retype = getSpec (operandType (right));
10593   letype = getSpec (operandType (result));
10594
10595   aopOp (result, ic, FALSE, FALSE);
10596
10597   /* if the value is already in a pointer register
10598      then don't need anything more */
10599   if (!AOP_INPREG (AOP (result)))
10600     {
10601       /* otherwise get a free pointer register */
10602       regs *preg;
10603         
10604       aop = newAsmop (0);
10605       preg = getFreePtr (ic, &aop, FALSE);
10606       emitcode ("mov", "%s,%s",
10607                 preg->name,
10608                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10609       rname = preg->name;
10610     }
10611   else
10612     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10613
10614   aopOp (right, ic, FALSE, FALSE);
10615
10616   /* if bitfield then unpack the bits */
10617   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10618     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10619   else
10620     {
10621       /* we have can just get the values */
10622       int size = AOP_SIZE (right);
10623       int offset = 0;
10624
10625       while (size--)
10626         {
10627           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10628
10629           emitcode ("movx", "@%s,a", rname);
10630
10631           if (size || pi)
10632             emitcode ("inc", "%s", rname);
10633
10634           offset++;
10635         }
10636     }
10637
10638   /* now some housekeeping stuff */
10639   if (aop)
10640     {
10641       if (pi) aopPut (AOP (result),rname,0);
10642       /* we had to allocate for this iCode */
10643       freeAsmop (NULL, aop, ic, TRUE);
10644     }
10645   else
10646     {
10647       /* we did not allocate which means left
10648          already in a pointer register, then
10649          if size > 0 && this could be used again
10650          we have to point it back to where it
10651          belongs */
10652       if (AOP_SIZE (right) > 1 &&
10653           !OP_SYMBOL (result)->remat &&
10654           (OP_SYMBOL (result)->liveTo > ic->seq ||
10655            ic->depth) &&
10656           !pi)
10657         {
10658           int size = AOP_SIZE (right) - 1;
10659           while (size--)
10660             emitcode ("dec", "%s", rname);
10661         }
10662     }
10663
10664   /* done */
10665   if (pi) pi->generated = 1;
10666   freeAsmop (result, NULL, ic, TRUE);
10667   freeAsmop (right, NULL, ic, TRUE);
10668
10669
10670 }
10671
10672 /*-----------------------------------------------------------------*/
10673 /* genFarPointerSet - set value from far space                     */
10674 /*-----------------------------------------------------------------*/
10675 static void
10676 genFarPointerSet (operand * right,
10677                   operand * result, iCode * ic, iCode *pi)
10678 {
10679   int size, offset, dopi=1;
10680   sym_link *retype = getSpec (operandType (right));
10681   sym_link *letype = getSpec (operandType (result));
10682
10683   aopOp (result, ic, FALSE, FALSE);
10684
10685   /* if the operand is already in dptr
10686      then we do nothing else we move the value to dptr */
10687   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10688     {
10689       /* if this is remateriazable */
10690       if (AOP_TYPE (result) == AOP_IMMD)
10691         emitcode ("mov", "dptr,%s", 
10692                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10693       else
10694         {
10695           /* we need to get it byte by byte */
10696           _startLazyDPSEvaluation ();
10697           if (AOP_TYPE (result) != AOP_DPTR)
10698             {
10699               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10700               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10701               if (options.model == MODEL_FLAT24)
10702                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10703             }
10704           else
10705             {
10706               /* We need to generate a load to DPTR indirect through DPTR. */
10707               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10708                 
10709               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10710               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10711               if (options.model == MODEL_FLAT24)
10712                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10713               emitcode ("pop", "dph");
10714               emitcode ("pop", "dpl");
10715               dopi=0;
10716             }
10717           _endLazyDPSEvaluation ();
10718         }
10719     }
10720   /* so dptr know contains the address */
10721   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10722
10723   /* if bit then unpack */
10724   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10725       if (AOP_INDPTRn(result)) {
10726           genSetDPTR(AOP(result)->aopu.dptr);
10727       }
10728       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10729       if (AOP_INDPTRn(result)) {
10730           genSetDPTR(0);
10731       }
10732   } else {
10733       size = AOP_SIZE (right);
10734       offset = 0;
10735       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10736           while (size--) {
10737               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10738               
10739               genSetDPTR(AOP(result)->aopu.dptr);
10740               emitcode ("movx", "@dptr,a");
10741               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10742                   emitcode ("inc", "dptr");
10743               genSetDPTR (0);
10744           }
10745       } else {
10746           _startLazyDPSEvaluation ();
10747           while (size--) {
10748               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10749               
10750               if (AOP_INDPTRn(result)) {
10751                   genSetDPTR(AOP(result)->aopu.dptr);
10752               } else {
10753                   genSetDPTR (0);
10754               }
10755               _flushLazyDPS ();
10756               
10757               emitcode ("movx", "@dptr,a");
10758               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10759                   emitcode ("inc", "dptr");
10760           }
10761           _endLazyDPSEvaluation ();
10762       }
10763   }
10764   
10765   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10766       if (!AOP_INDPTRn(result)) {
10767           _startLazyDPSEvaluation ();
10768           
10769           aopPut (AOP(result),"dpl",0);
10770           aopPut (AOP(result),"dph",1);
10771           if (options.model == MODEL_FLAT24)
10772               aopPut (AOP(result),"dpx",2);
10773
10774           _endLazyDPSEvaluation ();
10775       }
10776       pi->generated=1;
10777   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10778              AOP_SIZE(right) > 1 &&
10779              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10780       
10781       size = AOP_SIZE (right) - 1;
10782       if (AOP_INDPTRn(result)) {
10783           genSetDPTR(AOP(result)->aopu.dptr);
10784       } 
10785       while (size--) emitcode ("lcall","__decdptr");
10786       if (AOP_INDPTRn(result)) {
10787           genSetDPTR(0);
10788       }
10789   }
10790   freeAsmop (result, NULL, ic, TRUE);
10791   freeAsmop (right, NULL, ic, TRUE);
10792 }
10793
10794 /*-----------------------------------------------------------------*/
10795 /* genGenPointerSet - set value from generic pointer space         */
10796 /*-----------------------------------------------------------------*/
10797 static void
10798 genGenPointerSet (operand * right,
10799                   operand * result, iCode * ic, iCode *pi)
10800 {
10801   int size, offset;
10802   sym_link *retype = getSpec (operandType (right));
10803   sym_link *letype = getSpec (operandType (result));
10804
10805   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10806
10807   /* if the operand is already in dptr
10808      then we do nothing else we move the value to dptr */
10809   if (AOP_TYPE (result) != AOP_STR)
10810     {
10811       _startLazyDPSEvaluation ();
10812       /* if this is remateriazable */
10813       if (AOP_TYPE (result) == AOP_IMMD)
10814         {
10815           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10816           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10817           {
10818               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10819           }
10820           else
10821           {
10822               emitcode ("mov", 
10823                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10824           }
10825         }
10826       else
10827         {                       /* we need to get it byte by byte */
10828           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10829           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10830           if (options.model == MODEL_FLAT24) {
10831             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10832             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10833           } else {
10834             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10835           }
10836         }
10837       _endLazyDPSEvaluation ();
10838     }
10839   /* so dptr + b now contains the address */
10840   _G.bInUse++;
10841   aopOp (right, ic, FALSE, TRUE);
10842   _G.bInUse--;
10843     
10844
10845   /* if bit then unpack */
10846   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10847     {
10848         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10849     }
10850   else
10851     {
10852         size = AOP_SIZE (right);
10853         offset = 0;
10854
10855         _startLazyDPSEvaluation ();
10856         while (size--)
10857         {
10858             if (size)
10859             {
10860                 // Set two bytes at a time, passed in _AP & A.
10861                 // dptr will be incremented ONCE by __gptrputWord.
10862                 //
10863                 // Note: any change here must be coordinated
10864                 // with the implementation of __gptrputWord
10865                 // in device/lib/_gptrput.c
10866                 emitcode("mov", "_ap, %s", 
10867                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10868                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10869                 
10870                 genSetDPTR (0);
10871                 _flushLazyDPS ();
10872                 emitcode ("lcall", "__gptrputWord");
10873                 size--;
10874             }
10875             else
10876             {
10877                 // Only one byte to put.
10878                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10879
10880                 genSetDPTR (0);
10881                 _flushLazyDPS ();               
10882                 emitcode ("lcall", "__gptrput");
10883             }
10884             
10885             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10886             {
10887                 emitcode ("inc", "dptr");
10888             }
10889         }
10890         _endLazyDPSEvaluation ();
10891     }
10892
10893   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10894       _startLazyDPSEvaluation ();
10895       
10896       aopPut (AOP(result),"dpl",0);
10897       aopPut (AOP(result),"dph",1);
10898       if (options.model == MODEL_FLAT24) {
10899           aopPut (AOP(result),"dpx",2);
10900           aopPut (AOP(result),"b",3);
10901       } else {
10902           aopPut (AOP(result),"b",2);
10903       }
10904       _endLazyDPSEvaluation ();
10905       
10906       pi->generated=1;
10907   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10908              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10909       
10910       size = AOP_SIZE (right) - 1;
10911       while (size--) emitcode ("lcall","__decdptr");
10912   }
10913   freeAsmop (result, NULL, ic, TRUE);
10914   freeAsmop (right, NULL, ic, TRUE);
10915 }
10916
10917 /*-----------------------------------------------------------------*/
10918 /* genPointerSet - stores the value into a pointer location        */
10919 /*-----------------------------------------------------------------*/
10920 static void
10921 genPointerSet (iCode * ic, iCode *pi)
10922 {
10923   operand *right, *result;
10924   sym_link *type, *etype;
10925   int p_type;
10926
10927   D (emitcode (";", "genPointerSet "););
10928
10929   right = IC_RIGHT (ic);
10930   result = IC_RESULT (ic);
10931
10932   /* depending on the type of pointer we need to
10933      move it to the correct pointer register */
10934   type = operandType (result);
10935   etype = getSpec (type);
10936   /* if left is of type of pointer then it is simple */
10937   if (IS_PTR (type) && !IS_FUNC (type->next))
10938     {
10939       p_type = DCL_TYPE (type);
10940     }
10941   else
10942     {
10943       /* we have to go by the storage class */
10944       p_type = PTR_TYPE (SPEC_OCLS (etype));
10945     }
10946   /* special case when cast remat */
10947   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10948       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10949           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10950           type = operandType (result);
10951           p_type = DCL_TYPE (type);
10952   }
10953
10954   /* now that we have the pointer type we assign
10955      the pointer values */
10956   switch (p_type)
10957     {
10958
10959     case POINTER:
10960     case IPOINTER:
10961       genNearPointerSet (right, result, ic, pi);
10962       break;
10963
10964     case PPOINTER:
10965       genPagedPointerSet (right, result, ic, pi);
10966       break;
10967
10968     case FPOINTER:
10969       genFarPointerSet (right, result, ic, pi);
10970       break;
10971
10972     case GPOINTER:
10973       genGenPointerSet (right, result, ic, pi);
10974       break;
10975
10976     default:
10977       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10978               "genPointerSet: illegal pointer type");
10979     }
10980
10981 }
10982
10983 /*-----------------------------------------------------------------*/
10984 /* genIfx - generate code for Ifx statement                        */
10985 /*-----------------------------------------------------------------*/
10986 static void
10987 genIfx (iCode * ic, iCode * popIc)
10988 {
10989   operand *cond = IC_COND (ic);
10990   int isbit = 0;
10991
10992   D (emitcode (";", "genIfx "););
10993
10994   aopOp (cond, ic, FALSE, FALSE);
10995
10996   /* get the value into acc */
10997   if (AOP_TYPE (cond) != AOP_CRY)
10998     {
10999         toBoolean (cond);
11000     }
11001   else
11002     {
11003         isbit = 1;
11004     }
11005     
11006   /* the result is now in the accumulator */
11007   freeAsmop (cond, NULL, ic, TRUE);
11008
11009   /* if there was something to be popped then do it */
11010   if (popIc)
11011     genIpop (popIc);
11012
11013   /* if the condition is  a bit variable */
11014   if (isbit && IS_ITEMP (cond) &&
11015       SPIL_LOC (cond))
11016     {
11017         genIfxJump (ic, SPIL_LOC (cond)->rname);
11018     }
11019   else if (isbit && !IS_ITEMP (cond))
11020     {
11021         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11022     }
11023   else
11024     {
11025         genIfxJump (ic, "a");
11026     }
11027
11028   ic->generated = 1;
11029 }
11030
11031 /*-----------------------------------------------------------------*/
11032 /* genAddrOf - generates code for address of                       */
11033 /*-----------------------------------------------------------------*/
11034 static void
11035 genAddrOf (iCode * ic)
11036 {
11037   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11038   int size, offset;
11039
11040   D (emitcode (";", "genAddrOf ");
11041     );
11042
11043   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11044
11045   /* if the operand is on the stack then we
11046      need to get the stack offset of this
11047      variable */
11048   if (sym->onStack) {
11049       
11050       /* if 10 bit stack */
11051       if (options.stack10bit) {
11052           char buff[10];
11053           int  offset;
11054           
11055           tsprintf(buff, sizeof(buff), 
11056                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11057           /* if it has an offset then we need to compute it */
11058 /*        emitcode ("subb", "a,#!constbyte", */
11059 /*                  -((sym->stack < 0) ? */
11060 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11061 /*                    ((short) sym->stack)) & 0xff); */
11062 /*        emitcode ("mov","b,a"); */
11063 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11064 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11065 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11066           if (sym->stack) {
11067               emitcode ("mov", "a,_bpx");
11068               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
11069                                              ((char) (sym->stack - _G.nRegsSaved)) :
11070                                              ((char) sym->stack )) & 0xff);
11071               emitcode ("mov", "b,a");
11072               emitcode ("mov", "a,_bpx+1");
11073               
11074               offset = (((sym->stack < 0) ? 
11075                          ((short) (sym->stack - _G.nRegsSaved)) :
11076                          ((short) sym->stack )) >> 8) & 0xff;
11077           
11078               emitcode ("addc","a,#!constbyte", offset);
11079
11080               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11081               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11082               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11083           } else {
11084               /* we can just move _bp */
11085               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11086               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11087               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11088           }       
11089       } else {
11090           /* if it has an offset then we need to compute it */
11091           if (sym->stack) {
11092               emitcode ("mov", "a,_bp");
11093               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11094               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11095           } else {
11096               /* we can just move _bp */
11097               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11098           }
11099           /* fill the result with zero */
11100           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11101           
11102           
11103           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11104               fprintf (stderr,
11105                        "*** warning: pointer to stack var truncated.\n");
11106           }
11107
11108           offset = 1;
11109           while (size--) {
11110               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11111           }      
11112       }
11113       goto release;
11114   }
11115
11116   /* object not on stack then we need the name */
11117   size = AOP_SIZE (IC_RESULT (ic));
11118   offset = 0;
11119
11120   while (size--)
11121     {
11122       char s[SDCC_NAME_MAX];
11123       if (offset) {
11124           switch (offset) {
11125           case 1:
11126               tsprintf(s, sizeof(s), "#!his",sym->rname);
11127               break;
11128           case 2:
11129               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11130               break;
11131           case 3:
11132               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11133               break;
11134           default: /* should not need this (just in case) */
11135               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11136                        sym->rname,
11137                        offset * 8);
11138           }
11139       } 
11140       else
11141       {
11142           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11143       }
11144         
11145       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11146     }
11147
11148 release:
11149   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11150
11151 }
11152
11153 #if 0 // obsolete, and buggy for != xdata
11154 /*-----------------------------------------------------------------*/
11155 /* genArrayInit - generates code for address of                       */
11156 /*-----------------------------------------------------------------*/
11157 static void
11158 genArrayInit (iCode * ic)
11159 {
11160     literalList *iLoop;
11161     int         ix, count;
11162     int         elementSize = 0, eIndex;
11163     unsigned    val, lastVal;
11164     sym_link    *type;
11165     operand     *left=IC_LEFT(ic);
11166     
11167     D (emitcode (";", "genArrayInit "););
11168
11169     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11170     
11171     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11172     {
11173         // Load immediate value into DPTR.
11174         emitcode("mov", "dptr, %s",
11175              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11176     }
11177     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11178     {
11179 #if 0
11180       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11181               "Unexpected operand to genArrayInit.\n");
11182       exit(1);
11183 #else
11184       // a regression because of SDCCcse.c:1.52
11185       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11186       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11187       if (options.model == MODEL_FLAT24)
11188         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11189 #endif
11190     }
11191     
11192     type = operandType(IC_LEFT(ic));
11193     
11194     if (type && type->next)
11195     {
11196         elementSize = getSize(type->next);
11197     }
11198     else
11199     {
11200         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11201                                 "can't determine element size in genArrayInit.\n");
11202         exit(1);
11203     }
11204     
11205     iLoop = IC_ARRAYILIST(ic);
11206     lastVal = 0xffff;
11207     
11208     while (iLoop)
11209     {
11210         bool firstpass = TRUE;
11211         
11212         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
11213                  iLoop->count, (int)iLoop->literalValue, elementSize);
11214         
11215         ix = iLoop->count;
11216         
11217         while (ix)
11218         {
11219             symbol *tlbl = NULL;
11220             
11221             count = ix > 256 ? 256 : ix;
11222             
11223             if (count > 1)
11224             {
11225                 tlbl = newiTempLabel (NULL);
11226                 if (firstpass || (count & 0xff))
11227                 {
11228                     emitcode("mov", "b, #!constbyte", count & 0xff);
11229                 }
11230                 
11231                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11232             }
11233             
11234             firstpass = FALSE;
11235                 
11236             for (eIndex = 0; eIndex < elementSize; eIndex++)
11237             {
11238                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11239                 if (val != lastVal)
11240                 {
11241                     emitcode("mov", "a, #!constbyte", val);
11242                     lastVal = val;
11243                 }
11244                 
11245                 emitcode("movx", "@dptr, a");
11246                 emitcode("inc", "dptr");
11247             }
11248             
11249             if (count > 1)
11250             {
11251                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11252             }
11253             
11254             ix -= count;
11255         }
11256         
11257         iLoop = iLoop->next;
11258     }
11259     
11260     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11261 }
11262 #endif
11263
11264 /*-----------------------------------------------------------------*/
11265 /* genFarFarAssign - assignment when both are in far space         */
11266 /*-----------------------------------------------------------------*/
11267 static void
11268 genFarFarAssign (operand * result, operand * right, iCode * ic)
11269 {
11270   int size = AOP_SIZE (right);
11271   int offset = 0;
11272   symbol *rSym = NULL;
11273
11274   if (size == 1)
11275   {
11276       /* quick & easy case. */
11277       D(emitcode(";","genFarFarAssign (1 byte case)"););      
11278       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11279       freeAsmop (right, NULL, ic, FALSE);
11280       /* now assign DPTR to result */
11281       _G.accInUse++;
11282       aopOp(result, ic, FALSE, FALSE);
11283       _G.accInUse--;
11284       aopPut(AOP(result), "a", 0);
11285       freeAsmop(result, NULL, ic, FALSE);
11286       return;
11287   }
11288   
11289   /* See if we've got an underlying symbol to abuse. */
11290   if (IS_SYMOP(result) && OP_SYMBOL(result))
11291   {
11292       if (IS_TRUE_SYMOP(result))
11293       {
11294           rSym = OP_SYMBOL(result);
11295       }
11296       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11297       {
11298           rSym = OP_SYMBOL(result)->usl.spillLoc;
11299       }
11300   }
11301              
11302   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11303   {
11304       /* We can use the '390 auto-toggle feature to good effect here. */
11305       
11306       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11307       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11308       emitcode ("mov", "dptr,#%s", rSym->rname); 
11309       /* DP2 = result, DP1 = right, DP1 is current. */
11310       while (size)
11311       {
11312           emitcode("movx", "a,@dptr");
11313           emitcode("movx", "@dptr,a");
11314           if (--size)
11315           {
11316                emitcode("inc", "dptr");
11317                emitcode("inc", "dptr");
11318           }
11319       }
11320       emitcode("mov", "dps,#0");
11321       freeAsmop (right, NULL, ic, FALSE);
11322 #if 0
11323 some alternative code for processors without auto-toggle
11324 no time to test now, so later well put in...kpb
11325         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11326         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11327         emitcode ("mov", "dptr,#%s", rSym->rname); 
11328         /* DP2 = result, DP1 = right, DP1 is current. */
11329         while (size)
11330         {
11331           --size;
11332           emitcode("movx", "a,@dptr");
11333           if (size)
11334             emitcode("inc", "dptr");
11335           emitcode("inc", "dps");
11336           emitcode("movx", "@dptr,a");
11337           if (size)
11338             emitcode("inc", "dptr");
11339           emitcode("inc", "dps");
11340         }
11341         emitcode("mov", "dps,#0");
11342         freeAsmop (right, NULL, ic, FALSE);
11343 #endif
11344   }
11345   else
11346   {
11347       D (emitcode (";", "genFarFarAssign"););
11348       aopOp (result, ic, TRUE, TRUE);
11349
11350       _startLazyDPSEvaluation ();
11351       
11352       while (size--)
11353         {
11354           aopPut (AOP (result),
11355                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11356           offset++;
11357         }
11358       _endLazyDPSEvaluation ();
11359       freeAsmop (result, NULL, ic, FALSE);
11360       freeAsmop (right, NULL, ic, FALSE);
11361   }
11362 }
11363
11364 /*-----------------------------------------------------------------*/
11365 /* genAssign - generate code for assignment                        */
11366 /*-----------------------------------------------------------------*/
11367 static void
11368 genAssign (iCode * ic)
11369 {
11370   operand *result, *right;
11371   int size, offset;
11372   unsigned long lit = 0L;
11373
11374   D (emitcode (";", "genAssign ");
11375     );
11376
11377   result = IC_RESULT (ic);
11378   right = IC_RIGHT (ic);
11379
11380   /* if they are the same */
11381   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11382     return;
11383
11384   aopOp (right, ic, FALSE, FALSE);
11385
11386   emitcode (";", "genAssign: resultIsFar = %s",
11387             isOperandInFarSpace (result) ?
11388             "TRUE" : "FALSE");
11389
11390   /* special case both in far space */
11391   if ((AOP_TYPE (right) == AOP_DPTR ||
11392        AOP_TYPE (right) == AOP_DPTR2) &&
11393   /* IS_TRUE_SYMOP(result)       && */
11394       isOperandInFarSpace (result))
11395     {
11396       genFarFarAssign (result, right, ic);
11397       return;
11398     }
11399
11400   aopOp (result, ic, TRUE, FALSE);
11401
11402   /* if they are the same registers */
11403   if (sameRegs (AOP (right), AOP (result)))
11404     goto release;
11405
11406   /* if the result is a bit */
11407   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11408     {
11409       /* if the right size is a literal then
11410          we know what the value is */
11411       if (AOP_TYPE (right) == AOP_LIT)
11412         {
11413           if (((int) operandLitValue (right)))
11414             aopPut (AOP (result), one, 0);
11415           else
11416             aopPut (AOP (result), zero, 0);
11417           goto release;
11418         }
11419
11420       /* the right is also a bit variable */
11421       if (AOP_TYPE (right) == AOP_CRY)
11422         {
11423           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11424           aopPut (AOP (result), "c", 0);
11425           goto release;
11426         }
11427
11428       /* we need to or */
11429       toBoolean (right);
11430       aopPut (AOP (result), "a", 0);
11431       goto release;
11432     }
11433
11434   /* bit variables done */
11435   /* general case */
11436   size = AOP_SIZE (result);
11437   offset = 0;
11438   if (AOP_TYPE (right) == AOP_LIT)
11439     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11440
11441   if ((size > 1) &&
11442       (AOP_TYPE (result) != AOP_REG) &&
11443       (AOP_TYPE (right) == AOP_LIT) &&
11444       !IS_FLOAT (operandType (right)))
11445     {
11446       _startLazyDPSEvaluation ();
11447       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11448         {
11449           aopPut (AOP (result),
11450                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11451                   offset);
11452           offset++;
11453           size--;
11454         }
11455       /* And now fill the rest with zeros. */
11456       if (size)
11457         {
11458           emitcode ("clr", "a");
11459         }
11460       while (size--)
11461         {
11462           aopPut (AOP (result), "a", offset++);
11463         }
11464       _endLazyDPSEvaluation ();
11465     }
11466   else
11467     {
11468       _startLazyDPSEvaluation ();
11469       while (size--)
11470         {
11471           aopPut (AOP (result),
11472                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11473                   offset);
11474           offset++;
11475         }
11476       _endLazyDPSEvaluation ();
11477     }
11478
11479 release:
11480   freeAsmop (right, NULL, ic, FALSE);
11481   freeAsmop (result, NULL, ic, TRUE);
11482 }
11483
11484 /*-----------------------------------------------------------------*/
11485 /* genJumpTab - generates code for jump table                      */
11486 /*-----------------------------------------------------------------*/
11487 static void
11488 genJumpTab (iCode * ic)
11489 {
11490   symbol *jtab;
11491   char *l;
11492
11493   D (emitcode (";", "genJumpTab ");
11494     );
11495
11496   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11497   /* get the condition into accumulator */
11498   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11499   MOVA (l);
11500   /* multiply by four! */
11501   emitcode ("add", "a,acc");
11502   emitcode ("add", "a,acc");
11503   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11504
11505   jtab = newiTempLabel (NULL);
11506   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11507   emitcode ("jmp", "@a+dptr");
11508   emitcode ("", "!tlabeldef", jtab->key + 100);
11509   /* now generate the jump labels */
11510   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11511        jtab = setNextItem (IC_JTLABELS (ic)))
11512     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11513
11514 }
11515
11516 /*-----------------------------------------------------------------*/
11517 /* genCast - gen code for casting                                  */
11518 /*-----------------------------------------------------------------*/
11519 static void
11520 genCast (iCode * ic)
11521 {
11522   operand *result = IC_RESULT (ic);
11523   sym_link *ctype = operandType (IC_LEFT (ic));
11524   sym_link *rtype = operandType (IC_RIGHT (ic));
11525   operand *right = IC_RIGHT (ic);
11526   int size, offset;
11527
11528   D (emitcode (";", "genCast "););
11529
11530   /* if they are equivalent then do nothing */
11531   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11532     return;
11533
11534   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11535   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11536
11537   /* if the result is a bit */
11538   if (IS_BITVAR (OP_SYMBOL (result)->type)
11539       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11540     {
11541       /* if the right size is a literal then
11542          we know what the value is */
11543       if (AOP_TYPE (right) == AOP_LIT)
11544         {
11545           if (((int) operandLitValue (right)))
11546             aopPut (AOP (result), one, 0);
11547           else
11548             aopPut (AOP (result), zero, 0);
11549
11550           goto release;
11551         }
11552
11553       /* the right is also a bit variable */
11554       if (AOP_TYPE (right) == AOP_CRY)
11555         {
11556           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11557           aopPut (AOP (result), "c", 0);
11558           goto release;
11559         }
11560
11561       /* we need to or */
11562       toBoolean (right);
11563       aopPut (AOP (result), "a", 0);
11564       goto release;
11565     }
11566
11567   /* if they are the same size : or less */
11568   if (AOP_SIZE (result) <= AOP_SIZE (right))
11569     {
11570
11571       /* if they are in the same place */
11572       if (sameRegs (AOP (right), AOP (result)))
11573         goto release;
11574
11575       /* if they in different places then copy */
11576       size = AOP_SIZE (result);
11577       offset = 0;
11578       _startLazyDPSEvaluation ();
11579       while (size--)
11580         {
11581           aopPut (AOP (result),
11582                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11583                   offset);
11584           offset++;
11585         }
11586       _endLazyDPSEvaluation ();
11587       goto release;
11588     }
11589
11590
11591   /* if the result is of type pointer */
11592   if (IS_PTR (ctype))
11593     {
11594
11595       int p_type;
11596       sym_link *type = operandType (right);
11597
11598       /* pointer to generic pointer */
11599       if (IS_GENPTR (ctype))
11600         {
11601           if (IS_PTR (type))
11602             {
11603               p_type = DCL_TYPE (type);
11604             }
11605           else
11606             {
11607 #if OLD_CAST_BEHAVIOR
11608               /* KV: we are converting a non-pointer type to
11609                * a generic pointer. This (ifdef'd out) code
11610                * says that the resulting generic pointer
11611                * should have the same class as the storage
11612                * location of the non-pointer variable.
11613                *
11614                * For example, converting an int (which happens
11615                * to be stored in DATA space) to a pointer results
11616                * in a DATA generic pointer; if the original int
11617                * in XDATA space, so will be the resulting pointer.
11618                *
11619                * I don't like that behavior, and thus this change:
11620                * all such conversions will be forced to XDATA and
11621                * throw a warning. If you want some non-XDATA
11622                * type, or you want to suppress the warning, you
11623                * must go through an intermediate cast, like so:
11624                *
11625                * char _generic *gp = (char _xdata *)(intVar);
11626                */
11627               sym_link *etype = getSpec (type);
11628
11629               /* we have to go by the storage class */
11630               if (SPEC_OCLS (etype) != generic)
11631                 {
11632                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11633                 }
11634               else
11635 #endif
11636                 {
11637                   /* Converting unknown class (i.e. register variable)
11638                    * to generic pointer. This is not good, but
11639                    * we'll make a guess (and throw a warning).
11640                    */
11641                   p_type = FPOINTER;
11642                   werror (W_INT_TO_GEN_PTR_CAST);
11643                 }
11644             }
11645
11646           /* the first two bytes are known */
11647           size = GPTRSIZE - 1;
11648           offset = 0;
11649           _startLazyDPSEvaluation ();
11650           while (size--)
11651             {
11652               aopPut (AOP (result),
11653                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11654                       offset);
11655               offset++;
11656             }
11657           _endLazyDPSEvaluation ();
11658
11659           /* the last byte depending on type */
11660             {
11661                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11662                 char gpValStr[10];
11663             
11664                 if (gpVal == -1)
11665                 {
11666                     // pointerTypeToGPByte will have bitched.
11667                     exit(1);
11668                 }
11669             
11670                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11671                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11672             }
11673           goto release;
11674         }
11675
11676       /* just copy the pointers */
11677       size = AOP_SIZE (result);
11678       offset = 0;
11679       _startLazyDPSEvaluation ();
11680       while (size--)
11681         {
11682           aopPut (AOP (result),
11683                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11684                   offset);
11685           offset++;
11686         }
11687       _endLazyDPSEvaluation ();
11688       goto release;
11689     }
11690
11691   /* so we now know that the size of destination is greater
11692      than the size of the source */
11693   /* we move to result for the size of source */
11694   size = AOP_SIZE (right);
11695   offset = 0;
11696   _startLazyDPSEvaluation ();
11697   while (size--)
11698     {
11699       aopPut (AOP (result),
11700               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11701               offset);
11702       offset++;
11703     }
11704   _endLazyDPSEvaluation ();
11705
11706   /* now depending on the sign of the source && destination */
11707   size = AOP_SIZE (result) - AOP_SIZE (right);
11708   /* if unsigned or not an integral type */
11709   /* also, if the source is a bit, we don't need to sign extend, because
11710    * it can't possibly have set the sign bit.
11711    */
11712   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11713     {
11714       while (size--)
11715         {
11716           aopPut (AOP (result), zero, offset++);
11717         }
11718     }
11719   else
11720     {
11721       /* we need to extend the sign :{ */
11722       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11723                         FALSE, FALSE, NULL));
11724       emitcode ("rlc", "a");
11725       emitcode ("subb", "a,acc");
11726       while (size--)
11727         aopPut (AOP (result), "a", offset++);
11728     }
11729
11730   /* we are done hurray !!!! */
11731
11732 release:
11733   freeAsmop (right, NULL, ic, TRUE);
11734   freeAsmop (result, NULL, ic, TRUE);
11735
11736 }
11737
11738 /*-----------------------------------------------------------------*/
11739 /* genDjnz - generate decrement & jump if not zero instrucion      */
11740 /*-----------------------------------------------------------------*/
11741 static int
11742 genDjnz (iCode * ic, iCode * ifx)
11743 {
11744   symbol *lbl, *lbl1;
11745   if (!ifx)
11746     return 0;
11747
11748   /* if the if condition has a false label
11749      then we cannot save */
11750   if (IC_FALSE (ifx))
11751     return 0;
11752
11753   /* if the minus is not of the form
11754      a = a - 1 */
11755   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11756       !IS_OP_LITERAL (IC_RIGHT (ic)))
11757     return 0;
11758
11759   if (operandLitValue (IC_RIGHT (ic)) != 1)
11760     return 0;
11761
11762   /* if the size of this greater than one then no
11763      saving */
11764   if (getSize (operandType (IC_RESULT (ic))) > 1)
11765     return 0;
11766
11767   /* otherwise we can save BIG */
11768   D(emitcode(";", "genDjnz"););
11769
11770   lbl = newiTempLabel (NULL);
11771   lbl1 = newiTempLabel (NULL);
11772
11773   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11774
11775   if (AOP_NEEDSACC(IC_RESULT(ic)))
11776   {
11777       /* If the result is accessed indirectly via
11778        * the accumulator, we must explicitly write
11779        * it back after the decrement.
11780        */
11781       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11782       
11783       if (strcmp(rByte, "a"))
11784       {
11785            /* Something is hopelessly wrong */
11786            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11787                    __FILE__, __LINE__);
11788            /* We can just give up; the generated code will be inefficient,
11789             * but what the hey.
11790             */
11791            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11792            return 0;
11793       }
11794       emitcode ("dec", "%s", rByte);
11795       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11796       emitcode ("jnz", "!tlabel", lbl->key + 100);
11797   }
11798   else if (IS_AOP_PREG (IC_RESULT (ic)))
11799     {
11800       emitcode ("dec", "%s",
11801                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11802       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11803       emitcode ("jnz", "!tlabel", lbl->key + 100);
11804     }
11805   else
11806     {
11807       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11808                 lbl->key + 100);
11809     }
11810   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11811   emitcode ("", "!tlabeldef", lbl->key + 100);
11812   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11813   emitcode ("", "!tlabeldef", lbl1->key + 100);
11814
11815   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11816   ifx->generated = 1;
11817   return 1;
11818 }
11819
11820 /*-----------------------------------------------------------------*/
11821 /* genReceive - generate code for a receive iCode                  */
11822 /*-----------------------------------------------------------------*/
11823 static void
11824 genReceive (iCode * ic)
11825 {
11826     int size = getSize (operandType (IC_RESULT (ic)));
11827     int offset = 0;
11828     int rb1off ;
11829     
11830     D (emitcode (";", "genReceive "););
11831
11832     if (ic->argreg == 1) 
11833     {
11834         /* first parameter */
11835         if (AOP_IS_STR(IC_RESULT(ic)))
11836         {
11837             /* Nothing to do: it's already in the proper place. */
11838             return;
11839         }
11840         else
11841         {
11842             bool useDp2;
11843             
11844             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11845                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11846                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11847             
11848             _G.accInUse++;
11849             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11850             _G.accInUse--; 
11851             
11852             /* Sanity checking... */
11853             if (AOP_USESDPTR(IC_RESULT(ic)))
11854             {
11855                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11856                         "genReceive got unexpected DPTR.");
11857             }
11858             assignResultValue (IC_RESULT (ic));
11859         }
11860     } 
11861     else 
11862     { 
11863         /* second receive onwards */
11864         /* this gets a little tricky since unused recevies will be
11865          eliminated, we have saved the reg in the type field . and
11866          we use that to figure out which register to use */
11867         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11868         rb1off = ic->argreg;
11869         while (size--) 
11870         {
11871             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11872         }
11873     }
11874     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11875 }
11876
11877 /*-----------------------------------------------------------------*/
11878 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11879 /*-----------------------------------------------------------------*/
11880 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11881 {
11882     operand *from , *to , *count;
11883     symbol *lbl;
11884     bitVect *rsave;
11885     int i;
11886
11887     /* we know it has to be 3 parameters */
11888     assert (nparms == 3);
11889     
11890     rsave = newBitVect(16);
11891     /* save DPTR if it needs to be saved */
11892     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11893             if (bitVectBitValue(ic->rMask,i))
11894                     rsave = bitVectSetBit(rsave,i);
11895     }
11896     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11897                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11898     savermask(rsave);
11899     
11900     to = parms[0];
11901     from = parms[1];
11902     count = parms[2];
11903
11904     aopOp (from, ic->next, FALSE, FALSE);
11905
11906     /* get from into DPTR1 */
11907     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11908     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11909     if (options.model == MODEL_FLAT24) {
11910         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11911     }
11912
11913     freeAsmop (from, NULL, ic, FALSE);
11914     aopOp (to, ic, FALSE, FALSE);
11915     /* get "to" into DPTR */
11916     /* if the operand is already in dptr
11917        then we do nothing else we move the value to dptr */
11918     if (AOP_TYPE (to) != AOP_STR) {
11919         /* if already in DPTR then we need to push */
11920         if (AOP_TYPE(to) == AOP_DPTR) {
11921             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11922             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11923             if (options.model == MODEL_FLAT24)
11924                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11925             emitcode ("pop", "dph");
11926             emitcode ("pop", "dpl");        
11927         } else {
11928             _startLazyDPSEvaluation ();
11929             /* if this is remateriazable */
11930             if (AOP_TYPE (to) == AOP_IMMD) {
11931                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11932             } else {                    /* we need to get it byte by byte */
11933                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11934                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11935                 if (options.model == MODEL_FLAT24) {
11936                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11937                 }
11938             }
11939             _endLazyDPSEvaluation ();
11940         }
11941     }
11942     freeAsmop (to, NULL, ic, FALSE);
11943     _G.dptrInUse = _G.dptr1InUse = 1;
11944     aopOp (count, ic->next->next, FALSE,FALSE);
11945     lbl =newiTempLabel(NULL);
11946
11947     /* now for the actual copy */
11948     if (AOP_TYPE(count) == AOP_LIT && 
11949         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11950         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11951         if (fromc) {
11952             emitcode ("lcall","__bi_memcpyc2x_s");
11953         } else {
11954             emitcode ("lcall","__bi_memcpyx2x_s");
11955         }
11956         freeAsmop (count, NULL, ic, FALSE);
11957     } else {
11958         symbol *lbl1 = newiTempLabel(NULL);
11959         
11960         emitcode (";"," Auto increment but no djnz");
11961         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11962         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11963         freeAsmop (count, NULL, ic, FALSE);
11964         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11965         emitcode ("","!tlabeldef",lbl->key+100);
11966         if (fromc) {
11967             emitcode ("clr","a");
11968             emitcode ("movc", "a,@a+dptr");
11969         } else 
11970             emitcode ("movx", "a,@dptr");
11971         emitcode ("movx", "@dptr,a");
11972         emitcode ("inc", "dptr");
11973         emitcode ("inc", "dptr");
11974         emitcode ("mov","a,b");
11975         emitcode ("orl","a,_ap");
11976         emitcode ("jz","!tlabel",lbl1->key+100);
11977         emitcode ("mov","a,_ap");
11978         emitcode ("add","a,#!constbyte",0xFF);
11979         emitcode ("mov","_ap,a");
11980         emitcode ("mov","a,b");
11981         emitcode ("addc","a,#!constbyte",0xFF);
11982         emitcode ("mov","b,a");
11983         emitcode ("sjmp","!tlabel",lbl->key+100);
11984         emitcode ("","!tlabeldef",lbl1->key+100);
11985     }
11986     emitcode ("mov", "dps,#0"); 
11987     _G.dptrInUse = _G.dptr1InUse = 0;
11988     unsavermask(rsave);
11989
11990 }
11991
11992 /*-----------------------------------------------------------------*/
11993 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11994 /*-----------------------------------------------------------------*/
11995 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11996 {
11997     operand *from , *to , *count;
11998     symbol *lbl,*lbl2;
11999     bitVect *rsave;
12000     int i;
12001
12002     /* we know it has to be 3 parameters */
12003     assert (nparms == 3);
12004     
12005     rsave = newBitVect(16);
12006     /* save DPTR if it needs to be saved */
12007     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12008             if (bitVectBitValue(ic->rMask,i))
12009                     rsave = bitVectSetBit(rsave,i);
12010     }
12011     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12012                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12013     savermask(rsave);
12014     
12015     to = parms[0];
12016     from = parms[1];
12017     count = parms[2];
12018
12019     aopOp (from, ic->next, FALSE, FALSE);
12020
12021     /* get from into DPTR1 */
12022     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12023     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12024     if (options.model == MODEL_FLAT24) {
12025         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12026     }
12027
12028     freeAsmop (from, NULL, ic, FALSE);
12029     aopOp (to, ic, FALSE, FALSE);
12030     /* get "to" into DPTR */
12031     /* if the operand is already in dptr
12032        then we do nothing else we move the value to dptr */
12033     if (AOP_TYPE (to) != AOP_STR) {
12034         /* if already in DPTR then we need to push */
12035         if (AOP_TYPE(to) == AOP_DPTR) {
12036             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12037             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12038             if (options.model == MODEL_FLAT24)
12039                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12040             emitcode ("pop", "dph");
12041             emitcode ("pop", "dpl");        
12042         } else {
12043             _startLazyDPSEvaluation ();
12044             /* if this is remateriazable */
12045             if (AOP_TYPE (to) == AOP_IMMD) {
12046                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12047             } else {                    /* we need to get it byte by byte */
12048                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12049                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12050                 if (options.model == MODEL_FLAT24) {
12051                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12052                 }
12053             }
12054             _endLazyDPSEvaluation ();
12055         }
12056     }
12057     freeAsmop (to, NULL, ic, FALSE);
12058     _G.dptrInUse = _G.dptr1InUse = 1;
12059     aopOp (count, ic->next->next, FALSE,FALSE);
12060     lbl =newiTempLabel(NULL);
12061     lbl2 =newiTempLabel(NULL);
12062
12063     /* now for the actual compare */
12064     if (AOP_TYPE(count) == AOP_LIT && 
12065         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12066         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12067         if (fromc)
12068             emitcode("lcall","__bi_memcmpc2x_s");
12069         else
12070             emitcode("lcall","__bi_memcmpx2x_s");
12071         freeAsmop (count, NULL, ic, FALSE);
12072         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12073         aopPut(AOP(IC_RESULT(ic)),"a",0);
12074         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12075     } else {
12076         symbol *lbl1 = newiTempLabel(NULL);
12077
12078         emitcode("push","ar0");         
12079         emitcode (";"," Auto increment but no djnz");
12080         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12081         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12082         freeAsmop (count, NULL, ic, FALSE);
12083         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12084         emitcode ("","!tlabeldef",lbl->key+100);
12085         if (fromc) {
12086             emitcode ("clr","a");
12087             emitcode ("movc", "a,@a+dptr");
12088         } else 
12089             emitcode ("movx", "a,@dptr");
12090         emitcode ("mov","r0,a");
12091         emitcode ("movx", "a,@dptr");
12092         emitcode ("clr","c");
12093         emitcode ("subb","a,r0");
12094         emitcode ("jnz","!tlabel",lbl2->key+100);
12095         emitcode ("inc", "dptr");
12096         emitcode ("inc", "dptr");
12097         emitcode ("mov","a,b");
12098         emitcode ("orl","a,_ap");
12099         emitcode ("jz","!tlabel",lbl1->key+100);
12100         emitcode ("mov","a,_ap");
12101         emitcode ("add","a,#!constbyte",0xFF);
12102         emitcode ("mov","_ap,a");
12103         emitcode ("mov","a,b");
12104         emitcode ("addc","a,#!constbyte",0xFF);
12105         emitcode ("mov","b,a");
12106         emitcode ("sjmp","!tlabel",lbl->key+100);
12107         emitcode ("","!tlabeldef",lbl1->key+100);
12108         emitcode ("clr","a");
12109         emitcode ("","!tlabeldef",lbl2->key+100);
12110         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12111         aopPut(AOP(IC_RESULT(ic)),"a",0);
12112         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12113         emitcode("pop","ar0");
12114         emitcode ("mov", "dps,#0");      
12115     }
12116     _G.dptrInUse = _G.dptr1InUse = 0;
12117     unsavermask(rsave);
12118
12119 }
12120
12121 /*-----------------------------------------------------------------*/
12122 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12123 /* port, first parameter output area second parameter pointer to   */
12124 /* port third parameter count                                      */
12125 /*-----------------------------------------------------------------*/
12126 static void genInp( iCode *ic, int nparms, operand **parms)
12127 {
12128     operand *from , *to , *count;
12129     symbol *lbl;
12130     bitVect *rsave;
12131     int i;
12132
12133     /* we know it has to be 3 parameters */
12134     assert (nparms == 3);
12135     
12136     rsave = newBitVect(16);
12137     /* save DPTR if it needs to be saved */
12138     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12139             if (bitVectBitValue(ic->rMask,i))
12140                     rsave = bitVectSetBit(rsave,i);
12141     }
12142     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12143                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12144     savermask(rsave);
12145     
12146     to = parms[0];
12147     from = parms[1];
12148     count = parms[2];
12149
12150     aopOp (from, ic->next, FALSE, FALSE);
12151
12152     /* get from into DPTR1 */
12153     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12154     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12155     if (options.model == MODEL_FLAT24) {
12156         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12157     }
12158
12159     freeAsmop (from, NULL, ic, FALSE);
12160     aopOp (to, ic, FALSE, FALSE);
12161     /* get "to" into DPTR */
12162     /* if the operand is already in dptr
12163        then we do nothing else we move the value to dptr */
12164     if (AOP_TYPE (to) != AOP_STR) {
12165         /* if already in DPTR then we need to push */
12166         if (AOP_TYPE(to) == AOP_DPTR) {
12167             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12168             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12169             if (options.model == MODEL_FLAT24)
12170                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12171             emitcode ("pop", "dph");
12172             emitcode ("pop", "dpl");        
12173         } else {
12174             _startLazyDPSEvaluation ();
12175             /* if this is remateriazable */
12176             if (AOP_TYPE (to) == AOP_IMMD) {
12177                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12178             } else {                    /* we need to get it byte by byte */
12179                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12180                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12181                 if (options.model == MODEL_FLAT24) {
12182                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12183                 }
12184             }
12185             _endLazyDPSEvaluation ();
12186         }
12187     }
12188     freeAsmop (to, NULL, ic, FALSE);
12189
12190     _G.dptrInUse = _G.dptr1InUse = 1;
12191     aopOp (count, ic->next->next, FALSE,FALSE);
12192     lbl =newiTempLabel(NULL);
12193
12194     /* now for the actual copy */
12195     if (AOP_TYPE(count) == AOP_LIT && 
12196         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12197         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12198         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12199         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12200         freeAsmop (count, NULL, ic, FALSE);
12201         emitcode ("","!tlabeldef",lbl->key+100);
12202         emitcode ("movx", "a,@dptr");   /* read data from port */
12203         emitcode ("dec","dps");         /* switch to DPTR */
12204         emitcode ("movx", "@dptr,a");   /* save into location */
12205         emitcode ("inc", "dptr");       /* point to next area */
12206         emitcode ("inc","dps");         /* switch to DPTR2 */
12207         emitcode ("djnz","b,!tlabel",lbl->key+100);
12208     } else {
12209         symbol *lbl1 = newiTempLabel(NULL);
12210         
12211         emitcode (";"," Auto increment but no djnz");
12212         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12213         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12214         freeAsmop (count, NULL, ic, FALSE);
12215         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12216         emitcode ("","!tlabeldef",lbl->key+100);
12217         emitcode ("movx", "a,@dptr");
12218         emitcode ("dec","dps");         /* switch to DPTR */
12219         emitcode ("movx", "@dptr,a");
12220         emitcode ("inc", "dptr");
12221         emitcode ("inc","dps");         /* switch to DPTR2 */
12222 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12223 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12224         emitcode ("mov","a,b");
12225         emitcode ("orl","a,_ap");
12226         emitcode ("jz","!tlabel",lbl1->key+100);
12227         emitcode ("mov","a,_ap");
12228         emitcode ("add","a,#!constbyte",0xFF);
12229         emitcode ("mov","_ap,a");
12230         emitcode ("mov","a,b");
12231         emitcode ("addc","a,#!constbyte",0xFF);
12232         emitcode ("mov","b,a");
12233         emitcode ("sjmp","!tlabel",lbl->key+100);
12234         emitcode ("","!tlabeldef",lbl1->key+100);
12235     }
12236     emitcode ("mov", "dps,#0"); 
12237     _G.dptrInUse = _G.dptr1InUse = 0;
12238     unsavermask(rsave);
12239
12240 }
12241
12242 /*-----------------------------------------------------------------*/
12243 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12244 /* port, first parameter output area second parameter pointer to   */
12245 /* port third parameter count                                      */
12246 /*-----------------------------------------------------------------*/
12247 static void genOutp( iCode *ic, int nparms, operand **parms)
12248 {
12249     operand *from , *to , *count;
12250     symbol *lbl;
12251     bitVect *rsave;
12252     int i;
12253
12254     /* we know it has to be 3 parameters */
12255     assert (nparms == 3);
12256     
12257     rsave = newBitVect(16);
12258     /* save DPTR if it needs to be saved */
12259     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12260             if (bitVectBitValue(ic->rMask,i))
12261                     rsave = bitVectSetBit(rsave,i);
12262     }
12263     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12264                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12265     savermask(rsave);
12266     
12267     to = parms[0];
12268     from = parms[1];
12269     count = parms[2];
12270
12271     aopOp (from, ic->next, FALSE, FALSE);
12272
12273     /* get from into DPTR1 */
12274     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12275     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12276     if (options.model == MODEL_FLAT24) {
12277         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12278     }
12279
12280     freeAsmop (from, NULL, ic, FALSE);
12281     aopOp (to, ic, FALSE, FALSE);
12282     /* get "to" into DPTR */
12283     /* if the operand is already in dptr
12284        then we do nothing else we move the value to dptr */
12285     if (AOP_TYPE (to) != AOP_STR) {
12286         /* if already in DPTR then we need to push */
12287         if (AOP_TYPE(to) == AOP_DPTR) {
12288             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12289             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12290             if (options.model == MODEL_FLAT24)
12291                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12292             emitcode ("pop", "dph");
12293             emitcode ("pop", "dpl");        
12294         } else {
12295             _startLazyDPSEvaluation ();
12296             /* if this is remateriazable */
12297             if (AOP_TYPE (to) == AOP_IMMD) {
12298                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12299             } else {                    /* we need to get it byte by byte */
12300                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12301                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12302                 if (options.model == MODEL_FLAT24) {
12303                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12304                 }
12305             }
12306             _endLazyDPSEvaluation ();
12307         }
12308     }
12309     freeAsmop (to, NULL, ic, FALSE);
12310
12311     _G.dptrInUse = _G.dptr1InUse = 1;
12312     aopOp (count, ic->next->next, FALSE,FALSE);
12313     lbl =newiTempLabel(NULL);
12314
12315     /* now for the actual copy */
12316     if (AOP_TYPE(count) == AOP_LIT && 
12317         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12318         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12319         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12320         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12321         emitcode ("","!tlabeldef",lbl->key+100);
12322         emitcode ("movx", "a,@dptr");   /* read data from port */
12323         emitcode ("inc","dps");         /* switch to DPTR2 */
12324         emitcode ("movx", "@dptr,a");   /* save into location */
12325         emitcode ("inc", "dptr");       /* point to next area */
12326         emitcode ("dec","dps");         /* switch to DPTR */
12327         emitcode ("djnz","b,!tlabel",lbl->key+100);
12328         freeAsmop (count, NULL, ic, FALSE);
12329     } else {
12330         symbol *lbl1 = newiTempLabel(NULL);
12331         
12332         emitcode (";"," Auto increment but no djnz");
12333         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12334         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12335         freeAsmop (count, NULL, ic, FALSE);
12336         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12337         emitcode ("","!tlabeldef",lbl->key+100);
12338         emitcode ("movx", "a,@dptr");
12339         emitcode ("inc", "dptr");
12340         emitcode ("inc","dps");         /* switch to DPTR2 */
12341         emitcode ("movx", "@dptr,a");
12342         emitcode ("dec","dps");         /* switch to DPTR */
12343         emitcode ("mov","a,b");
12344         emitcode ("orl","a,_ap");
12345         emitcode ("jz","!tlabel",lbl1->key+100);
12346         emitcode ("mov","a,_ap");
12347         emitcode ("add","a,#!constbyte",0xFF);
12348         emitcode ("mov","_ap,a");
12349         emitcode ("mov","a,b");
12350         emitcode ("addc","a,#!constbyte",0xFF);
12351         emitcode ("mov","b,a");
12352         emitcode ("sjmp","!tlabel",lbl->key+100);
12353         emitcode ("","!tlabeldef",lbl1->key+100);
12354     }
12355     emitcode ("mov", "dps,#0"); 
12356     _G.dptrInUse = _G.dptr1InUse = 0;
12357     unsavermask(rsave);
12358
12359 }
12360
12361 /*-----------------------------------------------------------------*/
12362 /* genSwapW - swap lower & high order bytes                        */
12363 /*-----------------------------------------------------------------*/
12364 static void genSwapW(iCode *ic, int nparms, operand **parms)
12365 {
12366     operand *dest;
12367     operand *src;
12368     assert (nparms==1);
12369
12370     src = parms[0];
12371     dest=IC_RESULT(ic);
12372
12373     assert(getSize(operandType(src))==2);
12374
12375     aopOp (src, ic, FALSE, FALSE);
12376     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12377     _G.accInUse++;
12378     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12379     _G.accInUse--;
12380     freeAsmop (src, NULL, ic, FALSE);
12381     
12382     aopOp (dest,ic, FALSE, FALSE);
12383     aopPut(AOP(dest),"b",0);
12384     aopPut(AOP(dest),"a",1);
12385     freeAsmop (dest, NULL, ic, FALSE);    
12386 }
12387
12388 /*-----------------------------------------------------------------*/
12389 /* genMemsetX - gencode for memSetX data                           */
12390 /*-----------------------------------------------------------------*/
12391 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12392 {
12393     operand *to , *val , *count;
12394     symbol *lbl;
12395     char *l;
12396     int i;
12397     bitVect *rsave;
12398
12399     /* we know it has to be 3 parameters */
12400     assert (nparms == 3);
12401     
12402     to = parms[0];
12403     val = parms[1];
12404     count = parms[2];
12405         
12406     /* save DPTR if it needs to be saved */
12407     rsave = newBitVect(16);
12408     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12409             if (bitVectBitValue(ic->rMask,i))
12410                     rsave = bitVectSetBit(rsave,i);
12411     }
12412     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12413                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12414     savermask(rsave);
12415
12416     aopOp (to, ic, FALSE, FALSE);
12417     /* get "to" into DPTR */
12418     /* if the operand is already in dptr
12419        then we do nothing else we move the value to dptr */
12420     if (AOP_TYPE (to) != AOP_STR) {
12421         /* if already in DPTR then we need to push */
12422         if (AOP_TYPE(to) == AOP_DPTR) {
12423             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12424             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12425             if (options.model == MODEL_FLAT24)
12426                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12427             emitcode ("pop", "dph");
12428             emitcode ("pop", "dpl");        
12429         } else {
12430             _startLazyDPSEvaluation ();
12431             /* if this is remateriazable */
12432             if (AOP_TYPE (to) == AOP_IMMD) {
12433                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12434             } else {                    /* we need to get it byte by byte */
12435                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12436                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12437                 if (options.model == MODEL_FLAT24) {
12438                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12439                 }
12440             }
12441             _endLazyDPSEvaluation ();
12442         }
12443     }
12444     freeAsmop (to, NULL, ic, FALSE);
12445
12446     aopOp (val, ic->next->next, FALSE,FALSE);
12447     aopOp (count, ic->next->next, FALSE,FALSE);    
12448     lbl =newiTempLabel(NULL);
12449     /* now for the actual copy */
12450     if (AOP_TYPE(count) == AOP_LIT && 
12451         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12452         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12453         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12454         MOVA(l);
12455         emitcode ("","!tlabeldef",lbl->key+100);
12456         emitcode ("movx", "@dptr,a");
12457         emitcode ("inc", "dptr");
12458         emitcode ("djnz","b,!tlabel",lbl->key+100);
12459     } else {
12460         symbol *lbl1 = newiTempLabel(NULL);
12461         
12462         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12463         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12464         emitcode ("","!tlabeldef",lbl->key+100);
12465         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12466         emitcode ("movx", "@dptr,a");
12467         emitcode ("inc", "dptr");
12468         emitcode ("mov","a,b");
12469         emitcode ("orl","a,_ap");
12470         emitcode ("jz","!tlabel",lbl1->key+100);
12471         emitcode ("mov","a,_ap");
12472         emitcode ("add","a,#!constbyte",0xFF);
12473         emitcode ("mov","_ap,a");
12474         emitcode ("mov","a,b");
12475         emitcode ("addc","a,#!constbyte",0xFF);
12476         emitcode ("mov","b,a");
12477         emitcode ("sjmp","!tlabel",lbl->key+100);
12478         emitcode ("","!tlabeldef",lbl1->key+100);
12479     }
12480     freeAsmop (count, NULL, ic, FALSE);
12481     unsavermask(rsave);
12482 }
12483
12484 /*-----------------------------------------------------------------*/
12485 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12486 /*-----------------------------------------------------------------*/
12487 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12488 {
12489         bitVect *rsave ;
12490         operand *pnum, *result;
12491         int i;
12492     
12493         assert (nparms==1);
12494         /* save registers that need to be saved */
12495         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12496                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12497     
12498         pnum = parms[0]; 
12499         aopOp (pnum, ic, FALSE, FALSE);
12500         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12501         freeAsmop (pnum, NULL, ic, FALSE);
12502         emitcode ("lcall","NatLib_LoadPrimitive");
12503         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12504         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12505             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12506                 for (i = (size-1) ; i >= 0 ; i-- ) {
12507                         emitcode ("push","a%s",javaRet[i]);
12508                 }
12509                 for (i=0; i < size ; i++ ) {
12510                         emitcode ("pop","a%s",
12511                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12512                 }
12513         } else {
12514                 for (i = 0 ; i < size ; i++ ) {
12515                         aopPut(AOP(result),javaRet[i],i);
12516                 }
12517         }    
12518         freeAsmop (result, NULL, ic, FALSE);
12519         unsavermask(rsave);
12520 }
12521
12522 /*-----------------------------------------------------------------*/
12523 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12524 /*-----------------------------------------------------------------*/
12525 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12526 {
12527         bitVect *rsave ;
12528         operand *pnum, *result;
12529         int size = 3;
12530         int i;
12531     
12532         assert (nparms==1);
12533         /* save registers that need to be saved */
12534         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12535                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12536     
12537         pnum = parms[0]; 
12538         aopOp (pnum, ic, FALSE, FALSE);
12539         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12540         freeAsmop (pnum, NULL, ic, FALSE);
12541         emitcode ("lcall","NatLib_LoadPointer");
12542         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12543         if (AOP_TYPE(result)!=AOP_STR) {
12544                 for (i = 0 ; i < size ; i++ ) {
12545                         aopPut(AOP(result),fReturn[i],i);
12546                 }
12547         }    
12548         freeAsmop (result, NULL, ic, FALSE);
12549         unsavermask(rsave);
12550 }
12551
12552 /*-----------------------------------------------------------------*/
12553 /* genNatLibInstallStateBlock -                                    */
12554 /*-----------------------------------------------------------------*/
12555 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12556                                        operand **parms, const char *name)
12557 {
12558         bitVect *rsave ;
12559         operand *psb, *handle;
12560         assert (nparms==2);
12561
12562         /* save registers that need to be saved */
12563         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12564                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12565         psb = parms[0];
12566         handle = parms[1];
12567
12568         /* put pointer to state block into DPTR1 */
12569         aopOp (psb, ic, FALSE, FALSE);
12570         if (AOP_TYPE (psb) == AOP_IMMD) {
12571                 emitcode ("mov","dps,#1");
12572                 emitcode ("mov", "dptr,%s",
12573                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12574                 emitcode ("mov","dps,#0");
12575         } else {
12576                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12577                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12578                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12579         }
12580         freeAsmop (psb, NULL, ic, FALSE);
12581
12582         /* put libraryID into DPTR */
12583         emitcode ("mov","dptr,#LibraryID");
12584
12585         /* put handle into r3:r2 */
12586         aopOp (handle, ic, FALSE, FALSE);
12587         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12588                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12589                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12590                 emitcode ("pop","ar3");
12591                 emitcode ("pop","ar2");
12592         } else {        
12593                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12594                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12595         }
12596         freeAsmop (psb, NULL, ic, FALSE);
12597
12598         /* make the call */
12599         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12600
12601         /* put return value into place*/
12602         _G.accInUse++;
12603         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12604         _G.accInUse--;
12605         aopPut(AOP(IC_RESULT(ic)),"a",0);
12606         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12607         unsavermask(rsave);
12608 }
12609
12610 /*-----------------------------------------------------------------*/
12611 /* genNatLibRemoveStateBlock -                                     */
12612 /*-----------------------------------------------------------------*/
12613 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12614 {
12615         bitVect *rsave ;
12616
12617         assert(nparms==0);
12618
12619         /* save registers that need to be saved */
12620         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12621                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12622
12623         /* put libraryID into DPTR */
12624         emitcode ("mov","dptr,#LibraryID");
12625         /* make the call */
12626         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12627         unsavermask(rsave);
12628 }
12629
12630 /*-----------------------------------------------------------------*/
12631 /* genNatLibGetStateBlock -                                        */
12632 /*-----------------------------------------------------------------*/
12633 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12634                                    operand **parms,const char *name)
12635 {
12636         bitVect *rsave ;
12637         symbol *lbl = newiTempLabel(NULL);
12638         
12639         assert(nparms==0);
12640         /* save registers that need to be saved */
12641         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12642                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12643
12644         /* put libraryID into DPTR */
12645         emitcode ("mov","dptr,#LibraryID");
12646         /* make the call */
12647         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12648         emitcode ("jnz","!tlabel",lbl->key+100);
12649
12650         /* put return value into place */
12651         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12652         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12653                 emitcode ("push","ar3");
12654                 emitcode ("push","ar2");
12655                 emitcode ("pop","%s",
12656                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12657                 emitcode ("pop","%s",
12658                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12659         } else {
12660                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12661                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12662         }
12663         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12664         emitcode ("","!tlabeldef",lbl->key+100);
12665         unsavermask(rsave);
12666 }
12667
12668 /*-----------------------------------------------------------------*/
12669 /* genMMMalloc -                                                   */
12670 /*-----------------------------------------------------------------*/
12671 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12672                          int size, const char *name)
12673 {
12674         bitVect *rsave ;
12675         operand *bsize;
12676         symbol *rsym;
12677         symbol *lbl = newiTempLabel(NULL);
12678
12679         assert (nparms == 1);
12680         /* save registers that need to be saved */
12681         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12682                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12683         
12684         bsize=parms[0];
12685         aopOp (bsize,ic,FALSE,FALSE);
12686
12687         /* put the size in R4-R2 */
12688         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12689                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12690                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12691                 if (size==3) {
12692                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12693                         emitcode("pop","ar4");
12694                 }
12695                 emitcode("pop","ar3");
12696                 emitcode("pop","ar2");          
12697         } else {
12698                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12699                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12700                 if (size==3) {
12701                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12702                 }
12703         }
12704         freeAsmop (bsize, NULL, ic, FALSE);
12705
12706         /* make the call */
12707         emitcode ("lcall","MM_%s",name);
12708         emitcode ("jz","!tlabel",lbl->key+100);
12709         emitcode ("mov","r2,#!constbyte",0xff);
12710         emitcode ("mov","r3,#!constbyte",0xff);
12711         emitcode ("","!tlabeldef",lbl->key+100);
12712         /* we don't care about the pointer : we just save the handle */
12713         rsym = OP_SYMBOL(IC_RESULT(ic));
12714         if (rsym->liveFrom != rsym->liveTo) {
12715                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12716                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12717                         emitcode ("push","ar3");
12718                         emitcode ("push","ar2");
12719                         emitcode ("pop","%s",
12720                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12721                         emitcode ("pop","%s",
12722                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12723                 } else {
12724                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12725                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12726                 }
12727                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12728         }
12729         unsavermask(rsave);
12730 }
12731
12732 /*-----------------------------------------------------------------*/
12733 /* genMMDeref -                                                    */
12734 /*-----------------------------------------------------------------*/
12735 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12736 {
12737         bitVect *rsave ;
12738         operand *handle;
12739
12740         assert (nparms == 1);
12741         /* save registers that need to be saved */
12742         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12743                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12744         
12745         handle=parms[0];
12746         aopOp (handle,ic,FALSE,FALSE);
12747
12748         /* put the size in R4-R2 */
12749         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12750                 emitcode("push","%s",
12751                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12752                 emitcode("push","%s",
12753                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12754                 emitcode("pop","ar3");
12755                 emitcode("pop","ar2");          
12756         } else {
12757                 emitcode ("mov","r2,%s",
12758                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12759                 emitcode ("mov","r3,%s",
12760                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12761         }
12762         freeAsmop (handle, NULL, ic, FALSE);
12763
12764         /* make the call */
12765         emitcode ("lcall","MM_Deref");
12766         
12767         {
12768                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12769                 if (rsym->liveFrom != rsym->liveTo) {                   
12770                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12771                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12772                             _startLazyDPSEvaluation ();
12773                             
12774                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12775                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12776                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12777
12778                             _endLazyDPSEvaluation ();
12779                             
12780                         }
12781                 }
12782         }
12783         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12784         unsavermask(rsave);
12785 }
12786
12787 /*-----------------------------------------------------------------*/
12788 /* genMMUnrestrictedPersist -                                      */
12789 /*-----------------------------------------------------------------*/
12790 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12791 {
12792         bitVect *rsave ;
12793         operand *handle;
12794
12795         assert (nparms == 1);
12796         /* save registers that need to be saved */
12797         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12798                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12799         
12800         handle=parms[0];
12801         aopOp (handle,ic,FALSE,FALSE);
12802
12803         /* put the size in R3-R2 */
12804         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12805                 emitcode("push","%s",
12806                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12807                 emitcode("push","%s",
12808                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12809                 emitcode("pop","ar3");
12810                 emitcode("pop","ar2");          
12811         } else {
12812                 emitcode ("mov","r2,%s",
12813                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12814                 emitcode ("mov","r3,%s",
12815                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12816         }
12817         freeAsmop (handle, NULL, ic, FALSE);
12818
12819         /* make the call */
12820         emitcode ("lcall","MM_UnrestrictedPersist");
12821
12822         {
12823                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12824                 if (rsym->liveFrom != rsym->liveTo) {   
12825                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12826                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12827                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12828                 }
12829         }
12830         unsavermask(rsave);
12831 }
12832
12833 /*-----------------------------------------------------------------*/
12834 /* genSystemExecJavaProcess -                                      */
12835 /*-----------------------------------------------------------------*/
12836 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12837 {
12838         bitVect *rsave ;
12839         operand *handle, *pp;
12840
12841         assert (nparms==2);
12842         /* save registers that need to be saved */
12843         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12844                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12845         
12846         pp = parms[0];
12847         handle = parms[1];
12848         
12849         /* put the handle in R3-R2 */
12850         aopOp (handle,ic,FALSE,FALSE);
12851         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12852                 emitcode("push","%s",
12853                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12854                 emitcode("push","%s",
12855                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12856                 emitcode("pop","ar3");
12857                 emitcode("pop","ar2");          
12858         } else {
12859                 emitcode ("mov","r2,%s",
12860                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12861                 emitcode ("mov","r3,%s",
12862                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12863         }
12864         freeAsmop (handle, NULL, ic, FALSE);
12865         
12866         /* put pointer in DPTR */
12867         aopOp (pp,ic,FALSE,FALSE);
12868         if (AOP_TYPE(pp) == AOP_IMMD) {
12869                 emitcode ("mov", "dptr,%s",
12870                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12871         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12872                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12873                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12874                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12875         }
12876         freeAsmop (handle, NULL, ic, FALSE);
12877
12878         /* make the call */
12879         emitcode ("lcall","System_ExecJavaProcess");
12880         
12881         /* put result in place */
12882         {
12883                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12884                 if (rsym->liveFrom != rsym->liveTo) {   
12885                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12886                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12887                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12888                 }
12889         }
12890         
12891         unsavermask(rsave);
12892 }
12893
12894 /*-----------------------------------------------------------------*/
12895 /* genSystemRTCRegisters -                                         */
12896 /*-----------------------------------------------------------------*/
12897 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12898                                   char *name)
12899 {
12900         bitVect *rsave ;
12901         operand *pp;
12902
12903         assert (nparms==1);
12904         /* save registers that need to be saved */
12905         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12906                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12907         
12908         pp=parms[0];
12909         /* put pointer in DPTR */
12910         aopOp (pp,ic,FALSE,FALSE);
12911         if (AOP_TYPE (pp) == AOP_IMMD) {
12912                 emitcode ("mov","dps,#1");
12913                 emitcode ("mov", "dptr,%s", 
12914                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12915                 emitcode ("mov","dps,#0");
12916         } else {
12917                 emitcode ("mov","dpl1,%s",
12918                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12919                 emitcode ("mov","dph1,%s",
12920                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12921                 emitcode ("mov","dpx1,%s",
12922                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12923         }
12924         freeAsmop (pp, NULL, ic, FALSE);
12925
12926         /* make the call */
12927         emitcode ("lcall","System_%sRTCRegisters",name);
12928
12929         unsavermask(rsave);
12930 }
12931
12932 /*-----------------------------------------------------------------*/
12933 /* genSystemThreadSleep -                                          */
12934 /*-----------------------------------------------------------------*/
12935 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12936 {
12937         bitVect *rsave ;
12938         operand *to, *s;
12939
12940         assert (nparms==1);
12941         /* save registers that need to be saved */
12942         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12943                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12944
12945         to = parms[0];
12946         aopOp(to,ic,FALSE,FALSE);
12947         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12948             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12949                 emitcode ("push","%s",
12950                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12951                 emitcode ("push","%s",
12952                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12953                 emitcode ("push","%s",
12954                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12955                 emitcode ("push","%s",
12956                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12957                 emitcode ("pop","ar3");
12958                 emitcode ("pop","ar2");
12959                 emitcode ("pop","ar1");
12960                 emitcode ("pop","ar0");
12961         } else {
12962                 emitcode ("mov","r0,%s",
12963                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12964                 emitcode ("mov","r1,%s",
12965                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12966                 emitcode ("mov","r2,%s",
12967                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12968                 emitcode ("mov","r3,%s",
12969                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12970         }
12971         freeAsmop (to, NULL, ic, FALSE);
12972
12973         /* suspend in acc */
12974         s = parms[1];
12975         aopOp(s,ic,FALSE,FALSE);
12976         emitcode ("mov","a,%s",
12977                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12978         freeAsmop (s, NULL, ic, FALSE);
12979
12980         /* make the call */
12981         emitcode ("lcall","System_%s",name);
12982
12983         unsavermask(rsave);
12984 }
12985
12986 /*-----------------------------------------------------------------*/
12987 /* genSystemThreadResume -                                         */
12988 /*-----------------------------------------------------------------*/
12989 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12990 {
12991         bitVect *rsave ;
12992         operand *tid,*pid;
12993
12994         assert (nparms==2);
12995         /* save registers that need to be saved */
12996         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12997                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12998         
12999         tid = parms[0];
13000         pid = parms[1];
13001         
13002         /* PID in R0 */
13003         aopOp(pid,ic,FALSE,FALSE);
13004         emitcode ("mov","r0,%s",
13005                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13006         freeAsmop (pid, NULL, ic, FALSE);
13007         
13008         /* tid into ACC */
13009         aopOp(tid,ic,FALSE,FALSE);
13010         emitcode ("mov","a,%s",
13011                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13012         freeAsmop (tid, NULL, ic, FALSE);
13013         
13014         emitcode ("lcall","System_ThreadResume");
13015
13016         /* put result into place */
13017         {
13018                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13019                 if (rsym->liveFrom != rsym->liveTo) {   
13020                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13021                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13022                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13023                 }
13024         }
13025         unsavermask(rsave);
13026 }
13027
13028 /*-----------------------------------------------------------------*/
13029 /* genSystemProcessResume -                                        */
13030 /*-----------------------------------------------------------------*/
13031 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13032 {
13033         bitVect *rsave ;
13034         operand *pid;
13035
13036         assert (nparms==1);
13037         /* save registers that need to be saved */
13038         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13039                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13040         
13041         pid = parms[0];
13042         
13043         /* pid into ACC */
13044         aopOp(pid,ic,FALSE,FALSE);
13045         emitcode ("mov","a,%s",
13046                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13047         freeAsmop (pid, NULL, ic, FALSE);
13048         
13049         emitcode ("lcall","System_ProcessResume");
13050
13051         unsavermask(rsave);
13052 }
13053
13054 /*-----------------------------------------------------------------*/
13055 /* genSystem -                                                     */
13056 /*-----------------------------------------------------------------*/
13057 static void genSystem (iCode *ic,int nparms,char *name)
13058 {
13059         assert(nparms == 0);
13060
13061         emitcode ("lcall","System_%s",name);
13062 }
13063
13064 /*-----------------------------------------------------------------*/
13065 /* genSystemPoll -                                                  */
13066 /*-----------------------------------------------------------------*/
13067 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13068 {
13069         bitVect *rsave ;
13070         operand *fp;
13071
13072         assert (nparms==1);
13073         /* save registers that need to be saved */
13074         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13075                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13076
13077         fp = parms[0];
13078         aopOp (fp,ic,FALSE,FALSE);
13079         if (AOP_TYPE (fp) == AOP_IMMD) {
13080                 emitcode ("mov", "dptr,%s", 
13081                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13082         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13083                 emitcode ("mov","dpl,%s",
13084                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13085                 emitcode ("mov","dph,%s",
13086                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13087                 emitcode ("mov","dpx,%s",
13088                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13089         }
13090         freeAsmop (fp, NULL, ic, FALSE);
13091
13092         emitcode ("lcall","System_%sPoll",name);
13093
13094         /* put result into place */
13095         {
13096                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13097                 if (rsym->liveFrom != rsym->liveTo) {   
13098                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13099                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13100                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13101                 }
13102         }
13103         unsavermask(rsave);
13104 }
13105
13106 /*-----------------------------------------------------------------*/
13107 /* genSystemGetCurrentID -                                         */
13108 /*-----------------------------------------------------------------*/
13109 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13110 {
13111         assert (nparms==0);
13112
13113         emitcode ("lcall","System_GetCurrent%sId",name);
13114         /* put result into place */
13115         {
13116                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13117                 if (rsym->liveFrom != rsym->liveTo) {   
13118                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13119                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13120                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13121                 }
13122         }
13123 }
13124
13125 /*-----------------------------------------------------------------*/
13126 /* genDummyRead - generate code for dummy read of volatiles        */
13127 /*-----------------------------------------------------------------*/
13128 static void
13129 genDummyRead (iCode * ic)
13130 {
13131   operand *op;
13132   int size, offset;
13133
13134   D(emitcode(";     genDummyRead",""));
13135
13136   op = IC_RIGHT (ic);
13137   if (op && IS_SYMOP (op))
13138     {
13139       aopOp (op, ic, FALSE, FALSE);
13140
13141       /* if the result is a bit */
13142       if (AOP_TYPE (op) == AOP_CRY)
13143         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13144       else
13145         {
13146           /* bit variables done */
13147           /* general case */
13148           size = AOP_SIZE (op);
13149           offset = 0;
13150           while (size--)
13151           {
13152             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13153             offset++;
13154           }
13155         }
13156
13157       freeAsmop (op, NULL, ic, TRUE);
13158     }
13159
13160   op = IC_LEFT (ic);
13161   if (op && IS_SYMOP (op))
13162     {
13163       aopOp (op, ic, FALSE, FALSE);
13164
13165       /* if the result is a bit */
13166       if (AOP_TYPE (op) == AOP_CRY)
13167         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13168       else
13169         {
13170           /* bit variables done */
13171           /* general case */
13172           size = AOP_SIZE (op);
13173           offset = 0;
13174           while (size--)
13175           {
13176             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13177             offset++;
13178           }
13179         }
13180
13181       freeAsmop (op, NULL, ic, TRUE);
13182     }
13183     
13184 }
13185
13186 /*-----------------------------------------------------------------*/
13187 /* genCritical - generate code for start of a critical sequence    */
13188 /*-----------------------------------------------------------------*/
13189 static void
13190 genCritical (iCode *ic)
13191 {
13192   symbol *tlbl = newiTempLabel (NULL);
13193
13194   D(emitcode(";     genCritical",""));
13195   
13196   if (IC_RESULT (ic))
13197     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13198
13199   emitcode ("setb", "c");
13200   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13201   emitcode ("clr", "c");
13202   emitcode ("", "%05d$:", (tlbl->key + 100));
13203
13204   if (IC_RESULT (ic))
13205     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13206   else
13207     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13208
13209   if (IC_RESULT (ic))
13210     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13211 }
13212
13213 /*-----------------------------------------------------------------*/
13214 /* genEndCritical - generate code for end of a critical sequence   */
13215 /*-----------------------------------------------------------------*/
13216 static void
13217 genEndCritical (iCode *ic)
13218 {
13219   D(emitcode(";     genEndCritical",""));
13220   
13221   if (IC_RIGHT (ic))
13222     {
13223       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13224       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13225         {
13226           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13227           emitcode ("mov", "ea,c");
13228         }
13229       else
13230         {
13231           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13232           emitcode ("rrc", "a");
13233           emitcode ("mov", "ea,c");
13234         }
13235       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13236     }
13237   else
13238     {
13239       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13240       emitcode ("mov", "ea,c");
13241     }
13242 }
13243
13244
13245
13246 /*-----------------------------------------------------------------*/
13247 /* genBuiltIn - calls the appropriate function to  generating code */
13248 /* for a built in function                                         */
13249 /*-----------------------------------------------------------------*/
13250 static void genBuiltIn (iCode *ic)
13251 {
13252         operand *bi_parms[MAX_BUILTIN_ARGS];
13253         int nbi_parms;
13254         iCode *bi_iCode;
13255         symbol *bif;
13256
13257         /* get all the arguments for a built in function */
13258         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13259
13260         /* which function is it */
13261         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13262         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13263                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13264         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13265                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13266         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13267                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13268         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13269                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13270         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13271                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13272         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13273                 genInp(bi_iCode,nbi_parms,bi_parms);
13274         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13275                 genOutp(bi_iCode,nbi_parms,bi_parms);
13276         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13277                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13278                 /* JavaNative builtIns */               
13279         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13280                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13281         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13282                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13283         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13284                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13285         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13286                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13287         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13288                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13289         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13290                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13291         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13292                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13293         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13294                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13295         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13296                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13297         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13298                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13299         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13300                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13301         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13302                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13303         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13304                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13305         } else if (strcmp(bif->name,"MM_Free")==0) {
13306                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13307         } else if (strcmp(bif->name,"MM_Deref")==0) {
13308                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13309         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13310                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13311         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13312                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13313         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13314                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13315         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13316                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13317         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13318                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13319         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13320                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13321         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13322                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13323         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13324                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13325         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13326                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13327         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13328                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13329         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13330                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13331         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13332                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13333         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13334                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13335         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13336                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13337         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13338                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13339         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13340                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13341         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13342                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13343         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13344                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13345         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13346                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13347         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13348                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13349         } else {
13350                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13351                 return ;
13352         }
13353         return ;    
13354 }
13355
13356 /*-----------------------------------------------------------------*/
13357 /* gen390Code - generate code for Dallas 390 based controllers     */
13358 /*-----------------------------------------------------------------*/
13359 void
13360 gen390Code (iCode * lic)
13361 {
13362   iCode *ic;
13363   int cln = 0;
13364
13365   lineHead = lineCurr = NULL;
13366   dptrn[1][0] = "dpl1";
13367   dptrn[1][1] = "dph1";
13368   dptrn[1][2] = "dpx1";
13369   
13370   if (options.model == MODEL_FLAT24) {
13371     fReturnSizeDS390 = 5;
13372     fReturn = fReturn24;
13373   } else {
13374     fReturnSizeDS390 = 4;
13375     fReturn = fReturn16;
13376     options.stack10bit=0;
13377   }
13378 #if 1
13379   /* print the allocation information */
13380   if (allocInfo && currFunc)
13381     printAllocInfo (currFunc, codeOutFile);
13382 #endif
13383   /* if debug information required */
13384   if (options.debug && currFunc)
13385     {
13386       debugFile->writeFunction(currFunc);
13387       _G.debugLine = 1;
13388       if (IS_STATIC (currFunc->etype))
13389         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13390       else
13391         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13392       _G.debugLine = 0;
13393     }
13394   /* stack pointer name */
13395   if (options.useXstack)
13396     spname = "_spx";
13397   else
13398     spname = "sp";
13399
13400
13401   for (ic = lic; ic; ic = ic->next)
13402     {
13403
13404       _G.current_iCode = ic;
13405       
13406       if (ic->lineno && cln != ic->lineno)
13407         {
13408           if (options.debug)
13409             {
13410               _G.debugLine = 1;
13411               emitcode ("", "C$%s$%d$%d$%d ==.",
13412                         FileBaseName (ic->filename), ic->lineno,
13413                         ic->level, ic->block);
13414               _G.debugLine = 0;
13415             }
13416           if (!options.noCcodeInAsm) {
13417             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13418                       printCLine(ic->filename, ic->lineno));
13419           }
13420           cln = ic->lineno;
13421         }
13422       if (options.iCodeInAsm) {
13423         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13424       }
13425       /* if the result is marked as
13426          spilt and rematerializable or code for
13427          this has already been generated then
13428          do nothing */
13429       if (resultRemat (ic) || ic->generated)
13430         continue;
13431
13432       /* depending on the operation */
13433       switch (ic->op)
13434         {
13435         case '!':
13436           genNot (ic);
13437           break;
13438
13439         case '~':
13440           genCpl (ic);
13441           break;
13442
13443         case UNARYMINUS:
13444           genUminus (ic);
13445           break;
13446
13447         case IPUSH:
13448           genIpush (ic);
13449           break;
13450
13451         case IPOP:
13452           /* IPOP happens only when trying to restore a
13453              spilt live range, if there is an ifx statement
13454              following this pop then the if statement might
13455              be using some of the registers being popped which
13456              would destory the contents of the register so
13457              we need to check for this condition and handle it */
13458           if (ic->next &&
13459               ic->next->op == IFX &&
13460               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13461             genIfx (ic->next, ic);
13462           else
13463             genIpop (ic);
13464           break;
13465
13466         case CALL:
13467           genCall (ic);
13468           break;
13469
13470         case PCALL:
13471           genPcall (ic);
13472           break;
13473
13474         case FUNCTION:
13475           genFunction (ic);
13476           break;
13477
13478         case ENDFUNCTION:
13479           genEndFunction (ic);
13480           break;
13481
13482         case RETURN:
13483           genRet (ic);
13484           break;
13485
13486         case LABEL:
13487           genLabel (ic);
13488           break;
13489
13490         case GOTO:
13491           genGoto (ic);
13492           break;
13493
13494         case '+':
13495           genPlus (ic);
13496           break;
13497
13498         case '-':
13499           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13500             genMinus (ic);
13501           break;
13502
13503         case '*':
13504           genMult (ic);
13505           break;
13506
13507         case '/':
13508           genDiv (ic);
13509           break;
13510
13511         case '%':
13512           genMod (ic);
13513           break;
13514
13515         case '>':
13516           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13517           break;
13518
13519         case '<':
13520           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13521           break;
13522
13523         case LE_OP:
13524         case GE_OP:
13525         case NE_OP:
13526
13527           /* note these two are xlated by algebraic equivalence
13528              during parsing SDCC.y */
13529           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13530                   "got '>=' or '<=' shouldn't have come here");
13531           break;
13532
13533         case EQ_OP:
13534           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13535           break;
13536
13537         case AND_OP:
13538           genAndOp (ic);
13539           break;
13540
13541         case OR_OP:
13542           genOrOp (ic);
13543           break;
13544
13545         case '^':
13546           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13547           break;
13548
13549         case '|':
13550           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13551           break;
13552
13553         case BITWISEAND:
13554           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13555           break;
13556
13557         case INLINEASM:
13558           genInline (ic);
13559           break;
13560
13561         case RRC:
13562           genRRC (ic);
13563           break;
13564
13565         case RLC:
13566           genRLC (ic);
13567           break;
13568
13569         case GETHBIT:
13570           genGetHbit (ic);
13571           break;
13572
13573         case LEFT_OP:
13574           genLeftShift (ic);
13575           break;
13576
13577         case RIGHT_OP:
13578           genRightShift (ic);
13579           break;
13580
13581         case GET_VALUE_AT_ADDRESS:
13582           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13583           break;
13584
13585         case '=':
13586           if (POINTER_SET (ic))
13587             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13588           else
13589             genAssign (ic);
13590           break;
13591
13592         case IFX:
13593           genIfx (ic, NULL);
13594           break;
13595
13596         case ADDRESS_OF:
13597           genAddrOf (ic);
13598           break;
13599
13600         case JUMPTABLE:
13601           genJumpTab (ic);
13602           break;
13603
13604         case CAST:
13605           genCast (ic);
13606           break;
13607
13608         case RECEIVE:
13609           genReceive (ic);
13610           break;
13611
13612         case SEND:
13613           if (ic->builtinSEND) genBuiltIn(ic);
13614           else addSet (&_G.sendSet, ic);
13615           break;
13616
13617         case DUMMY_READ_VOLATILE:
13618           genDummyRead (ic);
13619           break;
13620
13621         case CRITICAL:
13622           genCritical (ic);
13623           break;
13624
13625         case ENDCRITICAL:
13626           genEndCritical (ic);
13627           break;
13628         
13629         case SWAP:
13630           genSwap (ic);
13631           break;
13632           
13633 #if 0 // obsolete, and buggy for != xdata
13634         case ARRAYINIT:
13635             genArrayInit(ic);
13636             break;
13637 #endif
13638             
13639         default:
13640           ic = ic;
13641         }
13642     }
13643
13644
13645   /* now we are ready to call the
13646      peep hole optimizer */
13647   if (!options.nopeep)
13648     peepHole (&lineHead);
13649
13650   /* now do the actual printing */
13651   printLine (lineHead, codeOutFile);
13652   return;
13653 }