* src/mcs51/gen.c (genCmp): fixed bug #975903
[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 /* ds390_emitDebuggerSymbol - associate the current code location  */
192 /*   with a debugger symbol                                        */
193 /*-----------------------------------------------------------------*/
194 void
195 ds390_emitDebuggerSymbol (char * debugSym)
196 {
197   _G.debugLine = 1;
198   emitcode ("", "%s ==.", debugSym);
199   _G.debugLine = 0;
200 }
201
202 //
203 // Move the passed value into A unless it is already there.
204 // 
205 static void
206 _movA(const char *s)
207 {
208     if (strcmp(s,"a") && strcmp(s,"acc"))
209     { 
210         emitcode("mov","a,%s",s);
211     } 
212 }
213
214 //
215 // Move the passed value into B unless it is already there.
216 // 
217 static void
218 _movB(const char *s)
219 {
220     if (strcmp(s,"b"))
221     { 
222         emitcode("mov","b,%s",s);
223     } 
224 }
225
226 /*-----------------------------------------------------------------*/
227 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
228 /*-----------------------------------------------------------------*/
229 static regs *
230 getFreePtr (iCode * ic, asmop ** aopp, bool result)
231 {
232   bool r0iu, r1iu;
233   bool r0ou, r1ou;
234
235   /* the logic: if r0 & r1 used in the instruction
236      then we are in trouble otherwise */
237
238   /* first check if r0 & r1 are used by this
239      instruction, in which case we are in trouble */
240   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
241   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
242   if (r0iu && r1iu) {
243       goto endOfWorld;
244     }
245
246   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
247   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
248
249   /* if no usage of r0 then return it */
250   if (!r0iu && !r0ou)
251     {
252       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
253       (*aopp)->type = AOP_R0;
254
255       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
256     }
257
258   /* if no usage of r1 then return it */
259   if (!r1iu && !r1ou)
260     {
261       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262       (*aopp)->type = AOP_R1;
263
264       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
265     }
266
267   /* now we know they both have usage */
268   /* if r0 not used in this instruction */
269   if (!r0iu)
270     {
271       /* push it if not already pushed */
272       if (!_G.r0Pushed)
273         {
274           emitcode ("push", "%s",
275                     ds390_regWithIdx (R0_IDX)->dname);
276           _G.r0Pushed++;
277         }
278
279       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
280       (*aopp)->type = AOP_R0;
281
282       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
283     }
284
285   /* if r1 not used then */
286
287   if (!r1iu)
288     {
289       /* push it if not already pushed */
290       if (!_G.r1Pushed)
291         {
292           emitcode ("push", "%s",
293                     ds390_regWithIdx (R1_IDX)->dname);
294           _G.r1Pushed++;
295         }
296
297       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
298       (*aopp)->type = AOP_R1;
299       return ds390_regWithIdx (R1_IDX);
300     }
301
302 endOfWorld:
303   /* I said end of world but not quite end of world yet */
304   /* if this is a result then we can push it on the stack */
305   if (result)
306     {
307       (*aopp)->type = AOP_STK;
308       return NULL;
309     }
310
311   /* other wise this is true end of the world */
312   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
313           "getFreePtr should never reach here");
314   exit (1);
315     
316   return NULL; // notreached, but makes compiler happy.
317 }
318
319 /*-----------------------------------------------------------------*/
320 /* newAsmop - creates a new asmOp                                  */
321 /*-----------------------------------------------------------------*/
322 static asmop *
323 newAsmop (short type)
324 {
325   asmop *aop;
326
327   aop = Safe_calloc (1, sizeof (asmop));
328   aop->type = type;
329   return aop;
330 }
331
332
333 /*-----------------------------------------------------------------*/
334 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
335 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
336 /* alternate DPTR (DPL1/DPH1/DPX1).          */
337 /*-----------------------------------------------------------------*/
338 static void
339 genSetDPTR (int n)
340 {
341
342   /* If we are doing lazy evaluation, simply note the desired
343    * change, but don't emit any code yet.
344    */
345   if (_lazyDPS)
346     {
347       _desiredDPS = n;
348       return;
349     }
350
351   if (!n)
352     {
353       emitcode ("mov", "dps,#0");
354     }
355   else
356     {
357       TR_DPTR("#1");
358       emitcode ("mov", "dps,#1");
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
364 /*                   */
365 /* Any code that operates on DPTR (NB: not on the individual     */
366 /* components, like DPH) *must* call _flushLazyDPS() before using  */
367 /* DPTR within a lazy DPS evaluation block.        */
368 /*                   */
369 /* Note that aopPut and aopGet already contain the proper calls to */
370 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
371 /* DPS evaluation block.             */
372 /*                   */
373 /* Also, _flushLazyDPS must be called before any flow control      */
374 /* operations that could potentially branch out of the block.    */
375 /*                         */
376 /* Lazy DPS evaluation is simply an optimization (though an      */
377 /* important one), so if in doubt, leave it out.       */
378 /*-----------------------------------------------------------------*/
379 static void
380 _startLazyDPSEvaluation (void)
381 {
382   _currentDPS = 0;
383   _desiredDPS = 0;
384 #ifdef BETTER_LITERAL_SHIFT  
385   _lazyDPS++;
386 #else
387   _lazyDPS = 1;
388 #endif  
389 }
390
391 /*-----------------------------------------------------------------*/
392 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
393 /* desired one. Call before using DPTR within a lazy DPS evaluation */
394 /* block.                */
395 /*-----------------------------------------------------------------*/
396 static void
397 _flushLazyDPS (void)
398 {
399   if (!_lazyDPS)
400     {
401       /* nothing to do. */
402       return;
403     }
404
405   if (_desiredDPS != _currentDPS)
406     {
407       if (_desiredDPS)
408         {
409           emitcode ("inc", "dps");
410         }
411       else
412         {
413           emitcode ("dec", "dps");
414         }
415       _currentDPS = _desiredDPS;
416     }
417 }
418
419 /*-----------------------------------------------------------------*/
420 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
421 /*                   */
422 /* Forces us back to the safe state (standard DPTR selected).    */
423 /*-----------------------------------------------------------------*/
424 static void
425 _endLazyDPSEvaluation (void)
426 {
427 #ifdef BETTER_LITERAL_SHIFT  
428   _lazyDPS--;
429 #else
430   _lazyDPS = 0;
431 #endif    
432   if (!_lazyDPS)
433   {
434     if (_currentDPS)
435     {
436       genSetDPTR (0);
437       _flushLazyDPS ();
438     }
439     _currentDPS = 0;
440     _desiredDPS = 0;
441   }
442 }
443
444
445
446 /*-----------------------------------------------------------------*/
447 /* pointerCode - returns the code for a pointer type               */
448 /*-----------------------------------------------------------------*/
449 static int
450 pointerCode (sym_link * etype)
451 {
452
453   return PTR_TYPE (SPEC_OCLS (etype));
454
455 }
456
457 /*-----------------------------------------------------------------*/
458 /* leftRightUseAcc - returns size of accumulator use by operands   */
459 /*-----------------------------------------------------------------*/
460 static int
461 leftRightUseAcc(iCode *ic)
462 {
463   operand *op;
464   int size;
465   int accuseSize = 0;
466   int accuse = 0;
467   
468   if (!ic)
469     {
470       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
471               "null iCode pointer");
472       return 0;
473     }
474
475   if (ic->op == IFX)
476     {
477       op = IC_COND (ic);
478       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
479         {
480           accuse = 1;
481           size = getSize (OP_SYMBOL (op)->type);
482           if (size>accuseSize)
483             accuseSize = size;
484         }
485     }
486   else if (ic->op == JUMPTABLE)
487     {
488       op = IC_JTCOND (ic);
489       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
490         {
491           accuse = 1;
492           size = getSize (OP_SYMBOL (op)->type);
493           if (size>accuseSize)
494             accuseSize = size;
495         }
496     }
497   else
498     {
499       op = IC_LEFT (ic);
500       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
501         {
502           accuse = 1;
503           size = getSize (OP_SYMBOL (op)->type);
504           if (size>accuseSize)
505             accuseSize = size;
506         }
507       op = IC_RIGHT (ic);
508       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
509         {
510           accuse = 1;
511           size = getSize (OP_SYMBOL (op)->type);
512           if (size>accuseSize)
513             accuseSize = size;
514         }
515     }
516   
517   if (accuseSize)
518     return accuseSize;
519   else
520     return accuse;
521 }
522
523 /*-----------------------------------------------------------------*/
524 /* aopForSym - for a true symbol                                   */
525 /*-----------------------------------------------------------------*/
526 static asmop *
527 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
528 {
529   asmop *aop;
530   memmap *space = SPEC_OCLS (sym->etype);
531   int accuse = leftRightUseAcc (ic);
532
533   /* if already has one */
534   if (sym->aop)
535     {
536       if ((sym->aop->type == AOP_DPTR && useDP2)
537           || (sym->aop->type == AOP_DPTR2 && !useDP2))
538         sym->aop = NULL;
539       else
540         return sym->aop;
541     }
542
543   /* assign depending on the storage class */
544   /* if it is on the stack or indirectly addressable */
545   /* space we need to assign either r0 or r1 to it   */
546   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
547     {
548       sym->aop = aop = newAsmop (0);
549       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
550       aop->size = getSize (sym->type);
551
552       /* now assign the address of the variable to
553          the pointer register */
554       if (aop->type != AOP_STK)
555         {
556
557           if (sym->onStack)
558             {
559               if (_G.accInUse || accuse)
560                 emitcode ("push", "acc");
561
562               if (_G.bInUse || (accuse>1))
563                 emitcode ("push", "b");
564
565               emitcode ("mov", "a,_bp");
566               emitcode ("add", "a,#!constbyte",
567                         ((sym->stack < 0) ?
568                          ((char) (sym->stack - _G.nRegsSaved)) :
569                          ((char) sym->stack)) & 0xff);
570               emitcode ("mov", "%s,a",
571                         aop->aopu.aop_ptr->name);
572
573               if (_G.bInUse || (accuse>1))
574                 emitcode ("pop", "b");
575
576               if (_G.accInUse || accuse)
577                 emitcode ("pop", "acc");
578             }
579           else
580             emitcode ("mov", "%s,#%s",
581                       aop->aopu.aop_ptr->name,
582                       sym->rname);
583           aop->paged = space->paged;
584         }
585       else
586         aop->aopu.aop_stk = sym->stack;
587       return aop;
588     }
589
590   if (sym->onStack && options.stack10bit)
591     {
592         short stack_val = -((sym->stack < 0) ?
593                             ((short) (sym->stack - _G.nRegsSaved)) :
594                             ((short) sym->stack)) ;
595         if (useDP2 && _G.dptr1InUse) {
596             emitcode ("push","dpl1");
597             emitcode ("push","dph1");
598             emitcode ("push","dpx1");
599         } else if (_G.dptrInUse ) {
600             emitcode ("push","dpl");
601             emitcode ("push","dph");
602             emitcode ("push","dpx");
603         }
604       /* It's on the 10 bit stack, which is located in
605        * far data space.
606        */           
607         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
608             if (useDP2) {
609                 if (options.model == MODEL_FLAT24)
610                 {
611                     emitcode ("mov", "dpx1,#!constbyte",
612                               (options.stack_loc >> 16) & 0xff);
613                 }
614                 emitcode ("mov", "dph1,_bpx+1");
615                 
616                 emitcode ("mov", "dpl1,_bpx");
617                 emitcode ("mov","dps,#1");
618             } else {
619                 if (options.model == MODEL_FLAT24)
620                 {
621                     emitcode ("mov", "dpx,#!constbyte",
622                               (options.stack_loc >> 16) & 0xff);
623                 }
624                 emitcode ("mov", "dph,_bpx+1");
625                 emitcode ("mov", "dpl,_bpx");
626             }
627             stack_val = -stack_val;
628             while (stack_val--) {
629                 emitcode ("inc","dptr");
630             }
631             if (useDP2) {
632                 emitcode("mov","dps,#0");
633             }
634         }  else {
635             if (_G.accInUse || accuse)
636                 emitcode ("push", "acc");
637             
638             if (_G.bInUse || (accuse>1))
639                 emitcode ("push", "b");
640         
641             emitcode ("mov", "a,_bpx");
642             emitcode ("clr","c");
643             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
644             emitcode ("mov","b,a");
645             emitcode ("mov","a,_bpx+1");
646             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
647             if (useDP2) {
648                 if (options.model == MODEL_FLAT24)
649                 {
650                     emitcode ("mov", "dpx1,#!constbyte",
651                               (options.stack_loc >> 16) & 0xff);
652                 }
653                 emitcode ("mov", "dph1,a");
654                 emitcode ("mov", "dpl1,b");
655             } else {
656                 if (options.model == MODEL_FLAT24)
657                 {
658                     emitcode ("mov", "dpx,#!constbyte",
659                               (options.stack_loc >> 16) & 0xff);
660                 }
661                 emitcode ("mov", "dph,a");
662                 emitcode ("mov", "dpl,b");
663             }
664             
665             if (_G.bInUse || (accuse>1))
666                 emitcode ("pop", "b");
667             
668             if (_G.accInUse || accuse)
669                 emitcode ("pop", "acc");
670         }
671         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
672         aop->size = getSize (sym->type);
673         return aop;
674     }
675
676   /* if in bit space */
677   if (IN_BITSPACE (space))
678     {
679       sym->aop = aop = newAsmop (AOP_CRY);
680       aop->aopu.aop_dir = sym->rname;
681       aop->size = getSize (sym->type);
682       return aop;
683     }
684   /* if it is in direct space */
685   if (IN_DIRSPACE (space))
686     {
687       sym->aop = aop = newAsmop (AOP_DIR);
688       aop->aopu.aop_dir = sym->rname;
689       aop->size = getSize (sym->type);
690       return aop;
691     }
692
693   /* special case for a function */
694   if (IS_FUNC (sym->type) && !(sym->isitmp))
695     {
696       sym->aop = aop = newAsmop (AOP_IMMD);
697       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
698       aop->size = FPTRSIZE;
699       return aop;
700     }
701
702   /* only remaining is far space */
703   /* in which case DPTR gets the address */
704   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
705   if (useDP2)
706     {
707       genSetDPTR (1);
708       _flushLazyDPS ();
709       emitcode ("mov", "dptr,#%s", sym->rname);
710       genSetDPTR (0);
711     }
712   else
713     {
714       emitcode ("mov", "dptr,#%s", sym->rname);
715     }
716   aop->size = getSize (sym->type);
717
718   /* if it is in code space */
719   if (IN_CODESPACE (space))
720     aop->code = 1;
721
722   return aop;
723 }
724
725 /*-----------------------------------------------------------------*/
726 /* aopForRemat - rematerialzes an object                           */
727 /*-----------------------------------------------------------------*/
728 static asmop *
729 aopForRemat (symbol * sym)
730 {
731   iCode *ic = sym->rematiCode;
732   asmop *aop = newAsmop (AOP_IMMD);
733   int ptr_type =0;
734   int val = 0;
735
736   for (;;)
737     {
738       if (ic->op == '+')
739         val += (int) operandLitValue (IC_RIGHT (ic));
740       else if (ic->op == '-')
741         val -= (int) operandLitValue (IC_RIGHT (ic));
742       else if (IS_CAST_ICODE(ic)) {
743               sym_link *from_type = operandType(IC_RIGHT(ic));
744               aop->aopu.aop_immd.from_cast_remat = 1;
745               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
746               ptr_type = DCL_TYPE(from_type);
747               if (ptr_type == IPOINTER) {
748                 // bug #481053
749                 ptr_type = POINTER;
750               }
751               continue ;
752       } else break;
753       
754       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
755     }
756
757   if (val)
758   {
759       SNPRINTF (buffer, sizeof(buffer),
760                 "(%s %c 0x%04x)",
761                 OP_SYMBOL (IC_LEFT (ic))->rname,
762                 val >= 0 ? '+' : '-',
763                 abs (val) & 0xffffff);
764   }
765   else 
766   {
767       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
768       {
769           SNPRINTF(buffer, sizeof(buffer), 
770                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
771       }
772       else
773       {
774           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
775       }
776   }
777
778   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
779   /* set immd2 field if required */
780   if (aop->aopu.aop_immd.from_cast_remat) 
781   {
782       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
783       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
784   }
785
786   return aop;
787 }
788
789 /*-----------------------------------------------------------------*/
790 /* aopHasRegs - returns true if aop has regs between from-to       */
791 /*-----------------------------------------------------------------*/
792 static int aopHasRegs(asmop *aop, int from, int to)
793 {
794     int size =0;
795
796     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
797
798     for (; size < aop->size ; size++) {
799         int reg;
800         for (reg = from ; reg <= to ; reg++)
801             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
802     }
803     return 0;
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* regsInCommon - two operands have some registers in common       */
808 /*-----------------------------------------------------------------*/
809 static bool
810 regsInCommon (operand * op1, operand * op2)
811 {
812   symbol *sym1, *sym2;
813   int i;
814
815   /* if they have registers in common */
816   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
817     return FALSE;
818
819   sym1 = OP_SYMBOL (op1);
820   sym2 = OP_SYMBOL (op2);
821
822   if (sym1->nRegs == 0 || sym2->nRegs == 0)
823     return FALSE;
824
825   for (i = 0; i < sym1->nRegs; i++)
826     {
827       int j;
828       if (!sym1->regs[i])
829         continue;
830
831       for (j = 0; j < sym2->nRegs; j++)
832         {
833           if (!sym2->regs[j])
834             continue;
835
836           if (sym2->regs[j] == sym1->regs[i])
837             return TRUE;
838         }
839     }
840
841   return FALSE;
842 }
843
844 /*-----------------------------------------------------------------*/
845 /* operandsEqu - equivalent                                        */
846 /*-----------------------------------------------------------------*/
847 static bool
848 operandsEqu (operand * op1, operand * op2)
849 {
850   symbol *sym1, *sym2;
851
852   /* if they not symbols */
853   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
854     return FALSE;
855
856   sym1 = OP_SYMBOL (op1);
857   sym2 = OP_SYMBOL (op2);
858
859   /* if both are itemps & one is spilt
860      and the other is not then false */
861   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
862       sym1->isspilt != sym2->isspilt)
863     return FALSE;
864
865   /* if they are the same */
866   if (sym1 == sym2)
867     return TRUE;
868
869   if (sym1->rname[0] && sym2->rname[0]
870       && strcmp (sym1->rname, sym2->rname) == 0)
871     return TRUE;
872
873
874   /* if left is a tmp & right is not */
875   if (IS_ITEMP (op1) &&
876       !IS_ITEMP (op2) &&
877       sym1->isspilt &&
878       (sym1->usl.spillLoc == sym2))
879     return TRUE;
880
881   if (IS_ITEMP (op2) &&
882       !IS_ITEMP (op1) &&
883       sym2->isspilt &&
884       sym1->level > 0 &&
885       (sym2->usl.spillLoc == sym1))
886     return TRUE;
887
888   /* are they spilt to the same location */
889   if (IS_ITEMP (op2) &&
890       IS_ITEMP (op1) &&
891       sym2->isspilt &&
892       sym1->isspilt &&
893       (sym1->usl.spillLoc == sym2->usl.spillLoc))
894     return TRUE;
895     
896   return FALSE;
897 }
898
899 /*-----------------------------------------------------------------*/
900 /* sameRegs - two asmops have the same registers                   */
901 /*-----------------------------------------------------------------*/
902 static bool
903 sameRegs (asmop * aop1, asmop * aop2)
904 {
905   int i;
906
907   if (aop1 == aop2)
908     {
909       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
910         {
911           return FALSE;
912         }
913       return TRUE;
914     }
915
916   if (aop1->type != AOP_REG ||
917       aop2->type != AOP_REG)
918     return FALSE;
919
920   if (aop1->size != aop2->size)
921     return FALSE;
922
923   for (i = 0; i < aop1->size; i++)
924     if (aop1->aopu.aop_reg[i] !=
925         aop2->aopu.aop_reg[i])
926       return FALSE;
927
928   return TRUE;
929 }
930
931 /*-----------------------------------------------------------------*/
932 /* aopOp - allocates an asmop for an operand  :                    */
933 /*-----------------------------------------------------------------*/
934 static void
935 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
936 {
937   asmop *aop;
938   symbol *sym;
939   int i;
940
941   if (!op)
942     return;
943
944   /* if this a literal */
945   if (IS_OP_LITERAL (op))
946     {
947       op->aop = aop = newAsmop (AOP_LIT);
948       aop->aopu.aop_lit = op->operand.valOperand;
949       aop->size = getSize (operandType (op));
950       return;
951     }
952
953   /* if already has a asmop then continue */
954   if (op->aop)
955     {
956       if ((op->aop->type == AOP_DPTR && useDP2)
957           || (op->aop->type == AOP_DPTR2 && !useDP2))
958         op->aop = NULL;
959       else
960         return;
961     }
962
963   /* if the underlying symbol has a aop */
964   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
965     {
966       op->aop = OP_SYMBOL (op)->aop;
967       if ((op->aop->type == AOP_DPTR && useDP2)
968           || (op->aop->type == AOP_DPTR2 && !useDP2))
969         op->aop = NULL;
970       else
971         return;
972     }
973
974   /* if this is a true symbol */
975   if (IS_TRUE_SYMOP (op))
976     {
977       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
978       return;
979     }
980
981   /* this is a temporary : this has
982      only four choices :
983      a) register
984      b) spillocation
985      c) rematerialize
986      d) conditional
987      e) can be a return use only */
988
989   sym = OP_SYMBOL (op);
990
991
992   /* if the type is a conditional */
993   if (sym->regType == REG_CND)
994     {
995       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
996       aop->size = 0;
997       return;
998     }
999
1000   /* if it is spilt then two situations
1001      a) is rematerialize
1002      b) has a spill location */
1003   if (sym->isspilt || sym->nRegs == 0)
1004     {
1005
1006       /* rematerialize it NOW */
1007       if (sym->remat)
1008         {
1009           sym->aop = op->aop = aop =
1010             aopForRemat (sym);
1011           aop->size = getSize (sym->type);
1012           return;
1013         }
1014
1015       if (sym->accuse)
1016         {
1017           int i;
1018           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1019           aop->size = getSize (sym->type);
1020           for (i = 0; i < 2; i++)
1021             aop->aopu.aop_str[i] = accUse[i];
1022           return;
1023         }
1024
1025       if (sym->ruonly)
1026         {
1027           int i;
1028
1029           if (useDP2)
1030             {
1031               /* a AOP_STR uses DPTR, but DPTR is already in use;
1032                * we're just hosed.
1033                */
1034                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1035             }
1036
1037           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1038           aop->size = getSize (sym->type);
1039           for (i = 0; i < (int) fReturnSizeDS390; i++)
1040             aop->aopu.aop_str[i] = fReturn[i];
1041           return;
1042         }
1043       
1044       if (sym->dptr) { /* has been allocated to a DPTRn */
1045           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1046           aop->size = getSize (sym->type);
1047           aop->aopu.dptr = sym->dptr;
1048           return ;
1049       }
1050       
1051       if (sym->usl.spillLoc)
1052         {
1053           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1054             {
1055               /* force a new aop if sizes differ */
1056               sym->usl.spillLoc->aop = NULL;
1057             }
1058           sym->aop = op->aop = aop =
1059                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1060           aop->size = getSize (sym->type);
1061           return;
1062         }
1063       
1064       /* else must be a dummy iTemp */
1065       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1066       aop->size = getSize (sym->type);
1067       return;
1068     }
1069
1070   /* must be in a register */
1071   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1072   aop->size = sym->nRegs;
1073   for (i = 0; i < sym->nRegs; i++)
1074     aop->aopu.aop_reg[i] = sym->regs[i];
1075 }
1076
1077 /*-----------------------------------------------------------------*/
1078 /* freeAsmop - free up the asmop given to an operand               */
1079 /*----------------------------------------------------------------*/
1080 static void
1081 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1082 {
1083   asmop *aop;
1084
1085   if (!op)
1086     aop = aaop;
1087   else
1088     aop = op->aop;
1089
1090   if (!aop)
1091     return;
1092
1093   if (aop->freed)
1094     goto dealloc;
1095
1096   aop->freed = 1;
1097
1098   /* depending on the asmop type only three cases need work AOP_RO
1099      , AOP_R1 && AOP_STK */
1100   switch (aop->type)
1101     {
1102     case AOP_R0:
1103       if (_G.r0Pushed)
1104         {
1105           if (pop)
1106             {
1107               emitcode ("pop", "ar0");
1108               _G.r0Pushed--;
1109             }
1110         }
1111       bitVectUnSetBit (ic->rUsed, R0_IDX);
1112       break;
1113
1114     case AOP_R1:
1115       if (_G.r1Pushed)
1116         {
1117           if (pop)
1118             {
1119               emitcode ("pop", "ar1");
1120               _G.r1Pushed--;
1121             }
1122         }
1123       bitVectUnSetBit (ic->rUsed, R1_IDX);
1124       break;
1125
1126     case AOP_STK:
1127       {
1128         int sz = aop->size;
1129         int stk = aop->aopu.aop_stk + aop->size;
1130         bitVectUnSetBit (ic->rUsed, R0_IDX);
1131         bitVectUnSetBit (ic->rUsed, R1_IDX);
1132
1133         getFreePtr (ic, &aop, FALSE);
1134
1135         if (options.stack10bit)
1136           {
1137             /* I'm not sure what to do here yet... */
1138             /* #STUB */
1139             fprintf (stderr,
1140                      "*** Warning: probably generating bad code for "
1141                      "10 bit stack mode.\n");
1142           }
1143
1144         if (stk)
1145           {
1146             emitcode ("mov", "a,_bp");
1147             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1148             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1149           }
1150         else
1151           {
1152             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1153           }
1154
1155         while (sz--)
1156           {
1157             emitcode ("pop", "acc");
1158             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1159             if (!sz)
1160               break;
1161             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1162           }
1163         op->aop = aop;
1164         freeAsmop (op, NULL, ic, TRUE);
1165         if (_G.r0Pushed)
1166           {
1167             emitcode ("pop", "ar0");
1168             _G.r0Pushed--;
1169           }
1170
1171         if (_G.r1Pushed)
1172           {
1173             emitcode ("pop", "ar1");
1174             _G.r1Pushed--;
1175           }
1176       }
1177     case AOP_DPTR2:
1178         if (_G.dptr1InUse) {
1179             emitcode ("pop","dpx1");
1180             emitcode ("pop","dph1");
1181             emitcode ("pop","dpl1");
1182         }
1183         break;
1184     case AOP_DPTR:
1185         if (_G.dptrInUse) {
1186             emitcode ("pop","dpx");
1187             emitcode ("pop","dph");
1188             emitcode ("pop","dpl");
1189         }
1190         break;
1191     }
1192 dealloc:
1193   /* all other cases just dealloc */
1194   if (op)
1195     {
1196       op->aop = NULL;
1197       if (IS_SYMOP (op))
1198         {
1199           OP_SYMBOL (op)->aop = NULL;
1200           /* if the symbol has a spill */
1201           if (SPIL_LOC (op))
1202             SPIL_LOC (op)->aop = NULL;
1203         }
1204     }
1205 }
1206
1207 #define DEFAULT_ACC_WARNING 0
1208 static int saveAccWarn = DEFAULT_ACC_WARNING;
1209
1210 /*-------------------------------------------------------------------*/
1211 /* aopGet - for fetching value of the aop                            */
1212 /*                                                                   */
1213 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1214 /* in the accumulator. Set it to the name of a free register         */
1215 /* if acc must be preserved; the register will be used to preserve   */
1216 /* acc temporarily and to return the result byte.                    */
1217 /*-------------------------------------------------------------------*/
1218
1219 static char *
1220 aopGet (asmop *aop,
1221         int   offset,
1222         bool  bit16,
1223         bool  dname,
1224         char  *saveAcc)
1225 {
1226   /* offset is greater than
1227      size then zero */
1228   if (offset > (aop->size - 1) &&
1229       aop->type != AOP_LIT)
1230     return zero;
1231
1232   /* depending on type */
1233   switch (aop->type)
1234     {
1235     case AOP_DUMMY:
1236       return zero;
1237
1238     case AOP_R0:
1239     case AOP_R1:
1240       /* if we need to increment it */
1241       while (offset > aop->coff)
1242         {
1243           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1244           aop->coff++;
1245         }
1246
1247       while (offset < aop->coff)
1248         {
1249           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1250           aop->coff--;
1251         }
1252
1253       aop->coff = offset;
1254       if (aop->paged)
1255         {
1256           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1257           return (dname ? "acc" : "a");
1258         }
1259       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1260       return Safe_strdup(buffer);       
1261
1262     case AOP_DPTRn:
1263         assert(offset <= 3);
1264         return dptrn[aop->aopu.dptr][offset];
1265
1266     case AOP_DPTR:
1267     case AOP_DPTR2:
1268
1269       if (aop->type == AOP_DPTR2)
1270         {
1271           genSetDPTR (1);
1272         }
1273         
1274       if (saveAcc)
1275         {
1276             TR_AP("#1");
1277 //          if (aop->type != AOP_DPTR2)
1278 //          {
1279 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1280 //              emitcode(";", "spanky: saveAcc for DPTR");
1281 //          }
1282             
1283             emitcode ("xch", "a, %s", saveAcc);
1284         }
1285
1286       _flushLazyDPS ();
1287
1288       while (offset > aop->coff)
1289         {
1290           emitcode ("inc", "dptr");
1291           aop->coff++;
1292         }
1293
1294       while (offset < aop->coff)
1295         {
1296           emitcode ("lcall", "__decdptr");
1297           aop->coff--;
1298         }
1299
1300       aop->coff = offset;
1301       if (aop->code)
1302         {
1303           emitcode ("clr", "a");
1304           emitcode ("movc", "a,@a+dptr");
1305         }
1306       else
1307         {
1308           emitcode ("movx", "a,@dptr");
1309         }
1310
1311       if (aop->type == AOP_DPTR2)
1312         {
1313           genSetDPTR (0);
1314         }
1315         
1316         if (saveAcc)
1317         {
1318        TR_AP("#2");
1319               emitcode ("xch", "a, %s", saveAcc);
1320 //            if (strcmp(saveAcc, "_ap"))
1321 //            {
1322 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1323 //            }
1324                   
1325               return saveAcc;
1326         }
1327       return (dname ? "acc" : "a");
1328
1329     case AOP_IMMD:
1330       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1331       {
1332           SNPRINTF(buffer, sizeof(buffer), 
1333                    "%s",aop->aopu.aop_immd.aop_immd2);
1334       } 
1335       else if (bit16)
1336       {
1337          SNPRINTF(buffer, sizeof(buffer), 
1338                   "#%s", aop->aopu.aop_immd.aop_immd1);
1339       }
1340       else if (offset) 
1341       {
1342           switch (offset) {
1343           case 1:
1344               tsprintf(buffer, sizeof(buffer),
1345                        "#!his",aop->aopu.aop_immd.aop_immd1);
1346               break;
1347           case 2:
1348               tsprintf(buffer, sizeof(buffer), 
1349                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1350               break;
1351           case 3:
1352               tsprintf(buffer, sizeof(buffer),
1353                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1354               break;
1355           default: /* should not need this (just in case) */
1356               SNPRINTF (buffer, sizeof(buffer), 
1357                         "#(%s >> %d)",
1358                        aop->aopu.aop_immd.aop_immd1,
1359                        offset * 8);
1360           }
1361       }
1362       else
1363       {
1364         SNPRINTF (buffer, sizeof(buffer), 
1365                   "#%s", aop->aopu.aop_immd.aop_immd1);
1366       }
1367       return Safe_strdup(buffer);       
1368
1369     case AOP_DIR:
1370       if (offset)
1371       {
1372         SNPRINTF (buffer, sizeof(buffer),
1373                   "(%s + %d)",
1374                  aop->aopu.aop_dir,
1375                  offset);
1376       }
1377       else
1378       {
1379         SNPRINTF(buffer, sizeof(buffer), 
1380                  "%s", aop->aopu.aop_dir);
1381       }
1382
1383       return Safe_strdup(buffer);
1384
1385     case AOP_REG:
1386       if (dname)
1387         return aop->aopu.aop_reg[offset]->dname;
1388       else
1389         return aop->aopu.aop_reg[offset]->name;
1390
1391     case AOP_CRY:
1392       emitcode ("clr", "a");
1393       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1394       emitcode ("rlc", "a");
1395       return (dname ? "acc" : "a");
1396
1397     case AOP_ACC:
1398       if (!offset && dname)
1399         return "acc";
1400       return aop->aopu.aop_str[offset];
1401
1402     case AOP_LIT:
1403       return aopLiteral (aop->aopu.aop_lit, offset);
1404
1405     case AOP_STR:
1406       aop->coff = offset;
1407       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1408           dname)
1409         return "acc";
1410
1411       return aop->aopu.aop_str[offset];
1412
1413     }
1414
1415   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416           "aopget got unsupported aop->type");
1417   exit (1);
1418     
1419   return NULL;  // not reached, but makes compiler happy.
1420 }
1421 /*-----------------------------------------------------------------*/
1422 /* aopPut - puts a string for a aop                                */
1423 /*-----------------------------------------------------------------*/
1424 static void
1425 aopPut (asmop * aop, char *s, int offset)
1426 {
1427   if (aop->size && offset > (aop->size - 1))
1428     {
1429       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1430               "aopPut got offset > aop->size");
1431       exit (1);
1432     }
1433
1434   /* will assign value to value */
1435   /* depending on where it is ofcourse */
1436   switch (aop->type)
1437     {
1438     case AOP_DUMMY:
1439       MOVA (s);         /* read s in case it was volatile */
1440       break;
1441       
1442     case AOP_DIR:
1443         if (offset)
1444         {
1445             SNPRINTF (buffer, sizeof(buffer),
1446                       "(%s + %d)",
1447                       aop->aopu.aop_dir, offset);
1448         }
1449         else
1450         {
1451             SNPRINTF (buffer, sizeof(buffer), 
1452                      "%s", aop->aopu.aop_dir);
1453         }
1454         
1455
1456         if (strcmp (buffer, s))
1457         {
1458             emitcode ("mov", "%s,%s", buffer, s);
1459         }
1460       break;
1461
1462     case AOP_REG:
1463       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1464           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1465         {
1466           if (*s == '@' ||
1467               strcmp (s, "r0") == 0 ||
1468               strcmp (s, "r1") == 0 ||
1469               strcmp (s, "r2") == 0 ||
1470               strcmp (s, "r3") == 0 ||
1471               strcmp (s, "r4") == 0 ||
1472               strcmp (s, "r5") == 0 ||
1473               strcmp (s, "r6") == 0 ||
1474               strcmp (s, "r7") == 0)
1475             {
1476                 emitcode ("mov", "%s,%s",
1477                           aop->aopu.aop_reg[offset]->dname, s);
1478             }
1479             else
1480             {
1481                 emitcode ("mov", "%s,%s",
1482                           aop->aopu.aop_reg[offset]->name, s);
1483             }
1484         }
1485       break;
1486
1487     case AOP_DPTRn:
1488         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1489         break;
1490
1491     case AOP_DPTR:
1492     case AOP_DPTR2:
1493
1494       if (aop->type == AOP_DPTR2)
1495         {
1496           genSetDPTR (1);
1497         }
1498       _flushLazyDPS ();
1499
1500       if (aop->code)
1501         {
1502           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503                   "aopPut writting to code space");
1504           exit (1);
1505         }
1506
1507       while (offset > aop->coff)
1508         {
1509           aop->coff++;
1510           emitcode ("inc", "dptr");
1511         }
1512
1513       while (offset < aop->coff)
1514         {
1515           aop->coff--;
1516           emitcode ("lcall", "__decdptr");
1517         }
1518
1519       aop->coff = offset;
1520
1521       /* if not in accumulater */
1522       MOVA (s);
1523
1524       emitcode ("movx", "@dptr,a");
1525
1526       if (aop->type == AOP_DPTR2)
1527         {
1528           genSetDPTR (0);
1529         }
1530       break;
1531
1532     case AOP_R0:
1533     case AOP_R1:
1534       while (offset > aop->coff)
1535         {
1536           aop->coff++;
1537           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1538         }
1539       while (offset < aop->coff)
1540         {
1541           aop->coff--;
1542           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1543         }
1544       aop->coff = offset;
1545
1546       if (aop->paged)
1547         {
1548           MOVA (s);
1549           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1550
1551         }
1552       else if (*s == '@')
1553         {
1554           MOVA (s);
1555           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1556         }
1557       else if (strcmp (s, "r0") == 0 ||
1558                strcmp (s, "r1") == 0 ||
1559                strcmp (s, "r2") == 0 ||
1560                strcmp (s, "r3") == 0 ||
1561                strcmp (s, "r4") == 0 ||
1562                strcmp (s, "r5") == 0 ||
1563                strcmp (s, "r6") == 0 ||
1564                strcmp (s, "r7") == 0)
1565         {
1566           char buff[10];
1567           SNPRINTF(buff, sizeof(buff), 
1568                    "a%s", s);
1569           emitcode ("mov", "@%s,%s",
1570                     aop->aopu.aop_ptr->name, buff);
1571         }
1572         else
1573         {
1574             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1575         }
1576       break;
1577
1578     case AOP_STK:
1579       if (strcmp (s, "a") == 0)
1580         emitcode ("push", "acc");
1581       else
1582         if (*s=='@') {
1583           MOVA(s);
1584           emitcode ("push", "acc");
1585         } else {
1586           emitcode ("push", s);
1587         }
1588
1589       break;
1590
1591     case AOP_CRY:
1592       /* if bit variable */
1593       if (!aop->aopu.aop_dir)
1594         {
1595           emitcode ("clr", "a");
1596           emitcode ("rlc", "a");
1597         }
1598       else
1599         {
1600           if (s == zero)
1601             emitcode ("clr", "%s", aop->aopu.aop_dir);
1602           else if (s == one)
1603             emitcode ("setb", "%s", aop->aopu.aop_dir);
1604           else if (!strcmp (s, "c"))
1605             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1606           else
1607             {
1608               if (strcmp (s, "a"))
1609                 {
1610                   MOVA (s);
1611                 }
1612               {
1613                 /* set C, if a >= 1 */
1614                 emitcode ("add", "a,#!constbyte",0xff);
1615                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1616               }
1617             }
1618         }
1619       break;
1620
1621     case AOP_STR:
1622       aop->coff = offset;
1623       if (strcmp (aop->aopu.aop_str[offset], s))
1624         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1625       break;
1626
1627     case AOP_ACC:
1628       aop->coff = offset;
1629       if (!offset && (strcmp (s, "acc") == 0))
1630         break;
1631
1632       if (strcmp (aop->aopu.aop_str[offset], s))
1633         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1634       break;
1635
1636     default:
1637       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1638               "aopPut got unsupported aop->type");
1639       exit (1);
1640     }
1641
1642 }
1643
1644
1645 /*--------------------------------------------------------------------*/
1646 /* reAdjustPreg - points a register back to where it should (coff==0) */
1647 /*--------------------------------------------------------------------*/
1648 static void
1649 reAdjustPreg (asmop * aop)
1650 {
1651   if ((aop->coff==0) || (aop->size <= 1)) {
1652     return;
1653   }
1654
1655   switch (aop->type)
1656     {
1657     case AOP_R0:
1658     case AOP_R1:
1659       while (aop->coff--)
1660         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1661       break;
1662     case AOP_DPTR:
1663     case AOP_DPTR2:
1664       if (aop->type == AOP_DPTR2)
1665         {
1666           genSetDPTR (1);
1667           _flushLazyDPS ();
1668         }
1669       while (aop->coff--)
1670         {
1671           emitcode ("lcall", "__decdptr");
1672         }
1673
1674       if (aop->type == AOP_DPTR2)
1675         {
1676           genSetDPTR (0);
1677         }
1678       break;
1679
1680     }
1681   aop->coff=0;
1682 }
1683
1684 #define AOP(op) op->aop
1685 #define AOP_TYPE(op) AOP(op)->type
1686 #define AOP_SIZE(op) AOP(op)->size
1687 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1688                        AOP_TYPE(x) == AOP_R0))
1689
1690 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1691                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1692                          AOP(x)->paged))
1693
1694 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1695                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1696                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1697 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1698 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1699 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1700
1701 // The following two macros can be used even if the aop has not yet been aopOp'd.
1702 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1703 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1704
1705 /* Workaround for DS80C390 bug: div ab may return bogus results
1706  * if A is accessed in instruction immediately before the div.
1707  *
1708  * Will be fixed in B4 rev of processor, Dallas claims.
1709  */
1710
1711 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1712     if (!AOP_NEEDSACC(RIGHT))         \
1713     {               \
1714       /* We can load A first, then B, since     \
1715        * B (the RIGHT operand) won't clobber A,   \
1716        * thus avoiding touching A right before the div. \
1717        */             \
1718       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1719       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1720       MOVA(L);            \
1721       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1722       MOVB(L); \
1723     }               \
1724     else              \
1725     {               \
1726       /* Just stuff in a nop after loading A. */    \
1727       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1728       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1729       MOVA(L);            \
1730       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1731     }
1732
1733
1734 /*-----------------------------------------------------------------*/
1735 /* opIsGptr: returns non-zero if the passed operand is       */
1736 /* a generic pointer type.             */
1737 /*-----------------------------------------------------------------*/
1738 static int
1739 opIsGptr (operand * op)
1740 {
1741   sym_link *type = operandType (op);
1742
1743   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1744     {
1745       return 1;
1746     }
1747   return 0;
1748 }
1749
1750 /*-----------------------------------------------------------------*/
1751 /* getDataSize - get the operand data size                         */
1752 /*-----------------------------------------------------------------*/
1753 static int
1754 getDataSize (operand * op)
1755 {
1756   int size;
1757   size = AOP_SIZE (op);
1758   if (size == GPTRSIZE)
1759     {
1760       sym_link *type = operandType (op);
1761       if (IS_GENPTR (type))
1762         {
1763           /* generic pointer; arithmetic operations
1764            * should ignore the high byte (pointer type).
1765            */
1766           size--;
1767         }
1768     }
1769   return size;
1770 }
1771
1772 /*-----------------------------------------------------------------*/
1773 /* outAcc - output Acc                                             */
1774 /*-----------------------------------------------------------------*/
1775 static void
1776 outAcc (operand * result)
1777 {
1778   int size, offset;
1779   size = getDataSize (result);
1780   if (size)
1781     {
1782       aopPut (AOP (result), "a", 0);
1783       size--;
1784       offset = 1;
1785       /* unsigned or positive */
1786       while (size--)
1787         {
1788           aopPut (AOP (result), zero, offset++);
1789         }
1790     }
1791 }
1792
1793 /*-----------------------------------------------------------------*/
1794 /* outBitC - output a bit C                                        */
1795 /*-----------------------------------------------------------------*/
1796 static void
1797 outBitC (operand * result)
1798 {
1799   /* if the result is bit */
1800   if (AOP_TYPE (result) == AOP_CRY)
1801     {
1802       aopPut (AOP (result), "c", 0);
1803     }
1804   else
1805     {
1806       emitcode ("clr", "a");
1807       emitcode ("rlc", "a");
1808       outAcc (result);
1809     }
1810 }
1811
1812 /*-----------------------------------------------------------------*/
1813 /* toBoolean - emit code for orl a,operator(sizeop)                */
1814 /*-----------------------------------------------------------------*/
1815 static void
1816 toBoolean (operand * oper)
1817 {
1818   int   size = AOP_SIZE (oper) - 1;
1819   int   offset = 1;
1820   bool usedB = FALSE;
1821
1822   /* The generic part of a generic pointer should
1823    * not participate in it's truth value.
1824    *
1825    * i.e. 0x10000000 is zero.
1826    */
1827   if (opIsGptr (oper))
1828     {
1829       D (emitcode (";", "toBoolean: generic ptr special case."););
1830       size--;
1831     }
1832
1833   _startLazyDPSEvaluation ();
1834   if (AOP_NEEDSACC (oper) && size)
1835     {
1836       usedB = TRUE;
1837       if (_G.bInUse)
1838       {
1839           emitcode ("push", "b");
1840       }
1841       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1842     }
1843   else
1844     {
1845       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1846     }
1847     
1848   while (size--)
1849     {
1850       if (usedB)
1851         {
1852           emitcode ("orl", "b,%s",
1853                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1854         }
1855       else
1856         {
1857           emitcode ("orl", "a,%s",
1858                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1859         }
1860     }
1861   _endLazyDPSEvaluation ();
1862
1863   if (usedB)
1864     {
1865       emitcode ("mov", "a,b");
1866       if (_G.bInUse)
1867       {
1868           emitcode ("pop", "b");
1869       }
1870         
1871     }
1872 }
1873
1874
1875 /*-----------------------------------------------------------------*/
1876 /* genNot - generate code for ! operation                          */
1877 /*-----------------------------------------------------------------*/
1878 static void
1879 genNot (iCode * ic)
1880 {
1881   symbol *tlbl;
1882
1883   D (emitcode (";", "genNot "););
1884
1885   /* assign asmOps to operand & result */
1886   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1887   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1888
1889   /* if in bit space then a special case */
1890   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1891     {
1892       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1893       emitcode ("cpl", "c");
1894       outBitC (IC_RESULT (ic));
1895       goto release;
1896     }
1897
1898   toBoolean (IC_LEFT (ic));
1899
1900   tlbl = newiTempLabel (NULL);
1901   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1902   emitcode ("", "!tlabeldef", tlbl->key + 100);
1903   outBitC (IC_RESULT (ic));
1904
1905 release:
1906   /* release the aops */
1907   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1908   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* genCpl - generate code for complement                           */
1914 /*-----------------------------------------------------------------*/
1915 static void
1916 genCpl (iCode * ic)
1917 {
1918   int offset = 0;
1919   int size;
1920   symbol *tlbl;
1921
1922   D (emitcode (";", "genCpl "););
1923
1924
1925   /* assign asmOps to operand & result */
1926   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1927   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1928
1929   /* special case if in bit space */
1930   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1931     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1932       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1933       emitcode ("cpl", "c");
1934       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1935       goto release;
1936     }
1937     tlbl=newiTempLabel(NULL);
1938     emitcode ("cjne", "%s,#0x01,%05d$", 
1939               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1940     emitcode ("", "%05d$:", tlbl->key+100);
1941     outBitC (IC_RESULT(ic));
1942     goto release;
1943   }
1944
1945   size = AOP_SIZE (IC_RESULT (ic));
1946   _startLazyDPSEvaluation ();
1947   while (size--)
1948     {
1949       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1950       emitcode ("cpl", "a");
1951       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1952     }
1953   _endLazyDPSEvaluation ();
1954
1955
1956 release:
1957   /* release the aops */
1958   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1959   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1960 }
1961
1962 /*-----------------------------------------------------------------*/
1963 /* genUminusFloat - unary minus for floating points                */
1964 /*-----------------------------------------------------------------*/
1965 static void
1966 genUminusFloat (operand * op, operand * result)
1967 {
1968   int size, offset = 0;
1969     
1970   D(emitcode (";", "genUminusFloat"););
1971   
1972   /* for this we just copy and then flip the bit */
1973     
1974   _startLazyDPSEvaluation ();
1975   size = AOP_SIZE (op) - 1;
1976
1977   while (size--)
1978   {
1979       aopPut (AOP (result),
1980               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1981               offset);
1982       offset++;
1983     }
1984   
1985   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1986
1987   emitcode ("cpl", "acc.7");
1988   aopPut (AOP (result), "a", offset);    
1989   _endLazyDPSEvaluation ();
1990 }
1991
1992 /*-----------------------------------------------------------------*/
1993 /* genUminus - unary minus code generation                         */
1994 /*-----------------------------------------------------------------*/
1995 static void
1996 genUminus (iCode * ic)
1997 {
1998   int offset, size;
1999   sym_link *optype;
2000
2001   D (emitcode (";", "genUminus "););
2002
2003   /* assign asmops */
2004   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2005   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2006
2007   /* if both in bit space then special
2008      case */
2009   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2010       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2011     {
2012
2013       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2014       emitcode ("cpl", "c");
2015       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2016       goto release;
2017     }
2018
2019   optype = operandType (IC_LEFT (ic));
2020
2021   /* if float then do float stuff */
2022   if (IS_FLOAT (optype))
2023     {
2024       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2025       goto release;
2026     }
2027
2028   /* otherwise subtract from zero */
2029   size = AOP_SIZE (IC_LEFT (ic));
2030   offset = 0;
2031   _startLazyDPSEvaluation ();
2032   while (size--)
2033     {
2034       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2035       if (!strcmp (l, "a"))
2036         {
2037           if (offset == 0)
2038             SETC;
2039           emitcode ("cpl", "a");
2040           emitcode ("addc", "a,#0");
2041         }
2042       else
2043         {
2044           if (offset == 0)
2045             CLRC;
2046           emitcode ("clr", "a");
2047           emitcode ("subb", "a,%s", l);
2048         }
2049       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2050     }
2051   _endLazyDPSEvaluation ();
2052
2053   /* if any remaining bytes in the result */
2054   /* we just need to propagate the sign   */
2055   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2056     {
2057       emitcode ("rlc", "a");
2058       emitcode ("subb", "a,acc");
2059       while (size--)
2060         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2061     }
2062
2063 release:
2064   /* release the aops */
2065   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2066   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2067 }
2068
2069 /*-----------------------------------------------------------------*/
2070 /* savermask - saves registers in the mask                         */
2071 /*-----------------------------------------------------------------*/
2072 static void savermask(bitVect *rs_mask)
2073 {
2074     int i;
2075     if (options.useXstack) {
2076         if (bitVectBitValue (rs_mask, R0_IDX))
2077             emitcode ("mov", "b,r0");
2078         emitcode ("mov", "r0,%s", spname);
2079         for (i = 0; i < ds390_nRegs; i++) {
2080             if (bitVectBitValue (rs_mask, i)) {
2081                 if (i == R0_IDX)
2082                     emitcode ("mov", "a,b");
2083                 else
2084                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2085                 emitcode ("movx", "@r0,a");
2086                 emitcode ("inc", "r0");
2087             }
2088         }
2089         emitcode ("mov", "%s,r0", spname);
2090         if (bitVectBitValue (rs_mask, R0_IDX))
2091             emitcode ("mov", "r0,b");
2092     } else {
2093         for (i = 0; i < ds390_nRegs; i++) {
2094             if (bitVectBitValue (rs_mask, i))
2095                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2096         }
2097     }
2098 }
2099
2100 /*-----------------------------------------------------------------*/
2101 /* saveRegisters - will look for a call and save the registers     */
2102 /*-----------------------------------------------------------------*/
2103 static void
2104 saveRegisters (iCode * lic)
2105 {
2106   iCode *ic;
2107   bitVect *rsave;
2108
2109   /* look for call */
2110   for (ic = lic; ic; ic = ic->next)
2111     if (ic->op == CALL || ic->op == PCALL)
2112       break;
2113
2114   if (!ic)
2115     {
2116       fprintf (stderr, "found parameter push with no function call\n");
2117       return;
2118     }
2119
2120   /* if the registers have been saved already then
2121      do nothing */
2122   if (ic->regsSaved 
2123       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2124     return ;
2125
2126   /* special case if DPTR alive across a function call then must save it 
2127      even though callee saves */
2128   if (IS_SYMOP(IC_LEFT(ic)) &&
2129       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2130       int i;
2131       rsave = newBitVect(ic->rMask->size);
2132       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2133           if (bitVectBitValue(ic->rMask,i))
2134               rsave = bitVectSetBit(rsave,i);
2135       }
2136       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2137   } else {
2138     /* safe the registers in use at this time but skip the
2139        ones for the result */
2140     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2141                            ds390_rUmaskForOp (IC_RESULT(ic)));
2142   }
2143   ic->regsSaved = 1;
2144   savermask(rsave);
2145 }
2146
2147 /*-----------------------------------------------------------------*/
2148 /* usavermask - restore registers with mask                        */
2149 /*-----------------------------------------------------------------*/
2150 static void unsavermask(bitVect *rs_mask)
2151 {
2152     int i;
2153     if (options.useXstack) {
2154         emitcode ("mov", "r0,%s", spname);
2155         for (i = ds390_nRegs; i >= 0; i--) {
2156             if (bitVectBitValue (rs_mask, i)) {
2157                 emitcode ("dec", "r0");
2158                 emitcode ("movx", "a,@r0");
2159                 if (i == R0_IDX)
2160                     emitcode ("mov", "b,a");
2161                 else
2162                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2163             }       
2164         }
2165         emitcode ("mov", "%s,r0", spname);
2166         if (bitVectBitValue (rs_mask, R0_IDX))
2167             emitcode ("mov", "r0,b");
2168     } else {
2169         for (i = ds390_nRegs; i >= 0; i--) {
2170             if (bitVectBitValue (rs_mask, i))
2171                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2172         }
2173     }
2174 }
2175
2176 /*-----------------------------------------------------------------*/
2177 /* unsaveRegisters - pop the pushed registers                      */
2178 /*-----------------------------------------------------------------*/
2179 static void
2180 unsaveRegisters (iCode * ic)
2181 {
2182   bitVect *rsave;
2183
2184   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2185       int i;
2186       rsave = newBitVect(ic->rMask->size);
2187       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2188           if (bitVectBitValue(ic->rMask,i))
2189               rsave = bitVectSetBit(rsave,i);
2190       }
2191       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2192   } else {
2193     /* restore the registers in use at this time but skip the
2194        ones for the result */
2195     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2196                            ds390_rUmaskForOp (IC_RESULT(ic)));
2197   }
2198   unsavermask(rsave);
2199 }
2200
2201
2202 /*-----------------------------------------------------------------*/
2203 /* pushSide -                */
2204 /*-----------------------------------------------------------------*/
2205 static void
2206 pushSide (operand * oper, int size)
2207 {
2208   int offset = 0;
2209   _startLazyDPSEvaluation ();
2210   while (size--)
2211     {
2212       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2213       if (AOP_TYPE (oper) != AOP_REG &&
2214           AOP_TYPE (oper) != AOP_DIR &&
2215           strcmp (l, "a"))
2216         {
2217           emitcode ("mov", "a,%s", l);
2218           emitcode ("push", "acc");
2219         }
2220       else
2221         emitcode ("push", "%s", l);
2222     }
2223   _endLazyDPSEvaluation ();
2224 }
2225
2226 /*-----------------------------------------------------------------*/
2227 /* assignResultValue -               */
2228 /*-----------------------------------------------------------------*/
2229 static void
2230 assignResultValue (operand * oper)
2231 {
2232   int offset = 0;
2233   int size = AOP_SIZE (oper);
2234   bool pushedAcc = FALSE;
2235
2236   if (size == fReturnSizeDS390)
2237   {
2238       /* I don't think this case can ever happen... */
2239       /* ACC is the last part of this. If writing the result
2240        * uses AC, we must preserve it.
2241        */
2242       if (AOP_NEEDSACC(oper))
2243       {
2244           emitcode(";", "assignResultValue special case for ACC.");
2245           emitcode("push", "acc");
2246           pushedAcc = TRUE;
2247           size--;
2248       }
2249   }
2250     
2251     
2252   _startLazyDPSEvaluation ();
2253   while (size--)
2254     {
2255       aopPut (AOP (oper), fReturn[offset], offset);
2256       offset++;
2257     }
2258   _endLazyDPSEvaluation ();
2259     
2260   if (pushedAcc)
2261     {
2262         emitcode("pop", "acc");
2263         aopPut(AOP(oper), "a", offset);
2264     }
2265 }
2266
2267
2268 /*-----------------------------------------------------------------*/
2269 /* genXpush - pushes onto the external stack                       */
2270 /*-----------------------------------------------------------------*/
2271 static void
2272 genXpush (iCode * ic)
2273 {
2274   asmop *aop = newAsmop (0);
2275   regs *r;
2276   int size, offset = 0;
2277
2278   D (emitcode (";", "genXpush ");
2279     );
2280
2281   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2282   r = getFreePtr (ic, &aop, FALSE);
2283
2284
2285   emitcode ("mov", "%s,_spx", r->name);
2286
2287   size = AOP_SIZE (IC_LEFT (ic));
2288   _startLazyDPSEvaluation ();
2289   while (size--)
2290     {
2291
2292       MOVA (aopGet (AOP (IC_LEFT (ic)),
2293                         offset++, FALSE, FALSE, NULL));
2294       emitcode ("movx", "@%s,a", r->name);
2295       emitcode ("inc", "%s", r->name);
2296
2297     }
2298   _endLazyDPSEvaluation ();
2299
2300
2301   emitcode ("mov", "_spx,%s", r->name);
2302
2303   freeAsmop (NULL, aop, ic, TRUE);
2304   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* genIpush - generate code for pushing this gets a little complex  */
2309 /*-----------------------------------------------------------------*/
2310 static void
2311 genIpush (iCode * ic)
2312 {
2313   int size, offset = 0;
2314   char *l;
2315
2316   D (emitcode (";", "genIpush ");
2317     );
2318
2319   /* if this is not a parm push : ie. it is spill push
2320      and spill push is always done on the local stack */
2321   if (!ic->parmPush)
2322     {
2323
2324       /* and the item is spilt then do nothing */
2325       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2326         return;
2327
2328       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329       size = AOP_SIZE (IC_LEFT (ic));
2330       /* push it on the stack */
2331       _startLazyDPSEvaluation ();
2332       while (size--)
2333         {
2334           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2335           if (*l == '#')
2336             {
2337               MOVA (l);
2338               l = "acc";
2339             }
2340           emitcode ("push", "%s", l);
2341         }
2342       _endLazyDPSEvaluation ();
2343       return;
2344     }
2345
2346   /* this is a paramter push: in this case we call
2347      the routine to find the call and save those
2348      registers that need to be saved */
2349   saveRegisters (ic);
2350
2351   /* if use external stack then call the external
2352      stack pushing routine */
2353   if (options.useXstack)
2354     {
2355       genXpush (ic);
2356       return;
2357     }
2358
2359   /* then do the push */
2360   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2361
2362   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2363   size = AOP_SIZE (IC_LEFT (ic));
2364
2365   _startLazyDPSEvaluation ();
2366   while (size--)
2367     {
2368       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2369       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2370           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2371           strcmp (l, "acc"))
2372         {
2373           emitcode ("mov", "a,%s", l);
2374           emitcode ("push", "acc");
2375         }
2376       else
2377         {
2378             emitcode ("push", "%s", l);
2379         }
2380     }
2381   _endLazyDPSEvaluation ();
2382
2383   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2384 }
2385
2386 /*-----------------------------------------------------------------*/
2387 /* genIpop - recover the registers: can happen only for spilling   */
2388 /*-----------------------------------------------------------------*/
2389 static void
2390 genIpop (iCode * ic)
2391 {
2392   int size, offset;
2393
2394   D (emitcode (";", "genIpop ");
2395     );
2396
2397
2398   /* if the temp was not pushed then */
2399   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2400     return;
2401
2402   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2403   size = AOP_SIZE (IC_LEFT (ic));
2404   offset = (size - 1);
2405   _startLazyDPSEvaluation ();
2406   while (size--)
2407     {
2408       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2409                                      FALSE, TRUE, NULL));
2410     }
2411   _endLazyDPSEvaluation ();
2412
2413   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2414 }
2415
2416 /*-----------------------------------------------------------------*/
2417 /* unsaveRBank - restores the resgister bank from stack            */
2418 /*-----------------------------------------------------------------*/
2419 static void
2420 unsaveRBank (int bank, iCode * ic, bool popPsw)
2421 {
2422   int i;
2423   asmop *aop = NULL;
2424   regs *r = NULL;
2425
2426   if (options.useXstack)
2427   {
2428       if (!ic)
2429       {
2430           /* Assume r0 is available for use. */
2431           r = ds390_regWithIdx (R0_IDX);;          
2432       } 
2433       else
2434       {
2435           aop = newAsmop (0);
2436           r = getFreePtr (ic, &aop, FALSE);
2437       }
2438       emitcode ("mov", "%s,_spx", r->name);      
2439   }
2440   
2441   if (popPsw)
2442     {
2443       if (options.useXstack)
2444       {
2445           emitcode ("movx", "a,@%s", r->name);
2446           emitcode ("mov", "psw,a");
2447           emitcode ("dec", "%s", r->name);
2448         }
2449       else
2450       {
2451         emitcode ("pop", "psw");
2452       }
2453     }
2454
2455   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2456     {
2457       if (options.useXstack)
2458         {
2459           emitcode ("movx", "a,@%s", r->name);
2460           emitcode ("mov", "(%s+%d),a",
2461                     regs390[i].base, 8 * bank + regs390[i].offset);
2462           emitcode ("dec", "%s", r->name);
2463
2464         }
2465       else
2466         emitcode ("pop", "(%s+%d)",
2467                   regs390[i].base, 8 * bank + regs390[i].offset);
2468     }
2469
2470   if (options.useXstack)
2471     {
2472       emitcode ("mov", "_spx,%s", r->name);
2473     }
2474     
2475   if (aop)
2476   {
2477       freeAsmop (NULL, aop, ic, TRUE);  
2478   }    
2479 }
2480
2481 /*-----------------------------------------------------------------*/
2482 /* saveRBank - saves an entire register bank on the stack          */
2483 /*-----------------------------------------------------------------*/
2484 static void
2485 saveRBank (int bank, iCode * ic, bool pushPsw)
2486 {
2487   int i;
2488   asmop *aop = NULL;
2489   regs *r = NULL;
2490
2491   if (options.useXstack)
2492     {
2493         if (!ic)
2494         {
2495           /* Assume r0 is available for use. */
2496                   r = ds390_regWithIdx (R0_IDX);;
2497         }
2498         else
2499         {
2500           aop = newAsmop (0);
2501           r = getFreePtr (ic, &aop, FALSE);
2502         }
2503         emitcode ("mov", "%s,_spx", r->name);    
2504     }
2505
2506   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2507     {
2508       if (options.useXstack)
2509         {
2510           emitcode ("inc", "%s", r->name);
2511           emitcode ("mov", "a,(%s+%d)",
2512                     regs390[i].base, 8 * bank + regs390[i].offset);
2513           emitcode ("movx", "@%s,a", r->name);
2514         }
2515       else
2516         emitcode ("push", "(%s+%d)",
2517                   regs390[i].base, 8 * bank + regs390[i].offset);
2518     }
2519
2520   if (pushPsw)
2521     {
2522       if (options.useXstack)
2523         {
2524           emitcode ("mov", "a,psw");
2525           emitcode ("movx", "@%s,a", r->name);
2526           emitcode ("inc", "%s", r->name);
2527           emitcode ("mov", "_spx,%s", r->name);
2528         }
2529       else
2530       {
2531         emitcode ("push", "psw");
2532       }
2533
2534       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2535     }
2536   
2537   if (aop)
2538   {
2539        freeAsmop (NULL, aop, ic, TRUE);
2540   }    
2541     
2542   if (ic)
2543   {  
2544       ic->bankSaved = 1;
2545   }
2546 }
2547
2548 /*-----------------------------------------------------------------*/
2549 /* genSend - gen code for SEND                                     */
2550 /*-----------------------------------------------------------------*/
2551 static void genSend(set *sendSet)
2552 {
2553     iCode *sic;
2554     int sendCount = 0 ;
2555     static int rb1_count = 0;
2556
2557     for (sic = setFirstItem (sendSet); sic;
2558          sic = setNextItem (sendSet)) {     
2559         int size, offset = 0;
2560         
2561         size=getSize(operandType(IC_LEFT(sic)));
2562         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2563         if (sendCount == 0) { /* first parameter */
2564             // we know that dpl(hxb) is the result, so
2565             rb1_count = 0 ;
2566             _startLazyDPSEvaluation ();
2567             if (size>1) {
2568                 aopOp (IC_LEFT (sic), sic, FALSE, 
2569                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2570             } else {
2571                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2572             }
2573             while (size--) {
2574                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2575                                   FALSE, FALSE, NULL);
2576                 if (strcmp (l, fReturn[offset])) {
2577                     emitcode ("mov", "%s,%s",
2578                               fReturn[offset],
2579                               l);
2580                 }
2581                 offset++;
2582             }
2583             _endLazyDPSEvaluation ();
2584             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2585             rb1_count =0;
2586         } else { /* if more parameter in registers */
2587             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2588             while (size--) {
2589                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2590                                                                 FALSE, FALSE, NULL));
2591             }
2592             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2593         }
2594         sendCount++;
2595     }
2596 }
2597
2598 static void
2599 adjustEsp(const char *reg)
2600 {
2601     emitcode ("anl","%s,#3", reg);
2602     if (TARGET_IS_DS400)
2603     {
2604         emitcode ("orl","%s,#!constbyte",
2605                   reg,
2606                   (options.stack_loc >> 8) & 0xff);
2607     }
2608 }
2609
2610 /*-----------------------------------------------------------------*/
2611 /* genCall - generates a call statement                            */
2612 /*-----------------------------------------------------------------*/
2613 static void
2614 genCall (iCode * ic)
2615 {
2616   sym_link *dtype;
2617   bool restoreBank = FALSE;
2618   bool swapBanks = FALSE;
2619
2620   D (emitcode (";", "genCall "););
2621
2622   /* if we are calling a not _naked function that is not using
2623      the same register bank then we need to save the
2624      destination registers on the stack */
2625   dtype = operandType (IC_LEFT (ic));
2626   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2627       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2628       IFFUNC_ISISR (currFunc->type))
2629   {
2630       if (!ic->bankSaved) 
2631       {
2632            /* This is unexpected; the bank should have been saved in
2633             * genFunction.
2634             */
2635            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2636            restoreBank = TRUE;
2637       }
2638       swapBanks = TRUE;
2639   }
2640   
2641     /* if caller saves & we have not saved then */
2642     if (!ic->regsSaved)
2643       saveRegisters (ic);
2644   
2645   /* if send set is not empty the assign */
2646   /* We've saved all the registers we care about;
2647   * therefore, we may clobber any register not used
2648   * in the calling convention (i.e. anything not in
2649   * fReturn.
2650   */
2651   if (_G.sendSet)
2652     {
2653         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2654             genSend(reverseSet(_G.sendSet));
2655         } else {
2656             genSend(_G.sendSet);
2657         }
2658       _G.sendSet = NULL;
2659     }  
2660     
2661   if (swapBanks)
2662   {
2663         emitcode ("mov", "psw,#!constbyte", 
2664            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2665   }
2666
2667   /* make the call */
2668   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2669                             OP_SYMBOL (IC_LEFT (ic))->rname :
2670                             OP_SYMBOL (IC_LEFT (ic))->name));
2671
2672   if (swapBanks)
2673   {
2674        emitcode ("mov", "psw,#!constbyte", 
2675           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2676   }
2677
2678   /* if we need assign a result value */
2679   if ((IS_ITEMP (IC_RESULT (ic)) &&
2680        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2681         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2682         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2683       IS_TRUE_SYMOP (IC_RESULT (ic)))
2684     {
2685       if (isOperandInFarSpace (IC_RESULT (ic))
2686           && getSize (operandType (IC_RESULT (ic))) <= 2)
2687         {
2688           int size = getSize (operandType (IC_RESULT (ic)));
2689
2690           /* Special case for 1 or 2 byte return in far space. */
2691           MOVA (fReturn[0]);
2692           if (size > 1)
2693             {
2694               emitcode ("mov", "b,%s", fReturn[1]);
2695               _G.bInUse++;
2696             }
2697
2698           _G.accInUse++;
2699           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2700           _G.accInUse--;
2701           
2702           if (size > 1)
2703             _G.bInUse--;
2704
2705           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2706
2707           if (size > 1)
2708             {
2709               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2710             }
2711           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2712         }
2713       else
2714         {
2715           _G.bInUse++;
2716           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2717           _G.bInUse--;
2718
2719           assignResultValue (IC_RESULT (ic));
2720
2721           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2722         }
2723     }
2724
2725   /* adjust the stack for parameters if
2726      required */
2727   if (ic->parmBytes) {
2728       int i;
2729       if (options.stack10bit) {
2730           if (ic->parmBytes <= 10) {
2731               emitcode(";","stack adjustment for parms");
2732               for (i=0; i < ic->parmBytes ; i++) {
2733                   emitcode("pop","acc");
2734               }
2735           } else {            
2736               PROTECT_SP;
2737               emitcode ("clr","c");
2738               emitcode ("mov","a,sp");
2739               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2740               emitcode ("mov","sp,a");
2741               emitcode ("mov","a,esp");
2742               adjustEsp("a");
2743               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2744               emitcode ("mov","esp,a");   
2745               UNPROTECT_SP;
2746           }
2747       } else {
2748           if (ic->parmBytes > 3) {
2749               emitcode ("mov", "a,%s", spname);
2750               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2751               emitcode ("mov", "%s,a", spname);
2752           } else
2753               for (i = 0; i < ic->parmBytes; i++)
2754                   emitcode ("dec", "%s", spname);
2755       }
2756   }
2757
2758   /* if we hade saved some registers then unsave them */
2759   if (ic->regsSaved)
2760     unsaveRegisters (ic);
2761
2762   /* if register bank was saved then pop them */
2763   if (restoreBank)
2764     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genPcall - generates a call by pointer statement                */
2769 /*-----------------------------------------------------------------*/
2770 static void
2771 genPcall (iCode * ic)
2772 {
2773   sym_link *dtype;
2774   symbol *rlbl = newiTempLabel (NULL);
2775   bool restoreBank=FALSE;
2776
2777   D (emitcode (";", "genPcall ");
2778     );
2779
2780
2781   /* if caller saves & we have not saved then */
2782   if (!ic->regsSaved)
2783     saveRegisters (ic);
2784
2785   /* if we are calling a function that is not using
2786      the same register bank then we need to save the
2787      destination registers on the stack */
2788   dtype = operandType (IC_LEFT (ic));
2789   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2790       IFFUNC_ISISR (currFunc->type) &&
2791       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2792     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2793     restoreBank=TRUE;
2794   }
2795
2796   /* push the return address on to the stack */
2797   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2798   emitcode ("push", "acc");
2799   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2800   emitcode ("push", "acc");
2801
2802   if (options.model == MODEL_FLAT24)
2803     {
2804       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2805       emitcode ("push", "acc");
2806     }
2807
2808   /* now push the calling address */
2809   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2810
2811   pushSide (IC_LEFT (ic), FPTRSIZE);
2812
2813   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2814
2815   /* if send set is not empty the assign */
2816   if (_G.sendSet)
2817     {
2818         genSend(reverseSet(_G.sendSet));
2819         _G.sendSet = NULL;
2820     }
2821
2822   emitcode ("ret", "");
2823   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2824
2825
2826   /* if we need assign a result value */
2827   if ((IS_ITEMP (IC_RESULT (ic)) &&
2828        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2829         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2830       IS_TRUE_SYMOP (IC_RESULT (ic)))
2831     {
2832
2833       _G.accInUse++;
2834       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2835       _G.accInUse--;
2836
2837       assignResultValue (IC_RESULT (ic));
2838
2839       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2840     }
2841
2842   /* adjust the stack for parameters if
2843      required */
2844   if (ic->parmBytes)
2845     {
2846       int i;
2847       if (options.stack10bit) {
2848           if (ic->parmBytes <= 10) {
2849               emitcode(";","stack adjustment for parms");
2850               for (i=0; i < ic->parmBytes ; i++) {
2851                   emitcode("pop","acc");
2852               }
2853           } else {            
2854               PROTECT_SP;
2855               emitcode ("clr","c");
2856               emitcode ("mov","a,sp");
2857               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2858               emitcode ("mov","sp,a");
2859               emitcode ("mov","a,esp");
2860               adjustEsp("a");
2861               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2862               emitcode ("mov","esp,a");   
2863               UNPROTECT_SP;
2864           }
2865       } else {
2866           if (ic->parmBytes > 3) {
2867               emitcode ("mov", "a,%s", spname);
2868               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2869               emitcode ("mov", "%s,a", spname);
2870           }
2871           else
2872               for (i = 0; i < ic->parmBytes; i++)
2873                   emitcode ("dec", "%s", spname);
2874           
2875       }
2876     }
2877   /* if register bank was saved then unsave them */
2878   if (restoreBank)
2879     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2880   
2881   /* if we hade saved some registers then
2882      unsave them */
2883   if (ic->regsSaved)
2884     unsaveRegisters (ic);
2885
2886 }
2887
2888 /*-----------------------------------------------------------------*/
2889 /* resultRemat - result  is rematerializable                       */
2890 /*-----------------------------------------------------------------*/
2891 static int
2892 resultRemat (iCode * ic)
2893 {
2894   if (SKIP_IC (ic) || ic->op == IFX)
2895     return 0;
2896
2897   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2898     {
2899       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2900       if (sym->remat && !POINTER_SET (ic))
2901         return 1;
2902     }
2903
2904   return 0;
2905 }
2906
2907 #if defined(__BORLANDC__) || defined(_MSC_VER)
2908 #define STRCASECMP stricmp
2909 #else
2910 #define STRCASECMP strcasecmp
2911 #endif
2912
2913 /*-----------------------------------------------------------------*/
2914 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2915 /*-----------------------------------------------------------------*/
2916 static int
2917 regsCmp(void *p1, void *p2)
2918 {
2919   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2920 }
2921
2922 static bool
2923 inExcludeList (char *s)
2924 {
2925   const char *p = setFirstItem(options.excludeRegsSet);
2926
2927   if (p == NULL || STRCASECMP(p, "none") == 0)
2928     return FALSE;
2929
2930
2931   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2932 }
2933
2934 /*-----------------------------------------------------------------*/
2935 /* genFunction - generated code for function entry                 */
2936 /*-----------------------------------------------------------------*/
2937 static void
2938 genFunction (iCode * ic)
2939 {
2940   symbol *sym;
2941   sym_link *ftype;
2942   bool   switchedPSW = FALSE;
2943
2944   D (emitcode (";", "genFunction "););
2945
2946   _G.nRegsSaved = 0;
2947   /* create the function header */
2948   emitcode (";", "-----------------------------------------");
2949   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2950   emitcode (";", "-----------------------------------------");
2951
2952   emitcode ("", "%s:", sym->rname);
2953   ftype = operandType (IC_LEFT (ic));
2954
2955   if (IFFUNC_ISNAKED(ftype))
2956   {
2957       emitcode(";", "naked function: no prologue.");
2958       return;
2959   }
2960   
2961   if (options.stack_probe) 
2962       emitcode ("lcall","__stack_probe");
2963
2964   /* here we need to generate the equates for the
2965      register bank if required */
2966   if (FUNC_REGBANK (ftype) != rbank)
2967     {
2968       int i;
2969
2970       rbank = FUNC_REGBANK (ftype);
2971       for (i = 0; i < ds390_nRegs; i++)
2972         {
2973           if (regs390[i].print) {
2974               if (strcmp (regs390[i].base, "0") == 0)
2975                   emitcode ("", "%s !equ !constbyte",
2976                             regs390[i].dname,
2977                             8 * rbank + regs390[i].offset);
2978               else
2979                   emitcode ("", "%s !equ %s + !constbyte",
2980                             regs390[i].dname,
2981                             regs390[i].base,
2982                             8 * rbank + regs390[i].offset);
2983           }
2984         }
2985     }
2986
2987   /* if this is an interrupt service routine then
2988      save acc, b, dpl, dph  */
2989   if (IFFUNC_ISISR (sym->type))
2990       { /* is ISR */
2991       if (!inExcludeList ("acc"))
2992         emitcode ("push", "acc");
2993       if (!inExcludeList ("b"))
2994         emitcode ("push", "b");
2995       if (!inExcludeList ("dpl"))
2996         emitcode ("push", "dpl");
2997       if (!inExcludeList ("dph"))
2998         emitcode ("push", "dph");
2999       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3000         {
3001           emitcode ("push", "dpx");
3002           /* Make sure we're using standard DPTR */
3003           emitcode ("push", "dps");
3004           emitcode ("mov", "dps,#0");
3005           if (options.stack10bit)
3006             {
3007               /* This ISR could conceivably use DPTR2. Better save it. */
3008               emitcode ("push", "dpl1");
3009               emitcode ("push", "dph1");
3010               emitcode ("push", "dpx1");
3011               emitcode ("push",  DP2_RESULT_REG);
3012             }
3013         }
3014       /* if this isr has no bank i.e. is going to
3015          run with bank 0 , then we need to save more
3016          registers :-) */
3017       if (!FUNC_REGBANK (sym->type))
3018         {
3019             int i;
3020
3021           /* if this function does not call any other
3022              function then we can be economical and
3023              save only those registers that are used */
3024           if (!IFFUNC_HASFCALL(sym->type))
3025             {
3026
3027               /* if any registers used */
3028               if (sym->regsUsed)
3029                 {
3030                   /* save the registers used */
3031                   for (i = 0; i < sym->regsUsed->size; i++)
3032                     {
3033                       if (bitVectBitValue (sym->regsUsed, i))
3034                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3035                     }
3036                 }
3037             }
3038           else
3039             {
3040               /* this function has  a function call cannot
3041                  determines register usage so we will have to push the
3042                  entire bank */
3043               saveRBank (0, ic, FALSE);
3044               if (options.parms_in_bank1) {
3045                   for (i=0; i < 8 ; i++ ) {
3046                       emitcode ("push","%s",rb1regs[i]);
3047                   }
3048               }
3049             }
3050         }
3051         else
3052         {
3053             /* This ISR uses a non-zero bank.
3054              *
3055              * We assume that the bank is available for our
3056              * exclusive use.
3057              *
3058              * However, if this ISR calls a function which uses some
3059              * other bank, we must save that bank entirely.
3060              */
3061             unsigned long banksToSave = 0;
3062             
3063             if (IFFUNC_HASFCALL(sym->type))
3064             {
3065
3066 #define MAX_REGISTER_BANKS 4
3067
3068                 iCode *i;
3069                 int ix;
3070
3071                 for (i = ic; i; i = i->next)
3072                 {
3073                     if (i->op == ENDFUNCTION)
3074                     {
3075                         /* we got to the end OK. */
3076                         break;
3077                     }
3078                     
3079                     if (i->op == CALL)
3080                     {
3081                         sym_link *dtype;
3082                         
3083                         dtype = operandType (IC_LEFT(i));
3084                         if (dtype 
3085                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3086                         {
3087                              /* Mark this bank for saving. */
3088                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3089                              {
3090                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3091                              }
3092                              else
3093                              {
3094                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3095                              }
3096                              
3097                              /* And note that we don't need to do it in 
3098                               * genCall.
3099                               */
3100                              i->bankSaved = 1;
3101                         }
3102                     }
3103                     if (i->op == PCALL)
3104                     {
3105                         /* This is a mess; we have no idea what
3106                          * register bank the called function might
3107                          * use.
3108                          *
3109                          * The only thing I can think of to do is
3110                          * throw a warning and hope.
3111                          */
3112                         werror(W_FUNCPTR_IN_USING_ISR);   
3113                     }
3114                 }
3115
3116                 if (banksToSave && options.useXstack)
3117                 {
3118                     /* Since we aren't passing it an ic, 
3119                      * saveRBank will assume r0 is available to abuse.
3120                      *
3121                      * So switch to our (trashable) bank now, so
3122                      * the caller's R0 isn't trashed.
3123                      */
3124                     emitcode ("push", "psw");
3125                     emitcode ("mov", "psw,#!constbyte", 
3126                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3127                     switchedPSW = TRUE;
3128                 }
3129                 
3130                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3131                 {
3132                      if (banksToSave & (1 << ix))
3133                      {
3134                          saveRBank(ix, NULL, FALSE);
3135                      }
3136                 }
3137             }
3138             // TODO: this needs a closer look
3139             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3140         }
3141     }
3142   else
3143     {
3144       /* if callee-save to be used for this function
3145          then save the registers being used in this function */
3146       if (IFFUNC_CALLEESAVES(sym->type))
3147         {
3148           int i;
3149
3150           /* if any registers used */
3151           if (sym->regsUsed)
3152             {
3153               /* save the registers used */
3154               for (i = 0; i < sym->regsUsed->size; i++)
3155                 {
3156                   if (bitVectBitValue (sym->regsUsed, i))
3157                     {
3158                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3159                       _G.nRegsSaved++;
3160                     }
3161                 }
3162             }
3163         }
3164     }
3165
3166   /* set the register bank to the desired value */
3167   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3168    && !switchedPSW)
3169     {
3170       emitcode ("push", "psw");
3171       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3172     }
3173
3174   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3175        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3176       if (options.stack10bit) {
3177           emitcode ("push","_bpx");
3178           emitcode ("push","_bpx+1");
3179           emitcode ("mov","_bpx,%s",spname);
3180           emitcode ("mov","_bpx+1,esp");
3181           adjustEsp("_bpx+1");
3182       } else {
3183           if (options.useXstack) {
3184               emitcode ("mov", "r0,%s", spname);
3185               emitcode ("mov", "a,_bp");
3186               emitcode ("movx", "@r0,a");
3187               emitcode ("inc", "%s", spname);
3188           } else {
3189               /* set up the stack */
3190               emitcode ("push", "_bp"); /* save the callers stack  */
3191           }
3192           emitcode ("mov", "_bp,%s", spname);
3193       }
3194   }
3195
3196   /* adjust the stack for the function */
3197   if (sym->stack) {
3198       int i = sym->stack;
3199       if (options.stack10bit) {
3200           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3201           assert (sym->recvSize <= 4);
3202           if (sym->stack <= 8) {
3203               while (i--) emitcode ("push","acc");
3204           } else {
3205               PROTECT_SP;
3206               emitcode ("mov","a,sp");
3207               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3208               emitcode ("mov","sp,a");
3209               emitcode ("mov","a,esp");
3210               adjustEsp("a");
3211               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3212               emitcode ("mov","esp,a");
3213               UNPROTECT_SP;
3214           }
3215       } else {
3216           if (i > 256)
3217               werror (W_STACK_OVERFLOW, sym->name);
3218           
3219           if (i > 3 && sym->recvSize < 4) {
3220               
3221               emitcode ("mov", "a,sp");
3222               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3223               emitcode ("mov", "sp,a");
3224               
3225           } else
3226               while (i--)
3227                   emitcode ("inc", "sp");
3228       }
3229   }
3230
3231   if (sym->xstack)
3232     {
3233
3234       emitcode ("mov", "a,_spx");
3235       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3236       emitcode ("mov", "_spx,a");
3237     }
3238   
3239   /* if critical function then turn interrupts off */
3240   if (IFFUNC_ISCRITICAL (ftype))
3241     {
3242       symbol *tlbl = newiTempLabel (NULL);
3243       emitcode ("setb", "c");
3244       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3245       emitcode ("clr", "c");
3246       emitcode ("", "%05d$:", (tlbl->key + 100));
3247       emitcode ("push", "psw"); /* save old ea via c in psw */
3248     }
3249
3250 }
3251
3252 /*-----------------------------------------------------------------*/
3253 /* genEndFunction - generates epilogue for functions               */
3254 /*-----------------------------------------------------------------*/
3255 static void
3256 genEndFunction (iCode * ic)
3257 {
3258   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3259   lineNode *lnp = lineCurr;
3260   bitVect *regsUsed;
3261   bitVect *regsUsedPrologue;
3262   bitVect *regsUnneeded;
3263   int idx;
3264
3265   D (emitcode (";", "genEndFunction "););
3266
3267   if (IFFUNC_ISNAKED(sym->type))
3268   {
3269       emitcode(";", "naked function: no epilogue.");
3270       if (options.debug && currFunc)
3271         debugFile->writeEndFunction (currFunc, ic, 0);
3272       return;
3273   }
3274
3275   if (IFFUNC_ISCRITICAL (sym->type))
3276     {
3277       emitcode ("pop", "psw"); /* restore ea via c in psw */
3278       emitcode ("mov", "ea,c");
3279     }
3280   
3281   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3282        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3283
3284       if (options.stack10bit) {
3285           PROTECT_SP;     
3286           emitcode ("mov", "sp,_bpx", spname);
3287           emitcode ("mov", "esp,_bpx+1", spname);
3288           UNPROTECT_SP;
3289       } else {
3290           emitcode ("mov", "%s,_bp", spname);
3291       }
3292   }
3293
3294   /* if use external stack but some variables were
3295      added to the local stack then decrement the
3296      local stack */
3297   if (options.useXstack && sym->stack) {
3298       emitcode ("mov", "a,sp");
3299       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3300       emitcode ("mov", "sp,a");
3301   }
3302
3303
3304   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3305        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3306
3307       if (options.useXstack) {
3308           emitcode ("mov", "r0,%s", spname);
3309           emitcode ("movx", "a,@r0");
3310           emitcode ("mov", "_bp,a");
3311           emitcode ("dec", "%s", spname);
3312       } else {
3313           if (options.stack10bit) {
3314               emitcode ("pop", "_bpx+1");
3315               emitcode ("pop", "_bpx");
3316           } else {
3317               emitcode ("pop", "_bp");
3318           }
3319       }
3320   }
3321
3322   /* restore the register bank  */
3323   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3324   {
3325     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3326      || !options.useXstack)
3327     {
3328         /* Special case of ISR using non-zero bank with useXstack
3329          * is handled below.
3330          */
3331         emitcode ("pop", "psw");
3332     }
3333   } 
3334
3335   if (IFFUNC_ISISR (sym->type))
3336       { /* is ISR */  
3337
3338       /* now we need to restore the registers */
3339       /* if this isr has no bank i.e. is going to
3340          run with bank 0 , then we need to save more
3341          registers :-) */
3342       if (!FUNC_REGBANK (sym->type))
3343         {
3344             int i;
3345           /* if this function does not call any other
3346              function then we can be economical and
3347              save only those registers that are used */
3348           if (!IFFUNC_HASFCALL(sym->type))
3349             {
3350
3351               /* if any registers used */
3352               if (sym->regsUsed)
3353                 {
3354                   /* save the registers used */
3355                   for (i = sym->regsUsed->size; i >= 0; i--)
3356                     {
3357                       if (bitVectBitValue (sym->regsUsed, i))
3358                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3359                     }
3360                 }
3361             }
3362           else
3363             {
3364               /* this function has  a function call cannot
3365                  determines register usage so we will have to pop the
3366                  entire bank */
3367               if (options.parms_in_bank1) {
3368                   for (i = 7 ; i >= 0 ; i-- ) {
3369                       emitcode ("pop","%s",rb1regs[i]);
3370                   }
3371               }
3372               unsaveRBank (0, ic, FALSE);
3373             }
3374         }
3375         else
3376         {
3377             /* This ISR uses a non-zero bank.
3378              *
3379              * Restore any register banks saved by genFunction
3380              * in reverse order.
3381              */
3382             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3383             int ix;
3384           
3385             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3386             {
3387                 if (savedBanks & (1 << ix))
3388                 {
3389                     unsaveRBank(ix, NULL, FALSE);
3390                 }
3391             }
3392             
3393             if (options.useXstack)
3394             {
3395                 /* Restore bank AFTER calling unsaveRBank,
3396                  * since it can trash r0.
3397                  */
3398                 emitcode ("pop", "psw");
3399             }
3400         }
3401
3402       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3403         {
3404           if (options.stack10bit)
3405             {
3406               emitcode ("pop", DP2_RESULT_REG);
3407               emitcode ("pop", "dpx1");
3408               emitcode ("pop", "dph1");
3409               emitcode ("pop", "dpl1");
3410             }
3411           emitcode ("pop", "dps");
3412           emitcode ("pop", "dpx");
3413         }
3414       if (!inExcludeList ("dph"))
3415         emitcode ("pop", "dph");
3416       if (!inExcludeList ("dpl"))
3417         emitcode ("pop", "dpl");
3418       if (!inExcludeList ("b"))
3419         emitcode ("pop", "b");
3420       if (!inExcludeList ("acc"))
3421         emitcode ("pop", "acc");
3422
3423       /* if debug then send end of function */
3424       if (options.debug && currFunc) {
3425           debugFile->writeEndFunction (currFunc, ic, 1);
3426         }
3427
3428       emitcode ("reti", "");
3429     }
3430   else
3431     {
3432       if (IFFUNC_CALLEESAVES(sym->type))
3433         {
3434           int i;
3435
3436           /* if any registers used */
3437           if (sym->regsUsed)
3438             {
3439               /* save the registers used */
3440               for (i = sym->regsUsed->size; i >= 0; i--)
3441                 {
3442                   if (bitVectBitValue (sym->regsUsed, i))
3443                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3444                 }
3445             }
3446         }
3447
3448       /* if debug then send end of function */
3449       if (options.debug && currFunc)
3450         {
3451           debugFile->writeEndFunction (currFunc, ic, 1);
3452         }
3453
3454       emitcode ("ret", "");
3455     }
3456
3457   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3458     return;
3459   
3460   /* If this was an interrupt handler using bank 0 that called another */
3461   /* function, then all registers must be saved; nothing to optimized. */
3462   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3463       && !FUNC_REGBANK(sym->type))
3464     return;
3465     
3466   /* There are no push/pops to optimize if not callee-saves or ISR */
3467   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3468     return;
3469   
3470   /* If there were stack parameters, we cannot optimize without also    */
3471   /* fixing all of the stack offsets; this is too dificult to consider. */
3472   if (FUNC_HASSTACKPARM(sym->type))
3473     return;
3474   
3475   /* Compute the registers actually used */
3476   regsUsed = newBitVect (ds390_nRegs);
3477   regsUsedPrologue = newBitVect (ds390_nRegs);
3478   while (lnp)
3479     {
3480       if (lnp->ic && lnp->ic->op == FUNCTION)
3481         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3482       else
3483         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3484       
3485       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3486           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3487         break;
3488       if (!lnp->prev)
3489         break;
3490       lnp = lnp->prev;
3491     }
3492
3493   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3494       && !bitVectBitValue (regsUsed, DPS_IDX))
3495     {
3496       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3497     }
3498     
3499   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3500       && !bitVectBitValue (regsUsed, CND_IDX))
3501     {
3502       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3503       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3504           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3505         bitVectUnSetBit (regsUsed, CND_IDX);
3506     }
3507   else
3508     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3509     
3510   /* If this was an interrupt handler that called another function */
3511   /* function, then assume working registers may be modified by it. */
3512   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3513     {
3514       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3515       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3516       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3517       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3518       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3519       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3520       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3521       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3522       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3523       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3524       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3525     }
3526
3527   /* Remove the unneeded push/pops */
3528   regsUnneeded = newBitVect (ds390_nRegs);
3529   while (lnp)
3530     {
3531       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3532         {
3533           if (!strncmp(lnp->line, "push", 4))
3534             {
3535               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3536               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3537                 {
3538                   connectLine (lnp->prev, lnp->next);
3539                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3540                 }
3541             }
3542           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3543             {
3544               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3545               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3546                 {
3547                   connectLine (lnp->prev, lnp->next);
3548                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3549                 }
3550             }
3551         }
3552       lnp = lnp->next;
3553     }  
3554   
3555   for (idx = 0; idx < regsUnneeded->size; idx++)
3556     if (bitVectBitValue (regsUnneeded, idx))
3557       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3558   
3559   freeBitVect (regsUnneeded);
3560   freeBitVect (regsUsed);
3561   freeBitVect (regsUsedPrologue);
3562 }
3563
3564 /*-----------------------------------------------------------------*/
3565 /* genJavaNativeRet - generate code for return JavaNative          */
3566 /*-----------------------------------------------------------------*/
3567 static void genJavaNativeRet(iCode *ic)
3568 {
3569     int i, size;
3570
3571     aopOp (IC_LEFT (ic), ic, FALSE, 
3572            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3573     size = AOP_SIZE (IC_LEFT (ic));
3574
3575     assert (size <= 4);
3576
3577     /* it is assigned to GPR0-R3 then push them */
3578     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3579         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3580         for (i = 0 ; i < size ; i++ ) {
3581             emitcode ("push","%s",
3582                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3583         }
3584         for (i = (size-1) ; i >= 0 ; i--) {
3585             emitcode ("pop","a%s",javaRet[i]);
3586         }
3587     } else {
3588         for (i = 0 ; i < size ; i++) 
3589             emitcode ("mov","%s,%s",javaRet[i],
3590                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3591     }
3592     for (i = size ; i < 4 ; i++ )
3593             emitcode ("mov","%s,#0",javaRet[i]);
3594     return;
3595 }
3596
3597 /*-----------------------------------------------------------------*/
3598 /* genRet - generate code for return statement                     */
3599 /*-----------------------------------------------------------------*/
3600 static void
3601 genRet (iCode * ic)
3602 {
3603   int size, offset = 0, pushed = 0;
3604
3605   D (emitcode (";", "genRet "););
3606
3607   /* if we have no return value then
3608      just generate the "ret" */
3609   if (!IC_LEFT (ic))
3610     goto jumpret;
3611
3612   /* if this is a JavaNative function then return 
3613      value in different register */
3614   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3615       genJavaNativeRet(ic);
3616       goto jumpret;
3617   }
3618   /* we have something to return then
3619      move the return value into place */
3620   aopOp (IC_LEFT (ic), ic, FALSE, 
3621          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3622   size = AOP_SIZE (IC_LEFT (ic));
3623
3624   _startLazyDPSEvaluation ();
3625   while (size--)
3626     {
3627       char *l;
3628       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3629         {
3630           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3631                       FALSE, TRUE, NULL);
3632           emitcode ("push", "%s", l);
3633           pushed++;
3634         }
3635       else
3636         {
3637           /* Since A is the last element of fReturn,
3638            * is is OK to clobber it in the aopGet.
3639            */
3640           l = aopGet (AOP (IC_LEFT (ic)), offset,
3641                       FALSE, FALSE, NULL);
3642           if (strcmp (fReturn[offset], l))
3643             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3644         }
3645     }
3646   _endLazyDPSEvaluation ();
3647
3648   if (pushed)
3649     {
3650       while (pushed)
3651         {
3652           pushed--;
3653           if (strcmp (fReturn[pushed], "a"))
3654             emitcode ("pop", fReturn[pushed]);
3655           else
3656             emitcode ("pop", "acc");
3657         }
3658     }
3659   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3660
3661 jumpret:
3662   /* generate a jump to the return label
3663      if the next is not the return statement */
3664   if (!(ic->next && ic->next->op == LABEL &&
3665         IC_LABEL (ic->next) == returnLabel))
3666
3667     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3668
3669 }
3670
3671 /*-----------------------------------------------------------------*/
3672 /* genLabel - generates a label                                    */
3673 /*-----------------------------------------------------------------*/
3674 static void
3675 genLabel (iCode * ic)
3676 {
3677   /* special case never generate */
3678   if (IC_LABEL (ic) == entryLabel)
3679     return;
3680
3681   D (emitcode (";", "genLabel ");
3682     );
3683
3684   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3685 }
3686
3687 /*-----------------------------------------------------------------*/
3688 /* genGoto - generates a ljmp                                      */
3689 /*-----------------------------------------------------------------*/
3690 static void
3691 genGoto (iCode * ic)
3692 {
3693   D (emitcode (";", "genGoto ");
3694     );
3695   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3696 }
3697
3698 /*-----------------------------------------------------------------*/
3699 /* findLabelBackwards: walks back through the iCode chain looking  */
3700 /* for the given label. Returns number of iCode instructions     */
3701 /* between that label and given ic.          */
3702 /* Returns zero if label not found.          */
3703 /*-----------------------------------------------------------------*/
3704 static int
3705 findLabelBackwards (iCode * ic, int key)
3706 {
3707   int count = 0;
3708
3709   while (ic->prev)
3710     {
3711       ic = ic->prev;
3712       count++;
3713
3714       /* If we have any pushes or pops, we cannot predict the distance.
3715          I don't like this at all, this should be dealt with in the 
3716          back-end */
3717       if (ic->op == IPUSH || ic->op == IPOP) {
3718         return 0;
3719       }
3720
3721       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3722         {
3723           /* printf("findLabelBackwards = %d\n", count); */
3724           return count;
3725         }
3726     }
3727
3728   return 0;
3729 }
3730
3731 /*-----------------------------------------------------------------*/
3732 /* genPlusIncr :- does addition with increment if possible         */
3733 /*-----------------------------------------------------------------*/
3734 static bool
3735 genPlusIncr (iCode * ic)
3736 {
3737   unsigned int icount;
3738   unsigned int size = getDataSize (IC_RESULT (ic));
3739
3740   /* will try to generate an increment */
3741   /* if the right side is not a literal
3742      we cannot */
3743   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3744     return FALSE;
3745
3746   /* if the literal value of the right hand side
3747      is greater than 4 then it is not worth it */
3748   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3749     return FALSE;
3750
3751   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3752       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3753       while (icount--) {
3754           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3755       }
3756       return TRUE;
3757   }
3758   /* if increment 16 bits in register */
3759   if (
3760        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3761        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3762        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3763        (size > 1) &&
3764        (icount == 1))
3765     {
3766       symbol  *tlbl;
3767       int     emitTlbl;
3768       int     labelRange;
3769       char    *l;
3770
3771       /* If the next instruction is a goto and the goto target
3772        * is <= 5 instructions previous to this, we can generate
3773        * jumps straight to that target.
3774        */
3775       if (ic->next && ic->next->op == GOTO
3776           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3777           && labelRange <= 5)
3778         {
3779           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3780           tlbl = IC_LABEL (ic->next);
3781           emitTlbl = 0;
3782         }
3783       else
3784         {
3785           tlbl = newiTempLabel (NULL);
3786           emitTlbl = 1;
3787         }
3788         
3789       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3790       emitcode ("inc", "%s", l);
3791       
3792       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3793           IS_AOP_PREG (IC_RESULT (ic)))
3794       {   
3795         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3796       }
3797       else
3798       {
3799           emitcode ("clr", "a");
3800           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3801       }
3802
3803       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3804       emitcode ("inc", "%s", l);
3805       if (size > 2)
3806         {
3807             if (!strcmp(l, "acc"))
3808             {
3809                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3810             }
3811             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3812                      IS_AOP_PREG (IC_RESULT (ic)))
3813             {
3814                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3815             }
3816             else
3817             {
3818                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3819             }
3820
3821             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3822             emitcode ("inc", "%s", l);
3823         }
3824       if (size > 3)
3825         {
3826             if (!strcmp(l, "acc"))
3827             {
3828                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3829             }
3830             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3831                      IS_AOP_PREG (IC_RESULT (ic)))
3832             {
3833                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3834             }
3835             else
3836             {
3837                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3838             }
3839
3840             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3841             emitcode ("inc", "%s", l);  }
3842
3843       if (emitTlbl)
3844         {
3845           emitcode ("", "!tlabeldef", tlbl->key + 100);
3846         }
3847       return TRUE;
3848     }
3849
3850   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3851       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3852       options.model == MODEL_FLAT24 ) {
3853
3854       switch (size) {
3855       case 3:
3856           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3857       case 2:
3858           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3859       case 1:
3860           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3861           break;
3862       }
3863       while (icount--) emitcode ("inc","dptr");      
3864       return TRUE;
3865   }
3866
3867   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3868       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3869       icount <= 5 ) {
3870       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3871       while (icount--) emitcode ("inc","dptr");
3872       emitcode ("mov","dps,#0");
3873       return TRUE;
3874   }
3875
3876   /* if the sizes are greater than 1 then we cannot */
3877   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3878       AOP_SIZE (IC_LEFT (ic)) > 1)
3879     return FALSE;
3880
3881   /* we can if the aops of the left & result match or
3882      if they are in registers and the registers are the
3883      same */
3884   if (
3885        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3886        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3887        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3888     {
3889
3890       if (icount > 3)
3891         {
3892           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3893           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3894           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3895         }
3896       else
3897         {
3898
3899           _startLazyDPSEvaluation ();
3900           while (icount--)
3901             {
3902               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3903             }
3904           _endLazyDPSEvaluation ();
3905         }
3906
3907       return TRUE;
3908     }
3909
3910   return FALSE;
3911 }
3912
3913 /*-----------------------------------------------------------------*/
3914 /* outBitAcc - output a bit in acc                                 */
3915 /*-----------------------------------------------------------------*/
3916 static void
3917 outBitAcc (operand * result)
3918 {
3919   symbol *tlbl = newiTempLabel (NULL);
3920   /* if the result is a bit */
3921   if (AOP_TYPE (result) == AOP_CRY)
3922     {
3923       aopPut (AOP (result), "a", 0);
3924     }
3925   else
3926     {
3927       emitcode ("jz", "!tlabel", tlbl->key + 100);
3928       emitcode ("mov", "a,%s", one);
3929       emitcode ("", "!tlabeldef", tlbl->key + 100);
3930       outAcc (result);
3931     }
3932 }
3933
3934 /*-----------------------------------------------------------------*/
3935 /* genPlusBits - generates code for addition of two bits           */
3936 /*-----------------------------------------------------------------*/
3937 static void
3938 genPlusBits (iCode * ic)
3939 {
3940   D (emitcode (";", "genPlusBits "););
3941     
3942   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3943     {
3944       symbol *lbl = newiTempLabel (NULL);
3945       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3946       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3947       emitcode ("cpl", "c");
3948       emitcode ("", "!tlabeldef", (lbl->key + 100));
3949       outBitC (IC_RESULT (ic));
3950     }
3951   else
3952     {
3953       emitcode ("clr", "a");
3954       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3955       emitcode ("rlc", "a");
3956       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3957       emitcode ("addc", "a,#0");
3958       outAcc (IC_RESULT (ic));
3959     }
3960 }
3961
3962 static void
3963 adjustArithmeticResult (iCode * ic)
3964 {
3965   if (opIsGptr (IC_RESULT (ic)) &&
3966       opIsGptr (IC_LEFT (ic)) &&
3967       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3968     {
3969       aopPut (AOP (IC_RESULT (ic)),
3970               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3971               GPTRSIZE - 1);
3972     }
3973
3974   if (opIsGptr (IC_RESULT (ic)) &&
3975       opIsGptr (IC_RIGHT (ic)) &&
3976       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3977     {
3978       aopPut (AOP (IC_RESULT (ic)),
3979             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3980               GPTRSIZE - 1);
3981     }
3982
3983   if (opIsGptr (IC_RESULT (ic)) &&
3984       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3985       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3986       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3987       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3988     {
3989       char buff[5];
3990       SNPRINTF (buff, sizeof(buff), 
3991                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3992       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3993     }
3994 }
3995
3996 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3997 // generates the result if possible. If result is generated, returns TRUE; otherwise
3998 // returns false and caller must deal with fact that result isn't aopOp'd.
3999 bool aopOp3(iCode * ic)
4000 {
4001     bool dp1InUse, dp2InUse;
4002     bool useDp2;
4003
4004     // First, generate the right opcode. DPTR may be used if neither left nor result are
4005     // of type AOP_STR.
4006     
4007 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4008 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4009 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4010 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4011 //      );
4012 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4013 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4014 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4015 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4016 //      );
4017     
4018     // Right uses DPTR unless left or result is an AOP_STR; however,
4019     // if right is an AOP_STR, it must use DPTR regardless.
4020     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4021      && !AOP_IS_STR(IC_RIGHT(ic)))
4022     {
4023         useDp2 = TRUE;
4024     }
4025     else
4026     {
4027         useDp2 = FALSE;
4028     }
4029         
4030     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4031     
4032     // if the right used DPTR, left MUST use DPTR2.
4033     // if the right used DPTR2, left MUST use DPTR.
4034     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4035     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4036     // enabling us to assign DPTR to result.
4037      
4038     if (AOP_USESDPTR(IC_RIGHT(ic)))
4039     {
4040         useDp2 = TRUE;
4041     }
4042     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4043     {
4044         useDp2 = FALSE;
4045     }
4046     else
4047     {
4048         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4049         {
4050             useDp2 = TRUE;
4051         }
4052         else
4053         {
4054             useDp2 = FALSE;
4055         }
4056     }
4057
4058     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4059
4060         
4061     // We've op'd the left & right. So, if left or right are the same operand as result, 
4062     // we know aopOp will succeed, and we can just do it & bail.
4063     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4064       {
4065         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4066         return TRUE;
4067       }
4068     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4069       {
4070 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4071         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4072         return TRUE;
4073       }
4074     
4075     // Operands may be equivalent (but not equal) if they share a spill location. If
4076     // so, use the same DPTR or DPTR2.
4077     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4078       {
4079         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4080         return TRUE;
4081       }
4082     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4083       {
4084         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4085         return TRUE;
4086       }
4087     
4088     // Note which dptrs are currently in use.
4089     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4090     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4091     
4092     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
4093     // generate it.
4094     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4095     {
4096         return FALSE;
4097     }
4098     
4099     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4100     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4101     {
4102         return FALSE;
4103     }
4104     
4105     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4106     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4107     {
4108         return FALSE;
4109     }
4110
4111     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4112
4113     // Some sanity checking...
4114     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4115     {
4116         fprintf(stderr,
4117                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4118                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4119         emitcode(";", ">>> unexpected DPTR here.");
4120     }
4121     
4122     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4123     {
4124         fprintf(stderr,
4125                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4126                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4127         emitcode(";", ">>> unexpected DPTR2 here.");
4128     }    
4129     
4130     return TRUE;
4131 }
4132
4133 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4134 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4135 // will be set TRUE. The caller must then handle the case specially, noting
4136 // that the IC_RESULT operand is not aopOp'd.
4137 // 
4138 #define AOP_OP_3_NOFATAL(ic, rc) \
4139             do { rc = !aopOp3(ic); } while (0)
4140
4141 // aopOp the left & right operands of an ic.
4142 #define AOP_OP_2(ic) \
4143     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4144     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4145
4146 // convienience macro.
4147 #define AOP_SET_LOCALS(ic) \
4148     left = IC_LEFT(ic); \
4149     right = IC_RIGHT(ic); \
4150     result = IC_RESULT(ic);
4151
4152
4153 // Given an integer value of pushedSize bytes on the stack,
4154 // adjust it to be resultSize bytes, either by discarding
4155 // the most significant bytes or by zero-padding.
4156 //
4157 // On exit from this macro, pushedSize will have been adjusted to
4158 // equal resultSize, and ACC may be trashed.
4159 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4160       /* If the pushed data is bigger than the result,          \
4161        * simply discard unused bytes. Icky, but works.          \
4162        */                                                       \
4163       while (pushedSize > resultSize)                           \
4164       {                                                         \
4165           D (emitcode (";", "discarding unused result byte."););\
4166           emitcode ("pop", "acc");                              \
4167           pushedSize--;                                         \
4168       }                                                         \
4169       if (pushedSize < resultSize)                              \
4170       {                                                         \
4171           emitcode ("clr", "a");                                \
4172           /* Conversly, we haven't pushed enough here.          \
4173            * just zero-pad, and all is well.                    \
4174            */                                                   \
4175           while (pushedSize < resultSize)                       \
4176           {                                                     \
4177               emitcode("push", "acc");                          \
4178               pushedSize++;                                     \
4179           }                                                     \
4180       }                                                         \
4181       assert(pushedSize == resultSize);
4182
4183 /*-----------------------------------------------------------------*/
4184 /* genPlus - generates code for addition                           */
4185 /*-----------------------------------------------------------------*/
4186 static void
4187 genPlus (iCode * ic)
4188 {
4189   int size, offset = 0;
4190   bool pushResult;
4191   int rSize;
4192
4193   D (emitcode (";", "genPlus "););
4194
4195   /* special cases :- */
4196   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4197       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4198       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4199       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4200       if (size <= 9) {
4201           while (size--) emitcode ("inc","dptr");
4202       } else {
4203           emitcode ("mov","a,dpl");
4204           emitcode ("add","a,#!constbyte",size & 0xff);
4205           emitcode ("mov","dpl,a");
4206           emitcode ("mov","a,dph");
4207           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4208           emitcode ("mov","dph,a");
4209           emitcode ("mov","a,dpx");
4210           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4211           emitcode ("mov","dpx,a");
4212       }
4213       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4214       return ;
4215   }
4216   if ( IS_SYMOP(IC_LEFT(ic)) && 
4217        OP_SYMBOL(IC_LEFT(ic))->remat &&
4218        isOperandInFarSpace(IC_RIGHT(ic))) {
4219       operand *op = IC_RIGHT(ic);
4220       IC_RIGHT(ic) = IC_LEFT(ic);
4221       IC_LEFT(ic) = op;
4222   }
4223                 
4224   AOP_OP_3_NOFATAL (ic, pushResult);
4225     
4226   if (pushResult)
4227     {
4228       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4229     }
4230
4231   if (!pushResult)
4232     {
4233       /* if literal, literal on the right or
4234          if left requires ACC or right is already
4235          in ACC */
4236       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4237        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4238           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4239         {
4240           operand *t = IC_RIGHT (ic);
4241           IC_RIGHT (ic) = IC_LEFT (ic);
4242           IC_LEFT (ic) = t;
4243           emitcode (";", "Swapped plus args.");
4244         }
4245
4246       /* if both left & right are in bit
4247          space */
4248       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4249           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4250         {
4251           genPlusBits (ic);
4252           goto release;
4253         }
4254
4255       /* if left in bit space & right literal */
4256       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4257           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4258         {
4259           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4260           /* if result in bit space */
4261           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4262             {
4263               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4264                 emitcode ("cpl", "c");
4265               outBitC (IC_RESULT (ic));
4266             }
4267           else
4268             {
4269               size = getDataSize (IC_RESULT (ic));
4270               _startLazyDPSEvaluation ();
4271               while (size--)
4272                 {
4273                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4274                   emitcode ("addc", "a,#0");
4275                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4276                 }
4277               _endLazyDPSEvaluation ();
4278             }
4279           goto release;
4280         }
4281
4282       /* if I can do an increment instead
4283          of add then GOOD for ME */
4284       if (genPlusIncr (ic) == TRUE)
4285         {
4286           emitcode (";", "did genPlusIncr");
4287           goto release;
4288         }
4289
4290     }
4291   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4292
4293   _startLazyDPSEvaluation ();
4294   while (size--)
4295     {
4296       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4297         {
4298           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4299           if (offset == 0)
4300             emitcode ("add", "a,%s",
4301                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4302           else
4303             emitcode ("addc", "a,%s",
4304                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4305         }
4306       else
4307         {
4308           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4309           {
4310               /* right is going to use ACC or we would have taken the
4311                * above branch.
4312                */
4313               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4314        TR_AP("#3");
4315               D(emitcode(";", "+ AOP_ACC special case."););
4316               emitcode("xch", "a, %s", DP2_RESULT_REG);
4317           }
4318           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4319           if (offset == 0)
4320           {
4321             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4322             {
4323          TR_AP("#4");
4324                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4325             }
4326             else
4327             {
4328                 emitcode ("add", "a,%s",
4329                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4330                                   DP2_RESULT_REG));
4331             }
4332           }
4333           else
4334           {
4335             emitcode ("addc", "a,%s",
4336                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4337                           DP2_RESULT_REG));
4338           }
4339         }
4340       if (!pushResult)
4341         {
4342           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4343         }
4344       else
4345         {
4346           emitcode ("push", "acc");
4347         }
4348       offset++;
4349     }
4350   _endLazyDPSEvaluation ();
4351
4352   if (pushResult)
4353     {
4354       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4355
4356       size = getDataSize (IC_LEFT (ic));
4357       rSize = getDataSize (IC_RESULT (ic));
4358
4359       ADJUST_PUSHED_RESULT(size, rSize);
4360
4361       _startLazyDPSEvaluation ();
4362       while (size--)
4363         {
4364           emitcode ("pop", "acc");
4365           aopPut (AOP (IC_RESULT (ic)), "a", size);
4366         }
4367       _endLazyDPSEvaluation ();
4368     }
4369
4370   adjustArithmeticResult (ic);
4371
4372 release:
4373   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4374   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4375   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genMinusDec :- does subtraction with deccrement if possible     */
4380 /*-----------------------------------------------------------------*/
4381 static bool
4382 genMinusDec (iCode * ic)
4383 {
4384   unsigned int icount;
4385   unsigned int size = getDataSize (IC_RESULT (ic));
4386
4387   /* will try to generate an increment */
4388   /* if the right side is not a literal
4389      we cannot */
4390   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4391     return FALSE;
4392
4393   /* if the literal value of the right hand side
4394      is greater than 4 then it is not worth it */
4395   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4396     return FALSE;
4397
4398   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4399       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4400       while (icount--) {
4401           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4402       }
4403       return TRUE;
4404   }
4405   /* if decrement 16 bits in register */
4406   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4407       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4408       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4409       (size > 1) &&
4410       (icount == 1))
4411     {
4412       symbol *tlbl;
4413       int    emitTlbl;
4414       int    labelRange;
4415       char   *l;
4416
4417       /* If the next instruction is a goto and the goto target
4418          * is <= 5 instructions previous to this, we can generate
4419          * jumps straight to that target.
4420        */
4421       if (ic->next && ic->next->op == GOTO
4422           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4423           && labelRange <= 5)
4424         {
4425           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4426           tlbl = IC_LABEL (ic->next);
4427           emitTlbl = 0;
4428         }
4429       else
4430         {
4431           tlbl = newiTempLabel (NULL);
4432           emitTlbl = 1;
4433         }
4434
4435       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4436       emitcode ("dec", "%s", l);
4437  
4438       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4439           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4440           IS_AOP_PREG (IC_RESULT (ic)))
4441       {     
4442           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4443       }
4444       else
4445       {
4446           emitcode ("mov", "a,#!constbyte",0xff);
4447           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4448       }
4449       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4450       emitcode ("dec", "%s", l);
4451       if (size > 2)
4452         {
4453             if (!strcmp(l, "acc"))
4454             {
4455                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4456             }
4457             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459                      IS_AOP_PREG (IC_RESULT (ic)))
4460             {       
4461                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4462             }
4463             else
4464             {
4465                 emitcode ("mov", "a,#!constbyte",0xff);
4466                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4467             }
4468             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4469             emitcode ("dec", "%s", l);
4470         }
4471       if (size > 3)
4472         {
4473             if (!strcmp(l, "acc"))
4474             {
4475                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4476             }
4477             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4479                      IS_AOP_PREG (IC_RESULT (ic)))
4480             {       
4481                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4482             }
4483             else
4484             {
4485                 emitcode ("mov", "a,#!constbyte",0xff);
4486                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4487             }       
4488             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4489             emitcode ("dec", "%s", l);
4490         }
4491       if (emitTlbl)
4492         {
4493           emitcode ("", "!tlabeldef", tlbl->key + 100);
4494         }
4495       return TRUE;
4496     }
4497
4498   /* if the sizes are greater than 1 then we cannot */
4499   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4500       AOP_SIZE (IC_LEFT (ic)) > 1)
4501     return FALSE;
4502
4503   /* we can if the aops of the left & result match or
4504      if they are in registers and the registers are the
4505      same */
4506   if (
4507        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4508        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4509        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4510     {
4511
4512       _startLazyDPSEvaluation ();
4513       while (icount--)
4514         {
4515           emitcode ("dec", "%s",
4516                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4517         }
4518       _endLazyDPSEvaluation ();
4519
4520       return TRUE;
4521     }
4522
4523   return FALSE;
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* addSign - complete with sign                                    */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 addSign (operand * result, int offset, int sign)
4531 {
4532   int size = (getDataSize (result) - offset);
4533   if (size > 0)
4534     {
4535       _startLazyDPSEvaluation();
4536       if (sign)
4537         {
4538           emitcode ("rlc", "a");
4539           emitcode ("subb", "a,acc");
4540           while (size--)
4541           {
4542             aopPut (AOP (result), "a", offset++);
4543           }
4544         }
4545       else
4546       {
4547         while (size--)
4548         {
4549           aopPut (AOP (result), zero, offset++);
4550         }
4551       }
4552       _endLazyDPSEvaluation();
4553     }
4554 }
4555
4556 /*-----------------------------------------------------------------*/
4557 /* genMinusBits - generates code for subtraction  of two bits      */
4558 /*-----------------------------------------------------------------*/
4559 static void
4560 genMinusBits (iCode * ic)
4561 {
4562   symbol *lbl = newiTempLabel (NULL);
4563
4564   D (emitcode (";", "genMinusBits "););
4565
4566   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4567     {
4568       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4569       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4570       emitcode ("cpl", "c");
4571       emitcode ("", "!tlabeldef", (lbl->key + 100));
4572       outBitC (IC_RESULT (ic));
4573     }
4574   else
4575     {
4576       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4577       emitcode ("subb", "a,acc");
4578       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4579       emitcode ("inc", "a");
4580       emitcode ("", "!tlabeldef", (lbl->key + 100));
4581       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4582       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4583     }
4584 }
4585
4586 /*-----------------------------------------------------------------*/
4587 /* genMinus - generates code for subtraction                       */
4588 /*-----------------------------------------------------------------*/
4589 static void
4590 genMinus (iCode * ic)
4591 {
4592     int size, offset = 0;
4593     int rSize;
4594     long lit = 0L;
4595     bool pushResult;
4596
4597     D (emitcode (";", "genMinus "););
4598
4599     AOP_OP_3_NOFATAL(ic, pushResult);   
4600
4601     if (!pushResult)
4602     {
4603       /* special cases :- */
4604       /* if both left & right are in bit space */
4605       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4606           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4607         {
4608           genMinusBits (ic);
4609           goto release;
4610         }
4611
4612       /* if I can do an decrement instead
4613          of subtract then GOOD for ME */
4614       if (genMinusDec (ic) == TRUE)
4615         goto release;
4616
4617     }
4618
4619   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4620
4621   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4622     {
4623       CLRC;
4624     }
4625   else
4626     {
4627       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4628       lit = -lit;
4629     }
4630
4631
4632   /* if literal, add a,#-lit, else normal subb */
4633   _startLazyDPSEvaluation ();
4634   while (size--) {
4635       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4636           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4637               emitcode ("mov","b,%s",
4638                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4639               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4640               emitcode ("subb","a,b");
4641           } else {
4642               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4643               emitcode ("subb", "a,%s",
4644                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4645                                 DP2_RESULT_REG));
4646           }
4647       } else {
4648           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4649           /* first add without previous c */
4650           if (!offset) {
4651               if (!size && lit==-1) {
4652                   emitcode ("dec", "a");
4653               } else {
4654                   emitcode ("add", "a,#!constbyte",
4655                             (unsigned int) (lit & 0x0FFL));
4656               }
4657           } else {
4658               emitcode ("addc", "a,#!constbyte",
4659                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4660           }
4661       }
4662       
4663       if (pushResult) {
4664           emitcode ("push", "acc");
4665       } else {
4666           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4667       }
4668       offset++;
4669   }
4670   _endLazyDPSEvaluation ();
4671   
4672   if (pushResult)
4673     {
4674       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4675
4676       size = getDataSize (IC_LEFT (ic));
4677       rSize = getDataSize (IC_RESULT (ic));
4678
4679       ADJUST_PUSHED_RESULT(size, rSize);
4680
4681       _startLazyDPSEvaluation ();
4682       while (size--)
4683         {
4684           emitcode ("pop", "acc");
4685           aopPut (AOP (IC_RESULT (ic)), "a", size);
4686         }
4687       _endLazyDPSEvaluation ();
4688     }
4689
4690   adjustArithmeticResult (ic);
4691
4692 release:
4693   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4695   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4696 }
4697
4698
4699 /*-----------------------------------------------------------------*/
4700 /* genMultbits :- multiplication of bits                           */
4701 /*-----------------------------------------------------------------*/
4702 static void
4703 genMultbits (operand * left,
4704              operand * right,
4705              operand * result,
4706              iCode   * ic)
4707 {
4708   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4709   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4710   aopOp(result, ic, TRUE, FALSE);
4711   outBitC (result);
4712 }
4713
4714
4715 /*-----------------------------------------------------------------*/
4716 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4717 /*-----------------------------------------------------------------*/
4718 static void
4719 genMultOneByte (operand * left,
4720                 operand * right,
4721                 operand * result,
4722                 iCode   * ic)
4723 {
4724   int size;
4725   symbol *lbl;
4726   bool runtimeSign, compiletimeSign;
4727   bool lUnsigned, rUnsigned;
4728   
4729
4730   /* (if two literals: the value is computed before) */
4731   /* if one literal, literal on the right */
4732   if (AOP_TYPE (left) == AOP_LIT)
4733     {
4734       operand *t = right;
4735       right = left;
4736       left = t;
4737       emitcode (";", "swapped left and right");
4738     }
4739
4740   /* (if two literals: the value is computed before) */
4741   /* if one literal, literal on the right */
4742   if (AOP_TYPE (left) == AOP_LIT)
4743     {
4744       operand *t = right;
4745       right = left;
4746       left = t;
4747       /* emitcode (";", "swapped left and right"); */
4748     }
4749   /* if no literal, unsigned on the right: shorter code */
4750   if (   AOP_TYPE (right) != AOP_LIT
4751       && SPEC_USIGN (getSpec (operandType (left))))
4752     {
4753       operand *t = right;
4754       right = left;
4755       left = t;
4756     }
4757
4758   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4759   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4760
4761   if ((lUnsigned && rUnsigned)
4762 /* sorry, I don't know how to get size
4763    without calling aopOp (result,...);
4764    see Feature Request  */
4765       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4766                    no need to take care about the signedness! */
4767     {
4768       /* just an unsigned 8 * 8 = 8 multiply
4769          or 8u * 8u = 16u */
4770       /* emitcode (";","unsigned"); */
4771       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4772       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4773       emitcode ("mul", "ab");
4774     
4775       _G.accInUse++; _G.bInUse++;
4776       aopOp (result, ic, TRUE, FALSE);
4777       size = AOP_SIZE (result);
4778   
4779       if (size < 1 || size > 2)
4780         {
4781           /* this should never happen */
4782           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4783                    size, __FILE__, lineno);
4784           exit (1);
4785         }
4786   
4787       aopPut (AOP (result), "a", 0);
4788       _G.accInUse--; _G.bInUse--;
4789       if (size == 2) 
4790         aopPut (AOP (result), "b", 1);
4791       return;
4792     }
4793
4794   /* we have to do a signed multiply */
4795   /* emitcode (";", "signed"); */
4796   
4797   /* now sign adjust for both left & right */
4798
4799   /* let's see what's needed: */
4800   /* apply negative sign during runtime */
4801   runtimeSign = FALSE;
4802   /* negative sign from literals */
4803   compiletimeSign = FALSE;
4804
4805   if (!lUnsigned)
4806     {
4807       if (AOP_TYPE(left) == AOP_LIT)
4808         {
4809           /* signed literal */
4810           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4811           if (val < 0)
4812             compiletimeSign = TRUE;
4813         }
4814       else
4815         /* signed but not literal */
4816         runtimeSign = TRUE;
4817     }
4818
4819   if (!rUnsigned)
4820     {
4821       if (AOP_TYPE(right) == AOP_LIT)
4822         {
4823           /* signed literal */
4824           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4825           if (val < 0)
4826             compiletimeSign ^= TRUE;
4827         }
4828       else
4829         /* signed but not literal */
4830         runtimeSign = TRUE;
4831     }
4832
4833   /* initialize F0, which stores the runtime sign */
4834   if (runtimeSign)
4835     {
4836       if (compiletimeSign)
4837         emitcode ("setb", "F0"); /* set sign flag */
4838       else
4839         emitcode ("clr", "F0"); /* reset sign flag */
4840     }
4841   
4842   /* save the signs of the operands */
4843   if (AOP_TYPE(right) == AOP_LIT)
4844     {
4845       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4846
4847       if (!rUnsigned && val < 0)
4848         emitcode ("mov", "b,#!constbyte", -val);
4849       else
4850         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4851     }
4852   else /* ! literal */
4853     {
4854       if (rUnsigned)  /* emitcode (";", "signed"); */
4855         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4856       else
4857         {
4858           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4859           lbl = newiTempLabel (NULL);
4860           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4861           emitcode ("cpl", "F0"); /* complement sign flag */
4862           emitcode ("cpl", "a");  /* 2's complement */
4863           emitcode ("inc", "a");
4864           emitcode ("", "!tlabeldef", lbl->key + 100);
4865           emitcode ("mov", "b,a");
4866         }
4867     }
4868
4869   if (AOP_TYPE(left) == AOP_LIT)
4870     {
4871       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4872
4873       if (!lUnsigned && val < 0)
4874         emitcode ("mov", "a,#!constbyte", -val);
4875       else
4876         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4877     }
4878   else /* ! literal */
4879     {
4880       if (lUnsigned)  /* emitcode (";", "signed"); */
4881
4882         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4883       else
4884         {
4885           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4886           lbl = newiTempLabel (NULL);
4887           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4888           emitcode ("cpl", "F0"); /* complement sign flag */
4889           emitcode ("cpl", "a");  /* 2's complement */
4890           emitcode ("inc", "a");
4891           emitcode ("", "!tlabeldef", lbl->key + 100);
4892         }
4893     }
4894
4895   /* now the multiplication */
4896   emitcode ("mul", "ab");
4897   _G.accInUse++;_G.bInUse++;
4898   aopOp(result, ic, TRUE, FALSE);
4899   size = AOP_SIZE (result);
4900
4901   if (size < 1 || size > 2) 
4902     {
4903       /* this should never happen */
4904       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4905                size, __FILE__, lineno);
4906       exit (1);
4907     }    
4908     
4909   if (runtimeSign || compiletimeSign)
4910     {
4911       lbl = newiTempLabel (NULL);
4912       if (runtimeSign)
4913         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4914       emitcode ("cpl", "a"); /* lsb 2's complement */
4915       if (size != 2)
4916         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4917       else
4918         {
4919           emitcode ("add", "a,#1"); /* this sets carry flag */
4920           emitcode ("xch", "a,b");
4921           emitcode ("cpl", "a"); /* msb 2's complement */
4922           emitcode ("addc", "a,#0");
4923           emitcode ("xch", "a,b");
4924         }
4925       emitcode ("", "!tlabeldef", lbl->key + 100);
4926     }
4927   aopPut (AOP (result), "a", 0);
4928   _G.accInUse--;_G.bInUse--;
4929   if (size == 2)
4930     aopPut (AOP (result), "b", 1);
4931 }
4932
4933 /*-----------------------------------------------------------------*/
4934 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4935 /*-----------------------------------------------------------------*/
4936 static void genMultTwoByte (operand *left, operand *right, 
4937                             operand *result, iCode *ic)
4938 {
4939         sym_link *retype = getSpec(operandType(right));
4940         sym_link *letype = getSpec(operandType(left));
4941         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4942         symbol *lbl;
4943
4944         if (AOP_TYPE (left) == AOP_LIT) {
4945                 operand *t = right;
4946                 right = left;
4947                 left = t;
4948         }
4949         /* save EA bit in F1 */
4950         lbl = newiTempLabel(NULL);
4951         emitcode ("setb","F1");
4952         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4953         emitcode ("clr","F1");
4954         emitcode("","!tlabeldef",lbl->key+100);
4955
4956         /* load up MB with right */
4957         if (!umult) {
4958                 emitcode("clr","F0");
4959                 if (AOP_TYPE(right) == AOP_LIT) {
4960                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4961                         if (val < 0) {
4962                                 emitcode("setb","F0");
4963                                 val = -val;
4964                         }
4965                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4966                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4967                 } else {
4968                         lbl = newiTempLabel(NULL);
4969                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4970                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4971                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4972                         emitcode ("xch", "a,b");
4973                         emitcode ("cpl","a");
4974                         emitcode ("add", "a,#1");
4975                         emitcode ("xch", "a,b");
4976                         emitcode ("cpl", "a"); // msb
4977                         emitcode ("addc", "a,#0");
4978                         emitcode ("setb","F0");
4979                         emitcode ("","!tlabeldef",lbl->key+100);
4980                         emitcode ("mov","mb,b");
4981                         emitcode ("mov","mb,a");
4982                 }
4983         } else {
4984                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4985                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4986         }
4987         /* load up MA with left */
4988         if (!umult) {
4989                 lbl = newiTempLabel(NULL);
4990                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4991                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4992                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4993                 emitcode ("xch", "a,b");
4994                 emitcode ("cpl","a");
4995                 emitcode ("add", "a,#1");
4996                 emitcode ("xch", "a,b");
4997                 emitcode ("cpl", "a"); // msb
4998                 emitcode ("addc","a,#0");
4999                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5000                 emitcode ("setb","F0");
5001                 emitcode ("","!tlabeldef",lbl->key+100);
5002                 emitcode ("mov","ma,b");
5003                 emitcode ("mov","ma,a");
5004         } else {
5005                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5006                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5007         }
5008         /* wait for multiplication to finish */
5009         lbl = newiTempLabel(NULL);
5010         emitcode("","!tlabeldef", lbl->key+100);
5011         emitcode("mov","a,mcnt1");
5012         emitcode("anl","a,#!constbyte",0x80);
5013         emitcode("jnz","!tlabel",lbl->key+100);
5014         
5015         freeAsmop (left, NULL, ic, TRUE);
5016         freeAsmop (right, NULL, ic,TRUE);
5017         aopOp(result, ic, TRUE, FALSE);
5018
5019         /* if unsigned then simple */   
5020         if (umult) {
5021                 emitcode ("mov","a,ma");
5022                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5023                 emitcode ("mov","a,ma");
5024                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5025                 aopPut(AOP(result),"ma",1);
5026                 aopPut(AOP(result),"ma",0);
5027         } else {
5028                 emitcode("push","ma");
5029                 emitcode("push","ma");
5030                 emitcode("push","ma");
5031                 MOVA("ma");
5032                 /* negate result if needed */
5033                 lbl = newiTempLabel(NULL);      
5034                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5035                 emitcode("cpl","a");
5036                 emitcode("add","a,#1");
5037                 emitcode("","!tlabeldef", lbl->key+100);
5038                 if (AOP_TYPE(result) == AOP_ACC)
5039                 {
5040                     D(emitcode(";", "ACC special case."););
5041                     /* We know result is the only live aop, and 
5042                      * it's obviously not a DPTR2, so AP is available.
5043                      */
5044                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5045                 }
5046                 else
5047                 {
5048                     aopPut(AOP(result),"a",0);
5049                 }
5050             
5051                 emitcode("pop","acc");
5052                 lbl = newiTempLabel(NULL);      
5053                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054                 emitcode("cpl","a");
5055                 emitcode("addc","a,#0");
5056                 emitcode("","!tlabeldef", lbl->key+100);
5057                 aopPut(AOP(result),"a",1);
5058                 emitcode("pop","acc");
5059                 if (AOP_SIZE(result) >= 3) {
5060                         lbl = newiTempLabel(NULL);      
5061                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5062                         emitcode("cpl","a");
5063                         emitcode("addc","a,#0");                        
5064                         emitcode("","!tlabeldef", lbl->key+100);
5065                         aopPut(AOP(result),"a",2);
5066                 }
5067                 emitcode("pop","acc");
5068                 if (AOP_SIZE(result) >= 4) {
5069                         lbl = newiTempLabel(NULL);      
5070                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5071                         emitcode("cpl","a");
5072                         emitcode("addc","a,#0");                        
5073                         emitcode("","!tlabeldef", lbl->key+100);
5074                         aopPut(AOP(result),"a",3);
5075                 }
5076                 if (AOP_TYPE(result) == AOP_ACC)
5077                 {
5078                     /* We stashed the result away above. */
5079                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5080                 }           
5081                 
5082         }
5083         freeAsmop (result, NULL, ic, TRUE);
5084
5085         /* restore EA bit in F1 */
5086         lbl = newiTempLabel(NULL);
5087         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5088         emitcode ("setb","EA");
5089         emitcode("","!tlabeldef",lbl->key+100);
5090         return ;
5091 }
5092
5093 /*-----------------------------------------------------------------*/
5094 /* genMult - generates code for multiplication                     */
5095 /*-----------------------------------------------------------------*/
5096 static void
5097 genMult (iCode * ic)
5098 {
5099   operand *left = IC_LEFT (ic);
5100   operand *right = IC_RIGHT (ic);
5101   operand *result = IC_RESULT (ic);
5102
5103   D (emitcode (";", "genMult "););
5104
5105   /* assign the amsops */
5106   AOP_OP_2 (ic);
5107
5108   /* special cases first */
5109   /* both are bits */
5110   if (AOP_TYPE (left) == AOP_CRY &&
5111       AOP_TYPE (right) == AOP_CRY)
5112     {
5113       genMultbits (left, right, result, ic);
5114       goto release;
5115     }
5116
5117   /* if both are of size == 1 */
5118   if (AOP_SIZE (left) == 1 &&
5119       AOP_SIZE (right) == 1)
5120     {
5121       genMultOneByte (left, right, result, ic);
5122       goto release;
5123     }
5124
5125   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5126           /* use the ds390 ARITHMETIC accel UNIT */
5127           genMultTwoByte (left, right, result, ic);
5128           return ;
5129   }
5130   /* should have been converted to function call */
5131   assert (0);
5132
5133 release:
5134   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136   freeAsmop (result, NULL, ic, TRUE);
5137 }
5138
5139 /*-----------------------------------------------------------------*/
5140 /* genDivbits :- division of bits                                  */
5141 /*-----------------------------------------------------------------*/
5142 static void
5143 genDivbits (operand * left,
5144             operand * right,
5145             operand * result,
5146             iCode   * ic)
5147 {
5148
5149   char *l;
5150
5151   /* the result must be bit */
5152   LOAD_AB_FOR_DIV (left, right, l);
5153   emitcode ("div", "ab");
5154   emitcode ("rrc", "a");
5155   aopOp(result, ic, TRUE, FALSE);
5156     
5157   aopPut (AOP (result), "c", 0);
5158 }
5159
5160 /*-----------------------------------------------------------------*/
5161 /* genDivOneByte : 8 bit division                                  */
5162 /*-----------------------------------------------------------------*/
5163 static void
5164 genDivOneByte (operand * left,
5165                operand * right,
5166                operand * result,
5167                iCode   * ic)
5168 {
5169   bool lUnsigned, rUnsigned;
5170   bool runtimeSign, compiletimeSign;
5171   char *l;
5172   symbol *lbl;
5173   int size, offset;
5174
5175   offset = 1;
5176   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5177   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5178   
5179   /* signed or unsigned */
5180   if (lUnsigned && rUnsigned)
5181     {
5182       /* unsigned is easy */
5183       LOAD_AB_FOR_DIV (left, right, l);
5184       emitcode ("div", "ab");
5185
5186       _G.accInUse++;
5187       aopOp (result, ic, TRUE, FALSE);
5188       aopPut (AOP (result), "a", 0);
5189       _G.accInUse--;
5190
5191       size = AOP_SIZE (result) - 1;
5192       
5193       while (size--)
5194         aopPut (AOP (result), zero, offset++);
5195       return;
5196     }
5197
5198   /* signed is a little bit more difficult */
5199
5200   /* now sign adjust for both left & right */
5201
5202   /* let's see what's needed: */
5203   /* apply negative sign during runtime */
5204   runtimeSign = FALSE;
5205   /* negative sign from literals */
5206   compiletimeSign = FALSE;
5207
5208   if (!lUnsigned)
5209     {
5210       if (AOP_TYPE(left) == AOP_LIT)
5211         {
5212           /* signed literal */
5213           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5214           if (val < 0)
5215             compiletimeSign = TRUE;
5216         }
5217       else
5218         /* signed but not literal */
5219         runtimeSign = TRUE;
5220     }
5221
5222   if (!rUnsigned)
5223     {
5224       if (AOP_TYPE(right) == AOP_LIT)
5225         {
5226           /* signed literal */
5227           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5228           if (val < 0)
5229             compiletimeSign ^= TRUE;
5230         }
5231       else
5232         /* signed but not literal */
5233         runtimeSign = TRUE;
5234     }
5235
5236   /* initialize F0, which stores the runtime sign */
5237   if (runtimeSign)
5238     {
5239       if (compiletimeSign)
5240         emitcode ("setb", "F0"); /* set sign flag */
5241       else
5242         emitcode ("clr", "F0"); /* reset sign flag */
5243     }
5244
5245   /* save the signs of the operands */
5246   if (AOP_TYPE(right) == AOP_LIT)
5247     {
5248       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5249
5250       if (!rUnsigned && val < 0)
5251         emitcode ("mov", "b,#0x%02x", -val);
5252       else
5253         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5254     }
5255   else /* ! literal */
5256     {
5257       if (rUnsigned)
5258         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5259       else
5260         {
5261           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5262           lbl = newiTempLabel (NULL);
5263           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5264           emitcode ("cpl", "F0"); /* complement sign flag */
5265           emitcode ("cpl", "a");  /* 2's complement */
5266           emitcode ("inc", "a");
5267           emitcode ("", "!tlabeldef", lbl->key + 100);
5268           emitcode ("mov", "b,a");
5269         }
5270     }
5271
5272   if (AOP_TYPE(left) == AOP_LIT)
5273     {
5274       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5275
5276       if (!lUnsigned && val < 0)
5277         emitcode ("mov", "a,#0x%02x", -val);
5278       else
5279         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5280     }
5281   else /* ! literal */
5282     {
5283       if (lUnsigned)
5284         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5285       else
5286         {
5287           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5288           lbl = newiTempLabel (NULL);
5289           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5290           emitcode ("cpl", "F0"); /* complement sign flag */
5291           emitcode ("cpl", "a");  /* 2's complement */
5292           emitcode ("inc", "a");
5293           emitcode ("", "!tlabeldef", lbl->key + 100);
5294         }
5295     }
5296   
5297   /* now the division */
5298   emitcode ("nop", "; workaround for DS80C390 div bug.");
5299   emitcode ("div", "ab");
5300   
5301   if (runtimeSign || compiletimeSign)
5302     {
5303       lbl = newiTempLabel (NULL);
5304       if (runtimeSign)
5305         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5306       emitcode ("cpl", "a"); /* lsb 2's complement */
5307       emitcode ("inc", "a");
5308       emitcode ("", "!tlabeldef", lbl->key + 100);
5309
5310       _G.accInUse++;     _G.bInUse++;
5311       aopOp (result, ic, TRUE, FALSE);
5312       size = AOP_SIZE (result) - 1;
5313
5314       if (size > 0)
5315         {
5316           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5317              then the result will be in b, a */
5318           emitcode ("mov", "b,a"); /* 1 */
5319           /* msb is 0x00 or 0xff depending on the sign */
5320           if (runtimeSign)
5321             {
5322               emitcode ("mov",  "c,F0");
5323               emitcode ("subb", "a,acc");
5324               emitcode ("xch",  "a,b"); /* 2 */
5325               while (size--)
5326                 aopPut (AOP (result), "b", offset++); /* write msb's */
5327             }
5328           else /* compiletimeSign */
5329             while (size--)
5330               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5331         }
5332       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5333     }
5334   else
5335     {
5336       _G.accInUse++;     _G.bInUse++;
5337       aopOp(result, ic, TRUE, FALSE);
5338       size = AOP_SIZE (result) - 1;
5339       
5340       aopPut (AOP (result), "a", 0);
5341       while (size--)
5342         aopPut (AOP (result), zero, offset++);
5343     }
5344   _G.accInUse--;     _G.bInUse--;
5345
5346 }
5347
5348 /*-----------------------------------------------------------------*/
5349 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5350 /*-----------------------------------------------------------------*/
5351 static void genDivTwoByte (operand *left, operand *right, 
5352                             operand *result, iCode *ic)
5353 {
5354         sym_link *retype = getSpec(operandType(right));
5355         sym_link *letype = getSpec(operandType(left));
5356         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5357         symbol *lbl;
5358
5359         /* save EA bit in F1 */
5360         lbl = newiTempLabel(NULL);
5361         emitcode ("setb","F1");
5362         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5363         emitcode ("clr","F1");
5364         emitcode("","!tlabeldef",lbl->key+100);
5365
5366         /* load up MA with left */
5367         if (!umult) {
5368                 emitcode("clr","F0");
5369                 lbl = newiTempLabel(NULL);
5370                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5371                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5372                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5373                 emitcode ("xch", "a,b");
5374                 emitcode ("cpl","a");
5375                 emitcode ("add", "a,#1");
5376                 emitcode ("xch", "a,b");
5377                 emitcode ("cpl", "a"); // msb
5378                 emitcode ("addc","a,#0");
5379                 emitcode ("setb","F0");
5380                 emitcode ("","!tlabeldef",lbl->key+100);
5381                 emitcode ("mov","ma,b");
5382                 emitcode ("mov","ma,a");
5383         } else {
5384                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5385                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5386         }
5387
5388         /* load up MB with right */
5389         if (!umult) {
5390                 if (AOP_TYPE(right) == AOP_LIT) {
5391                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5392                         if (val < 0) {
5393                                 lbl = newiTempLabel(NULL);
5394                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5395                                 emitcode("setb","F0");
5396                                 emitcode ("","!tlabeldef",lbl->key+100);
5397                                 val = -val;
5398                         } 
5399                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5400                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5401                 } else {
5402                         lbl = newiTempLabel(NULL);
5403                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5404                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5405                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5406                         emitcode ("xch", "a,b");
5407                         emitcode ("cpl","a");
5408                         emitcode ("add", "a,#1");
5409                         emitcode ("xch", "a,b");
5410                         emitcode ("cpl", "a"); // msb
5411                         emitcode ("addc", "a,#0");
5412                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5413                         emitcode ("setb","F0");
5414                         emitcode ("","!tlabeldef",lbl->key+100);
5415                         emitcode ("mov","mb,b");
5416                         emitcode ("mov","mb,a");
5417                 }
5418         } else {
5419                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5420                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5421         }
5422
5423         /* wait for multiplication to finish */
5424         lbl = newiTempLabel(NULL);
5425         emitcode("","!tlabeldef", lbl->key+100);
5426         emitcode("mov","a,mcnt1");
5427         emitcode("anl","a,#!constbyte",0x80);
5428         emitcode("jnz","!tlabel",lbl->key+100);
5429         
5430         freeAsmop (left, NULL, ic, TRUE);
5431         freeAsmop (right, NULL, ic,TRUE);
5432         aopOp(result, ic, TRUE, FALSE);
5433
5434         /* if unsigned then simple */   
5435         if (umult) {
5436                 aopPut(AOP(result),"ma",1);
5437                 aopPut(AOP(result),"ma",0);
5438         } else {
5439                 emitcode("push","ma");
5440                 MOVA("ma");
5441                 /* negate result if needed */
5442                 lbl = newiTempLabel(NULL);      
5443                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5444                 emitcode("cpl","a");
5445                 emitcode("add","a,#1");
5446                 emitcode("","!tlabeldef", lbl->key+100);
5447                 aopPut(AOP(result),"a",0);
5448                 emitcode("pop","acc");
5449                 lbl = newiTempLabel(NULL);      
5450                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5451                 emitcode("cpl","a");
5452                 emitcode("addc","a,#0");
5453                 emitcode("","!tlabeldef", lbl->key+100);
5454                 aopPut(AOP(result),"a",1);
5455         }
5456         freeAsmop (result, NULL, ic, TRUE);
5457         /* restore EA bit in F1 */
5458         lbl = newiTempLabel(NULL);
5459         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5460         emitcode ("setb","EA");
5461         emitcode("","!tlabeldef",lbl->key+100);
5462         return ;
5463 }
5464
5465 /*-----------------------------------------------------------------*/
5466 /* genDiv - generates code for division                            */
5467 /*-----------------------------------------------------------------*/
5468 static void
5469 genDiv (iCode * ic)
5470 {
5471   operand *left = IC_LEFT (ic);
5472   operand *right = IC_RIGHT (ic);
5473   operand *result = IC_RESULT (ic);
5474
5475   D (emitcode (";", "genDiv "););
5476
5477   /* assign the amsops */
5478   AOP_OP_2 (ic);
5479
5480   /* special cases first */
5481   /* both are bits */
5482   if (AOP_TYPE (left) == AOP_CRY &&
5483       AOP_TYPE (right) == AOP_CRY)
5484     {
5485       genDivbits (left, right, result, ic);
5486       goto release;
5487     }
5488
5489   /* if both are of size == 1 */
5490   if (AOP_SIZE (left) == 1 &&
5491       AOP_SIZE (right) == 1)
5492     {
5493       genDivOneByte (left, right, result, ic);
5494       goto release;
5495     }
5496
5497   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5498           /* use the ds390 ARITHMETIC accel UNIT */
5499           genDivTwoByte (left, right, result, ic);
5500           return ;
5501   }
5502   /* should have been converted to function call */
5503   assert (0);
5504 release:
5505   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5507   freeAsmop (result, NULL, ic, TRUE);
5508 }
5509
5510 /*-----------------------------------------------------------------*/
5511 /* genModbits :- modulus of bits                                   */
5512 /*-----------------------------------------------------------------*/
5513 static void
5514 genModbits (operand * left,
5515             operand * right,
5516             operand * result,
5517             iCode   * ic)
5518 {
5519
5520   char *l;
5521
5522   /* the result must be bit */
5523   LOAD_AB_FOR_DIV (left, right, l);
5524   emitcode ("div", "ab");
5525   emitcode ("mov", "a,b");
5526   emitcode ("rrc", "a");
5527   aopOp(result, ic, TRUE, FALSE);
5528   aopPut (AOP (result), "c", 0);
5529 }
5530
5531 /*-----------------------------------------------------------------*/
5532 /* genModOneByte : 8 bit modulus                                   */
5533 /*-----------------------------------------------------------------*/
5534 static void
5535 genModOneByte (operand * left,
5536                operand * right,
5537                operand * result,
5538                iCode   * ic)
5539 {
5540   bool lUnsigned, rUnsigned;
5541   bool runtimeSign, compiletimeSign;
5542   char *l;
5543   symbol *lbl;
5544   int size, offset;
5545
5546   offset = 1;
5547   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5548   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5549   
5550   /* signed or unsigned */
5551   if (lUnsigned && rUnsigned)
5552     {
5553       /* unsigned is easy */
5554       LOAD_AB_FOR_DIV (left, right, l);
5555       emitcode ("div", "ab");
5556       aopOp (result, ic, TRUE, FALSE);  
5557       aopPut (AOP (result), "b", 0);
5558
5559       for (size = AOP_SIZE (result) - 1; size--;)
5560         aopPut (AOP (result), zero, offset++);
5561       return;
5562     }
5563
5564   /* signed is a little bit more difficult */
5565
5566   /* now sign adjust for both left & right */
5567
5568   /* modulus: sign of the right operand has no influence on the result! */
5569   if (AOP_TYPE(right) == AOP_LIT)
5570     {
5571       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5572
5573       if (!rUnsigned && val < 0)
5574         emitcode ("mov", "b,#0x%02x", -val);
5575       else
5576         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5577     }
5578   else /* ! literal */
5579     {
5580       if (rUnsigned)
5581         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5582       else
5583         {
5584           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5585           lbl = newiTempLabel (NULL);
5586           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5587           emitcode ("cpl", "a");  /* 2's complement */
5588           emitcode ("inc", "a");
5589           emitcode ("", "!tlabeldef", lbl->key + 100);
5590           emitcode ("mov", "b,a");
5591         }
5592     }
5593   
5594   /* let's see what's needed: */
5595   /* apply negative sign during runtime */
5596   runtimeSign = FALSE;
5597   /* negative sign from literals */
5598   compiletimeSign = FALSE;
5599
5600   /* sign adjust left side */
5601   if (AOP_TYPE(left) == AOP_LIT)
5602     {
5603       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5604
5605       if (!lUnsigned && val < 0)
5606         {
5607           compiletimeSign = TRUE; /* set sign flag */
5608           emitcode ("mov", "a,#0x%02x", -val);
5609         }
5610       else
5611         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5612     }
5613   else /* ! literal */
5614     {
5615       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5616       
5617       if (!lUnsigned)
5618         {
5619           runtimeSign = TRUE;
5620           emitcode ("clr", "F0"); /* clear sign flag */
5621           
5622           lbl = newiTempLabel (NULL);
5623           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5624           emitcode ("setb", "F0"); /* set sign flag */
5625           emitcode ("cpl", "a");   /* 2's complement */
5626           emitcode ("inc", "a");
5627           emitcode ("", "!tlabeldef", lbl->key + 100);
5628         }
5629     }
5630   
5631   /* now the modulus */
5632   emitcode ("nop", "; workaround for DS80C390 div bug.");
5633   emitcode ("div", "ab");
5634   
5635   if (runtimeSign || compiletimeSign)
5636     {
5637       emitcode ("mov", "a,b");
5638       lbl = newiTempLabel (NULL);
5639       if (runtimeSign)
5640         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5641       emitcode ("cpl", "a"); /* lsb 2's complement */
5642       emitcode ("inc", "a");
5643       emitcode ("", "!tlabeldef", lbl->key + 100);
5644
5645       _G.accInUse++;     _G.bInUse++;
5646       aopOp (result, ic, TRUE, FALSE);
5647       size = AOP_SIZE (result) - 1;
5648       
5649       if (size > 0)
5650         {
5651           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5652              then the result will be in b, a */
5653           emitcode ("mov", "b,a"); /* 1 */
5654           /* msb is 0x00 or 0xff depending on the sign */
5655           if (runtimeSign)
5656             {
5657               emitcode ("mov",  "c,F0");
5658               emitcode ("subb", "a,acc");
5659               emitcode ("xch",  "a,b"); /* 2 */
5660               while (size--)
5661                 aopPut (AOP (result), "b", offset++); /* write msb's */
5662             }
5663           else /* compiletimeSign */
5664             while (size--)
5665               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5666         }
5667       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5668     }
5669   else
5670     {
5671       _G.accInUse++;     _G.bInUse++;
5672       aopOp(result, ic, TRUE, FALSE);
5673       size = AOP_SIZE (result) - 1;
5674       
5675       aopPut (AOP (result), "b", 0);
5676       while (size--)
5677         aopPut (AOP (result), zero, offset++);
5678     }
5679   _G.accInUse--;     _G.bInUse--;
5680
5681 }
5682
5683 /*-----------------------------------------------------------------*/
5684 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5685 /*-----------------------------------------------------------------*/
5686 static void genModTwoByte (operand *left, operand *right, 
5687                             operand *result, iCode *ic)
5688 {
5689         sym_link *retype = getSpec(operandType(right));
5690         sym_link *letype = getSpec(operandType(left));
5691         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5692         symbol *lbl;
5693
5694         /* load up MA with left */
5695         /* save EA bit in F1 */
5696         lbl = newiTempLabel(NULL);
5697         emitcode ("setb","F1");
5698         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5699         emitcode ("clr","F1");
5700         emitcode("","!tlabeldef",lbl->key+100);
5701
5702         if (!umult) {
5703                 lbl = newiTempLabel(NULL);
5704                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5705                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5706                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5707                 emitcode ("xch", "a,b");
5708                 emitcode ("cpl","a");
5709                 emitcode ("add", "a,#1");
5710                 emitcode ("xch", "a,b");
5711                 emitcode ("cpl", "a"); // msb
5712                 emitcode ("addc","a,#0");
5713                 emitcode ("","!tlabeldef",lbl->key+100);
5714                 emitcode ("mov","ma,b");
5715                 emitcode ("mov","ma,a");
5716         } else {
5717                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5718                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5719         }
5720
5721         /* load up MB with right */
5722         if (!umult) {
5723                 if (AOP_TYPE(right) == AOP_LIT) {
5724                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5725                         if (val < 0) {
5726                                 val = -val;
5727                         } 
5728                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5729                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5730                 } else {
5731                         lbl = newiTempLabel(NULL);
5732                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5733                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5734                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5735                         emitcode ("xch", "a,b");
5736                         emitcode ("cpl","a");
5737                         emitcode ("add", "a,#1");
5738                         emitcode ("xch", "a,b");
5739                         emitcode ("cpl", "a"); // msb
5740                         emitcode ("addc", "a,#0");
5741                         emitcode ("","!tlabeldef",lbl->key+100);
5742                         emitcode ("mov","mb,b");
5743                         emitcode ("mov","mb,a");
5744                 }
5745         } else {
5746                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5747                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5748         }
5749
5750         /* wait for multiplication to finish */
5751         lbl = newiTempLabel(NULL);
5752         emitcode("","!tlabeldef", lbl->key+100);
5753         emitcode("mov","a,mcnt1");
5754         emitcode("anl","a,#!constbyte",0x80);
5755         emitcode("jnz","!tlabel",lbl->key+100);
5756         
5757         freeAsmop (left, NULL, ic, TRUE);
5758         freeAsmop (right, NULL, ic,TRUE);
5759         aopOp(result, ic, TRUE, FALSE);
5760
5761         aopPut(AOP(result),"mb",1);
5762         aopPut(AOP(result),"mb",0);
5763         freeAsmop (result, NULL, ic, TRUE);
5764
5765         /* restore EA bit in F1 */
5766         lbl = newiTempLabel(NULL);
5767         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5768         emitcode ("setb","EA");
5769         emitcode("","!tlabeldef",lbl->key+100);
5770         return ;
5771 }
5772
5773 /*-----------------------------------------------------------------*/
5774 /* genMod - generates code for division                            */
5775 /*-----------------------------------------------------------------*/
5776 static void
5777 genMod (iCode * ic)
5778 {
5779   operand *left = IC_LEFT (ic);
5780   operand *right = IC_RIGHT (ic);
5781   operand *result = IC_RESULT (ic);
5782
5783   D (emitcode (";", "genMod "); );
5784
5785   /* assign the amsops */
5786   AOP_OP_2 (ic);
5787
5788   /* special cases first */
5789   /* both are bits */
5790   if (AOP_TYPE (left) == AOP_CRY &&
5791       AOP_TYPE (right) == AOP_CRY)
5792     {
5793       genModbits (left, right, result, ic);
5794       goto release;
5795     }
5796
5797   /* if both are of size == 1 */
5798   if (AOP_SIZE (left) == 1 &&
5799       AOP_SIZE (right) == 1)
5800     {
5801       genModOneByte (left, right, result, ic);
5802       goto release;
5803     }
5804
5805   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5806           /* use the ds390 ARITHMETIC accel UNIT */
5807           genModTwoByte (left, right, result, ic);
5808           return ;
5809   }
5810
5811   /* should have been converted to function call */
5812   assert (0);
5813
5814 release:
5815   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817   freeAsmop (result, NULL, ic, TRUE);
5818 }
5819
5820 /*-----------------------------------------------------------------*/
5821 /* genIfxJump :- will create a jump depending on the ifx           */
5822 /*-----------------------------------------------------------------*/
5823 static void
5824 genIfxJump (iCode * ic, char *jval)
5825 {
5826   symbol *jlbl;
5827   symbol *tlbl = newiTempLabel (NULL);
5828   char *inst;
5829
5830   D (emitcode (";", "genIfxJump"););
5831
5832   /* if true label then we jump if condition
5833      supplied is true */
5834   if (IC_TRUE (ic))
5835     {
5836       jlbl = IC_TRUE (ic);
5837       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5838                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5839     }
5840   else
5841     {
5842       /* false label is present */
5843       jlbl = IC_FALSE (ic);
5844       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5845                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5846     }
5847   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5848     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5849   else
5850     emitcode (inst, "!tlabel", tlbl->key + 100);
5851   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5852   emitcode ("", "!tlabeldef", tlbl->key + 100);
5853
5854   /* mark the icode as generated */
5855   ic->generated = 1;
5856 }
5857
5858 /*-----------------------------------------------------------------*/
5859 /* genCmp :- greater or less than comparison                       */
5860 /*-----------------------------------------------------------------*/
5861 static void
5862 genCmp (operand * left, operand * right,
5863         iCode * ic, iCode * ifx, int sign)
5864 {
5865   int size, offset = 0;
5866   unsigned long lit = 0L;
5867   operand *result;
5868
5869   D (emitcode (";", "genCmp"););
5870
5871   result = IC_RESULT (ic);
5872
5873   /* if left & right are bit variables */
5874   if (AOP_TYPE (left) == AOP_CRY &&
5875       AOP_TYPE (right) == AOP_CRY)
5876     {
5877       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5878       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5879     }
5880   else
5881     {
5882       /* subtract right from left if at the
5883          end the carry flag is set then we know that
5884          left is greater than right */
5885       size = max (AOP_SIZE (left), AOP_SIZE (right));
5886
5887       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5888       if ((size == 1) && !sign 
5889           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5890         {
5891           symbol *lbl = newiTempLabel (NULL);
5892           emitcode ("cjne", "%s,%s,!tlabel",
5893                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5894                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5895                     lbl->key + 100);
5896           emitcode ("", "!tlabeldef", lbl->key + 100);
5897         }
5898       else
5899         {
5900           if (AOP_TYPE (right) == AOP_LIT)
5901             {
5902               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5903               /* optimize if(x < 0) or if(x >= 0) */
5904               if (lit == 0L)
5905                 {
5906                   if (!sign)
5907                     {
5908                       CLRC;
5909                     }
5910                   else
5911                     {
5912                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5913
5914                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5915                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5916
5917                       aopOp (result, ic, FALSE, FALSE);
5918
5919                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5920                         {
5921                           freeAsmop (result, NULL, ic, TRUE);
5922                           genIfxJump (ifx, "acc.7");
5923                           return;
5924                         }
5925                       else
5926                         {
5927                           emitcode ("rlc", "a");
5928                         }
5929                       goto release_freedLR;
5930                     }
5931                   goto release;
5932                 }
5933             }
5934           CLRC;
5935           while (size--)
5936             {
5937               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5938               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5939               // emitcode (";", "genCmp #2");
5940               if (sign && (size == 0))
5941                 {
5942                   // emitcode (";", "genCmp #3");
5943                   emitcode ("xrl", "a,#!constbyte",0x80);
5944                   if (AOP_TYPE (right) == AOP_LIT)
5945                     {
5946                       unsigned long lit = (unsigned long)
5947                       floatFromVal (AOP (right)->aopu.aop_lit);
5948                       // emitcode (";", "genCmp #3.1");
5949                       emitcode ("subb", "a,#!constbyte",
5950                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5951                     }
5952                   else
5953                     {
5954                       // emitcode (";", "genCmp #3.2");
5955                       saveAccWarn = 0;  
5956                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5957                       saveAccWarn = DEFAULT_ACC_WARNING;
5958                       emitcode ("xrl", "b,#!constbyte",0x80);
5959                       emitcode ("subb", "a,b");
5960                     }
5961                 }
5962               else
5963                 {
5964                   const char *s;
5965
5966                   // emitcode (";", "genCmp #4");
5967                   saveAccWarn = 0;
5968                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5969                   saveAccWarn = DEFAULT_ACC_WARNING;
5970
5971                   emitcode ("subb", "a,%s", s);
5972                 }
5973             }
5974         }
5975     }
5976
5977 release:
5978 /* Don't need the left & right operands any more; do need the result. */
5979   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5981
5982   aopOp (result, ic, FALSE, FALSE);
5983
5984 release_freedLR:
5985
5986   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5987     {
5988       outBitC (result);
5989     }
5990   else
5991     {
5992       /* if the result is used in the next
5993          ifx conditional branch then generate
5994          code a little differently */
5995       if (ifx)
5996         {
5997           genIfxJump (ifx, "c");
5998         }
5999       else
6000         {
6001           outBitC (result);
6002         }
6003       /* leave the result in acc */
6004     }
6005   freeAsmop (result, NULL, ic, TRUE);
6006 }
6007
6008 /*-----------------------------------------------------------------*/
6009 /* genCmpGt :- greater than comparison                             */
6010 /*-----------------------------------------------------------------*/
6011 static void
6012 genCmpGt (iCode * ic, iCode * ifx)
6013 {
6014   operand *left, *right;
6015   sym_link *letype, *retype;
6016   int sign;
6017
6018   D (emitcode (";", "genCmpGt ");
6019     );
6020
6021   left = IC_LEFT (ic);
6022   right = IC_RIGHT (ic);
6023
6024   letype = getSpec (operandType (left));
6025   retype = getSpec (operandType (right));
6026   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6027
6028   /* assign the left & right amsops */
6029   AOP_OP_2 (ic);
6030
6031   genCmp (right, left, ic, ifx, sign);
6032 }
6033
6034 /*-----------------------------------------------------------------*/
6035 /* genCmpLt - less than comparisons                                */
6036 /*-----------------------------------------------------------------*/
6037 static void
6038 genCmpLt (iCode * ic, iCode * ifx)
6039 {
6040   operand *left, *right;
6041   sym_link *letype, *retype;
6042   int sign;
6043
6044   D (emitcode (";", "genCmpLt "););
6045
6046   left = IC_LEFT (ic);
6047   right = IC_RIGHT (ic);
6048
6049   letype = getSpec (operandType (left));
6050   retype = getSpec (operandType (right));
6051   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6052
6053   /* assign the left & right amsops */
6054   AOP_OP_2 (ic);
6055
6056   genCmp (left, right, ic, ifx, sign);
6057 }
6058
6059 /*-----------------------------------------------------------------*/
6060 /* gencjneshort - compare and jump if not equal                    */
6061 /*-----------------------------------------------------------------*/
6062 static void
6063 gencjneshort (operand * left, operand * right, symbol * lbl)
6064 {
6065   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6066   int offset = 0;
6067   unsigned long lit = 0L;
6068
6069   D (emitcode (";", "gencjneshort");
6070     );
6071
6072   /* if the left side is a literal or
6073      if the right is in a pointer register and left
6074      is not */
6075   if ((AOP_TYPE (left) == AOP_LIT) ||
6076       (AOP_TYPE (left) == AOP_IMMD) ||
6077       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6078     {
6079       operand *t = right;
6080       right = left;
6081       left = t;
6082     }
6083
6084   if (AOP_TYPE (right) == AOP_LIT)
6085     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6086
6087   if (opIsGptr (left) || opIsGptr (right))
6088     {
6089       /* We are comparing a generic pointer to something.
6090        * Exclude the generic type byte from the comparison.
6091        */
6092       size--;
6093       D (emitcode (";", "cjneshort: generic ptr special case."););
6094     }
6095
6096
6097   /* if the right side is a literal then anything goes */
6098   if (AOP_TYPE (right) == AOP_LIT &&
6099       AOP_TYPE (left) != AOP_DIR)
6100     {
6101       while (size--)
6102         {
6103           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6104           emitcode ("cjne", "a,%s,!tlabel",
6105                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6106                     lbl->key + 100);
6107           offset++;
6108         }
6109     }
6110
6111   /* if the right side is in a register or in direct space or
6112      if the left is a pointer register & right is not */
6113   else if (AOP_TYPE (right) == AOP_REG ||
6114            AOP_TYPE (right) == AOP_DIR ||
6115            AOP_TYPE (right) == AOP_LIT ||
6116            AOP_TYPE (right) == AOP_IMMD ||
6117            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6118            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6119     {
6120       while (size--)
6121         {
6122           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6124               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6125             emitcode ("jnz", "!tlabel", lbl->key + 100);
6126           else
6127             emitcode ("cjne", "a,%s,!tlabel",
6128                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6129                       lbl->key + 100);
6130           offset++;
6131         }
6132     }
6133   else
6134     {
6135       /* right is a pointer reg need both a & b */
6136       while (size--)
6137         {
6138           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6139           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6140           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6141           offset++;
6142         }
6143     }
6144 }
6145
6146 /*-----------------------------------------------------------------*/
6147 /* gencjne - compare and jump if not equal                         */
6148 /*-----------------------------------------------------------------*/
6149 static void
6150 gencjne (operand * left, operand * right, symbol * lbl)
6151 {
6152   symbol *tlbl = newiTempLabel (NULL);
6153
6154   D (emitcode (";", "gencjne");
6155     );
6156
6157   gencjneshort (left, right, lbl);
6158
6159   emitcode ("mov", "a,%s", one);
6160   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6161   emitcode ("", "!tlabeldef", lbl->key + 100);
6162   emitcode ("clr", "a");
6163   emitcode ("", "!tlabeldef", tlbl->key + 100);
6164 }
6165
6166 /*-----------------------------------------------------------------*/
6167 /* genCmpEq - generates code for equal to                          */
6168 /*-----------------------------------------------------------------*/
6169 static void
6170 genCmpEq (iCode * ic, iCode * ifx)
6171 {
6172   operand *left, *right, *result;
6173
6174   D (emitcode (";", "genCmpEq ");
6175     );
6176
6177   AOP_OP_2 (ic);
6178   AOP_SET_LOCALS (ic);
6179
6180   /* if literal, literal on the right or
6181      if the right is in a pointer register and left
6182      is not */
6183   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6184       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6185     {
6186       operand *t = IC_RIGHT (ic);
6187       IC_RIGHT (ic) = IC_LEFT (ic);
6188       IC_LEFT (ic) = t;
6189     }
6190
6191   if (ifx &&                    /* !AOP_SIZE(result) */
6192       OP_SYMBOL (result) &&
6193       OP_SYMBOL (result)->regType == REG_CND)
6194     {
6195       symbol *tlbl;
6196       /* if they are both bit variables */
6197       if (AOP_TYPE (left) == AOP_CRY &&
6198           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6199         {
6200           if (AOP_TYPE (right) == AOP_LIT)
6201             {
6202               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6203               if (lit == 0L)
6204                 {
6205                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6206                   emitcode ("cpl", "c");
6207                 }
6208               else if (lit == 1L)
6209                 {
6210                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6211                 }
6212               else
6213                 {
6214                   emitcode ("clr", "c");
6215                 }
6216               /* AOP_TYPE(right) == AOP_CRY */
6217             }
6218           else
6219             {
6220               symbol *lbl = newiTempLabel (NULL);
6221               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6222               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6223               emitcode ("cpl", "c");
6224               emitcode ("", "!tlabeldef", (lbl->key + 100));
6225             }
6226           /* if true label then we jump if condition
6227              supplied is true */
6228           tlbl = newiTempLabel (NULL);
6229           if (IC_TRUE (ifx))
6230             {
6231               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6232               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6233             }
6234           else
6235             {
6236               emitcode ("jc", "!tlabel", tlbl->key + 100);
6237               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6238             }
6239           emitcode ("", "!tlabeldef", tlbl->key + 100);
6240         }
6241       else
6242         {
6243           tlbl = newiTempLabel (NULL);
6244           gencjneshort (left, right, tlbl);
6245           if (IC_TRUE (ifx))
6246             {
6247               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6248               emitcode ("", "!tlabeldef", tlbl->key + 100);
6249             }
6250           else
6251             {
6252               symbol *lbl = newiTempLabel (NULL);
6253               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6254               emitcode ("", "!tlabeldef", tlbl->key + 100);
6255               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6256               emitcode ("", "!tlabeldef", lbl->key + 100);
6257             }
6258         }
6259       /* mark the icode as generated */
6260       ifx->generated = 1;
6261
6262       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6263       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6264       return;
6265     }
6266
6267   /* if they are both bit variables */
6268   if (AOP_TYPE (left) == AOP_CRY &&
6269       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6270     {
6271       if (AOP_TYPE (right) == AOP_LIT)
6272         {
6273           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6274           if (lit == 0L)
6275             {
6276               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277               emitcode ("cpl", "c");
6278             }
6279           else if (lit == 1L)
6280             {
6281               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6282             }
6283           else
6284             {
6285               emitcode ("clr", "c");
6286             }
6287           /* AOP_TYPE(right) == AOP_CRY */
6288         }
6289       else
6290         {
6291           symbol *lbl = newiTempLabel (NULL);
6292           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6294           emitcode ("cpl", "c");
6295           emitcode ("", "!tlabeldef", (lbl->key + 100));
6296         }
6297
6298       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300
6301       aopOp (result, ic, TRUE, FALSE);
6302
6303       /* c = 1 if egal */
6304       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6305         {
6306           outBitC (result);
6307           goto release;
6308         }
6309       if (ifx)
6310         {
6311           genIfxJump (ifx, "c");
6312           goto release;
6313         }
6314       /* if the result is used in an arithmetic operation
6315          then put the result in place */
6316       outBitC (result);
6317     }
6318   else
6319     {
6320       gencjne (left, right, newiTempLabel (NULL));
6321
6322       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324
6325       aopOp (result, ic, TRUE, FALSE);
6326
6327       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6328         {
6329           aopPut (AOP (result), "a", 0);
6330           goto release;
6331         }
6332       if (ifx)
6333         {
6334           genIfxJump (ifx, "a");
6335           goto release;
6336         }
6337       /* if the result is used in an arithmetic operation
6338          then put the result in place */
6339       if (AOP_TYPE (result) != AOP_CRY)
6340         outAcc (result);
6341       /* leave the result in acc */
6342     }
6343
6344 release:
6345   freeAsmop (result, NULL, ic, TRUE);
6346 }
6347
6348 /*-----------------------------------------------------------------*/
6349 /* ifxForOp - returns the icode containing the ifx for operand     */
6350 /*-----------------------------------------------------------------*/
6351 static iCode *
6352 ifxForOp (operand * op, iCode * ic)
6353 {
6354   /* if true symbol then needs to be assigned */
6355   if (IS_TRUE_SYMOP (op))
6356     return NULL;
6357
6358   /* if this has register type condition and
6359      the next instruction is ifx with the same operand
6360      and live to of the operand is upto the ifx only then */
6361   if (ic->next &&
6362       ic->next->op == IFX &&
6363       IC_COND (ic->next)->key == op->key &&
6364       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6365     return ic->next;
6366
6367   return NULL;
6368 }
6369 /*-----------------------------------------------------------------*/
6370 /* hasInc - operand is incremented before any other use            */
6371 /*-----------------------------------------------------------------*/
6372 static iCode *
6373 hasInc (operand *op, iCode *ic, int osize)
6374 {
6375   sym_link *type = operandType(op);
6376   sym_link *retype = getSpec (type);
6377   iCode *lic = ic->next;
6378   int isize ;
6379   
6380   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6381   if (!IS_SYMOP(op)) return NULL;
6382
6383   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6384   if (IS_AGGREGATE(type->next)) return NULL;
6385   if (osize != (isize = getSize(type->next))) return NULL;
6386
6387   while (lic) {
6388       /* if operand of the form op = op + <sizeof *op> */
6389       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6390           isOperandEqual(IC_RESULT(lic),op) && 
6391           isOperandLiteral(IC_RIGHT(lic)) &&
6392           operandLitValue(IC_RIGHT(lic)) == isize) {
6393           return lic;
6394       }
6395       /* if the operand used or deffed */
6396       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6397           return NULL;
6398       }
6399       /* if GOTO or IFX */
6400       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6401       lic = lic->next;
6402   }
6403   return NULL;
6404 }
6405
6406 /*-----------------------------------------------------------------*/
6407 /* genAndOp - for && operation                                     */
6408 /*-----------------------------------------------------------------*/
6409 static void
6410 genAndOp (iCode * ic)
6411 {
6412   operand *left, *right, *result;
6413   symbol *tlbl;
6414
6415   D (emitcode (";", "genAndOp "););
6416
6417   /* note here that && operations that are in an
6418      if statement are taken away by backPatchLabels
6419      only those used in arthmetic operations remain */
6420   AOP_OP_2 (ic);
6421   AOP_SET_LOCALS (ic);
6422
6423   /* if both are bit variables */
6424   if (AOP_TYPE (left) == AOP_CRY &&
6425       AOP_TYPE (right) == AOP_CRY)
6426     {
6427       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6428       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6429       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6430       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431   
6432       aopOp (result,ic,FALSE, FALSE);
6433       outBitC (result);
6434     }
6435   else
6436     {
6437       tlbl = newiTempLabel (NULL);
6438       toBoolean (left);
6439       emitcode ("jz", "!tlabel", tlbl->key + 100);
6440       toBoolean (right);
6441       emitcode ("", "!tlabeldef", tlbl->key + 100);
6442       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444   
6445       aopOp (result,ic,FALSE, FALSE);
6446       outBitAcc (result);
6447     }
6448     freeAsmop (result, NULL, ic, TRUE);
6449 }
6450
6451
6452 /*-----------------------------------------------------------------*/
6453 /* genOrOp - for || operation                                      */
6454 /*-----------------------------------------------------------------*/
6455 static void
6456 genOrOp (iCode * ic)
6457 {
6458   operand *left, *right, *result;
6459   symbol *tlbl;
6460
6461   D (emitcode (";", "genOrOp "););
6462
6463   /* note here that || operations that are in an
6464      if statement are taken away by backPatchLabels
6465      only those used in arthmetic operations remain */
6466   AOP_OP_2 (ic);
6467   AOP_SET_LOCALS (ic);
6468
6469   /* if both are bit variables */
6470   if (AOP_TYPE (left) == AOP_CRY &&
6471       AOP_TYPE (right) == AOP_CRY)
6472     {
6473       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6474       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6475       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6476       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477   
6478       aopOp (result,ic,FALSE, FALSE);
6479       
6480       outBitC (result);
6481     }
6482   else
6483     {
6484       tlbl = newiTempLabel (NULL);
6485       toBoolean (left);
6486       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6487       toBoolean (right);
6488       emitcode ("", "!tlabeldef", tlbl->key + 100);
6489       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491   
6492       aopOp (result,ic,FALSE, FALSE);
6493       
6494       outBitAcc (result);
6495     }
6496
6497   freeAsmop (result, NULL, ic, TRUE);
6498 }
6499
6500 /*-----------------------------------------------------------------*/
6501 /* isLiteralBit - test if lit == 2^n                               */
6502 /*-----------------------------------------------------------------*/
6503 static int
6504 isLiteralBit (unsigned long lit)
6505 {
6506   unsigned long pw[32] =
6507   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6508    0x100L, 0x200L, 0x400L, 0x800L,
6509    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6510    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6511    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6512    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6513    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6514   int idx;
6515
6516   for (idx = 0; idx < 32; idx++)
6517     if (lit == pw[idx])
6518       return idx + 1;
6519   return 0;
6520 }
6521
6522 /*-----------------------------------------------------------------*/
6523 /* continueIfTrue -                                                */
6524 /*-----------------------------------------------------------------*/
6525 static void
6526 continueIfTrue (iCode * ic)
6527 {
6528   if (IC_TRUE (ic))
6529     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6530   ic->generated = 1;
6531 }
6532
6533 /*-----------------------------------------------------------------*/
6534 /* jmpIfTrue -                                                     */
6535 /*-----------------------------------------------------------------*/
6536 static void
6537 jumpIfTrue (iCode * ic)
6538 {
6539   if (!IC_TRUE (ic))
6540     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6541   ic->generated = 1;
6542 }
6543
6544 /*-----------------------------------------------------------------*/
6545 /* jmpTrueOrFalse -                                                */
6546 /*-----------------------------------------------------------------*/
6547 static void
6548 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6549 {
6550   // ugly but optimized by peephole
6551   if (IC_TRUE (ic))
6552     {
6553       symbol *nlbl = newiTempLabel (NULL);
6554       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6555       emitcode ("", "!tlabeldef", tlbl->key + 100);
6556       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6557       emitcode ("", "!tlabeldef", nlbl->key + 100);
6558     }
6559   else
6560     {
6561       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6562       emitcode ("", "!tlabeldef", tlbl->key + 100);
6563     }
6564   ic->generated = 1;
6565 }
6566
6567 // Generate code to perform a bit-wise logic operation
6568 // on two operands in far space (assumed to already have been 
6569 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6570 // in far space. This requires pushing the result on the stack
6571 // then popping it into the result.
6572 static void
6573 genFarFarLogicOp(iCode *ic, char *logicOp)
6574 {
6575       int size, resultSize, compSize;
6576       int offset = 0;
6577       
6578       TR_AP("#5");
6579       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6580       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6581                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6582       
6583       _startLazyDPSEvaluation();
6584       for (size = compSize; (size--); offset++)
6585       {
6586           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6587           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6588           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6589           
6590           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6591           emitcode ("push", "acc");
6592       }
6593       _endLazyDPSEvaluation();
6594      
6595       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6596       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6597       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6598      
6599       resultSize = AOP_SIZE(IC_RESULT(ic));
6600
6601       ADJUST_PUSHED_RESULT(compSize, resultSize);
6602
6603       _startLazyDPSEvaluation();
6604       while (compSize--)
6605       {
6606           emitcode ("pop", "acc");
6607           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6608       }
6609       _endLazyDPSEvaluation();
6610       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6611 }
6612
6613
6614 /*-----------------------------------------------------------------*/
6615 /* genAnd  - code for and                                          */
6616 /*-----------------------------------------------------------------*/
6617 static void
6618 genAnd (iCode * ic, iCode * ifx)
6619 {
6620   operand *left, *right, *result;
6621   int size, offset = 0;
6622   unsigned long lit = 0L;
6623   int bytelit;
6624   char buff[10];
6625   bool pushResult;
6626
6627   D (emitcode (";", "genAnd "););
6628
6629   AOP_OP_3_NOFATAL (ic, pushResult);
6630   AOP_SET_LOCALS (ic);
6631
6632   if (pushResult)
6633   {
6634       genFarFarLogicOp(ic, "anl");
6635       return;
6636   }  
6637
6638 #ifdef DEBUG_TYPE
6639   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6640             AOP_TYPE (result),
6641             AOP_TYPE (left), AOP_TYPE (right));
6642   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6643             AOP_SIZE (result),
6644             AOP_SIZE (left), AOP_SIZE (right));
6645 #endif
6646
6647   /* if left is a literal & right is not then exchange them */
6648   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6649 #ifdef LOGIC_OPS_BROKEN      
6650     ||  AOP_NEEDSACC (left)
6651 #endif
6652     )
6653     {
6654       operand *tmp = right;
6655       right = left;
6656       left = tmp;
6657     }
6658
6659   /* if result = right then exchange them */
6660   if (sameRegs (AOP (result), AOP (right)))
6661     {
6662       operand *tmp = right;
6663       right = left;
6664       left = tmp;
6665     }
6666
6667   /* if right is bit then exchange them */
6668   if (AOP_TYPE (right) == AOP_CRY &&
6669       AOP_TYPE (left) != AOP_CRY)
6670     {
6671       operand *tmp = right;
6672       right = left;
6673       left = tmp;
6674     }
6675   if (AOP_TYPE (right) == AOP_LIT)
6676     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6677
6678   size = AOP_SIZE (result);
6679
6680   // if(bit & yy)
6681   // result = bit & yy;
6682   if (AOP_TYPE (left) == AOP_CRY)
6683     {
6684       // c = bit & literal;
6685       if (AOP_TYPE (right) == AOP_LIT)
6686         {
6687           if (lit & 1)
6688             {
6689               if (size && sameRegs (AOP (result), AOP (left)))
6690                 // no change
6691                 goto release;
6692               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6693             }
6694           else
6695             {
6696               // bit(result) = 0;
6697               if (size && (AOP_TYPE (result) == AOP_CRY))
6698                 {
6699                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6700                   goto release;
6701                 }
6702               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6703                 {
6704                   jumpIfTrue (ifx);
6705                   goto release;
6706                 }
6707               emitcode ("clr", "c");
6708             }
6709         }
6710       else
6711         {
6712           if (AOP_TYPE (right) == AOP_CRY)
6713             {
6714               // c = bit & bit;
6715               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6716               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6717             }
6718           else
6719             {
6720               // c = bit & val;
6721               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6722               // c = lsb
6723               emitcode ("rrc", "a");
6724               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6725             }
6726         }
6727       // bit = c
6728       // val = c
6729       if (size)
6730         outBitC (result);
6731       // if(bit & ...)
6732       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6733         genIfxJump (ifx, "c");
6734       goto release;
6735     }
6736
6737   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6738   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6739   if ((AOP_TYPE (right) == AOP_LIT) &&
6740       (AOP_TYPE (result) == AOP_CRY) &&
6741       (AOP_TYPE (left) != AOP_CRY))
6742     {
6743       int posbit = isLiteralBit (lit);
6744       /* left &  2^n */
6745       if (posbit)
6746         {
6747           posbit--;
6748           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6749           // bit = left & 2^n
6750           if (size)
6751             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6752           // if(left &  2^n)
6753           else
6754             {
6755               if (ifx)
6756                 {
6757                   SNPRINTF (buff, sizeof(buff), 
6758                             "acc.%d", posbit & 0x07);
6759                   genIfxJump (ifx, buff);
6760                 }
6761               else 
6762                   {
6763                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6764                   }
6765               goto release;
6766             }
6767         }
6768       else
6769         {
6770           symbol *tlbl = newiTempLabel (NULL);
6771           int sizel = AOP_SIZE (left);
6772           if (size)
6773             emitcode ("setb", "c");
6774           while (sizel--)
6775             {
6776               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6777                 {
6778                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6779                   // byte ==  2^n ?
6780                   if ((posbit = isLiteralBit (bytelit)) != 0)
6781                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6782                   else
6783                     {
6784                       if (bytelit != 0x0FFL)
6785                         emitcode ("anl", "a,%s",
6786                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6787                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6788                     }
6789                 }
6790               offset++;
6791             }
6792           // bit = left & literal
6793           if (size)
6794             {
6795               emitcode ("clr", "c");
6796               emitcode ("", "!tlabeldef", tlbl->key + 100);
6797             }
6798           // if(left & literal)
6799           else
6800             {
6801               if (ifx)
6802                 jmpTrueOrFalse (ifx, tlbl);
6803               else
6804                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6805               goto release;
6806             }
6807         }
6808       outBitC (result);
6809       goto release;
6810     }
6811
6812   /* if left is same as result */
6813   if (sameRegs (AOP (result), AOP (left)))
6814     {
6815       for (; size--; offset++)
6816         {
6817           if (AOP_TYPE (right) == AOP_LIT)
6818             {
6819               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6820                 continue;
6821               else if (bytelit == 0)
6822                 aopPut (AOP (result), zero, offset);
6823               else if (IS_AOP_PREG (result))
6824                 {
6825                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6826                   emitcode ("anl", "a,%s",
6827                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6828                   aopPut (AOP (result), "a", offset);
6829                 }
6830               else
6831                 emitcode ("anl", "%s,%s",
6832                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6833                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6834             }
6835           else
6836             {
6837               if (AOP_TYPE (left) == AOP_ACC)
6838                 emitcode ("anl", "a,%s",
6839                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6840               else
6841                 {
6842                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6843                   if (IS_AOP_PREG (result))
6844                     {
6845                       emitcode ("anl", "a,%s",
6846                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6847                       aopPut (AOP (result), "a", offset);
6848                     }
6849                   else
6850                     emitcode ("anl", "%s,a",
6851                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6852                 }
6853             }
6854         }
6855     }
6856   else
6857     {
6858       // left & result in different registers
6859       if (AOP_TYPE (result) == AOP_CRY)
6860         {
6861           // result = bit
6862           // if(size), result in bit
6863           // if(!size && ifx), conditional oper: if(left & right)
6864           symbol *tlbl = newiTempLabel (NULL);
6865           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6866           if (size)
6867             emitcode ("setb", "c");
6868           while (sizer--)
6869             {
6870               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6871                 emitcode ("anl", "a,%s",
6872                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6873               } else {
6874                 if (AOP_TYPE(left)==AOP_ACC) {
6875                   emitcode("mov", "b,a");
6876                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6877                   emitcode("anl", "a,b");
6878                 }else {
6879                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6880                   emitcode ("anl", "a,%s",
6881                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6882                 }
6883               }
6884               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6885               offset++;
6886             }
6887           if (size)
6888             {
6889               CLRC;
6890               emitcode ("", "!tlabeldef", tlbl->key + 100);
6891               outBitC (result);
6892             }
6893           else if (ifx)
6894             jmpTrueOrFalse (ifx, tlbl);
6895           else
6896             emitcode ("", "!tlabeldef", tlbl->key + 100);
6897         }
6898       else
6899         {
6900           for (; (size--); offset++)
6901             {
6902               // normal case
6903               // result = left & right
6904               if (AOP_TYPE (right) == AOP_LIT)
6905                 {
6906                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6907                     {
6908                       aopPut (AOP (result),
6909                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6910                               offset);
6911                       continue;
6912                     }
6913                   else if (bytelit == 0)
6914                     {
6915                       aopPut (AOP (result), zero, offset);
6916                       continue;
6917                     }
6918                   D (emitcode (";", "better literal AND."););
6919                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6920                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6921                                                     FALSE, FALSE, DP2_RESULT_REG));
6922
6923                 }
6924               else
6925                 {
6926                   // faster than result <- left, anl result,right
6927                   // and better if result is SFR
6928                   if (AOP_TYPE (left) == AOP_ACC)
6929                     {
6930                       emitcode ("anl", "a,%s", 
6931                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6932                     }
6933                   else
6934                     {
6935                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6936                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6937                       {
6938                           emitcode("mov", "b,a");
6939                           rOp = "b";
6940                       }
6941                         
6942                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6943                       emitcode ("anl", "a,%s", rOp);
6944                     }                   
6945                 }
6946               aopPut (AOP (result), "a", offset);
6947             }
6948         }
6949     }
6950
6951 release:
6952   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6953   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954   freeAsmop (result, NULL, ic, TRUE);
6955 }
6956
6957
6958 /*-----------------------------------------------------------------*/
6959 /* genOr  - code for or                                            */
6960 /*-----------------------------------------------------------------*/
6961 static void
6962 genOr (iCode * ic, iCode * ifx)
6963 {
6964   operand *left, *right, *result;
6965   int size, offset = 0;
6966   unsigned long lit = 0L;
6967   bool     pushResult;
6968
6969   D (emitcode (";", "genOr "););
6970
6971   AOP_OP_3_NOFATAL (ic, pushResult);
6972   AOP_SET_LOCALS (ic);
6973
6974   if (pushResult)
6975   {
6976       genFarFarLogicOp(ic, "orl");
6977       return;
6978   }
6979
6980
6981 #ifdef DEBUG_TYPE
6982   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6983             AOP_TYPE (result),
6984             AOP_TYPE (left), AOP_TYPE (right));
6985   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6986             AOP_SIZE (result),
6987             AOP_SIZE (left), AOP_SIZE (right));
6988 #endif
6989
6990   /* if left is a literal & right is not then exchange them */
6991   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6992 #ifdef LOGIC_OPS_BROKEN
6993    || AOP_NEEDSACC (left) // I think this is a net loss now.
6994 #endif      
6995       )
6996     {
6997       operand *tmp = right;
6998       right = left;
6999       left = tmp;
7000     }
7001
7002   /* if result = right then exchange them */
7003   if (sameRegs (AOP (result), AOP (right)))
7004     {
7005       operand *tmp = right;
7006       right = left;
7007       left = tmp;
7008     }
7009
7010   /* if right is bit then exchange them */
7011   if (AOP_TYPE (right) == AOP_CRY &&
7012       AOP_TYPE (left) != AOP_CRY)
7013     {
7014       operand *tmp = right;
7015       right = left;
7016       left = tmp;
7017     }
7018   if (AOP_TYPE (right) == AOP_LIT)
7019     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7020
7021   size = AOP_SIZE (result);
7022
7023   // if(bit | yy)
7024   // xx = bit | yy;
7025   if (AOP_TYPE (left) == AOP_CRY)
7026     {
7027       if (AOP_TYPE (right) == AOP_LIT)
7028         {
7029           // c = bit & literal;
7030           if (lit)
7031             {
7032               // lit != 0 => result = 1
7033               if (AOP_TYPE (result) == AOP_CRY)
7034                 {
7035                   if (size)
7036                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7037                   else if (ifx)
7038                     continueIfTrue (ifx);
7039                   goto release;
7040                 }
7041               emitcode ("setb", "c");
7042             }
7043           else
7044             {
7045               // lit == 0 => result = left
7046               if (size && sameRegs (AOP (result), AOP (left)))
7047                 goto release;
7048               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7049             }
7050         }
7051       else
7052         {
7053           if (AOP_TYPE (right) == AOP_CRY)
7054             {
7055               // c = bit | bit;
7056               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7057               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7058             }
7059           else
7060             {
7061               // c = bit | val;
7062               symbol *tlbl = newiTempLabel (NULL);
7063               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7064                 emitcode ("setb", "c");
7065               emitcode ("jb", "%s,!tlabel",
7066                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7067               toBoolean (right);
7068               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7069               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7070                 {
7071                   jmpTrueOrFalse (ifx, tlbl);
7072                   goto release;
7073                 }
7074               else
7075                 {
7076                   CLRC;
7077                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7078                 }
7079             }
7080         }
7081       // bit = c
7082       // val = c
7083       if (size)
7084         outBitC (result);
7085       // if(bit | ...)
7086       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7087            genIfxJump (ifx, "c");
7088       goto release;
7089     }
7090
7091   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7092   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7093   if ((AOP_TYPE (right) == AOP_LIT) &&
7094       (AOP_TYPE (result) == AOP_CRY) &&
7095       (AOP_TYPE (left) != AOP_CRY))
7096     {
7097       if (lit)
7098         {
7099           // result = 1
7100           if (size)
7101             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7102           else
7103             continueIfTrue (ifx);
7104           goto release;
7105         }
7106       else
7107         {
7108           // lit = 0, result = boolean(left)
7109           if (size)
7110             emitcode ("setb", "c");
7111           toBoolean (right);
7112           if (size)
7113             {
7114               symbol *tlbl = newiTempLabel (NULL);
7115               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7116               CLRC;
7117               emitcode ("", "!tlabeldef", tlbl->key + 100);
7118             }
7119           else
7120             {
7121               genIfxJump (ifx, "a");
7122               goto release;
7123             }
7124         }
7125       outBitC (result);
7126       goto release;
7127     }
7128
7129   /* if left is same as result */
7130   if (sameRegs (AOP (result), AOP (left)))
7131     {
7132       for (; size--; offset++)
7133         {
7134           if (AOP_TYPE (right) == AOP_LIT)
7135             {
7136               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7137                 {
7138                   continue;
7139                 }
7140               else
7141                 {
7142                   if (IS_AOP_PREG (left))
7143                     {
7144                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7145                       emitcode ("orl", "a,%s",
7146                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7147                       aopPut (AOP (result), "a", offset);
7148                     }
7149                   else
7150                     {
7151                       emitcode ("orl", "%s,%s",
7152                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7153                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7154                     }
7155                 }
7156             }
7157           else
7158             {
7159               if (AOP_TYPE (left) == AOP_ACC)
7160                 {
7161                   emitcode ("orl", "a,%s",
7162                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7163                 }
7164               else
7165                 {
7166                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7167                   if (IS_AOP_PREG (left))
7168                     {
7169                       emitcode ("orl", "a,%s", 
7170                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7171                       aopPut (AOP (result), "a", offset);
7172                     }
7173                   else
7174                     {
7175                       emitcode ("orl", "%s,a",
7176                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7177                     }
7178                 }
7179             }
7180         }
7181     }
7182   else
7183     {
7184       // left & result in different registers
7185       if (AOP_TYPE (result) == AOP_CRY)
7186         {
7187           // result = bit
7188           // if(size), result in bit
7189           // if(!size && ifx), conditional oper: if(left | right)
7190           symbol *tlbl = newiTempLabel (NULL);
7191           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7192           if (size)
7193             emitcode ("setb", "c");
7194           while (sizer--)
7195             {
7196               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7197                 emitcode ("orl", "a,%s",
7198                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7199               } else {
7200                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7201                 emitcode ("orl", "a,%s",
7202                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7203               }
7204               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7205               offset++;
7206             }
7207           if (size)
7208             {
7209               CLRC;
7210               emitcode ("", "!tlabeldef", tlbl->key + 100);
7211               outBitC (result);
7212             }
7213           else if (ifx)
7214             jmpTrueOrFalse (ifx, tlbl);
7215           else
7216             emitcode ("", "!tlabeldef", tlbl->key + 100);
7217         }
7218       else
7219         {
7220             _startLazyDPSEvaluation();
7221           for (; (size--); offset++)
7222             {
7223               // normal case
7224               // result = left & right
7225               if (AOP_TYPE (right) == AOP_LIT)
7226                 {
7227                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7228                     {
7229                       aopPut (AOP (result),
7230                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7231                               offset);
7232                       continue;
7233                     }
7234                   D (emitcode (";", "better literal OR."););
7235                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7236                   emitcode ("orl", "a, %s",
7237                             aopGet (AOP (right), offset,
7238                                     FALSE, FALSE, DP2_RESULT_REG));
7239
7240                 }
7241               else
7242                 {
7243                   // faster than result <- left, anl result,right
7244                   // and better if result is SFR
7245                   if (AOP_TYPE (left) == AOP_ACC)
7246                     {
7247                       emitcode ("orl", "a,%s",
7248                                 aopGet (AOP (right), offset,
7249                                         FALSE, FALSE, DP2_RESULT_REG));
7250                     }
7251                   else
7252                     {
7253                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7254                         
7255                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7256                       {
7257                           emitcode("mov", "b,a");
7258                           rOp = "b";
7259                       }
7260                         
7261                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7262                       emitcode ("orl", "a,%s", rOp);
7263                     }
7264                 }
7265               aopPut (AOP (result), "a", offset);
7266             }
7267             _endLazyDPSEvaluation();
7268         }
7269     }
7270
7271 release:
7272   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7273   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7274   freeAsmop (result, NULL, ic, TRUE);
7275 }
7276
7277 /*-----------------------------------------------------------------*/
7278 /* genXor - code for xclusive or                                   */
7279 /*-----------------------------------------------------------------*/
7280 static void
7281 genXor (iCode * ic, iCode * ifx)
7282 {
7283   operand *left, *right, *result;
7284   int size, offset = 0;
7285   unsigned long lit = 0L;
7286   bool pushResult;
7287
7288   D (emitcode (";", "genXor "););
7289
7290   AOP_OP_3_NOFATAL (ic, pushResult);
7291   AOP_SET_LOCALS (ic);
7292
7293   if (pushResult)
7294   {
7295       genFarFarLogicOp(ic, "xrl");
7296       return;
7297   }  
7298
7299 #ifdef DEBUG_TYPE
7300   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7301             AOP_TYPE (result),
7302             AOP_TYPE (left), AOP_TYPE (right));
7303   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7304             AOP_SIZE (result),
7305             AOP_SIZE (left), AOP_SIZE (right));
7306 #endif
7307
7308   /* if left is a literal & right is not ||
7309      if left needs acc & right does not */
7310   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
7311 #ifdef LOGIC_OPS_BROKEN      
7312       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7313 #endif
7314      )
7315     {
7316       operand *tmp = right;
7317       right = left;
7318       left = tmp;
7319     }
7320
7321   /* if result = right then exchange them */
7322   if (sameRegs (AOP (result), AOP (right)))
7323     {
7324       operand *tmp = right;
7325       right = left;
7326       left = tmp;
7327     }
7328
7329   /* if right is bit then exchange them */
7330   if (AOP_TYPE (right) == AOP_CRY &&
7331       AOP_TYPE (left) != AOP_CRY)
7332     {
7333       operand *tmp = right;
7334       right = left;
7335       left = tmp;
7336     }
7337   if (AOP_TYPE (right) == AOP_LIT)
7338     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7339
7340   size = AOP_SIZE (result);
7341
7342   // if(bit ^ yy)
7343   // xx = bit ^ yy;
7344   if (AOP_TYPE (left) == AOP_CRY)
7345     {
7346       if (AOP_TYPE (right) == AOP_LIT)
7347         {
7348           // c = bit & literal;
7349           if (lit >> 1)
7350             {
7351               // lit>>1  != 0 => result = 1
7352               if (AOP_TYPE (result) == AOP_CRY)
7353                 {
7354                   if (size)
7355                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7356                   else if (ifx)
7357                     continueIfTrue (ifx);
7358                   goto release;
7359                 }
7360               emitcode ("setb", "c");
7361             }
7362           else
7363             {
7364               // lit == (0 or 1)
7365               if (lit == 0)
7366                 {
7367                   // lit == 0, result = left
7368                   if (size && sameRegs (AOP (result), AOP (left)))
7369                     goto release;
7370                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7371                 }
7372               else
7373                 {
7374                   // lit == 1, result = not(left)
7375                   if (size && sameRegs (AOP (result), AOP (left)))
7376                     {
7377                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7378                       goto release;
7379                     }
7380                   else
7381                     {
7382                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7383                       emitcode ("cpl", "c");
7384                     }
7385                 }
7386             }
7387
7388         }
7389       else
7390         {
7391           // right != literal
7392           symbol *tlbl = newiTempLabel (NULL);
7393           if (AOP_TYPE (right) == AOP_CRY)
7394             {
7395               // c = bit ^ bit;
7396               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7397             }
7398           else
7399             {
7400               int sizer = AOP_SIZE (right);
7401               // c = bit ^ val
7402               // if val>>1 != 0, result = 1
7403               emitcode ("setb", "c");
7404               while (sizer)
7405                 {
7406                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7407                   if (sizer == 1)
7408                     // test the msb of the lsb
7409                     emitcode ("anl", "a,#!constbyte",0xfe);
7410                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7411                   sizer--;
7412                 }
7413               // val = (0,1)
7414               emitcode ("rrc", "a");
7415             }
7416           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7417           emitcode ("cpl", "c");
7418           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7419         }
7420       // bit = c
7421       // val = c
7422       if (size)
7423         outBitC (result);
7424       // if(bit | ...)
7425       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7426         genIfxJump (ifx, "c");
7427       goto release;
7428     }
7429
7430   if (sameRegs (AOP (result), AOP (left)))
7431     {
7432       /* if left is same as result */
7433       for (; size--; offset++)
7434         {
7435           if (AOP_TYPE (right) == AOP_LIT)
7436             {
7437               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7438                 continue;
7439               else if (IS_AOP_PREG (left))
7440                 {
7441                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7442                   emitcode ("xrl", "a,%s",
7443                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7444                   aopPut (AOP (result), "a", offset);
7445                 }
7446               else
7447                 emitcode ("xrl", "%s,%s",
7448                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7449                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7450             }
7451           else
7452             {
7453               if (AOP_TYPE (left) == AOP_ACC)
7454                 emitcode ("xrl", "a,%s",
7455                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7456               else
7457                 {
7458                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7459                   if (IS_AOP_PREG (left))
7460                     {
7461                       emitcode ("xrl", "a,%s",
7462                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7463                       aopPut (AOP (result), "a", offset);
7464                     }
7465                   else
7466                     emitcode ("xrl", "%s,a",
7467                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7468                 }
7469             }
7470         }
7471     }
7472   else
7473     {
7474       // left & result in different registers
7475       if (AOP_TYPE (result) == AOP_CRY)
7476         {
7477           // result = bit
7478           // if(size), result in bit
7479           // if(!size && ifx), conditional oper: if(left ^ right)
7480           symbol *tlbl = newiTempLabel (NULL);
7481           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7482                   
7483           if (size)
7484             emitcode ("setb", "c");
7485           while (sizer--)
7486             {
7487               if ((AOP_TYPE (right) == AOP_LIT) &&
7488                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7489                 {
7490                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7491                 }
7492               else
7493                 {
7494                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7495                     emitcode ("xrl", "a,%s",
7496                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7497                   } else {
7498                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7499                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7500                       {
7501                           emitcode("mov", "b,a");
7502                           rOp = "b";
7503                       }
7504                         
7505                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7506                       emitcode ("xrl", "a,%s", rOp);                  
7507                   }
7508                 }
7509               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7510               offset++;
7511             }
7512           if (size)
7513             {
7514               CLRC;
7515               emitcode ("", "!tlabeldef", tlbl->key + 100);
7516               outBitC (result);
7517             }
7518           else if (ifx)
7519             jmpTrueOrFalse (ifx, tlbl);
7520         }
7521       else
7522         {
7523         for (; (size--); offset++)
7524           {
7525             // normal case
7526             // result = left & right
7527             if (AOP_TYPE (right) == AOP_LIT)
7528               {
7529                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7530                   {
7531                     aopPut (AOP (result),
7532                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7533                             offset);
7534                     continue;
7535                   }
7536                 D (emitcode (";", "better literal XOR."););
7537                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7538                 emitcode ("xrl", "a, %s",
7539                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7540               }
7541             else
7542               {
7543                 // faster than result <- left, anl result,right
7544                 // and better if result is SFR
7545                 if (AOP_TYPE (left) == AOP_ACC)
7546                   {
7547                     emitcode ("xrl", "a,%s",
7548                               aopGet (AOP (right), offset,
7549                                       FALSE, FALSE, DP2_RESULT_REG));
7550                   }
7551                 else
7552                   {
7553                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7554                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7555                       {
7556                           emitcode("mov", "b,a");
7557                           rOp = "b";
7558                       }
7559                         
7560                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7561                       emitcode ("xrl", "a,%s", rOp);
7562                   }
7563               }
7564             aopPut (AOP (result), "a", offset);
7565           }
7566         }
7567         
7568     }
7569
7570 release:
7571   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7572   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7573   freeAsmop (result, NULL, ic, TRUE);
7574 }
7575
7576 /*-----------------------------------------------------------------*/
7577 /* genInline - write the inline code out                           */
7578 /*-----------------------------------------------------------------*/
7579 static void
7580 genInline (iCode * ic)
7581 {
7582   char *buffer, *bp, *bp1;
7583
7584   D (emitcode (";", "genInline "); );
7585
7586   _G.inLine += (!options.asmpeep);
7587
7588   buffer = Safe_strdup(IC_INLINE(ic));
7589   bp = buffer;
7590   bp1 = buffer;
7591
7592   /* emit each line as a code */
7593   while (*bp)
7594     {
7595       if (*bp == '\n')
7596         {
7597           *bp++ = '\0';
7598           emitcode (bp1, "");
7599           bp1 = bp;
7600         }
7601       else
7602         {
7603           if (*bp == ':')
7604             {
7605               bp++;
7606               *bp = '\0';
7607               bp++;
7608               emitcode (bp1, "");
7609               bp1 = bp;
7610             }
7611           else
7612             bp++;
7613         }
7614     }
7615   if (bp1 != bp)
7616     emitcode (bp1, "");
7617   /*     emitcode("",buffer); */
7618   _G.inLine -= (!options.asmpeep);
7619 }
7620
7621 /*-----------------------------------------------------------------*/
7622 /* genRRC - rotate right with carry                                */
7623 /*-----------------------------------------------------------------*/
7624 static void
7625 genRRC (iCode * ic)
7626 {
7627   operand *left, *result;
7628   int     size, offset;
7629
7630   D (emitcode (";", "genRRC "););
7631
7632   /* rotate right with carry */
7633   left = IC_LEFT (ic);
7634   result = IC_RESULT (ic);
7635   aopOp (left, ic, FALSE, FALSE);
7636   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7637
7638   /* move it to the result */
7639   size = AOP_SIZE (result);
7640   offset = size - 1;
7641   CLRC;
7642
7643   _startLazyDPSEvaluation ();
7644   while (size--)
7645     {
7646       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7647       emitcode ("rrc", "a");
7648       if (AOP_SIZE (result) > 1)
7649         aopPut (AOP (result), "a", offset--);
7650     }
7651   _endLazyDPSEvaluation ();
7652
7653   /* now we need to put the carry into the
7654      highest order byte of the result */
7655   if (AOP_SIZE (result) > 1)
7656     {
7657       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7658     }
7659   emitcode ("mov", "acc.7,c");
7660   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7661   freeAsmop (left, NULL, ic, TRUE);
7662   freeAsmop (result, NULL, ic, TRUE);
7663 }
7664
7665 /*-----------------------------------------------------------------*/
7666 /* genRLC - generate code for rotate left with carry               */
7667 /*-----------------------------------------------------------------*/
7668 static void
7669 genRLC (iCode * ic)
7670 {
7671   operand *left, *result;
7672   int size, offset;
7673   char *l;
7674
7675   D (emitcode (";", "genRLC "););
7676
7677   /* rotate right with carry */
7678   left = IC_LEFT (ic);
7679   result = IC_RESULT (ic);
7680   aopOp (left, ic, FALSE, FALSE);
7681   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7682
7683   /* move it to the result */
7684   size = AOP_SIZE (result);
7685   offset = 0;
7686   if (size--)
7687     {
7688       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7689       MOVA (l);
7690       emitcode ("add", "a,acc");
7691       if (AOP_SIZE (result) > 1)
7692         {
7693           aopPut (AOP (result), "a", offset++);
7694         }
7695
7696       _startLazyDPSEvaluation ();
7697       while (size--)
7698         {
7699           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7700           MOVA (l);
7701           emitcode ("rlc", "a");
7702           if (AOP_SIZE (result) > 1)
7703             aopPut (AOP (result), "a", offset++);
7704         }
7705       _endLazyDPSEvaluation ();
7706     }
7707   /* now we need to put the carry into the
7708      highest order byte of the result */
7709   if (AOP_SIZE (result) > 1)
7710     {
7711       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7712       MOVA (l);
7713     }
7714   emitcode ("mov", "acc.0,c");
7715   aopPut (AOP (result), "a", 0);
7716   freeAsmop (left, NULL, ic, TRUE);
7717   freeAsmop (result, NULL, ic, TRUE);
7718 }
7719
7720 /*-----------------------------------------------------------------*/
7721 /* genGetHbit - generates code get highest order bit               */
7722 /*-----------------------------------------------------------------*/
7723 static void
7724 genGetHbit (iCode * ic)
7725 {
7726   operand *left, *result;
7727   left = IC_LEFT (ic);
7728   result = IC_RESULT (ic);
7729   aopOp (left, ic, FALSE, FALSE);
7730   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7731
7732   D (emitcode (";", "genGetHbit "););
7733
7734   /* get the highest order byte into a */
7735   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7736   if (AOP_TYPE (result) == AOP_CRY)
7737     {
7738       emitcode ("rlc", "a");
7739       outBitC (result);
7740     }
7741   else
7742     {
7743       emitcode ("rl", "a");
7744       emitcode ("anl", "a,#1");
7745       outAcc (result);
7746     }
7747
7748
7749   freeAsmop (left, NULL, ic, TRUE);
7750   freeAsmop (result, NULL, ic, TRUE);
7751 }
7752
7753 /*-----------------------------------------------------------------*/
7754 /* genSwap - generates code to swap nibbles or bytes               */
7755 /*-----------------------------------------------------------------*/
7756 static void
7757 genSwap (iCode * ic)
7758 {
7759   operand *left, *result;
7760
7761   D(emitcode (";     genSwap",""));
7762
7763   left = IC_LEFT (ic);
7764   result = IC_RESULT (ic);
7765   aopOp (left, ic, FALSE, FALSE);
7766   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7767   
7768   _startLazyDPSEvaluation ();
7769   switch (AOP_SIZE (left))
7770     {
7771     case 1: /* swap nibbles in byte */
7772       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7773       emitcode ("swap", "a");
7774       aopPut (AOP (result), "a", 0);
7775       break;
7776     case 2: /* swap bytes in word */
7777       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7778         {
7779           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7780           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7781           aopPut (AOP (result), "a", 1);
7782         }
7783       else if (operandsEqu (left, result))
7784         {
7785           char * reg = "a";
7786           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7787           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7788             {
7789               emitcode ("mov", "b,a");
7790               reg = "b";
7791               _G.bInUse=1;
7792             }
7793           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7794           aopPut (AOP (result), reg, 1);
7795           _G.bInUse=0;
7796         }
7797       else
7798         {
7799           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7800           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7801         }
7802       break;
7803     default:
7804       wassertl(FALSE, "unsupported SWAP operand size");
7805     }
7806   _endLazyDPSEvaluation ();
7807   
7808   freeAsmop (left, NULL, ic, TRUE);
7809   freeAsmop (result, NULL, ic, TRUE);
7810 }
7811
7812 /*-----------------------------------------------------------------*/
7813 /* AccRol - rotate left accumulator by known count                 */
7814 /*-----------------------------------------------------------------*/
7815 static void
7816 AccRol (int shCount)
7817 {
7818   shCount &= 0x0007;            // shCount : 0..7
7819
7820   switch (shCount)
7821     {
7822     case 0:
7823       break;
7824     case 1:
7825       emitcode ("rl", "a");
7826       break;
7827     case 2:
7828       emitcode ("rl", "a");
7829       emitcode ("rl", "a");
7830       break;
7831     case 3:
7832       emitcode ("swap", "a");
7833       emitcode ("rr", "a");
7834       break;
7835     case 4:
7836       emitcode ("swap", "a");
7837       break;
7838     case 5:
7839       emitcode ("swap", "a");
7840       emitcode ("rl", "a");
7841       break;
7842     case 6:
7843       emitcode ("rr", "a");
7844       emitcode ("rr", "a");
7845       break;
7846     case 7:
7847       emitcode ("rr", "a");
7848       break;
7849     }
7850 }
7851
7852 /*-----------------------------------------------------------------*/
7853 /* AccLsh - left shift accumulator by known count                  */
7854 /*-----------------------------------------------------------------*/
7855 static void
7856 AccLsh (int shCount)
7857 {
7858   if (shCount != 0)
7859     {
7860       if (shCount == 1)
7861         emitcode ("add", "a,acc");
7862       else if (shCount == 2)
7863         {
7864           emitcode ("add", "a,acc");
7865           emitcode ("add", "a,acc");
7866         }
7867       else
7868         {
7869           /* rotate left accumulator */
7870           AccRol (shCount);
7871           /* and kill the lower order bits */
7872           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7873         }
7874     }
7875 }
7876
7877 /*-----------------------------------------------------------------*/
7878 /* AccRsh - right shift accumulator by known count                 */
7879 /*-----------------------------------------------------------------*/
7880 static void
7881 AccRsh (int shCount)
7882 {
7883   if (shCount != 0)
7884     {
7885       if (shCount == 1)
7886         {
7887           CLRC;
7888           emitcode ("rrc", "a");
7889         }
7890       else
7891         {
7892           /* rotate right accumulator */
7893           AccRol (8 - shCount);
7894           /* and kill the higher order bits */
7895           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7896         }
7897     }
7898 }
7899
7900 #ifdef BETTER_LITERAL_SHIFT
7901 /*-----------------------------------------------------------------*/
7902 /* AccSRsh - signed right shift accumulator by known count                 */
7903 /*-----------------------------------------------------------------*/
7904 static void
7905 AccSRsh (int shCount)
7906 {
7907   symbol *tlbl;
7908   if (shCount != 0)
7909     {
7910       if (shCount == 1)
7911         {
7912           emitcode ("mov", "c,acc.7");
7913           emitcode ("rrc", "a");
7914         }
7915       else if (shCount == 2)
7916         {
7917           emitcode ("mov", "c,acc.7");
7918           emitcode ("rrc", "a");
7919           emitcode ("mov", "c,acc.7");
7920           emitcode ("rrc", "a");
7921         }
7922       else
7923         {
7924           tlbl = newiTempLabel (NULL);
7925           /* rotate right accumulator */
7926           AccRol (8 - shCount);
7927           /* and kill the higher order bits */
7928           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7929           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7930           emitcode ("orl", "a,#!constbyte",
7931                     (unsigned char) ~SRMask[shCount]);
7932           emitcode ("", "!tlabeldef", tlbl->key + 100);
7933         }
7934     }
7935 }
7936 #endif
7937
7938 #ifdef BETTER_LITERAL_SHIFT
7939 /*-----------------------------------------------------------------*/
7940 /* shiftR1Left2Result - shift right one byte from left to result   */
7941 /*-----------------------------------------------------------------*/
7942 static void
7943 shiftR1Left2Result (operand * left, int offl,
7944                     operand * result, int offr,
7945                     int shCount, int sign)
7946 {
7947   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7948   /* shift right accumulator */
7949   if (sign)
7950     AccSRsh (shCount);
7951   else
7952     AccRsh (shCount);
7953   aopPut (AOP (result), "a", offr);
7954 }
7955 #endif
7956
7957 #ifdef BETTER_LITERAL_SHIFT
7958 /*-----------------------------------------------------------------*/
7959 /* shiftL1Left2Result - shift left one byte from left to result    */
7960 /*-----------------------------------------------------------------*/
7961 static void
7962 shiftL1Left2Result (operand * left, int offl,
7963                     operand * result, int offr, int shCount)
7964 {
7965   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7966   /* shift left accumulator */
7967   AccLsh (shCount);
7968   aopPut (AOP (result), "a", offr);
7969 }
7970 #endif
7971
7972 #ifdef BETTER_LITERAL_SHIFT
7973 /*-----------------------------------------------------------------*/
7974 /* movLeft2Result - move byte from left to result                  */
7975 /*-----------------------------------------------------------------*/
7976 static void
7977 movLeft2Result (operand * left, int offl,
7978                 operand * result, int offr, int sign)
7979 {
7980   char *l;
7981   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7982   {
7983       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7984
7985       if (*l == '@' && (IS_AOP_PREG (result)))
7986       {
7987           emitcode ("mov", "a,%s", l);
7988           aopPut (AOP (result), "a", offr);
7989       }
7990       else
7991       {
7992           if (!sign)
7993           {
7994             aopPut (AOP (result), l, offr);
7995           }
7996           else
7997             {
7998               /* MSB sign in acc.7 ! */
7999               if (getDataSize (left) == offl + 1)
8000                 {
8001                   emitcode ("mov", "a,%s", l);
8002                   aopPut (AOP (result), "a", offr);
8003                 }
8004             }
8005       }
8006   }
8007 }
8008 #endif
8009
8010 #ifdef BETTER_LITERAL_SHIFT
8011 /*-----------------------------------------------------------------*/
8012 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8013 /*-----------------------------------------------------------------*/
8014 static void
8015 AccAXRrl1 (char *x)
8016 {
8017   emitcode ("rrc", "a");
8018   emitcode ("xch", "a,%s", x);
8019   emitcode ("rrc", "a");
8020   emitcode ("xch", "a,%s", x);
8021 }
8022 #endif
8023
8024 #ifdef BETTER_LITERAL_SHIFT
8025 //REMOVE ME!!!
8026 /*-----------------------------------------------------------------*/
8027 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 AccAXLrl1 (char *x)
8031 {
8032   emitcode ("xch", "a,%s", x);
8033   emitcode ("rlc", "a");
8034   emitcode ("xch", "a,%s", x);
8035   emitcode ("rlc", "a");
8036 }
8037 #endif
8038
8039 #ifdef BETTER_LITERAL_SHIFT
8040 /*-----------------------------------------------------------------*/
8041 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8042 /*-----------------------------------------------------------------*/
8043 static void
8044 AccAXLsh1 (char *x)
8045 {
8046   emitcode ("xch", "a,%s", x);
8047   emitcode ("add", "a,acc");
8048   emitcode ("xch", "a,%s", x);
8049   emitcode ("rlc", "a");
8050 }
8051 #endif
8052
8053 #ifdef BETTER_LITERAL_SHIFT
8054 /*-----------------------------------------------------------------*/
8055 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8056 /*-----------------------------------------------------------------*/
8057 static void
8058 AccAXLsh (char *x, int shCount)
8059 {
8060   switch (shCount)
8061     {
8062     case 0:
8063       break;
8064     case 1:
8065       AccAXLsh1 (x);
8066       break;
8067     case 2:
8068       AccAXLsh1 (x);
8069       AccAXLsh1 (x);
8070       break;
8071     case 3:
8072     case 4:
8073     case 5:                     // AAAAABBB:CCCCCDDD
8074
8075       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8076
8077       emitcode ("anl", "a,#!constbyte",
8078                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8079
8080       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8081
8082       AccRol (shCount);         // DDDCCCCC:BBB00000
8083
8084       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8085
8086       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8087
8088       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8089
8090       emitcode ("anl", "a,#!constbyte",
8091                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8092
8093       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8094
8095       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8096
8097       break;
8098     case 6:                     // AAAAAABB:CCCCCCDD
8099       emitcode ("anl", "a,#!constbyte",
8100                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8101       emitcode ("mov", "c,acc.0");      // c = B
8102       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8103 #if 0
8104       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8105       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8106 #else
8107       emitcode("rrc","a"); 
8108       emitcode("xch","a,%s", x); 
8109       emitcode("rrc","a"); 
8110       emitcode("mov","c,acc.0"); //<< get correct bit 
8111       emitcode("xch","a,%s", x); 
8112
8113       emitcode("rrc","a"); 
8114       emitcode("xch","a,%s", x); 
8115       emitcode("rrc","a"); 
8116       emitcode("xch","a,%s", x); 
8117 #endif
8118       break;
8119     case 7:                     // a:x <<= 7
8120
8121       emitcode ("anl", "a,#!constbyte",
8122                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8123
8124       emitcode ("mov", "c,acc.0");      // c = B
8125
8126       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8127
8128       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8129
8130       break;
8131     default:
8132       break;
8133     }
8134 }
8135 #endif
8136
8137 #ifdef BETTER_LITERAL_SHIFT
8138 //REMOVE ME!!!
8139 /*-----------------------------------------------------------------*/
8140 /* AccAXRsh - right shift a:x known count (0..7)                   */
8141 /*-----------------------------------------------------------------*/
8142 static void
8143 AccAXRsh (char *x, int shCount)
8144 {
8145   switch (shCount)
8146     {
8147     case 0:
8148       break;
8149     case 1:
8150       CLRC;
8151       AccAXRrl1 (x);            // 0->a:x
8152
8153       break;
8154     case 2:
8155       CLRC;
8156       AccAXRrl1 (x);            // 0->a:x
8157
8158       CLRC;
8159       AccAXRrl1 (x);            // 0->a:x
8160
8161       break;
8162     case 3:
8163     case 4:
8164     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8165
8166       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8167
8168       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8169
8170       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8171
8172       emitcode ("anl", "a,#!constbyte",
8173                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8174
8175       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8176
8177       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8178
8179       emitcode ("anl", "a,#!constbyte",
8180                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8181
8182       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8183
8184       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8185
8186       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8187
8188       break;
8189     case 6:                     // AABBBBBB:CCDDDDDD
8190
8191       emitcode ("mov", "c,acc.7");
8192       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8193
8194       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8195
8196       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8197
8198       emitcode ("anl", "a,#!constbyte",
8199                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8200
8201       break;
8202     case 7:                     // ABBBBBBB:CDDDDDDD
8203
8204       emitcode ("mov", "c,acc.7");      // c = A
8205
8206       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8207
8208       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8209
8210       emitcode ("anl", "a,#!constbyte",
8211                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8212
8213       break;
8214     default:
8215       break;
8216     }
8217 }
8218 #endif
8219
8220 #ifdef BETTER_LITERAL_SHIFT
8221 /*-----------------------------------------------------------------*/
8222 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8223 /*-----------------------------------------------------------------*/
8224 static void
8225 AccAXRshS (char *x, int shCount)
8226 {
8227   symbol *tlbl;
8228   switch (shCount)
8229     {
8230     case 0:
8231       break;
8232     case 1:
8233       emitcode ("mov", "c,acc.7");
8234       AccAXRrl1 (x);            // s->a:x
8235
8236       break;
8237     case 2:
8238       emitcode ("mov", "c,acc.7");
8239       AccAXRrl1 (x);            // s->a:x
8240
8241       emitcode ("mov", "c,acc.7");
8242       AccAXRrl1 (x);            // s->a:x
8243
8244       break;
8245     case 3:
8246     case 4:
8247     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8248
8249       tlbl = newiTempLabel (NULL);
8250       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8251
8252       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8253
8254       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8255
8256       emitcode ("anl", "a,#!constbyte",
8257                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8258
8259       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8260
8261       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8262
8263       emitcode ("anl", "a,#!constbyte",
8264                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8265
8266       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8267
8268       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8269
8270       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8271
8272       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8273       emitcode ("orl", "a,#!constbyte",
8274                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8275
8276       emitcode ("", "!tlabeldef", tlbl->key + 100);
8277       break;                    // SSSSAAAA:BBBCCCCC
8278
8279     case 6:                     // AABBBBBB:CCDDDDDD
8280
8281       tlbl = newiTempLabel (NULL);
8282       emitcode ("mov", "c,acc.7");
8283       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8284
8285       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8286
8287       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8288
8289       emitcode ("anl", "a,#!constbyte",
8290                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8291
8292       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8293       emitcode ("orl", "a,#!constbyte",
8294                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8295
8296       emitcode ("", "!tlabeldef", tlbl->key + 100);
8297       break;
8298     case 7:                     // ABBBBBBB:CDDDDDDD
8299
8300       tlbl = newiTempLabel (NULL);
8301       emitcode ("mov", "c,acc.7");      // c = A
8302
8303       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8304
8305       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8306
8307       emitcode ("anl", "a,#!constbyte",
8308                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8309
8310       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8311       emitcode ("orl", "a,#!constbyte",
8312                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8313
8314       emitcode ("", "!tlabeldef", tlbl->key + 100);
8315       break;
8316     default:
8317       break;
8318     }
8319 }
8320 #endif
8321
8322 #ifdef BETTER_LITERAL_SHIFT
8323 static void
8324 _loadLeftIntoAx(char    **lsb, 
8325                 operand *left, 
8326                 operand *result,
8327                 int     offl,
8328                 int     offr)
8329 {
8330   // Get the initial value from left into a pair of registers.
8331   // MSB must be in A, LSB can be any register.
8332   //
8333   // If the result is held in registers, it is an optimization
8334   // if the LSB can be held in the register which will hold the,
8335   // result LSB since this saves us from having to copy it into
8336   // the result following AccAXLsh.
8337   //
8338   // If the result is addressed indirectly, this is not a gain.
8339   if (AOP_NEEDSACC(result))
8340   {
8341        char *leftByte;
8342        
8343        _startLazyDPSEvaluation();
8344       if (AOP_TYPE(left) == AOP_DPTR2)
8345        {
8346            // Get MSB in A.
8347            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8348            // get LSB in DP2_RESULT_REG.
8349            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8350            assert(!strcmp(leftByte, DP2_RESULT_REG));
8351        }
8352        else
8353        {
8354            // get LSB into DP2_RESULT_REG
8355            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8356            if (strcmp(leftByte, DP2_RESULT_REG))
8357            {
8358                TR_AP("#7");
8359                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8360            }
8361            // And MSB in A.
8362            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8363            assert(strcmp(leftByte, DP2_RESULT_REG));
8364            MOVA(leftByte);
8365        }
8366        _endLazyDPSEvaluation();
8367        *lsb = DP2_RESULT_REG;
8368   }
8369   else
8370   {
8371       if (sameRegs (AOP (result), AOP (left)) &&
8372         ((offl + MSB16) == offr))
8373       {
8374           /* don't crash result[offr] */
8375           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8376           emitcode ("xch", "a,%s", 
8377                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8378       }
8379       else
8380       {
8381           movLeft2Result (left, offl, result, offr, 0);
8382           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8383       }
8384       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8385       assert(strcmp(*lsb,"a"));      
8386   }
8387 }
8388
8389 static void
8390 _storeAxResults(char    *lsb,
8391                 operand *result,
8392                 int     offr)
8393 {
8394   _startLazyDPSEvaluation();
8395   if (AOP_NEEDSACC(result))
8396   {
8397       /* We have to explicitly update the result LSB.
8398        */
8399       emitcode("xch","a,%s", lsb);
8400       aopPut(AOP(result), "a", offr);
8401       emitcode("mov","a,%s", lsb);
8402   }
8403   if (getDataSize (result) > 1)
8404   {
8405       aopPut (AOP (result), "a", offr + MSB16);
8406   }
8407   _endLazyDPSEvaluation();
8408 }
8409
8410 /*-----------------------------------------------------------------*/
8411 /* shiftL2Left2Result - shift left two bytes from left to result   */
8412 /*-----------------------------------------------------------------*/
8413 static void
8414 shiftL2Left2Result (operand * left, int offl,
8415                     operand * result, int offr, int shCount)
8416 {
8417   char *lsb;
8418
8419   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8420   
8421   AccAXLsh (lsb, shCount);
8422   
8423   _storeAxResults(lsb, result, offr);
8424 }
8425 #endif
8426
8427 #ifdef BETTER_LITERAL_SHIFT
8428 /*-----------------------------------------------------------------*/
8429 /* shiftR2Left2Result - shift right two bytes from left to result  */
8430 /*-----------------------------------------------------------------*/
8431 static void
8432 shiftR2Left2Result (operand * left, int offl,
8433                     operand * result, int offr,
8434                     int shCount, int sign)
8435 {
8436   char *lsb;
8437   
8438   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8439   
8440   /* a:x >> shCount (x = lsb(result)) */
8441   if (sign)
8442   {
8443      AccAXRshS(lsb, shCount);
8444   }
8445   else
8446   {
8447     AccAXRsh(lsb, shCount);
8448   }
8449   
8450   _storeAxResults(lsb, result, offr);
8451 }
8452 #endif
8453
8454 /*-----------------------------------------------------------------*/
8455 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8456 /*-----------------------------------------------------------------*/
8457 static void
8458 shiftLLeftOrResult (operand * left, int offl,
8459                     operand * result, int offr, int shCount)
8460 {
8461   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8462   /* shift left accumulator */
8463   AccLsh (shCount);
8464   /* or with result */
8465   emitcode ("orl", "a,%s",
8466             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8467   /* back to result */
8468   aopPut (AOP (result), "a", offr);
8469 }
8470
8471 #if 0
8472 //REMOVE ME!!!
8473 /*-----------------------------------------------------------------*/
8474 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8475 /*-----------------------------------------------------------------*/
8476 static void
8477 shiftRLeftOrResult (operand * left, int offl,
8478                     operand * result, int offr, int shCount)
8479 {
8480   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8481   /* shift right accumulator */
8482   AccRsh (shCount);
8483   /* or with result */
8484   emitcode ("orl", "a,%s",
8485             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8486   /* back to result */
8487   aopPut (AOP (result), "a", offr);
8488 }
8489 #endif
8490
8491 #ifdef BETTER_LITERAL_SHIFT
8492 /*-----------------------------------------------------------------*/
8493 /* genlshOne - left shift a one byte quantity by known count       */
8494 /*-----------------------------------------------------------------*/
8495 static void
8496 genlshOne (operand * result, operand * left, int shCount)
8497 {
8498   D (emitcode (";", "genlshOne "););
8499   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8500 }
8501 #endif
8502
8503 #ifdef BETTER_LITERAL_SHIFT
8504 /*-----------------------------------------------------------------*/
8505 /* genlshTwo - left shift two bytes by known amount != 0           */
8506 /*-----------------------------------------------------------------*/
8507 static void
8508 genlshTwo (operand * result, operand * left, int shCount)
8509 {
8510   int size;
8511
8512   D (emitcode (";", "genlshTwo "););
8513
8514   size = getDataSize (result);
8515
8516   /* if shCount >= 8 */
8517   if (shCount >= 8)
8518   {
8519       shCount -= 8;
8520
8521       _startLazyDPSEvaluation();
8522
8523       if (size > 1)
8524         {
8525           if (shCount)
8526           {
8527             _endLazyDPSEvaluation();
8528             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8529             aopPut (AOP (result), zero, LSB);       
8530           }
8531           else
8532           {
8533             movLeft2Result (left, LSB, result, MSB16, 0);
8534             aopPut (AOP (result), zero, LSB);
8535             _endLazyDPSEvaluation();
8536           }
8537         }
8538         else
8539         {
8540           aopPut (AOP (result), zero, LSB);
8541           _endLazyDPSEvaluation();
8542         }
8543   }
8544
8545   /*  1 <= shCount <= 7 */
8546   else
8547     {
8548       if (size == 1)
8549       {
8550         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8551       }
8552       else
8553       {
8554         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8555       }
8556     }
8557 }
8558 #endif
8559
8560 #if 0
8561 //REMOVE ME!!!
8562 /*-----------------------------------------------------------------*/
8563 /* shiftLLong - shift left one long from left to result            */
8564 /* offl = LSB or MSB16                                             */
8565 /*-----------------------------------------------------------------*/
8566 static void
8567 shiftLLong (operand * left, operand * result, int offr)
8568 {
8569   char *l;
8570   int size = AOP_SIZE (result);
8571
8572   if (size >= LSB + offr)
8573     {
8574       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8575       MOVA (l);
8576       emitcode ("add", "a,acc");
8577       if (sameRegs (AOP (left), AOP (result)) &&
8578           size >= MSB16 + offr && offr != LSB)
8579         emitcode ("xch", "a,%s",
8580                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8581       else
8582         aopPut (AOP (result), "a", LSB + offr);
8583     }
8584
8585   if (size >= MSB16 + offr)
8586     {
8587       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8588         {
8589           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8590         }
8591       emitcode ("rlc", "a");
8592       if (sameRegs (AOP (left), AOP (result)) &&
8593           size >= MSB24 + offr && offr != LSB)
8594         emitcode ("xch", "a,%s",
8595                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8596       else
8597         aopPut (AOP (result), "a", MSB16 + offr);
8598     }
8599
8600   if (size >= MSB24 + offr)
8601     {
8602       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8603         {
8604           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8605         }
8606       emitcode ("rlc", "a");
8607       if (sameRegs (AOP (left), AOP (result)) &&
8608           size >= MSB32 + offr && offr != LSB)
8609         emitcode ("xch", "a,%s",
8610                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8611       else
8612         aopPut (AOP (result), "a", MSB24 + offr);
8613     }
8614
8615   if (size > MSB32 + offr)
8616     {
8617       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8618         {
8619           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8620         }
8621       emitcode ("rlc", "a");
8622       aopPut (AOP (result), "a", MSB32 + offr);
8623     }
8624   if (offr != LSB)
8625     aopPut (AOP (result), zero, LSB);
8626 }
8627 #endif
8628
8629 #if 0
8630 //REMOVE ME!!!
8631 /*-----------------------------------------------------------------*/
8632 /* genlshFour - shift four byte by a known amount != 0             */
8633 /*-----------------------------------------------------------------*/
8634 static void
8635 genlshFour (operand * result, operand * left, int shCount)
8636 {
8637   int size;
8638
8639   D (emitcode (";", "genlshFour ");
8640     );
8641
8642   size = AOP_SIZE (result);
8643
8644   /* if shifting more that 3 bytes */
8645   if (shCount >= 24)
8646     {
8647       shCount -= 24;
8648       if (shCount)
8649         /* lowest order of left goes to the highest
8650            order of the destination */
8651         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8652       else
8653         movLeft2Result (left, LSB, result, MSB32, 0);
8654       aopPut (AOP (result), zero, LSB);
8655       aopPut (AOP (result), zero, MSB16);
8656       aopPut (AOP (result), zero, MSB24);
8657       return;
8658     }
8659
8660   /* more than two bytes */
8661   else if (shCount >= 16)
8662     {
8663       /* lower order two bytes goes to higher order two bytes */
8664       shCount -= 16;
8665       /* if some more remaining */
8666       if (shCount)
8667         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8668       else
8669         {
8670           movLeft2Result (left, MSB16, result, MSB32, 0);
8671           movLeft2Result (left, LSB, result, MSB24, 0);
8672         }
8673       aopPut (AOP (result), zero, MSB16);
8674       aopPut (AOP (result), zero, LSB);
8675       return;
8676     }
8677
8678   /* if more than 1 byte */
8679   else if (shCount >= 8)
8680     {
8681       /* lower order three bytes goes to higher order  three bytes */
8682       shCount -= 8;
8683       if (size == 2)
8684         {
8685           if (shCount)
8686             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8687           else
8688             movLeft2Result (left, LSB, result, MSB16, 0);
8689         }
8690       else
8691         {                       /* size = 4 */
8692           if (shCount == 0)
8693             {
8694               movLeft2Result (left, MSB24, result, MSB32, 0);
8695               movLeft2Result (left, MSB16, result, MSB24, 0);
8696               movLeft2Result (left, LSB, result, MSB16, 0);
8697               aopPut (AOP (result), zero, LSB);
8698             }
8699           else if (shCount == 1)
8700             shiftLLong (left, result, MSB16);
8701           else
8702             {
8703               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8704               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8705               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8706               aopPut (AOP (result), zero, LSB);
8707             }
8708         }
8709     }
8710
8711   /* 1 <= shCount <= 7 */
8712   else if (shCount <= 2)
8713     {
8714       shiftLLong (left, result, LSB);
8715       if (shCount == 2)
8716         shiftLLong (result, result, LSB);
8717     }
8718   /* 3 <= shCount <= 7, optimize */
8719   else
8720     {
8721       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8722       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8723       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8724     }
8725 }
8726 #endif
8727
8728 #ifdef BETTER_LITERAL_SHIFT
8729 /*-----------------------------------------------------------------*/
8730 /* genLeftShiftLiteral - left shifting by known count              */
8731 /*-----------------------------------------------------------------*/
8732 static bool
8733 genLeftShiftLiteral (operand * left,
8734                      operand * right,
8735                      operand * result,
8736                      iCode * ic)
8737 {
8738   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8739   int size;
8740
8741   size = getSize (operandType (result));
8742
8743   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8744
8745   /* We only handle certain easy cases so far. */
8746   if ((shCount != 0)
8747    && (shCount < (size * 8))
8748    && (size != 1)
8749    && (size != 2))
8750   {
8751       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8752       return FALSE;
8753   }
8754
8755   freeAsmop (right, NULL, ic, TRUE);
8756
8757   aopOp(left, ic, FALSE, FALSE);
8758   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8759
8760 #if 0 // debug spew
8761   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8762   {
8763         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8764         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8765         {
8766            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8767         }
8768   }
8769   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8770   {
8771         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8772         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8773         {
8774            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8775         }       
8776   }  
8777 #endif
8778   
8779 #if VIEW_SIZE
8780   emitcode ("; shift left ", "result %d, left %d", size,
8781             AOP_SIZE (left));
8782 #endif
8783
8784   /* I suppose that the left size >= result size */
8785   if (shCount == 0)
8786   {
8787         _startLazyDPSEvaluation();
8788         while (size--)
8789         {
8790           movLeft2Result (left, size, result, size, 0);
8791         }
8792         _endLazyDPSEvaluation();
8793   }
8794   else if (shCount >= (size * 8))
8795   {
8796     _startLazyDPSEvaluation();
8797     while (size--)
8798     {
8799       aopPut (AOP (result), zero, size);
8800     }
8801     _endLazyDPSEvaluation();
8802   }
8803   else
8804   {
8805       switch (size)
8806         {
8807         case 1:
8808           genlshOne (result, left, shCount);
8809           break;
8810
8811         case 2:
8812           genlshTwo (result, left, shCount);
8813           break;
8814 #if 0
8815         case 4:
8816           genlshFour (result, left, shCount);
8817           break;
8818 #endif
8819         default:
8820           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8821           break;
8822         }
8823     }
8824   freeAsmop (left, NULL, ic, TRUE);
8825   freeAsmop (result, NULL, ic, TRUE);
8826   return TRUE;
8827 }
8828 #endif
8829
8830 /*-----------------------------------------------------------------*/
8831 /* genLeftShift - generates code for left shifting                 */
8832 /*-----------------------------------------------------------------*/
8833 static void
8834 genLeftShift (iCode * ic)
8835 {
8836   operand *left, *right, *result;
8837   int size, offset;
8838   char *l;
8839   symbol *tlbl, *tlbl1;
8840
8841   D (emitcode (";", "genLeftShift "););
8842
8843   right = IC_RIGHT (ic);
8844   left = IC_LEFT (ic);
8845   result = IC_RESULT (ic);
8846
8847   aopOp (right, ic, FALSE, FALSE);
8848
8849
8850 #ifdef BETTER_LITERAL_SHIFT
8851   /* if the shift count is known then do it
8852      as efficiently as possible */
8853   if (AOP_TYPE (right) == AOP_LIT)
8854     {
8855       if (genLeftShiftLiteral (left, right, result, ic))
8856       {
8857         return;
8858       }
8859     }
8860 #endif
8861
8862   /* shift count is unknown then we have to form
8863      a loop get the loop count in B : Note: we take
8864      only the lower order byte since shifting
8865      more that 32 bits make no sense anyway, ( the
8866      largest size of an object can be only 32 bits ) */
8867
8868   if (AOP_TYPE (right) == AOP_LIT)
8869   {
8870       /* Really should be handled by genLeftShiftLiteral,
8871        * but since I'm too lazy to fix that today, at least we can make
8872        * some small improvement.
8873        */
8874        emitcode("mov", "b,#!constbyte",
8875                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8876   }
8877   else
8878   {
8879       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8880       emitcode ("inc", "b");
8881   }
8882   freeAsmop (right, NULL, ic, TRUE);
8883   aopOp (left, ic, FALSE, FALSE);
8884   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8885
8886   /* now move the left to the result if they are not the
8887      same */
8888   if (!sameRegs (AOP (left), AOP (result)) &&
8889       AOP_SIZE (result) > 1)
8890     {
8891
8892       size = AOP_SIZE (result);
8893       offset = 0;
8894       _startLazyDPSEvaluation ();
8895       while (size--)
8896         {
8897           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8898           if (*l == '@' && (IS_AOP_PREG (result)))
8899             {
8900
8901               emitcode ("mov", "a,%s", l);
8902               aopPut (AOP (result), "a", offset);
8903             }
8904           else
8905             aopPut (AOP (result), l, offset);
8906           offset++;
8907         }
8908       _endLazyDPSEvaluation ();
8909     }
8910
8911   tlbl = newiTempLabel (NULL);
8912   size = AOP_SIZE (result);
8913   offset = 0;
8914   tlbl1 = newiTempLabel (NULL);
8915
8916   /* if it is only one byte then */
8917   if (size == 1)
8918     {
8919       symbol *tlbl1 = newiTempLabel (NULL);
8920
8921       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8922       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8923       emitcode ("", "!tlabeldef", tlbl->key + 100);
8924       emitcode ("add", "a,acc");
8925       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8926       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8927       aopPut (AOP (result), "a", 0);
8928       goto release;
8929     }
8930
8931   reAdjustPreg (AOP (result));
8932
8933   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8934   emitcode ("", "!tlabeldef", tlbl->key + 100);
8935   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8936   emitcode ("add", "a,acc");
8937   aopPut (AOP (result), "a", offset++);
8938   _startLazyDPSEvaluation ();
8939   while (--size)
8940     {
8941       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8942       emitcode ("rlc", "a");
8943       aopPut (AOP (result), "a", offset++);
8944     }
8945   _endLazyDPSEvaluation ();
8946   reAdjustPreg (AOP (result));
8947
8948   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8949   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8950 release:
8951   freeAsmop (left, NULL, ic, TRUE);
8952   freeAsmop (result, NULL, ic, TRUE);
8953 }
8954
8955 #ifdef BETTER_LITERAL_SHIFT
8956 /*-----------------------------------------------------------------*/
8957 /* genrshOne - right shift a one byte quantity by known count      */
8958 /*-----------------------------------------------------------------*/
8959 static void
8960 genrshOne (operand * result, operand * left,
8961            int shCount, int sign)
8962 {
8963   D (emitcode (";", "genrshOne"););
8964   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8965 }
8966 #endif
8967
8968 #ifdef BETTER_LITERAL_SHIFT
8969 /*-----------------------------------------------------------------*/
8970 /* genrshTwo - right shift two bytes by known amount != 0          */
8971 /*-----------------------------------------------------------------*/
8972 static void
8973 genrshTwo (operand * result, operand * left,
8974            int shCount, int sign)
8975 {
8976   D (emitcode (";", "genrshTwo"););
8977
8978   /* if shCount >= 8 */
8979   if (shCount >= 8)
8980     {
8981       shCount -= 8;
8982       _startLazyDPSEvaluation();
8983       if (shCount)
8984       {
8985         shiftR1Left2Result (left, MSB16, result, LSB,
8986                             shCount, sign);
8987       }                     
8988       else
8989       {
8990         movLeft2Result (left, MSB16, result, LSB, sign);
8991       }
8992       addSign (result, MSB16, sign);
8993       _endLazyDPSEvaluation();
8994     }
8995
8996   /*  1 <= shCount <= 7 */
8997   else
8998   {
8999     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9000   }
9001 }
9002 #endif
9003
9004 /*-----------------------------------------------------------------*/
9005 /* shiftRLong - shift right one long from left to result           */
9006 /* offl = LSB or MSB16                                             */
9007 /*-----------------------------------------------------------------*/
9008 static void
9009 shiftRLong (operand * left, int offl,
9010             operand * result, int sign)
9011 {
9012   int isSameRegs=sameRegs(AOP(left),AOP(result));
9013
9014   if (isSameRegs && offl>1) {
9015     // we are in big trouble, but this shouldn't happen
9016     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9017   }
9018
9019   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9020   
9021   if (offl==MSB16) {
9022     // shift is > 8
9023     if (sign) {
9024       emitcode ("rlc", "a");
9025       emitcode ("subb", "a,acc");
9026       emitcode ("xch", "a,%s",
9027                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9028     } else {
9029       aopPut (AOP(result), zero, MSB32);
9030     }
9031   }
9032
9033   if (!sign) {
9034     emitcode ("clr", "c");
9035   } else {
9036     emitcode ("mov", "c,acc.7");
9037   }
9038
9039   emitcode ("rrc", "a");
9040
9041   if (isSameRegs && offl==MSB16) {
9042     emitcode ("xch",
9043               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9044   } else {
9045     aopPut (AOP (result), "a", MSB32);
9046     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9047   }
9048
9049   emitcode ("rrc", "a");
9050   if (isSameRegs && offl==1) {
9051     emitcode ("xch", "a,%s",
9052               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9053   } else {
9054     aopPut (AOP (result), "a", MSB24);
9055     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9056   }
9057   emitcode ("rrc", "a");
9058   aopPut (AOP (result), "a", MSB16 - offl);
9059
9060   if (offl == LSB)
9061     {
9062       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9063       emitcode ("rrc", "a");
9064       aopPut (AOP (result), "a", LSB);
9065     }
9066 }
9067
9068 /*-----------------------------------------------------------------*/
9069 /* genrshFour - shift four byte by a known amount != 0             */
9070 /*-----------------------------------------------------------------*/
9071 static void
9072 genrshFour (operand * result, operand * left,
9073             int shCount, int sign)
9074 {
9075   D (emitcode (";", "genrshFour"););
9076
9077   /* if shifting more that 3 bytes */
9078   if (shCount >= 24)
9079     {
9080       shCount -= 24;
9081       _startLazyDPSEvaluation();
9082       if (shCount)
9083         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9084       else
9085         movLeft2Result (left, MSB32, result, LSB, sign);
9086       addSign (result, MSB16, sign);
9087       _endLazyDPSEvaluation();
9088     }
9089   else if (shCount >= 16)
9090     {
9091       shCount -= 16;
9092       _startLazyDPSEvaluation();
9093       if (shCount)
9094         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9095       else
9096         {
9097           movLeft2Result (left, MSB24, result, LSB, 0);
9098           movLeft2Result (left, MSB32, result, MSB16, sign);
9099         }
9100       addSign (result, MSB24, sign);
9101       _endLazyDPSEvaluation();
9102     }
9103   else if (shCount >= 8)
9104     {
9105       shCount -= 8;
9106       _startLazyDPSEvaluation();
9107       if (shCount == 1)
9108         {
9109             shiftRLong (left, MSB16, result, sign);
9110         }
9111       else if (shCount == 0)
9112         {
9113           movLeft2Result (left, MSB16, result, LSB, 0);
9114           movLeft2Result (left, MSB24, result, MSB16, 0);
9115           movLeft2Result (left, MSB32, result, MSB24, sign);
9116           addSign (result, MSB32, sign);
9117         }
9118       else
9119         {
9120           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9121           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9122           /* the last shift is signed */
9123           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9124           addSign (result, MSB32, sign);
9125         }
9126         _endLazyDPSEvaluation();
9127     }
9128   else
9129     {   
9130         /* 1 <= shCount <= 7 */
9131       if (shCount <= 2)
9132         {
9133           shiftRLong (left, LSB, result, sign);
9134           if (shCount == 2)
9135             shiftRLong (result, LSB, result, sign);
9136         }
9137       else
9138         {
9139           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9140           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9141           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9142         }
9143     }
9144 }
9145
9146 #ifdef BETTER_LITERAL_SHIFT
9147 /*-----------------------------------------------------------------*/
9148 /* genRightShiftLiteral - right shifting by known count            */
9149 /*-----------------------------------------------------------------*/
9150 static bool
9151 genRightShiftLiteral (operand * left,
9152                       operand * right,
9153                       operand * result,
9154                       iCode * ic,
9155                       int sign)
9156 {
9157   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9158   int size;
9159
9160   size = getSize (operandType (result));
9161
9162   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9163
9164   /* We only handle certain easy cases so far. */
9165   if ((shCount != 0)
9166    && (shCount < (size * 8))
9167    && (size != 1)
9168    && (size != 2)
9169    && (size != 4))
9170   {
9171       D(emitcode (";", "genRightShiftLiteral wimping out"););
9172       return FALSE;
9173   }
9174
9175   freeAsmop (right, NULL, ic, TRUE);
9176
9177   aopOp (left, ic, FALSE, FALSE);
9178   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9179
9180 #if VIEW_SIZE
9181   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9182             AOP_SIZE (left));
9183 #endif
9184
9185   /* test the LEFT size !!! */
9186
9187   /* I suppose that the left size >= result size */
9188   if (shCount == 0)
9189   {
9190       size = getDataSize (result);
9191       _startLazyDPSEvaluation();
9192       while (size--)
9193       {
9194         movLeft2Result (left, size, result, size, 0);
9195       }
9196       _endLazyDPSEvaluation();
9197   }
9198   else if (shCount >= (size * 8))
9199     {
9200       if (sign)
9201       {
9202         /* get sign in acc.7 */
9203         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9204       }
9205       addSign (result, LSB, sign);
9206     }
9207   else
9208     {
9209       switch (size)
9210         {
9211         case 1:
9212           genrshOne (result, left, shCount, sign);
9213           break;
9214
9215         case 2:
9216           genrshTwo (result, left, shCount, sign);
9217           break;
9218 #if 1
9219         case 4:
9220           genrshFour (result, left, shCount, sign);
9221           break;
9222 #endif    
9223         default:
9224           break;
9225         }
9226     }
9227   freeAsmop (left, NULL, ic, TRUE);
9228   freeAsmop (result, NULL, ic, TRUE);
9229   
9230   return TRUE;
9231 }
9232 #endif
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genSignedRightShift - right shift of signed number              */
9236 /*-----------------------------------------------------------------*/
9237 static void
9238 genSignedRightShift (iCode * ic)
9239 {
9240   operand *right, *left, *result;
9241   int size, offset;
9242   char *l;
9243   symbol *tlbl, *tlbl1;
9244
9245   D (emitcode (";", "genSignedRightShift "););
9246
9247   /* we do it the hard way put the shift count in b
9248      and loop thru preserving the sign */
9249
9250   right = IC_RIGHT (ic);
9251   left = IC_LEFT (ic);
9252   result = IC_RESULT (ic);
9253
9254   aopOp (right, ic, FALSE, FALSE);
9255
9256 #ifdef BETTER_LITERAL_SHIFT
9257   if (AOP_TYPE (right) == AOP_LIT)
9258     {
9259       if (genRightShiftLiteral (left, right, result, ic, 1))
9260       {
9261         return;
9262       }
9263     }
9264 #endif
9265   /* shift count is unknown then we have to form
9266      a loop get the loop count in B : Note: we take
9267      only the lower order byte since shifting
9268      more that 32 bits make no sense anyway, ( the
9269      largest size of an object can be only 32 bits ) */
9270
9271   if (AOP_TYPE (right) == AOP_LIT)
9272   {
9273       /* Really should be handled by genRightShiftLiteral,
9274        * but since I'm too lazy to fix that today, at least we can make
9275        * some small improvement.
9276        */
9277        emitcode("mov", "b,#!constbyte",
9278                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9279   }
9280   else
9281   {
9282         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9283         emitcode ("inc", "b");
9284   }
9285   freeAsmop (right, NULL, ic, TRUE);
9286   aopOp (left, ic, FALSE, FALSE);
9287   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
9288
9289   /* now move the left to the result if they are not the
9290      same */
9291   if (!sameRegs (AOP (left), AOP (result)) &&
9292       AOP_SIZE (result) > 1)
9293     {
9294
9295       size = AOP_SIZE (result);
9296       offset = 0;
9297       _startLazyDPSEvaluation ();
9298       while (size--)
9299         {
9300           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9301           if (*l == '@' && IS_AOP_PREG (result))
9302             {
9303
9304               emitcode ("mov", "a,%s", l);
9305               aopPut (AOP (result), "a", offset);
9306             }
9307           else
9308             aopPut (AOP (result), l, offset);
9309           offset++;
9310         }
9311       _endLazyDPSEvaluation ();
9312     }
9313
9314   /* mov the highest order bit to OVR */
9315   tlbl = newiTempLabel (NULL);
9316   tlbl1 = newiTempLabel (NULL);
9317
9318   size = AOP_SIZE (result);
9319   offset = size - 1;
9320   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9321   emitcode ("rlc", "a");
9322   emitcode ("mov", "ov,c");
9323   /* if it is only one byte then */
9324   if (size == 1)
9325     {
9326       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9327       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9328       emitcode ("", "!tlabeldef", tlbl->key + 100);
9329       emitcode ("mov", "c,ov");
9330       emitcode ("rrc", "a");
9331       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9332       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9333       aopPut (AOP (result), "a", 0);
9334       goto release;
9335     }
9336
9337   reAdjustPreg (AOP (result));
9338   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9339   emitcode ("", "!tlabeldef", tlbl->key + 100);
9340   emitcode ("mov", "c,ov");
9341   _startLazyDPSEvaluation ();
9342   while (size--)
9343     {
9344       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9345       emitcode ("rrc", "a");
9346       aopPut (AOP (result), "a", offset--);
9347     }
9348   _endLazyDPSEvaluation ();
9349   reAdjustPreg (AOP (result));
9350   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9351   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9352
9353 release:
9354   freeAsmop (left, NULL, ic, TRUE);
9355   freeAsmop (result, NULL, ic, TRUE);
9356 }
9357
9358 /*-----------------------------------------------------------------*/
9359 /* genRightShift - generate code for right shifting                */
9360 /*-----------------------------------------------------------------*/
9361 static void
9362 genRightShift (iCode * ic)
9363 {
9364   operand *right, *left, *result;
9365   sym_link *letype;
9366   int size, offset;
9367   char *l;
9368   symbol *tlbl, *tlbl1;
9369
9370   D (emitcode (";", "genRightShift "););
9371
9372   /* if signed then we do it the hard way preserve the
9373      sign bit moving it inwards */
9374   letype = getSpec (operandType (IC_LEFT (ic)));
9375
9376   if (!SPEC_USIGN (letype))
9377     {
9378       genSignedRightShift (ic);
9379       return;
9380     }
9381
9382   /* signed & unsigned types are treated the same : i.e. the
9383      signed is NOT propagated inwards : quoting from the
9384      ANSI - standard : "for E1 >> E2, is equivalent to division
9385      by 2**E2 if unsigned or if it has a non-negative value,
9386      otherwise the result is implementation defined ", MY definition
9387      is that the sign does not get propagated */
9388
9389   right = IC_RIGHT (ic);
9390   left = IC_LEFT (ic);
9391   result = IC_RESULT (ic);
9392
9393   aopOp (right, ic, FALSE, FALSE);
9394
9395 #ifdef BETTER_LITERAL_SHIFT
9396   /* if the shift count is known then do it
9397      as efficiently as possible */
9398   if (AOP_TYPE (right) == AOP_LIT)
9399     {
9400       if (genRightShiftLiteral (left, right, result, ic, 0))
9401       {
9402         return;
9403       }
9404     }
9405 #endif
9406
9407   /* shift count is unknown then we have to form
9408      a loop get the loop count in B : Note: we take
9409      only the lower order byte since shifting
9410      more that 32 bits make no sense anyway, ( the
9411      largest size of an object can be only 32 bits ) */
9412   
9413   if (AOP_TYPE (right) == AOP_LIT)
9414   {
9415       /* Really should be handled by genRightShiftLiteral,
9416        * but since I'm too lazy to fix that today, at least we can make
9417        * some small improvement.
9418        */
9419        emitcode("mov", "b,#!constbyte",
9420                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9421   }
9422   else
9423   {
9424       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9425       emitcode ("inc", "b");
9426   }
9427   freeAsmop (right, NULL, ic, TRUE);
9428   aopOp (left, ic, FALSE, FALSE);
9429   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9430
9431   /* now move the left to the result if they are not the
9432      same */
9433   if (!sameRegs (AOP (left), AOP (result)) &&
9434       AOP_SIZE (result) > 1)
9435     {
9436
9437       size = AOP_SIZE (result);
9438       offset = 0;
9439       _startLazyDPSEvaluation ();
9440       while (size--)
9441         {
9442           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9443           if (*l == '@' && IS_AOP_PREG (result))
9444             {
9445
9446               emitcode ("mov", "a,%s", l);
9447               aopPut (AOP (result), "a", offset);
9448             }
9449           else
9450             aopPut (AOP (result), l, offset);
9451           offset++;
9452         }
9453       _endLazyDPSEvaluation ();
9454     }
9455
9456   tlbl = newiTempLabel (NULL);
9457   tlbl1 = newiTempLabel (NULL);
9458   size = AOP_SIZE (result);
9459   offset = size - 1;
9460
9461   /* if it is only one byte then */
9462   if (size == 1)
9463     {
9464       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9465       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9466       emitcode ("", "!tlabeldef", tlbl->key + 100);
9467       CLRC;
9468       emitcode ("rrc", "a");
9469       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9470       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9471       aopPut (AOP (result), "a", 0);
9472       goto release;
9473     }
9474
9475   reAdjustPreg (AOP (result));
9476   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9477   emitcode ("", "!tlabeldef", tlbl->key + 100);
9478   CLRC;
9479   _startLazyDPSEvaluation ();
9480   while (size--)
9481     {
9482       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9483       emitcode ("rrc", "a");
9484       aopPut (AOP (result), "a", offset--);
9485     }
9486   _endLazyDPSEvaluation ();
9487   reAdjustPreg (AOP (result));
9488
9489   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9490   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9491
9492 release:
9493   freeAsmop (left, NULL, ic, TRUE);
9494   freeAsmop (result, NULL, ic, TRUE);
9495 }
9496
9497
9498 /*-----------------------------------------------------------------*/
9499 /* emitPtrByteGet - emits code to get a byte into A through a      */
9500 /*                  pointer register (R0, R1, or DPTR). The        */
9501 /*                  original value of A can be preserved in B.     */
9502 /*-----------------------------------------------------------------*/
9503 static void
9504 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9505 {
9506   switch (p_type)
9507     {
9508     case IPOINTER:
9509     case POINTER:
9510       if (preserveAinB)
9511         emitcode ("mov", "b,a");
9512       emitcode ("mov", "a,@%s", rname);
9513       break;
9514
9515     case PPOINTER:
9516       if (preserveAinB)
9517         emitcode ("mov", "b,a");
9518       emitcode ("movx", "a,@%s", rname);
9519       break;
9520       
9521     case FPOINTER:
9522       if (preserveAinB)
9523         emitcode ("mov", "b,a");
9524       emitcode ("movx", "a,@dptr");
9525       break;
9526
9527     case CPOINTER:
9528       if (preserveAinB)
9529         emitcode ("mov", "b,a");
9530       emitcode ("clr", "a");
9531       emitcode ("movc", "a,@a+dptr");
9532       break;
9533
9534     case GPOINTER:
9535       if (preserveAinB)
9536         {
9537           emitcode ("push", "b");
9538           emitcode ("push", "acc");
9539         }
9540       emitcode ("lcall", "__gptrget");
9541       if (preserveAinB)
9542         emitcode ("pop", "b");
9543       break;
9544     }
9545 }
9546
9547 /*-----------------------------------------------------------------*/
9548 /* emitPtrByteSet - emits code to set a byte from src through a    */
9549 /*                  pointer register (R0, R1, or DPTR).            */
9550 /*-----------------------------------------------------------------*/
9551 static void
9552 emitPtrByteSet (char *rname, int p_type, char *src)
9553 {
9554   switch (p_type)
9555     {
9556     case IPOINTER:
9557     case POINTER:
9558       if (*src=='@')
9559         {
9560           MOVA (src);
9561           emitcode ("mov", "@%s,a", rname);
9562         }
9563       else
9564         emitcode ("mov", "@%s,%s", rname, src);
9565       break;
9566
9567     case PPOINTER:
9568       MOVA (src);
9569       emitcode ("movx", "@%s,a", rname);
9570       break;
9571       
9572     case FPOINTER:
9573       MOVA (src);
9574       emitcode ("movx", "@dptr,a");
9575       break;
9576
9577     case GPOINTER:
9578       MOVA (src);
9579       emitcode ("lcall", "__gptrput");
9580       break;
9581     }
9582 }
9583
9584 /*-----------------------------------------------------------------*/
9585 /* genUnpackBits - generates code for unpacking bits               */
9586 /*-----------------------------------------------------------------*/
9587 static void
9588 genUnpackBits (operand * result, char *rname, int ptype)
9589 {
9590   int offset = 0;       /* result byte offset */
9591   int rsize;            /* result size */
9592   int rlen = 0;         /* remaining bitfield length */
9593   sym_link *etype;      /* bitfield type information */
9594   int blen;             /* bitfield length */
9595   int bstr;             /* bitfield starting bit within byte */
9596
9597   D(emitcode (";     genUnpackBits",""));
9598
9599   etype = getSpec (operandType (result));
9600   rsize = getSize (operandType (result));
9601   blen = SPEC_BLEN (etype);
9602   bstr = SPEC_BSTR (etype);
9603
9604   /* If the bitfield length is less than a byte */
9605   if (blen < 8)
9606     {
9607       emitPtrByteGet (rname, ptype, FALSE);
9608       AccRsh (bstr);
9609       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9610       aopPut (AOP (result), "a", offset++);
9611       goto finish;
9612     }
9613
9614   /* Bit field did not fit in a byte. Copy all
9615      but the partial byte at the end.  */
9616   for (rlen=blen;rlen>=8;rlen-=8)
9617     {
9618       emitPtrByteGet (rname, ptype, FALSE);
9619       aopPut (AOP (result), "a", offset++);
9620       if (rlen>8)
9621         emitcode ("inc", "%s", rname);
9622     }
9623
9624   /* Handle the partial byte at the end */
9625   if (rlen)
9626     {
9627       emitPtrByteGet (rname, ptype, FALSE);
9628       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9629       aopPut (AOP (result), "a", offset++);
9630     }
9631
9632 finish:
9633   if (offset < rsize)
9634     {
9635       rsize -= offset;
9636       while (rsize--)
9637         aopPut (AOP (result), zero, offset++);
9638     }
9639 }
9640
9641
9642 /*-----------------------------------------------------------------*/
9643 /* genDataPointerGet - generates code when ptr offset is known     */
9644 /*-----------------------------------------------------------------*/
9645 static void
9646 genDataPointerGet (operand * left,
9647                    operand * result,
9648                    iCode * ic)
9649 {
9650   char *l;
9651   char buff[256];
9652   int size, offset = 0;
9653   aopOp (result, ic, TRUE, FALSE);
9654
9655   /* get the string representation of the name */
9656   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9657   size = AOP_SIZE (result);
9658   _startLazyDPSEvaluation ();
9659   while (size--)
9660     {
9661         if (offset)
9662         {
9663             SNPRINTF (buff, sizeof(buff), 
9664                       "(%s + %d)", l + 1, offset);
9665         }
9666         else
9667         {
9668             SNPRINTF (buff, sizeof(buff), 
9669                       "%s", l + 1);
9670         }
9671       aopPut (AOP (result), buff, offset++);
9672     }
9673   _endLazyDPSEvaluation ();
9674
9675   freeAsmop (left, NULL, ic, TRUE);
9676   freeAsmop (result, NULL, ic, TRUE);
9677 }
9678
9679 /*-----------------------------------------------------------------*/
9680 /* genNearPointerGet - emitcode for near pointer fetch             */
9681 /*-----------------------------------------------------------------*/
9682 static void
9683 genNearPointerGet (operand * left,
9684                    operand * result,
9685                    iCode * ic,
9686                    iCode *pi)
9687 {
9688   asmop *aop = NULL;
9689   regs *preg;
9690   char *rname;
9691   sym_link *rtype, *retype, *letype;
9692   sym_link *ltype = operandType (left);
9693   char buff[80];
9694
9695   rtype = operandType (result);
9696   retype = getSpec (rtype);
9697   letype = getSpec (ltype);
9698
9699   aopOp (left, ic, FALSE, FALSE);
9700
9701   /* if left is rematerialisable and
9702      result is not bitfield variable type and
9703      the left is pointer to data space i.e
9704      lower 128 bytes of space */
9705   if (AOP_TYPE (left) == AOP_IMMD &&
9706       !IS_BITFIELD (retype) &&
9707       !IS_BITFIELD (letype) &&
9708       DCL_TYPE (ltype) == POINTER)
9709     {
9710       genDataPointerGet (left, result, ic);
9711       return;
9712     }
9713
9714   /* if the value is already in a pointer register
9715      then don't need anything more */
9716   if (!AOP_INPREG (AOP (left)))
9717     {
9718       /* otherwise get a free pointer register */
9719       aop = newAsmop (0);
9720       preg = getFreePtr (ic, &aop, FALSE);
9721       emitcode ("mov", "%s,%s",
9722                 preg->name,
9723                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9724       rname = preg->name;
9725     }
9726   else
9727     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9728
9729   freeAsmop (left, NULL, ic, TRUE);
9730   aopOp (result, ic, FALSE, FALSE);
9731
9732   /* if bitfield then unpack the bits */
9733   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9734     genUnpackBits (result, rname, POINTER);
9735   else
9736     {
9737       /* we have can just get the values */
9738       int size = AOP_SIZE (result);
9739       int offset = 0;
9740
9741       while (size--)
9742         {
9743           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9744             {
9745
9746               emitcode ("mov", "a,@%s", rname);
9747               aopPut (AOP (result), "a", offset);
9748             }
9749           else
9750             {
9751               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9752               aopPut (AOP (result), buff, offset);
9753             }
9754           offset++;
9755           if (size || pi)
9756             {
9757                 emitcode ("inc", "%s", rname);
9758             }
9759         }
9760     }
9761
9762   /* now some housekeeping stuff */
9763   if (aop)
9764     {
9765       /* we had to allocate for this iCode */
9766       if (pi) { /* post increment present */
9767         aopPut(AOP ( left ),rname,0);
9768       }
9769       freeAsmop (NULL, aop, ic, TRUE);
9770     }
9771   else
9772     {
9773       /* we did not allocate which means left
9774          already in a pointer register, then
9775          if size > 0 && this could be used again
9776          we have to point it back to where it
9777          belongs */
9778       if (AOP_SIZE (result) > 1 &&
9779           !OP_SYMBOL (left)->remat &&
9780           (OP_SYMBOL (left)->liveTo > ic->seq ||
9781            ic->depth) &&
9782           !pi)
9783         {
9784           int size = AOP_SIZE (result) - 1;
9785           while (size--)
9786             emitcode ("dec", "%s", rname);
9787         }
9788     }
9789
9790   /* done */
9791   freeAsmop (result, NULL, ic, TRUE);
9792   if (pi) pi->generated = 1;
9793 }
9794
9795 /*-----------------------------------------------------------------*/
9796 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9797 /*-----------------------------------------------------------------*/
9798 static void
9799 genPagedPointerGet (operand * left,
9800                     operand * result,
9801                     iCode * ic,
9802                     iCode * pi)
9803 {
9804   asmop *aop = NULL;
9805   regs *preg;
9806   char *rname;
9807   sym_link *rtype, *retype, *letype;
9808
9809   rtype = operandType (result);
9810   retype = getSpec (rtype);
9811   letype = getSpec (operandType (left));
9812   aopOp (left, ic, FALSE, FALSE);
9813
9814   /* if the value is already in a pointer register
9815      then don't need anything more */
9816   if (!AOP_INPREG (AOP (left)))
9817     {
9818       /* otherwise get a free pointer register */
9819       aop = newAsmop (0);
9820       preg = getFreePtr (ic, &aop, FALSE);
9821       emitcode ("mov", "%s,%s",
9822                 preg->name,
9823                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9824       rname = preg->name;
9825     }
9826   else
9827     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9828
9829   freeAsmop (left, NULL, ic, TRUE);
9830   aopOp (result, ic, FALSE, FALSE);
9831
9832   /* if bitfield then unpack the bits */
9833   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9834     genUnpackBits (result, rname, PPOINTER);
9835   else
9836     {
9837       /* we have can just get the values */
9838       int size = AOP_SIZE (result);
9839       int offset = 0;
9840
9841       while (size--)
9842         {
9843
9844           emitcode ("movx", "a,@%s", rname);
9845           aopPut (AOP (result), "a", offset);
9846
9847           offset++;
9848
9849           if (size || pi)
9850             emitcode ("inc", "%s", rname);
9851         }
9852     }
9853
9854   /* now some housekeeping stuff */
9855   if (aop)
9856     {
9857       /* we had to allocate for this iCode */
9858       if (pi) aopPut ( AOP (left), rname, 0);
9859       freeAsmop (NULL, aop, ic, TRUE);
9860     }
9861   else
9862     {
9863       /* we did not allocate which means left
9864          already in a pointer register, then
9865          if size > 0 && this could be used again
9866          we have to point it back to where it
9867          belongs */
9868       if (AOP_SIZE (result) > 1 &&
9869           !OP_SYMBOL (left)->remat &&
9870           (OP_SYMBOL (left)->liveTo > ic->seq ||
9871            ic->depth) &&
9872           !pi)
9873         {
9874           int size = AOP_SIZE (result) - 1;
9875           while (size--)
9876             emitcode ("dec", "%s", rname);
9877         }
9878     }
9879
9880   /* done */
9881   freeAsmop (result, NULL, ic, TRUE);
9882   if (pi) pi->generated = 1;
9883 }
9884
9885 /*-----------------------------------------------------------------*/
9886 /* genFarPointerGet - gget value from far space                    */
9887 /*-----------------------------------------------------------------*/
9888 static void
9889 genFarPointerGet (operand * left,
9890                   operand * result, iCode * ic, iCode *pi)
9891 {
9892     int size, offset, dopi=1;
9893   sym_link *retype = getSpec (operandType (result));
9894   sym_link *letype = getSpec (operandType (left));
9895   D (emitcode (";", "genFarPointerGet"););
9896
9897   aopOp (left, ic, FALSE, FALSE);
9898
9899   /* if the operand is already in dptr
9900      then we do nothing else we move the value to dptr */
9901   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9902     {
9903       /* if this is remateriazable */
9904       if (AOP_TYPE (left) == AOP_IMMD)
9905         {
9906           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9907         }
9908       else
9909         {
9910           /* we need to get it byte by byte */
9911           _startLazyDPSEvaluation ();
9912           if (AOP_TYPE (left) != AOP_DPTR)
9913             {
9914               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9915               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9916               if (options.model == MODEL_FLAT24)
9917                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9918             }
9919           else
9920             {
9921               /* We need to generate a load to DPTR indirect through DPTR. */
9922               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9923               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9924               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9925               if (options.model == MODEL_FLAT24)
9926                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9927               emitcode ("pop", "dph");
9928               emitcode ("pop", "dpl");
9929               dopi =0;
9930             }
9931           _endLazyDPSEvaluation ();
9932         }
9933     }
9934   /* so dptr know contains the address */
9935   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9936
9937   /* if bit then unpack */
9938   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9939       if (AOP_INDPTRn(left)) {
9940           genSetDPTR(AOP(left)->aopu.dptr);
9941       }
9942       genUnpackBits (result, "dptr", FPOINTER);
9943       if (AOP_INDPTRn(left)) {
9944           genSetDPTR(0);
9945       }
9946   } else
9947     {
9948       size = AOP_SIZE (result);
9949       offset = 0;
9950
9951       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9952           while (size--) {
9953               genSetDPTR(AOP(left)->aopu.dptr);
9954               emitcode ("movx", "a,@dptr");
9955               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9956                   emitcode ("inc", "dptr");
9957               genSetDPTR (0);
9958               aopPut (AOP (result), "a", offset++);
9959           }
9960       } else {
9961           _startLazyDPSEvaluation ();
9962           while (size--) {
9963               if (AOP_INDPTRn(left)) {
9964                   genSetDPTR(AOP(left)->aopu.dptr);
9965               } else {
9966                   genSetDPTR (0);
9967               }
9968               _flushLazyDPS ();
9969               
9970               emitcode ("movx", "a,@dptr");
9971               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9972                   emitcode ("inc", "dptr");
9973               
9974               aopPut (AOP (result), "a", offset++);
9975           }
9976           _endLazyDPSEvaluation ();
9977       }
9978     }
9979   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9980       if (!AOP_INDPTRn(left)) {
9981           _startLazyDPSEvaluation ();
9982           aopPut ( AOP (left), "dpl", 0);
9983           aopPut ( AOP (left), "dph", 1);
9984           if (options.model == MODEL_FLAT24)
9985               aopPut ( AOP (left), "dpx", 2);
9986           _endLazyDPSEvaluation ();
9987       }
9988     pi->generated = 1;
9989   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9990              AOP_SIZE(result) > 1 &&
9991              IS_SYMOP(left) &&
9992              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9993       
9994       size = AOP_SIZE (result) - 1;
9995       if (AOP_INDPTRn(left)) {
9996           genSetDPTR(AOP(left)->aopu.dptr);
9997       }
9998       while (size--) emitcode ("lcall","__decdptr");
9999       if (AOP_INDPTRn(left)) {
10000           genSetDPTR(0);
10001       }
10002   }
10003
10004   freeAsmop (left, NULL, ic, TRUE);
10005   freeAsmop (result, NULL, ic, TRUE);
10006 }
10007
10008 /*-----------------------------------------------------------------*/
10009 /* genCodePointerGet - get value from code space                  */
10010 /*-----------------------------------------------------------------*/
10011 static void
10012 genCodePointerGet (operand * left,
10013                     operand * result, iCode * ic, iCode *pi)
10014 {
10015   int size, offset, dopi=1;
10016   sym_link *retype = getSpec (operandType (result));
10017
10018   aopOp (left, ic, FALSE, FALSE);
10019
10020   /* if the operand is already in dptr
10021      then we do nothing else we move the value to dptr */
10022   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10023     {
10024       /* if this is remateriazable */
10025       if (AOP_TYPE (left) == AOP_IMMD)
10026         {
10027           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10028         }
10029       else
10030         {                       /* we need to get it byte by byte */
10031           _startLazyDPSEvaluation ();
10032           if (AOP_TYPE (left) != AOP_DPTR)
10033             {
10034               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10035               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10036               if (options.model == MODEL_FLAT24)
10037                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10038             }
10039           else
10040             {
10041               /* We need to generate a load to DPTR indirect through DPTR. */
10042               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10043               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10044               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10045               if (options.model == MODEL_FLAT24)
10046                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10047               emitcode ("pop", "dph");
10048               emitcode ("pop", "dpl");
10049               dopi=0;
10050             }
10051           _endLazyDPSEvaluation ();
10052         }
10053     }
10054   /* so dptr know contains the address */
10055   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10056
10057   /* if bit then unpack */
10058   if (IS_BITFIELD (retype)) {
10059       if (AOP_INDPTRn(left)) {
10060           genSetDPTR(AOP(left)->aopu.dptr);
10061       }
10062       genUnpackBits (result, "dptr", CPOINTER);
10063       if (AOP_INDPTRn(left)) {
10064           genSetDPTR(0);
10065       }
10066   } else
10067     {
10068       size = AOP_SIZE (result);
10069       offset = 0;
10070       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10071           while (size--) {
10072               genSetDPTR(AOP(left)->aopu.dptr);
10073               emitcode ("clr", "a");
10074               emitcode ("movc", "a,@a+dptr");
10075               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10076                   emitcode ("inc", "dptr");
10077               genSetDPTR (0);
10078               aopPut (AOP (result), "a", offset++);
10079           }
10080       } else {
10081           _startLazyDPSEvaluation ();
10082           while (size--)
10083               {
10084                   if (AOP_INDPTRn(left)) {
10085                       genSetDPTR(AOP(left)->aopu.dptr);
10086                   } else {
10087                       genSetDPTR (0);
10088                   }
10089                   _flushLazyDPS ();
10090                   
10091                   emitcode ("clr", "a");
10092                   emitcode ("movc", "a,@a+dptr");
10093                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10094                       emitcode ("inc", "dptr");
10095                   aopPut (AOP (result), "a", offset++);
10096               }
10097           _endLazyDPSEvaluation ();
10098       }
10099     }
10100   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10101       if (!AOP_INDPTRn(left)) {
10102           _startLazyDPSEvaluation ();
10103           
10104           aopPut ( AOP (left), "dpl", 0);
10105           aopPut ( AOP (left), "dph", 1);
10106           if (options.model == MODEL_FLAT24)
10107               aopPut ( AOP (left), "dpx", 2);
10108
10109           _endLazyDPSEvaluation ();
10110       }
10111       pi->generated = 1;
10112   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
10113              AOP_SIZE(result) > 1 &&
10114              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10115       
10116       size = AOP_SIZE (result) - 1;
10117       if (AOP_INDPTRn(left)) {
10118           genSetDPTR(AOP(left)->aopu.dptr);
10119       }
10120       while (size--) emitcode ("lcall","__decdptr");
10121       if (AOP_INDPTRn(left)) {
10122           genSetDPTR(0);
10123       }
10124   }
10125   
10126   freeAsmop (left, NULL, ic, TRUE);
10127   freeAsmop (result, NULL, ic, TRUE);
10128 }
10129
10130 /*-----------------------------------------------------------------*/
10131 /* genGenPointerGet - gget value from generic pointer space        */
10132 /*-----------------------------------------------------------------*/
10133 static void
10134 genGenPointerGet (operand * left,
10135                   operand * result, iCode * ic, iCode * pi)
10136 {
10137   int size, offset;
10138   sym_link *retype = getSpec (operandType (result));
10139   sym_link *letype = getSpec (operandType (left));
10140
10141   D (emitcode (";", "genGenPointerGet "); );
10142
10143   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10144
10145   /* if the operand is already in dptr
10146      then we do nothing else we move the value to dptr */
10147   if (AOP_TYPE (left) != AOP_STR)
10148     {
10149       /* if this is remateriazable */
10150       if (AOP_TYPE (left) == AOP_IMMD)
10151         {
10152           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10153           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
10154             {
10155                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10156             }
10157             else
10158             {
10159                 emitcode ("mov", "b,#%d", pointerCode (retype));
10160             }
10161         }
10162       else
10163         {                       /* we need to get it byte by byte */
10164             _startLazyDPSEvaluation ();
10165             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10166             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10167             if (options.model == MODEL_FLAT24) {
10168                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10169                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10170             } else {
10171                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10172             }
10173             _endLazyDPSEvaluation ();
10174         }
10175     }
10176
10177   /* so dptr-b now contains the address */
10178   _G.bInUse++;
10179   aopOp (result, ic, FALSE, TRUE);
10180   _G.bInUse--;
10181
10182   /* if bit then unpack */
10183   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10184   {
10185     genUnpackBits (result, "dptr", GPOINTER);
10186   }
10187   else
10188     {
10189         size = AOP_SIZE (result);
10190         offset = 0;
10191
10192         while (size--)
10193         {
10194             if (size)
10195             {
10196                 // Get two bytes at a time, results in _AP & A.
10197                 // dptr will be incremented ONCE by __gptrgetWord.
10198                 //
10199                 // Note: any change here must be coordinated
10200                 // with the implementation of __gptrgetWord
10201                 // in device/lib/_gptrget.c
10202                 emitcode ("lcall", "__gptrgetWord");
10203                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10204                 aopPut (AOP (result), "a", offset++);
10205                 size--;
10206             }
10207             else
10208             {
10209                 // Only one byte to get.
10210                 emitcode ("lcall", "__gptrget");
10211                 aopPut (AOP (result), "a", offset++);
10212             }
10213             
10214             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10215             {
10216                 emitcode ("inc", "dptr");
10217             }
10218         }
10219     }
10220
10221   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10222     _startLazyDPSEvaluation ();
10223       
10224     aopPut ( AOP (left), "dpl", 0);
10225     aopPut ( AOP (left), "dph", 1);
10226     if (options.model == MODEL_FLAT24) {
10227         aopPut ( AOP (left), "dpx", 2);
10228         aopPut ( AOP (left), "b", 3);   
10229     } else  aopPut ( AOP (left), "b", 2);       
10230     
10231     _endLazyDPSEvaluation ();
10232       
10233     pi->generated = 1;
10234   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10235              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10236       
10237       size = AOP_SIZE (result) - 1;
10238       while (size--) emitcode ("lcall","__decdptr");
10239   }
10240
10241   freeAsmop (left, NULL, ic, TRUE);
10242   freeAsmop (result, NULL, ic, TRUE);
10243 }
10244
10245 /*-----------------------------------------------------------------*/
10246 /* genPointerGet - generate code for pointer get                   */
10247 /*-----------------------------------------------------------------*/
10248 static void
10249 genPointerGet (iCode * ic, iCode *pi)
10250 {
10251   operand *left, *result;
10252   sym_link *type, *etype;
10253   int p_type;
10254
10255   D (emitcode (";", "genPointerGet ");
10256     );
10257
10258   left = IC_LEFT (ic);
10259   result = IC_RESULT (ic);
10260
10261   /* depending on the type of pointer we need to
10262      move it to the correct pointer register */
10263   type = operandType (left);
10264   etype = getSpec (type);
10265   /* if left is of type of pointer then it is simple */
10266   if (IS_PTR (type) && !IS_FUNC (type->next))
10267     p_type = DCL_TYPE (type);
10268   else
10269     {
10270       /* we have to go by the storage class */
10271       p_type = PTR_TYPE (SPEC_OCLS (etype));
10272     }
10273   /* special case when cast remat */
10274   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10275       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10276           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10277           type = operandType (left);
10278           p_type = DCL_TYPE (type);
10279   }
10280   /* now that we have the pointer type we assign
10281      the pointer values */
10282   switch (p_type)
10283     {
10284
10285     case POINTER:
10286     case IPOINTER:
10287       genNearPointerGet (left, result, ic, pi);
10288       break;
10289
10290     case PPOINTER:
10291       genPagedPointerGet (left, result, ic, pi);
10292       break;
10293
10294     case FPOINTER:
10295       genFarPointerGet (left, result, ic, pi);
10296       break;
10297
10298     case CPOINTER:
10299       genCodePointerGet (left, result, ic, pi);
10300       break;
10301
10302     case GPOINTER:
10303       genGenPointerGet (left, result, ic, pi);
10304       break;
10305     }
10306
10307 }
10308
10309 /*-----------------------------------------------------------------*/
10310 /* genPackBits - generates code for packed bit storage             */
10311 /*-----------------------------------------------------------------*/
10312 static void
10313 genPackBits (sym_link * etype,
10314              operand * right,
10315              char *rname, int p_type)
10316 {
10317   int offset = 0;       /* source byte offset */
10318   int rlen = 0;         /* remaining bitfield length */
10319   int blen;             /* bitfield length */
10320   int bstr;             /* bitfield starting bit within byte */
10321   int litval;           /* source literal value (if AOP_LIT) */
10322   unsigned char mask;   /* bitmask within current byte */
10323
10324   D(emitcode (";     genPackBits",""));
10325
10326   blen = SPEC_BLEN (etype);
10327   bstr = SPEC_BSTR (etype);
10328
10329   /* If the bitfield length is less than a byte */
10330   if (blen < 8)
10331     {
10332       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10333               (unsigned char) (0xFF >> (8 - bstr)));
10334
10335       if (AOP_TYPE (right) == AOP_LIT)
10336         {
10337           /* Case with a bitfield length <8 and literal source
10338           */
10339           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10340           litval <<= bstr;
10341           litval &= (~mask) & 0xff;
10342           emitPtrByteGet (rname, p_type, FALSE);
10343           if ((mask|litval)!=0xff)
10344             emitcode ("anl","a,#!constbyte", mask);
10345           if (litval)
10346             emitcode ("orl","a,#!constbyte", litval);
10347         }
10348       else
10349         {
10350           if ((blen==1) && (p_type!=GPOINTER))
10351             {
10352               /* Case with a bitfield length == 1 and no generic pointer
10353               */
10354               if (AOP_TYPE (right) == AOP_CRY)
10355                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10356               else
10357                 {
10358                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10359                   emitcode ("rrc","a");
10360                 }
10361               emitPtrByteGet (rname, p_type, FALSE);
10362               emitcode ("mov","acc.%d,c",bstr);
10363             }
10364           else
10365             {
10366               /* Case with a bitfield length < 8 and arbitrary source
10367               */
10368               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10369               /* shift and mask source value */
10370               AccLsh (bstr);
10371               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10372
10373               /* transfer A to B and get next byte */
10374               emitPtrByteGet (rname, p_type, TRUE);
10375
10376               emitcode ("anl", "a,#!constbyte", mask);
10377               emitcode ("orl", "a,b");
10378               if (p_type == GPOINTER)
10379                 emitcode ("pop", "b");
10380            }
10381         }
10382
10383       emitPtrByteSet (rname, p_type, "a");
10384       return;
10385     }
10386
10387   /* Bit length is greater than 7 bits. In this case, copy  */
10388   /* all except the partial byte at the end                 */
10389   for (rlen=blen;rlen>=8;rlen-=8)
10390     {
10391       emitPtrByteSet (rname, p_type, 
10392                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10393       if (rlen>8)
10394         emitcode ("inc", "%s", rname);
10395     }
10396
10397   /* If there was a partial byte at the end */
10398   if (rlen)
10399     {
10400       mask = (((unsigned char) -1 << rlen) & 0xff);
10401       
10402       if (AOP_TYPE (right) == AOP_LIT)
10403         {
10404           /* Case with partial byte and literal source
10405           */
10406           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10407           litval >>= (blen-rlen);
10408           litval &= (~mask) & 0xff;
10409           emitPtrByteGet (rname, p_type, FALSE);
10410           if ((mask|litval)!=0xff)
10411             emitcode ("anl","a,#!constbyte", mask);
10412           if (litval)
10413             emitcode ("orl","a,#!constbyte", litval);
10414         }
10415       else
10416         {
10417           /* Case with partial byte and arbitrary source
10418           */
10419           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10420           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10421
10422           /* transfer A to B and get next byte */
10423           emitPtrByteGet (rname, p_type, TRUE);
10424
10425           emitcode ("anl", "a,#!constbyte", mask);
10426           emitcode ("orl", "a,b");
10427           if (p_type == GPOINTER)
10428             emitcode ("pop", "b");
10429         }
10430       emitPtrByteSet (rname, p_type, "a");
10431     }
10432
10433 }
10434
10435
10436 /*-----------------------------------------------------------------*/
10437 /* genDataPointerSet - remat pointer to data space                 */
10438 /*-----------------------------------------------------------------*/
10439 static void
10440 genDataPointerSet (operand * right,
10441                    operand * result,
10442                    iCode * ic)
10443 {
10444   int size, offset = 0;
10445   char *l, buff[256];
10446
10447   aopOp (right, ic, FALSE, FALSE);
10448
10449   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10450   size = AOP_SIZE (right);
10451   while (size--)
10452     {
10453       if (offset)
10454         {
10455             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10456         }
10457       else
10458         {
10459             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10460         }
10461         
10462       emitcode ("mov", "%s,%s", buff,
10463                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10464     }
10465
10466   freeAsmop (right, NULL, ic, TRUE);
10467   freeAsmop (result, NULL, ic, TRUE);
10468 }
10469
10470 /*-----------------------------------------------------------------*/
10471 /* genNearPointerSet - emitcode for near pointer put                */
10472 /*-----------------------------------------------------------------*/
10473 static void
10474 genNearPointerSet (operand * right,
10475                    operand * result,
10476                    iCode * ic,
10477                    iCode * pi)
10478 {
10479   asmop *aop = NULL;
10480   char *rname, *l;
10481   sym_link *retype, *letype;
10482   sym_link *ptype = operandType (result);
10483
10484   retype = getSpec (operandType (right));
10485   letype = getSpec (ptype);
10486
10487   aopOp (result, ic, FALSE, FALSE);
10488
10489   /* if the result is rematerializable &
10490      in data space & not a bit variable */
10491   if (AOP_TYPE (result) == AOP_IMMD &&
10492       DCL_TYPE (ptype) == POINTER &&
10493       !IS_BITVAR (retype) &&
10494       !IS_BITVAR (letype))
10495     {
10496       genDataPointerSet (right, result, ic);
10497       return;
10498     }
10499
10500   /* if the value is already in a pointer register
10501      then don't need anything more */
10502   if (!AOP_INPREG (AOP (result)))
10503     {
10504       /* otherwise get a free pointer register */
10505       regs *preg;
10506         
10507       aop = newAsmop (0);
10508       preg = getFreePtr (ic, &aop, FALSE);
10509       emitcode ("mov", "%s,%s",
10510                 preg->name,
10511                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10512       rname = preg->name;
10513     }
10514   else
10515     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10516
10517   aopOp (right, ic, FALSE, FALSE);
10518
10519   /* if bitfield then unpack the bits */
10520   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10521     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10522   else
10523     {
10524       /* we have can just get the values */
10525       int size = AOP_SIZE (right);
10526       int offset = 0;
10527
10528       while (size--)
10529         {
10530           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10531           if (*l == '@')
10532             {
10533               MOVA (l);
10534               emitcode ("mov", "@%s,a", rname);
10535             }
10536           else
10537             emitcode ("mov", "@%s,%s", rname, l);
10538           if (size || pi)
10539             emitcode ("inc", "%s", rname);
10540           offset++;
10541         }
10542     }
10543
10544   /* now some housekeeping stuff */
10545   if (aop)
10546     {
10547       /* we had to allocate for this iCode */
10548       if (pi) aopPut (AOP (result),rname,0);
10549       freeAsmop (NULL, aop, ic, TRUE);
10550     }
10551   else
10552     {
10553       /* we did not allocate which means left
10554          already in a pointer register, then
10555          if size > 0 && this could be used again
10556          we have to point it back to where it
10557          belongs */
10558       if (AOP_SIZE (right) > 1 &&
10559           !OP_SYMBOL (result)->remat &&
10560           (OP_SYMBOL (result)->liveTo > ic->seq ||
10561            ic->depth) &&
10562           !pi)
10563         {
10564           int size = AOP_SIZE (right) - 1;
10565           while (size--)
10566             emitcode ("dec", "%s", rname);
10567         }
10568     }
10569
10570   /* done */
10571   if (pi) pi->generated = 1;
10572   freeAsmop (result, NULL, ic, TRUE);
10573   freeAsmop (right, NULL, ic, TRUE);
10574
10575
10576 }
10577
10578 /*-----------------------------------------------------------------*/
10579 /* genPagedPointerSet - emitcode for Paged pointer put             */
10580 /*-----------------------------------------------------------------*/
10581 static void
10582 genPagedPointerSet (operand * right,
10583                     operand * result,
10584                     iCode * ic,
10585                     iCode *pi)
10586 {
10587   asmop *aop = NULL;
10588   char *rname;
10589   sym_link *retype, *letype;
10590
10591   retype = getSpec (operandType (right));
10592   letype = getSpec (operandType (result));
10593
10594   aopOp (result, ic, FALSE, FALSE);
10595
10596   /* if the value is already in a pointer register
10597      then don't need anything more */
10598   if (!AOP_INPREG (AOP (result)))
10599     {
10600       /* otherwise get a free pointer register */
10601       regs *preg;
10602         
10603       aop = newAsmop (0);
10604       preg = getFreePtr (ic, &aop, FALSE);
10605       emitcode ("mov", "%s,%s",
10606                 preg->name,
10607                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10608       rname = preg->name;
10609     }
10610   else
10611     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10612
10613   aopOp (right, ic, FALSE, FALSE);
10614
10615   /* if bitfield then unpack the bits */
10616   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10617     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10618   else
10619     {
10620       /* we have can just get the values */
10621       int size = AOP_SIZE (right);
10622       int offset = 0;
10623
10624       while (size--)
10625         {
10626           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10627
10628           emitcode ("movx", "@%s,a", rname);
10629
10630           if (size || pi)
10631             emitcode ("inc", "%s", rname);
10632
10633           offset++;
10634         }
10635     }
10636
10637   /* now some housekeeping stuff */
10638   if (aop)
10639     {
10640       if (pi) aopPut (AOP (result),rname,0);
10641       /* we had to allocate for this iCode */
10642       freeAsmop (NULL, aop, ic, TRUE);
10643     }
10644   else
10645     {
10646       /* we did not allocate which means left
10647          already in a pointer register, then
10648          if size > 0 && this could be used again
10649          we have to point it back to where it
10650          belongs */
10651       if (AOP_SIZE (right) > 1 &&
10652           !OP_SYMBOL (result)->remat &&
10653           (OP_SYMBOL (result)->liveTo > ic->seq ||
10654            ic->depth) &&
10655           !pi)
10656         {
10657           int size = AOP_SIZE (right) - 1;
10658           while (size--)
10659             emitcode ("dec", "%s", rname);
10660         }
10661     }
10662
10663   /* done */
10664   if (pi) pi->generated = 1;
10665   freeAsmop (result, NULL, ic, TRUE);
10666   freeAsmop (right, NULL, ic, TRUE);
10667
10668
10669 }
10670
10671 /*-----------------------------------------------------------------*/
10672 /* genFarPointerSet - set value from far space                     */
10673 /*-----------------------------------------------------------------*/
10674 static void
10675 genFarPointerSet (operand * right,
10676                   operand * result, iCode * ic, iCode *pi)
10677 {
10678   int size, offset, dopi=1;
10679   sym_link *retype = getSpec (operandType (right));
10680   sym_link *letype = getSpec (operandType (result));
10681
10682   aopOp (result, ic, FALSE, FALSE);
10683
10684   /* if the operand is already in dptr
10685      then we do nothing else we move the value to dptr */
10686   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10687     {
10688       /* if this is remateriazable */
10689       if (AOP_TYPE (result) == AOP_IMMD)
10690         emitcode ("mov", "dptr,%s", 
10691                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10692       else
10693         {
10694           /* we need to get it byte by byte */
10695           _startLazyDPSEvaluation ();
10696           if (AOP_TYPE (result) != AOP_DPTR)
10697             {
10698               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10699               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10700               if (options.model == MODEL_FLAT24)
10701                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10702             }
10703           else
10704             {
10705               /* We need to generate a load to DPTR indirect through DPTR. */
10706               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10707                 
10708               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10709               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10710               if (options.model == MODEL_FLAT24)
10711                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10712               emitcode ("pop", "dph");
10713               emitcode ("pop", "dpl");
10714               dopi=0;
10715             }
10716           _endLazyDPSEvaluation ();
10717         }
10718     }
10719   /* so dptr know contains the address */
10720   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10721
10722   /* if bit then unpack */
10723   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10724       if (AOP_INDPTRn(result)) {
10725           genSetDPTR(AOP(result)->aopu.dptr);
10726       }
10727       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10728       if (AOP_INDPTRn(result)) {
10729           genSetDPTR(0);
10730       }
10731   } else {
10732       size = AOP_SIZE (right);
10733       offset = 0;
10734       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10735           while (size--) {
10736               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10737               
10738               genSetDPTR(AOP(result)->aopu.dptr);
10739               emitcode ("movx", "@dptr,a");
10740               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10741                   emitcode ("inc", "dptr");
10742               genSetDPTR (0);
10743           }
10744       } else {
10745           _startLazyDPSEvaluation ();
10746           while (size--) {
10747               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10748               
10749               if (AOP_INDPTRn(result)) {
10750                   genSetDPTR(AOP(result)->aopu.dptr);
10751               } else {
10752                   genSetDPTR (0);
10753               }
10754               _flushLazyDPS ();
10755               
10756               emitcode ("movx", "@dptr,a");
10757               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10758                   emitcode ("inc", "dptr");
10759           }
10760           _endLazyDPSEvaluation ();
10761       }
10762   }
10763   
10764   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10765       if (!AOP_INDPTRn(result)) {
10766           _startLazyDPSEvaluation ();
10767           
10768           aopPut (AOP(result),"dpl",0);
10769           aopPut (AOP(result),"dph",1);
10770           if (options.model == MODEL_FLAT24)
10771               aopPut (AOP(result),"dpx",2);
10772
10773           _endLazyDPSEvaluation ();
10774       }
10775       pi->generated=1;
10776   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10777              AOP_SIZE(right) > 1 &&
10778              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10779       
10780       size = AOP_SIZE (right) - 1;
10781       if (AOP_INDPTRn(result)) {
10782           genSetDPTR(AOP(result)->aopu.dptr);
10783       } 
10784       while (size--) emitcode ("lcall","__decdptr");
10785       if (AOP_INDPTRn(result)) {
10786           genSetDPTR(0);
10787       }
10788   }
10789   freeAsmop (result, NULL, ic, TRUE);
10790   freeAsmop (right, NULL, ic, TRUE);
10791 }
10792
10793 /*-----------------------------------------------------------------*/
10794 /* genGenPointerSet - set value from generic pointer space         */
10795 /*-----------------------------------------------------------------*/
10796 static void
10797 genGenPointerSet (operand * right,
10798                   operand * result, iCode * ic, iCode *pi)
10799 {
10800   int size, offset;
10801   sym_link *retype = getSpec (operandType (right));
10802   sym_link *letype = getSpec (operandType (result));
10803
10804   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10805
10806   /* if the operand is already in dptr
10807      then we do nothing else we move the value to dptr */
10808   if (AOP_TYPE (result) != AOP_STR)
10809     {
10810       _startLazyDPSEvaluation ();
10811       /* if this is remateriazable */
10812       if (AOP_TYPE (result) == AOP_IMMD)
10813         {
10814           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10815           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10816           {
10817               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10818           }
10819           else
10820           {
10821               emitcode ("mov", 
10822                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10823           }
10824         }
10825       else
10826         {                       /* we need to get it byte by byte */
10827           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10828           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10829           if (options.model == MODEL_FLAT24) {
10830             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10831             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10832           } else {
10833             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10834           }
10835         }
10836       _endLazyDPSEvaluation ();
10837     }
10838   /* so dptr + b now contains the address */
10839   _G.bInUse++;
10840   aopOp (right, ic, FALSE, TRUE);
10841   _G.bInUse--;
10842     
10843
10844   /* if bit then unpack */
10845   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10846     {
10847         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10848     }
10849   else
10850     {
10851         size = AOP_SIZE (right);
10852         offset = 0;
10853
10854         _startLazyDPSEvaluation ();
10855         while (size--)
10856         {
10857             if (size)
10858             {
10859                 // Set two bytes at a time, passed in _AP & A.
10860                 // dptr will be incremented ONCE by __gptrputWord.
10861                 //
10862                 // Note: any change here must be coordinated
10863                 // with the implementation of __gptrputWord
10864                 // in device/lib/_gptrput.c
10865                 emitcode("mov", "_ap, %s", 
10866                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10867                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10868                 
10869                 genSetDPTR (0);
10870                 _flushLazyDPS ();
10871                 emitcode ("lcall", "__gptrputWord");
10872                 size--;
10873             }
10874             else
10875             {
10876                 // Only one byte to put.
10877                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10878
10879                 genSetDPTR (0);
10880                 _flushLazyDPS ();               
10881                 emitcode ("lcall", "__gptrput");
10882             }
10883             
10884             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10885             {
10886                 emitcode ("inc", "dptr");
10887             }
10888         }
10889         _endLazyDPSEvaluation ();
10890     }
10891
10892   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10893       _startLazyDPSEvaluation ();
10894       
10895       aopPut (AOP(result),"dpl",0);
10896       aopPut (AOP(result),"dph",1);
10897       if (options.model == MODEL_FLAT24) {
10898           aopPut (AOP(result),"dpx",2);
10899           aopPut (AOP(result),"b",3);
10900       } else {
10901           aopPut (AOP(result),"b",2);
10902       }
10903       _endLazyDPSEvaluation ();
10904       
10905       pi->generated=1;
10906   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10907              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10908       
10909       size = AOP_SIZE (right) - 1;
10910       while (size--) emitcode ("lcall","__decdptr");
10911   }
10912   freeAsmop (result, NULL, ic, TRUE);
10913   freeAsmop (right, NULL, ic, TRUE);
10914 }
10915
10916 /*-----------------------------------------------------------------*/
10917 /* genPointerSet - stores the value into a pointer location        */
10918 /*-----------------------------------------------------------------*/
10919 static void
10920 genPointerSet (iCode * ic, iCode *pi)
10921 {
10922   operand *right, *result;
10923   sym_link *type, *etype;
10924   int p_type;
10925
10926   D (emitcode (";", "genPointerSet "););
10927
10928   right = IC_RIGHT (ic);
10929   result = IC_RESULT (ic);
10930
10931   /* depending on the type of pointer we need to
10932      move it to the correct pointer register */
10933   type = operandType (result);
10934   etype = getSpec (type);
10935   /* if left is of type of pointer then it is simple */
10936   if (IS_PTR (type) && !IS_FUNC (type->next))
10937     {
10938       p_type = DCL_TYPE (type);
10939     }
10940   else
10941     {
10942       /* we have to go by the storage class */
10943       p_type = PTR_TYPE (SPEC_OCLS (etype));
10944     }
10945   /* special case when cast remat */
10946   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10947       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10948           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10949           type = operandType (result);
10950           p_type = DCL_TYPE (type);
10951   }
10952
10953   /* now that we have the pointer type we assign
10954      the pointer values */
10955   switch (p_type)
10956     {
10957
10958     case POINTER:
10959     case IPOINTER:
10960       genNearPointerSet (right, result, ic, pi);
10961       break;
10962
10963     case PPOINTER:
10964       genPagedPointerSet (right, result, ic, pi);
10965       break;
10966
10967     case FPOINTER:
10968       genFarPointerSet (right, result, ic, pi);
10969       break;
10970
10971     case GPOINTER:
10972       genGenPointerSet (right, result, ic, pi);
10973       break;
10974
10975     default:
10976       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10977               "genPointerSet: illegal pointer type");
10978     }
10979
10980 }
10981
10982 /*-----------------------------------------------------------------*/
10983 /* genIfx - generate code for Ifx statement                        */
10984 /*-----------------------------------------------------------------*/
10985 static void
10986 genIfx (iCode * ic, iCode * popIc)
10987 {
10988   operand *cond = IC_COND (ic);
10989   int isbit = 0;
10990
10991   D (emitcode (";", "genIfx "););
10992
10993   aopOp (cond, ic, FALSE, FALSE);
10994
10995   /* get the value into acc */
10996   if (AOP_TYPE (cond) != AOP_CRY)
10997     {
10998         toBoolean (cond);
10999     }
11000   else
11001     {
11002         isbit = 1;
11003     }
11004     
11005   /* the result is now in the accumulator */
11006   freeAsmop (cond, NULL, ic, TRUE);
11007
11008   /* if there was something to be popped then do it */
11009   if (popIc)
11010     genIpop (popIc);
11011
11012   /* if the condition is  a bit variable */
11013   if (isbit && IS_ITEMP (cond) &&
11014       SPIL_LOC (cond))
11015     {
11016         genIfxJump (ic, SPIL_LOC (cond)->rname);
11017     }
11018   else if (isbit && !IS_ITEMP (cond))
11019     {
11020         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11021     }
11022   else
11023     {
11024         genIfxJump (ic, "a");
11025     }
11026
11027   ic->generated = 1;
11028 }
11029
11030 /*-----------------------------------------------------------------*/
11031 /* genAddrOf - generates code for address of                       */
11032 /*-----------------------------------------------------------------*/
11033 static void
11034 genAddrOf (iCode * ic)
11035 {
11036   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11037   int size, offset;
11038
11039   D (emitcode (";", "genAddrOf ");
11040     );
11041
11042   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11043
11044   /* if the operand is on the stack then we
11045      need to get the stack offset of this
11046      variable */
11047   if (sym->onStack) {
11048       
11049       /* if 10 bit stack */
11050       if (options.stack10bit) {
11051           char buff[10];
11052           int  offset;
11053           
11054           tsprintf(buff, sizeof(buff), 
11055                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11056           /* if it has an offset then we need to compute it */
11057 /*        emitcode ("subb", "a,#!constbyte", */
11058 /*                  -((sym->stack < 0) ? */
11059 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11060 /*                    ((short) sym->stack)) & 0xff); */
11061 /*        emitcode ("mov","b,a"); */
11062 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11063 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11064 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11065           if (sym->stack) {
11066               emitcode ("mov", "a,_bpx");
11067               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
11068                                              ((char) (sym->stack - _G.nRegsSaved)) :
11069                                              ((char) sym->stack )) & 0xff);
11070               emitcode ("mov", "b,a");
11071               emitcode ("mov", "a,_bpx+1");
11072               
11073               offset = (((sym->stack < 0) ? 
11074                          ((short) (sym->stack - _G.nRegsSaved)) :
11075                          ((short) sym->stack )) >> 8) & 0xff;
11076           
11077               emitcode ("addc","a,#!constbyte", offset);
11078
11079               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11080               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11081               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11082           } else {
11083               /* we can just move _bp */
11084               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11085               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11086               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11087           }       
11088       } else {
11089           /* if it has an offset then we need to compute it */
11090           if (sym->stack) {
11091               emitcode ("mov", "a,_bp");
11092               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11093               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11094           } else {
11095               /* we can just move _bp */
11096               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11097           }
11098           /* fill the result with zero */
11099           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11100           
11101           
11102           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11103               fprintf (stderr,
11104                        "*** warning: pointer to stack var truncated.\n");
11105           }
11106
11107           offset = 1;
11108           while (size--) {
11109               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11110           }      
11111       }
11112       goto release;
11113   }
11114
11115   /* object not on stack then we need the name */
11116   size = AOP_SIZE (IC_RESULT (ic));
11117   offset = 0;
11118
11119   while (size--)
11120     {
11121       char s[SDCC_NAME_MAX];
11122       if (offset) {
11123           switch (offset) {
11124           case 1:
11125               tsprintf(s, sizeof(s), "#!his",sym->rname);
11126               break;
11127           case 2:
11128               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11129               break;
11130           case 3:
11131               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11132               break;
11133           default: /* should not need this (just in case) */
11134               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11135                        sym->rname,
11136                        offset * 8);
11137           }
11138       } 
11139       else
11140       {
11141           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11142       }
11143         
11144       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11145     }
11146
11147 release:
11148   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11149
11150 }
11151
11152 #if 0 // obsolete, and buggy for != xdata
11153 /*-----------------------------------------------------------------*/
11154 /* genArrayInit - generates code for address of                       */
11155 /*-----------------------------------------------------------------*/
11156 static void
11157 genArrayInit (iCode * ic)
11158 {
11159     literalList *iLoop;
11160     int         ix, count;
11161     int         elementSize = 0, eIndex;
11162     unsigned    val, lastVal;
11163     sym_link    *type;
11164     operand     *left=IC_LEFT(ic);
11165     
11166     D (emitcode (";", "genArrayInit "););
11167
11168     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11169     
11170     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11171     {
11172         // Load immediate value into DPTR.
11173         emitcode("mov", "dptr, %s",
11174              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11175     }
11176     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11177     {
11178 #if 0
11179       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11180               "Unexpected operand to genArrayInit.\n");
11181       exit(1);
11182 #else
11183       // a regression because of SDCCcse.c:1.52
11184       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11185       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11186       if (options.model == MODEL_FLAT24)
11187         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11188 #endif
11189     }
11190     
11191     type = operandType(IC_LEFT(ic));
11192     
11193     if (type && type->next)
11194     {
11195         elementSize = getSize(type->next);
11196     }
11197     else
11198     {
11199         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11200                                 "can't determine element size in genArrayInit.\n");
11201         exit(1);
11202     }
11203     
11204     iLoop = IC_ARRAYILIST(ic);
11205     lastVal = 0xffff;
11206     
11207     while (iLoop)
11208     {
11209         bool firstpass = TRUE;
11210         
11211         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
11212                  iLoop->count, (int)iLoop->literalValue, elementSize);
11213         
11214         ix = iLoop->count;
11215         
11216         while (ix)
11217         {
11218             symbol *tlbl = NULL;
11219             
11220             count = ix > 256 ? 256 : ix;
11221             
11222             if (count > 1)
11223             {
11224                 tlbl = newiTempLabel (NULL);
11225                 if (firstpass || (count & 0xff))
11226                 {
11227                     emitcode("mov", "b, #!constbyte", count & 0xff);
11228                 }
11229                 
11230                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11231             }
11232             
11233             firstpass = FALSE;
11234                 
11235             for (eIndex = 0; eIndex < elementSize; eIndex++)
11236             {
11237                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11238                 if (val != lastVal)
11239                 {
11240                     emitcode("mov", "a, #!constbyte", val);
11241                     lastVal = val;
11242                 }
11243                 
11244                 emitcode("movx", "@dptr, a");
11245                 emitcode("inc", "dptr");
11246             }
11247             
11248             if (count > 1)
11249             {
11250                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11251             }
11252             
11253             ix -= count;
11254         }
11255         
11256         iLoop = iLoop->next;
11257     }
11258     
11259     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11260 }
11261 #endif
11262
11263 /*-----------------------------------------------------------------*/
11264 /* genFarFarAssign - assignment when both are in far space         */
11265 /*-----------------------------------------------------------------*/
11266 static void
11267 genFarFarAssign (operand * result, operand * right, iCode * ic)
11268 {
11269   int size = AOP_SIZE (right);
11270   int offset = 0;
11271   symbol *rSym = NULL;
11272
11273   if (size == 1)
11274   {
11275       /* quick & easy case. */
11276       D(emitcode(";","genFarFarAssign (1 byte case)"););      
11277       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11278       freeAsmop (right, NULL, ic, FALSE);
11279       /* now assign DPTR to result */
11280       _G.accInUse++;
11281       aopOp(result, ic, FALSE, FALSE);
11282       _G.accInUse--;
11283       aopPut(AOP(result), "a", 0);
11284       freeAsmop(result, NULL, ic, FALSE);
11285       return;
11286   }
11287   
11288   /* See if we've got an underlying symbol to abuse. */
11289   if (IS_SYMOP(result) && OP_SYMBOL(result))
11290   {
11291       if (IS_TRUE_SYMOP(result))
11292       {
11293           rSym = OP_SYMBOL(result);
11294       }
11295       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11296       {
11297           rSym = OP_SYMBOL(result)->usl.spillLoc;
11298       }
11299   }
11300              
11301   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11302   {
11303       /* We can use the '390 auto-toggle feature to good effect here. */
11304       
11305       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11306       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11307       emitcode ("mov", "dptr,#%s", rSym->rname); 
11308       /* DP2 = result, DP1 = right, DP1 is current. */
11309       while (size)
11310       {
11311           emitcode("movx", "a,@dptr");
11312           emitcode("movx", "@dptr,a");
11313           if (--size)
11314           {
11315                emitcode("inc", "dptr");
11316                emitcode("inc", "dptr");
11317           }
11318       }
11319       emitcode("mov", "dps,#0");
11320       freeAsmop (right, NULL, ic, FALSE);
11321 #if 0
11322 some alternative code for processors without auto-toggle
11323 no time to test now, so later well put in...kpb
11324         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11325         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11326         emitcode ("mov", "dptr,#%s", rSym->rname); 
11327         /* DP2 = result, DP1 = right, DP1 is current. */
11328         while (size)
11329         {
11330           --size;
11331           emitcode("movx", "a,@dptr");
11332           if (size)
11333             emitcode("inc", "dptr");
11334           emitcode("inc", "dps");
11335           emitcode("movx", "@dptr,a");
11336           if (size)
11337             emitcode("inc", "dptr");
11338           emitcode("inc", "dps");
11339         }
11340         emitcode("mov", "dps,#0");
11341         freeAsmop (right, NULL, ic, FALSE);
11342 #endif
11343   }
11344   else
11345   {
11346       D (emitcode (";", "genFarFarAssign"););
11347       aopOp (result, ic, TRUE, TRUE);
11348
11349       _startLazyDPSEvaluation ();
11350       
11351       while (size--)
11352         {
11353           aopPut (AOP (result),
11354                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11355           offset++;
11356         }
11357       _endLazyDPSEvaluation ();
11358       freeAsmop (result, NULL, ic, FALSE);
11359       freeAsmop (right, NULL, ic, FALSE);
11360   }
11361 }
11362
11363 /*-----------------------------------------------------------------*/
11364 /* genAssign - generate code for assignment                        */
11365 /*-----------------------------------------------------------------*/
11366 static void
11367 genAssign (iCode * ic)
11368 {
11369   operand *result, *right;
11370   int size, offset;
11371   unsigned long lit = 0L;
11372
11373   D (emitcode (";", "genAssign ");
11374     );
11375
11376   result = IC_RESULT (ic);
11377   right = IC_RIGHT (ic);
11378
11379   /* if they are the same */
11380   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11381     return;
11382
11383   aopOp (right, ic, FALSE, FALSE);
11384
11385   emitcode (";", "genAssign: resultIsFar = %s",
11386             isOperandInFarSpace (result) ?
11387             "TRUE" : "FALSE");
11388
11389   /* special case both in far space */
11390   if ((AOP_TYPE (right) == AOP_DPTR ||
11391        AOP_TYPE (right) == AOP_DPTR2) &&
11392   /* IS_TRUE_SYMOP(result)       && */
11393       isOperandInFarSpace (result))
11394     {
11395       genFarFarAssign (result, right, ic);
11396       return;
11397     }
11398
11399   aopOp (result, ic, TRUE, FALSE);
11400
11401   /* if they are the same registers */
11402   if (sameRegs (AOP (right), AOP (result)))
11403     goto release;
11404
11405   /* if the result is a bit */
11406   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11407     {
11408       /* if the right size is a literal then
11409          we know what the value is */
11410       if (AOP_TYPE (right) == AOP_LIT)
11411         {
11412           if (((int) operandLitValue (right)))
11413             aopPut (AOP (result), one, 0);
11414           else
11415             aopPut (AOP (result), zero, 0);
11416           goto release;
11417         }
11418
11419       /* the right is also a bit variable */
11420       if (AOP_TYPE (right) == AOP_CRY)
11421         {
11422           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11423           aopPut (AOP (result), "c", 0);
11424           goto release;
11425         }
11426
11427       /* we need to or */
11428       toBoolean (right);
11429       aopPut (AOP (result), "a", 0);
11430       goto release;
11431     }
11432
11433   /* bit variables done */
11434   /* general case */
11435   size = AOP_SIZE (result);
11436   offset = 0;
11437   if (AOP_TYPE (right) == AOP_LIT)
11438     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11439
11440   if ((size > 1) &&
11441       (AOP_TYPE (result) != AOP_REG) &&
11442       (AOP_TYPE (right) == AOP_LIT) &&
11443       !IS_FLOAT (operandType (right)))
11444     {
11445       _startLazyDPSEvaluation ();
11446       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11447         {
11448           aopPut (AOP (result),
11449                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11450                   offset);
11451           offset++;
11452           size--;
11453         }
11454       /* And now fill the rest with zeros. */
11455       if (size)
11456         {
11457           emitcode ("clr", "a");
11458         }
11459       while (size--)
11460         {
11461           aopPut (AOP (result), "a", offset++);
11462         }
11463       _endLazyDPSEvaluation ();
11464     }
11465   else
11466     {
11467       _startLazyDPSEvaluation ();
11468       while (size--)
11469         {
11470           aopPut (AOP (result),
11471                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11472                   offset);
11473           offset++;
11474         }
11475       _endLazyDPSEvaluation ();
11476     }
11477
11478 release:
11479   freeAsmop (right, NULL, ic, FALSE);
11480   freeAsmop (result, NULL, ic, TRUE);
11481 }
11482
11483 /*-----------------------------------------------------------------*/
11484 /* genJumpTab - generates code for jump table                      */
11485 /*-----------------------------------------------------------------*/
11486 static void
11487 genJumpTab (iCode * ic)
11488 {
11489   symbol *jtab;
11490   char *l;
11491
11492   D (emitcode (";", "genJumpTab ");
11493     );
11494
11495   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11496   /* get the condition into accumulator */
11497   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11498   MOVA (l);
11499   /* multiply by four! */
11500   emitcode ("add", "a,acc");
11501   emitcode ("add", "a,acc");
11502   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11503
11504   jtab = newiTempLabel (NULL);
11505   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11506   emitcode ("jmp", "@a+dptr");
11507   emitcode ("", "!tlabeldef", jtab->key + 100);
11508   /* now generate the jump labels */
11509   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11510        jtab = setNextItem (IC_JTLABELS (ic)))
11511     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11512
11513 }
11514
11515 /*-----------------------------------------------------------------*/
11516 /* genCast - gen code for casting                                  */
11517 /*-----------------------------------------------------------------*/
11518 static void
11519 genCast (iCode * ic)
11520 {
11521   operand *result = IC_RESULT (ic);
11522   sym_link *ctype = operandType (IC_LEFT (ic));
11523   sym_link *rtype = operandType (IC_RIGHT (ic));
11524   operand *right = IC_RIGHT (ic);
11525   int size, offset;
11526
11527   D (emitcode (";", "genCast "););
11528
11529   /* if they are equivalent then do nothing */
11530   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11531     return;
11532
11533   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11534   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11535
11536   /* if the result is a bit */
11537   if (IS_BITVAR (OP_SYMBOL (result)->type)
11538       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11539     {
11540       /* if the right size is a literal then
11541          we know what the value is */
11542       if (AOP_TYPE (right) == AOP_LIT)
11543         {
11544           if (((int) operandLitValue (right)))
11545             aopPut (AOP (result), one, 0);
11546           else
11547             aopPut (AOP (result), zero, 0);
11548
11549           goto release;
11550         }
11551
11552       /* the right is also a bit variable */
11553       if (AOP_TYPE (right) == AOP_CRY)
11554         {
11555           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11556           aopPut (AOP (result), "c", 0);
11557           goto release;
11558         }
11559
11560       /* we need to or */
11561       toBoolean (right);
11562       aopPut (AOP (result), "a", 0);
11563       goto release;
11564     }
11565
11566   /* if they are the same size : or less */
11567   if (AOP_SIZE (result) <= AOP_SIZE (right))
11568     {
11569
11570       /* if they are in the same place */
11571       if (sameRegs (AOP (right), AOP (result)))
11572         goto release;
11573
11574       /* if they in different places then copy */
11575       size = AOP_SIZE (result);
11576       offset = 0;
11577       _startLazyDPSEvaluation ();
11578       while (size--)
11579         {
11580           aopPut (AOP (result),
11581                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11582                   offset);
11583           offset++;
11584         }
11585       _endLazyDPSEvaluation ();
11586       goto release;
11587     }
11588
11589
11590   /* if the result is of type pointer */
11591   if (IS_PTR (ctype))
11592     {
11593
11594       int p_type;
11595       sym_link *type = operandType (right);
11596
11597       /* pointer to generic pointer */
11598       if (IS_GENPTR (ctype))
11599         {
11600           if (IS_PTR (type))
11601             {
11602               p_type = DCL_TYPE (type);
11603             }
11604           else
11605             {
11606 #if OLD_CAST_BEHAVIOR
11607               /* KV: we are converting a non-pointer type to
11608                * a generic pointer. This (ifdef'd out) code
11609                * says that the resulting generic pointer
11610                * should have the same class as the storage
11611                * location of the non-pointer variable.
11612                *
11613                * For example, converting an int (which happens
11614                * to be stored in DATA space) to a pointer results
11615                * in a DATA generic pointer; if the original int
11616                * in XDATA space, so will be the resulting pointer.
11617                *
11618                * I don't like that behavior, and thus this change:
11619                * all such conversions will be forced to XDATA and
11620                * throw a warning. If you want some non-XDATA
11621                * type, or you want to suppress the warning, you
11622                * must go through an intermediate cast, like so:
11623                *
11624                * char _generic *gp = (char _xdata *)(intVar);
11625                */
11626               sym_link *etype = getSpec (type);
11627
11628               /* we have to go by the storage class */
11629               if (SPEC_OCLS (etype) != generic)
11630                 {
11631                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11632                 }
11633               else
11634 #endif
11635                 {
11636                   /* Converting unknown class (i.e. register variable)
11637                    * to generic pointer. This is not good, but
11638                    * we'll make a guess (and throw a warning).
11639                    */
11640                   p_type = FPOINTER;
11641                   werror (W_INT_TO_GEN_PTR_CAST);
11642                 }
11643             }
11644
11645           /* the first two bytes are known */
11646           size = GPTRSIZE - 1;
11647           offset = 0;
11648           _startLazyDPSEvaluation ();
11649           while (size--)
11650             {
11651               aopPut (AOP (result),
11652                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11653                       offset);
11654               offset++;
11655             }
11656           _endLazyDPSEvaluation ();
11657
11658           /* the last byte depending on type */
11659             {
11660                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11661                 char gpValStr[10];
11662             
11663                 if (gpVal == -1)
11664                 {
11665                     // pointerTypeToGPByte will have bitched.
11666                     exit(1);
11667                 }
11668             
11669                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11670                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11671             }
11672           goto release;
11673         }
11674
11675       /* just copy the pointers */
11676       size = AOP_SIZE (result);
11677       offset = 0;
11678       _startLazyDPSEvaluation ();
11679       while (size--)
11680         {
11681           aopPut (AOP (result),
11682                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11683                   offset);
11684           offset++;
11685         }
11686       _endLazyDPSEvaluation ();
11687       goto release;
11688     }
11689
11690   /* so we now know that the size of destination is greater
11691      than the size of the source */
11692   /* we move to result for the size of source */
11693   size = AOP_SIZE (right);
11694   offset = 0;
11695   _startLazyDPSEvaluation ();
11696   while (size--)
11697     {
11698       aopPut (AOP (result),
11699               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11700               offset);
11701       offset++;
11702     }
11703   _endLazyDPSEvaluation ();
11704
11705   /* now depending on the sign of the source && destination */
11706   size = AOP_SIZE (result) - AOP_SIZE (right);
11707   /* if unsigned or not an integral type */
11708   /* also, if the source is a bit, we don't need to sign extend, because
11709    * it can't possibly have set the sign bit.
11710    */
11711   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11712     {
11713       while (size--)
11714         {
11715           aopPut (AOP (result), zero, offset++);
11716         }
11717     }
11718   else
11719     {
11720       /* we need to extend the sign :{ */
11721       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11722                         FALSE, FALSE, NULL));
11723       emitcode ("rlc", "a");
11724       emitcode ("subb", "a,acc");
11725       while (size--)
11726         aopPut (AOP (result), "a", offset++);
11727     }
11728
11729   /* we are done hurray !!!! */
11730
11731 release:
11732   freeAsmop (right, NULL, ic, TRUE);
11733   freeAsmop (result, NULL, ic, TRUE);
11734
11735 }
11736
11737 /*-----------------------------------------------------------------*/
11738 /* genDjnz - generate decrement & jump if not zero instrucion      */
11739 /*-----------------------------------------------------------------*/
11740 static int
11741 genDjnz (iCode * ic, iCode * ifx)
11742 {
11743   symbol *lbl, *lbl1;
11744   if (!ifx)
11745     return 0;
11746
11747   /* if the if condition has a false label
11748      then we cannot save */
11749   if (IC_FALSE (ifx))
11750     return 0;
11751
11752   /* if the minus is not of the form
11753      a = a - 1 */
11754   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11755       !IS_OP_LITERAL (IC_RIGHT (ic)))
11756     return 0;
11757
11758   if (operandLitValue (IC_RIGHT (ic)) != 1)
11759     return 0;
11760
11761   /* if the size of this greater than one then no
11762      saving */
11763   if (getSize (operandType (IC_RESULT (ic))) > 1)
11764     return 0;
11765
11766   /* otherwise we can save BIG */
11767   D(emitcode(";", "genDjnz"););
11768
11769   lbl = newiTempLabel (NULL);
11770   lbl1 = newiTempLabel (NULL);
11771
11772   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11773
11774   if (AOP_NEEDSACC(IC_RESULT(ic)))
11775   {
11776       /* If the result is accessed indirectly via
11777        * the accumulator, we must explicitly write
11778        * it back after the decrement.
11779        */
11780       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11781       
11782       if (strcmp(rByte, "a"))
11783       {
11784            /* Something is hopelessly wrong */
11785            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11786                    __FILE__, __LINE__);
11787            /* We can just give up; the generated code will be inefficient,
11788             * but what the hey.
11789             */
11790            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11791            return 0;
11792       }
11793       emitcode ("dec", "%s", rByte);
11794       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11795       emitcode ("jnz", "!tlabel", lbl->key + 100);
11796   }
11797   else if (IS_AOP_PREG (IC_RESULT (ic)))
11798     {
11799       emitcode ("dec", "%s",
11800                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11801       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11802       emitcode ("jnz", "!tlabel", lbl->key + 100);
11803     }
11804   else
11805     {
11806       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11807                 lbl->key + 100);
11808     }
11809   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11810   emitcode ("", "!tlabeldef", lbl->key + 100);
11811   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11812   emitcode ("", "!tlabeldef", lbl1->key + 100);
11813
11814   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11815   ifx->generated = 1;
11816   return 1;
11817 }
11818
11819 /*-----------------------------------------------------------------*/
11820 /* genReceive - generate code for a receive iCode                  */
11821 /*-----------------------------------------------------------------*/
11822 static void
11823 genReceive (iCode * ic)
11824 {
11825     int size = getSize (operandType (IC_RESULT (ic)));
11826     int offset = 0;
11827     int rb1off ;
11828     
11829     D (emitcode (";", "genReceive "););
11830
11831     if (ic->argreg == 1) 
11832     {
11833         /* first parameter */
11834         if (AOP_IS_STR(IC_RESULT(ic)))
11835         {
11836             /* Nothing to do: it's already in the proper place. */
11837             return;
11838         }
11839         else
11840         {
11841             bool useDp2;
11842             
11843             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11844                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11845                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11846             
11847             _G.accInUse++;
11848             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11849             _G.accInUse--; 
11850             
11851             /* Sanity checking... */
11852             if (AOP_USESDPTR(IC_RESULT(ic)))
11853             {
11854                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11855                         "genReceive got unexpected DPTR.");
11856             }
11857             assignResultValue (IC_RESULT (ic));
11858         }
11859     } 
11860     else 
11861     { 
11862         /* second receive onwards */
11863         /* this gets a little tricky since unused recevies will be
11864          eliminated, we have saved the reg in the type field . and
11865          we use that to figure out which register to use */
11866         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11867         rb1off = ic->argreg;
11868         while (size--) 
11869         {
11870             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11871         }
11872     }
11873     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11874 }
11875
11876 /*-----------------------------------------------------------------*/
11877 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11878 /*-----------------------------------------------------------------*/
11879 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11880 {
11881     operand *from , *to , *count;
11882     symbol *lbl;
11883     bitVect *rsave;
11884     int i;
11885
11886     /* we know it has to be 3 parameters */
11887     assert (nparms == 3);
11888     
11889     rsave = newBitVect(16);
11890     /* save DPTR if it needs to be saved */
11891     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11892             if (bitVectBitValue(ic->rMask,i))
11893                     rsave = bitVectSetBit(rsave,i);
11894     }
11895     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11896                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11897     savermask(rsave);
11898     
11899     to = parms[0];
11900     from = parms[1];
11901     count = parms[2];
11902
11903     aopOp (from, ic->next, FALSE, FALSE);
11904
11905     /* get from into DPTR1 */
11906     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11907     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11908     if (options.model == MODEL_FLAT24) {
11909         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11910     }
11911
11912     freeAsmop (from, NULL, ic, FALSE);
11913     aopOp (to, ic, FALSE, FALSE);
11914     /* get "to" into DPTR */
11915     /* if the operand is already in dptr
11916        then we do nothing else we move the value to dptr */
11917     if (AOP_TYPE (to) != AOP_STR) {
11918         /* if already in DPTR then we need to push */
11919         if (AOP_TYPE(to) == AOP_DPTR) {
11920             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11921             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11922             if (options.model == MODEL_FLAT24)
11923                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11924             emitcode ("pop", "dph");
11925             emitcode ("pop", "dpl");        
11926         } else {
11927             _startLazyDPSEvaluation ();
11928             /* if this is remateriazable */
11929             if (AOP_TYPE (to) == AOP_IMMD) {
11930                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11931             } else {                    /* we need to get it byte by byte */
11932                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11933                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11934                 if (options.model == MODEL_FLAT24) {
11935                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11936                 }
11937             }
11938             _endLazyDPSEvaluation ();
11939         }
11940     }
11941     freeAsmop (to, NULL, ic, FALSE);
11942     _G.dptrInUse = _G.dptr1InUse = 1;
11943     aopOp (count, ic->next->next, FALSE,FALSE);
11944     lbl =newiTempLabel(NULL);
11945
11946     /* now for the actual copy */
11947     if (AOP_TYPE(count) == AOP_LIT && 
11948         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11950         if (fromc) {
11951             emitcode ("lcall","__bi_memcpyc2x_s");
11952         } else {
11953             emitcode ("lcall","__bi_memcpyx2x_s");
11954         }
11955         freeAsmop (count, NULL, ic, FALSE);
11956     } else {
11957         symbol *lbl1 = newiTempLabel(NULL);
11958         
11959         emitcode (";"," Auto increment but no djnz");
11960         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11961         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11962         freeAsmop (count, NULL, ic, FALSE);
11963         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11964         emitcode ("","!tlabeldef",lbl->key+100);
11965         if (fromc) {
11966             emitcode ("clr","a");
11967             emitcode ("movc", "a,@a+dptr");
11968         } else 
11969             emitcode ("movx", "a,@dptr");
11970         emitcode ("movx", "@dptr,a");
11971         emitcode ("inc", "dptr");
11972         emitcode ("inc", "dptr");
11973         emitcode ("mov","a,b");
11974         emitcode ("orl","a,_ap");
11975         emitcode ("jz","!tlabel",lbl1->key+100);
11976         emitcode ("mov","a,_ap");
11977         emitcode ("add","a,#!constbyte",0xFF);
11978         emitcode ("mov","_ap,a");
11979         emitcode ("mov","a,b");
11980         emitcode ("addc","a,#!constbyte",0xFF);
11981         emitcode ("mov","b,a");
11982         emitcode ("sjmp","!tlabel",lbl->key+100);
11983         emitcode ("","!tlabeldef",lbl1->key+100);
11984     }
11985     emitcode ("mov", "dps,#0"); 
11986     _G.dptrInUse = _G.dptr1InUse = 0;
11987     unsavermask(rsave);
11988
11989 }
11990
11991 /*-----------------------------------------------------------------*/
11992 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11993 /*-----------------------------------------------------------------*/
11994 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11995 {
11996     operand *from , *to , *count;
11997     symbol *lbl,*lbl2;
11998     bitVect *rsave;
11999     int i;
12000
12001     /* we know it has to be 3 parameters */
12002     assert (nparms == 3);
12003     
12004     rsave = newBitVect(16);
12005     /* save DPTR if it needs to be saved */
12006     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12007             if (bitVectBitValue(ic->rMask,i))
12008                     rsave = bitVectSetBit(rsave,i);
12009     }
12010     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12011                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12012     savermask(rsave);
12013     
12014     to = parms[0];
12015     from = parms[1];
12016     count = parms[2];
12017
12018     aopOp (from, ic->next, FALSE, FALSE);
12019
12020     /* get from into DPTR1 */
12021     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12022     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12023     if (options.model == MODEL_FLAT24) {
12024         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12025     }
12026
12027     freeAsmop (from, NULL, ic, FALSE);
12028     aopOp (to, ic, FALSE, FALSE);
12029     /* get "to" into DPTR */
12030     /* if the operand is already in dptr
12031        then we do nothing else we move the value to dptr */
12032     if (AOP_TYPE (to) != AOP_STR) {
12033         /* if already in DPTR then we need to push */
12034         if (AOP_TYPE(to) == AOP_DPTR) {
12035             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12036             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12037             if (options.model == MODEL_FLAT24)
12038                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12039             emitcode ("pop", "dph");
12040             emitcode ("pop", "dpl");        
12041         } else {
12042             _startLazyDPSEvaluation ();
12043             /* if this is remateriazable */
12044             if (AOP_TYPE (to) == AOP_IMMD) {
12045                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12046             } else {                    /* we need to get it byte by byte */
12047                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12048                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12049                 if (options.model == MODEL_FLAT24) {
12050                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12051                 }
12052             }
12053             _endLazyDPSEvaluation ();
12054         }
12055     }
12056     freeAsmop (to, NULL, ic, FALSE);
12057     _G.dptrInUse = _G.dptr1InUse = 1;
12058     aopOp (count, ic->next->next, FALSE,FALSE);
12059     lbl =newiTempLabel(NULL);
12060     lbl2 =newiTempLabel(NULL);
12061
12062     /* now for the actual compare */
12063     if (AOP_TYPE(count) == AOP_LIT && 
12064         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12065         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12066         if (fromc)
12067             emitcode("lcall","__bi_memcmpc2x_s");
12068         else
12069             emitcode("lcall","__bi_memcmpx2x_s");
12070         freeAsmop (count, NULL, ic, FALSE);
12071         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12072         aopPut(AOP(IC_RESULT(ic)),"a",0);
12073         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12074     } else {
12075         symbol *lbl1 = newiTempLabel(NULL);
12076
12077         emitcode("push","ar0");         
12078         emitcode (";"," Auto increment but no djnz");
12079         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12080         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12081         freeAsmop (count, NULL, ic, FALSE);
12082         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12083         emitcode ("","!tlabeldef",lbl->key+100);
12084         if (fromc) {
12085             emitcode ("clr","a");
12086             emitcode ("movc", "a,@a+dptr");
12087         } else 
12088             emitcode ("movx", "a,@dptr");
12089         emitcode ("mov","r0,a");
12090         emitcode ("movx", "a,@dptr");
12091         emitcode ("clr","c");
12092         emitcode ("subb","a,r0");
12093         emitcode ("jnz","!tlabel",lbl2->key+100);
12094         emitcode ("inc", "dptr");
12095         emitcode ("inc", "dptr");
12096         emitcode ("mov","a,b");
12097         emitcode ("orl","a,_ap");
12098         emitcode ("jz","!tlabel",lbl1->key+100);
12099         emitcode ("mov","a,_ap");
12100         emitcode ("add","a,#!constbyte",0xFF);
12101         emitcode ("mov","_ap,a");
12102         emitcode ("mov","a,b");
12103         emitcode ("addc","a,#!constbyte",0xFF);
12104         emitcode ("mov","b,a");
12105         emitcode ("sjmp","!tlabel",lbl->key+100);
12106         emitcode ("","!tlabeldef",lbl1->key+100);
12107         emitcode ("clr","a");
12108         emitcode ("","!tlabeldef",lbl2->key+100);
12109         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12110         aopPut(AOP(IC_RESULT(ic)),"a",0);
12111         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12112         emitcode("pop","ar0");
12113         emitcode ("mov", "dps,#0");      
12114     }
12115     _G.dptrInUse = _G.dptr1InUse = 0;
12116     unsavermask(rsave);
12117
12118 }
12119
12120 /*-----------------------------------------------------------------*/
12121 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12122 /* port, first parameter output area second parameter pointer to   */
12123 /* port third parameter count                                      */
12124 /*-----------------------------------------------------------------*/
12125 static void genInp( iCode *ic, int nparms, operand **parms)
12126 {
12127     operand *from , *to , *count;
12128     symbol *lbl;
12129     bitVect *rsave;
12130     int i;
12131
12132     /* we know it has to be 3 parameters */
12133     assert (nparms == 3);
12134     
12135     rsave = newBitVect(16);
12136     /* save DPTR if it needs to be saved */
12137     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12138             if (bitVectBitValue(ic->rMask,i))
12139                     rsave = bitVectSetBit(rsave,i);
12140     }
12141     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12142                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12143     savermask(rsave);
12144     
12145     to = parms[0];
12146     from = parms[1];
12147     count = parms[2];
12148
12149     aopOp (from, ic->next, FALSE, FALSE);
12150
12151     /* get from into DPTR1 */
12152     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12153     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12154     if (options.model == MODEL_FLAT24) {
12155         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12156     }
12157
12158     freeAsmop (from, NULL, ic, FALSE);
12159     aopOp (to, ic, FALSE, FALSE);
12160     /* get "to" into DPTR */
12161     /* if the operand is already in dptr
12162        then we do nothing else we move the value to dptr */
12163     if (AOP_TYPE (to) != AOP_STR) {
12164         /* if already in DPTR then we need to push */
12165         if (AOP_TYPE(to) == AOP_DPTR) {
12166             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12167             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12168             if (options.model == MODEL_FLAT24)
12169                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12170             emitcode ("pop", "dph");
12171             emitcode ("pop", "dpl");        
12172         } else {
12173             _startLazyDPSEvaluation ();
12174             /* if this is remateriazable */
12175             if (AOP_TYPE (to) == AOP_IMMD) {
12176                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12177             } else {                    /* we need to get it byte by byte */
12178                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12179                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12180                 if (options.model == MODEL_FLAT24) {
12181                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12182                 }
12183             }
12184             _endLazyDPSEvaluation ();
12185         }
12186     }
12187     freeAsmop (to, NULL, ic, FALSE);
12188
12189     _G.dptrInUse = _G.dptr1InUse = 1;
12190     aopOp (count, ic->next->next, FALSE,FALSE);
12191     lbl =newiTempLabel(NULL);
12192
12193     /* now for the actual copy */
12194     if (AOP_TYPE(count) == AOP_LIT && 
12195         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12196         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12197         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12198         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12199         freeAsmop (count, NULL, ic, FALSE);
12200         emitcode ("","!tlabeldef",lbl->key+100);
12201         emitcode ("movx", "a,@dptr");   /* read data from port */
12202         emitcode ("dec","dps");         /* switch to DPTR */
12203         emitcode ("movx", "@dptr,a");   /* save into location */
12204         emitcode ("inc", "dptr");       /* point to next area */
12205         emitcode ("inc","dps");         /* switch to DPTR2 */
12206         emitcode ("djnz","b,!tlabel",lbl->key+100);
12207     } else {
12208         symbol *lbl1 = newiTempLabel(NULL);
12209         
12210         emitcode (";"," Auto increment but no djnz");
12211         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12212         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12213         freeAsmop (count, NULL, ic, FALSE);
12214         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12215         emitcode ("","!tlabeldef",lbl->key+100);
12216         emitcode ("movx", "a,@dptr");
12217         emitcode ("dec","dps");         /* switch to DPTR */
12218         emitcode ("movx", "@dptr,a");
12219         emitcode ("inc", "dptr");
12220         emitcode ("inc","dps");         /* switch to DPTR2 */
12221 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12222 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12223         emitcode ("mov","a,b");
12224         emitcode ("orl","a,_ap");
12225         emitcode ("jz","!tlabel",lbl1->key+100);
12226         emitcode ("mov","a,_ap");
12227         emitcode ("add","a,#!constbyte",0xFF);
12228         emitcode ("mov","_ap,a");
12229         emitcode ("mov","a,b");
12230         emitcode ("addc","a,#!constbyte",0xFF);
12231         emitcode ("mov","b,a");
12232         emitcode ("sjmp","!tlabel",lbl->key+100);
12233         emitcode ("","!tlabeldef",lbl1->key+100);
12234     }
12235     emitcode ("mov", "dps,#0"); 
12236     _G.dptrInUse = _G.dptr1InUse = 0;
12237     unsavermask(rsave);
12238
12239 }
12240
12241 /*-----------------------------------------------------------------*/
12242 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12243 /* port, first parameter output area second parameter pointer to   */
12244 /* port third parameter count                                      */
12245 /*-----------------------------------------------------------------*/
12246 static void genOutp( iCode *ic, int nparms, operand **parms)
12247 {
12248     operand *from , *to , *count;
12249     symbol *lbl;
12250     bitVect *rsave;
12251     int i;
12252
12253     /* we know it has to be 3 parameters */
12254     assert (nparms == 3);
12255     
12256     rsave = newBitVect(16);
12257     /* save DPTR if it needs to be saved */
12258     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12259             if (bitVectBitValue(ic->rMask,i))
12260                     rsave = bitVectSetBit(rsave,i);
12261     }
12262     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12263                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12264     savermask(rsave);
12265     
12266     to = parms[0];
12267     from = parms[1];
12268     count = parms[2];
12269
12270     aopOp (from, ic->next, FALSE, FALSE);
12271
12272     /* get from into DPTR1 */
12273     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12274     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12275     if (options.model == MODEL_FLAT24) {
12276         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12277     }
12278
12279     freeAsmop (from, NULL, ic, FALSE);
12280     aopOp (to, ic, FALSE, FALSE);
12281     /* get "to" into DPTR */
12282     /* if the operand is already in dptr
12283        then we do nothing else we move the value to dptr */
12284     if (AOP_TYPE (to) != AOP_STR) {
12285         /* if already in DPTR then we need to push */
12286         if (AOP_TYPE(to) == AOP_DPTR) {
12287             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12288             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12289             if (options.model == MODEL_FLAT24)
12290                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12291             emitcode ("pop", "dph");
12292             emitcode ("pop", "dpl");        
12293         } else {
12294             _startLazyDPSEvaluation ();
12295             /* if this is remateriazable */
12296             if (AOP_TYPE (to) == AOP_IMMD) {
12297                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12298             } else {                    /* we need to get it byte by byte */
12299                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12300                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12301                 if (options.model == MODEL_FLAT24) {
12302                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12303                 }
12304             }
12305             _endLazyDPSEvaluation ();
12306         }
12307     }
12308     freeAsmop (to, NULL, ic, FALSE);
12309
12310     _G.dptrInUse = _G.dptr1InUse = 1;
12311     aopOp (count, ic->next->next, FALSE,FALSE);
12312     lbl =newiTempLabel(NULL);
12313
12314     /* now for the actual copy */
12315     if (AOP_TYPE(count) == AOP_LIT && 
12316         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12317         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12318         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12319         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12320         emitcode ("","!tlabeldef",lbl->key+100);
12321         emitcode ("movx", "a,@dptr");   /* read data from port */
12322         emitcode ("inc","dps");         /* switch to DPTR2 */
12323         emitcode ("movx", "@dptr,a");   /* save into location */
12324         emitcode ("inc", "dptr");       /* point to next area */
12325         emitcode ("dec","dps");         /* switch to DPTR */
12326         emitcode ("djnz","b,!tlabel",lbl->key+100);
12327         freeAsmop (count, NULL, ic, FALSE);
12328     } else {
12329         symbol *lbl1 = newiTempLabel(NULL);
12330         
12331         emitcode (";"," Auto increment but no djnz");
12332         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12333         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12334         freeAsmop (count, NULL, ic, FALSE);
12335         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12336         emitcode ("","!tlabeldef",lbl->key+100);
12337         emitcode ("movx", "a,@dptr");
12338         emitcode ("inc", "dptr");
12339         emitcode ("inc","dps");         /* switch to DPTR2 */
12340         emitcode ("movx", "@dptr,a");
12341         emitcode ("dec","dps");         /* switch to DPTR */
12342         emitcode ("mov","a,b");
12343         emitcode ("orl","a,_ap");
12344         emitcode ("jz","!tlabel",lbl1->key+100);
12345         emitcode ("mov","a,_ap");
12346         emitcode ("add","a,#!constbyte",0xFF);
12347         emitcode ("mov","_ap,a");
12348         emitcode ("mov","a,b");
12349         emitcode ("addc","a,#!constbyte",0xFF);
12350         emitcode ("mov","b,a");
12351         emitcode ("sjmp","!tlabel",lbl->key+100);
12352         emitcode ("","!tlabeldef",lbl1->key+100);
12353     }
12354     emitcode ("mov", "dps,#0"); 
12355     _G.dptrInUse = _G.dptr1InUse = 0;
12356     unsavermask(rsave);
12357
12358 }
12359
12360 /*-----------------------------------------------------------------*/
12361 /* genSwapW - swap lower & high order bytes                        */
12362 /*-----------------------------------------------------------------*/
12363 static void genSwapW(iCode *ic, int nparms, operand **parms)
12364 {
12365     operand *dest;
12366     operand *src;
12367     assert (nparms==1);
12368
12369     src = parms[0];
12370     dest=IC_RESULT(ic);
12371
12372     assert(getSize(operandType(src))==2);
12373
12374     aopOp (src, ic, FALSE, FALSE);
12375     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12376     _G.accInUse++;
12377     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12378     _G.accInUse--;
12379     freeAsmop (src, NULL, ic, FALSE);
12380     
12381     aopOp (dest,ic, FALSE, FALSE);
12382     aopPut(AOP(dest),"b",0);
12383     aopPut(AOP(dest),"a",1);
12384     freeAsmop (dest, NULL, ic, FALSE);    
12385 }
12386
12387 /*-----------------------------------------------------------------*/
12388 /* genMemsetX - gencode for memSetX data                           */
12389 /*-----------------------------------------------------------------*/
12390 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12391 {
12392     operand *to , *val , *count;
12393     symbol *lbl;
12394     char *l;
12395     int i;
12396     bitVect *rsave;
12397
12398     /* we know it has to be 3 parameters */
12399     assert (nparms == 3);
12400     
12401     to = parms[0];
12402     val = parms[1];
12403     count = parms[2];
12404         
12405     /* save DPTR if it needs to be saved */
12406     rsave = newBitVect(16);
12407     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12408             if (bitVectBitValue(ic->rMask,i))
12409                     rsave = bitVectSetBit(rsave,i);
12410     }
12411     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12412                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12413     savermask(rsave);
12414
12415     aopOp (to, ic, FALSE, FALSE);
12416     /* get "to" into DPTR */
12417     /* if the operand is already in dptr
12418        then we do nothing else we move the value to dptr */
12419     if (AOP_TYPE (to) != AOP_STR) {
12420         /* if already in DPTR then we need to push */
12421         if (AOP_TYPE(to) == AOP_DPTR) {
12422             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12423             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12424             if (options.model == MODEL_FLAT24)
12425                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12426             emitcode ("pop", "dph");
12427             emitcode ("pop", "dpl");        
12428         } else {
12429             _startLazyDPSEvaluation ();
12430             /* if this is remateriazable */
12431             if (AOP_TYPE (to) == AOP_IMMD) {
12432                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12433             } else {                    /* we need to get it byte by byte */
12434                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12435                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12436                 if (options.model == MODEL_FLAT24) {
12437                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12438                 }
12439             }
12440             _endLazyDPSEvaluation ();
12441         }
12442     }
12443     freeAsmop (to, NULL, ic, FALSE);
12444
12445     aopOp (val, ic->next->next, FALSE,FALSE);
12446     aopOp (count, ic->next->next, FALSE,FALSE);    
12447     lbl =newiTempLabel(NULL);
12448     /* now for the actual copy */
12449     if (AOP_TYPE(count) == AOP_LIT && 
12450         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12451         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12452         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12453         MOVA(l);
12454         emitcode ("","!tlabeldef",lbl->key+100);
12455         emitcode ("movx", "@dptr,a");
12456         emitcode ("inc", "dptr");
12457         emitcode ("djnz","b,!tlabel",lbl->key+100);
12458     } else {
12459         symbol *lbl1 = newiTempLabel(NULL);
12460         
12461         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12462         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12463         emitcode ("","!tlabeldef",lbl->key+100);
12464         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12465         emitcode ("movx", "@dptr,a");
12466         emitcode ("inc", "dptr");
12467         emitcode ("mov","a,b");
12468         emitcode ("orl","a,_ap");
12469         emitcode ("jz","!tlabel",lbl1->key+100);
12470         emitcode ("mov","a,_ap");
12471         emitcode ("add","a,#!constbyte",0xFF);
12472         emitcode ("mov","_ap,a");
12473         emitcode ("mov","a,b");
12474         emitcode ("addc","a,#!constbyte",0xFF);
12475         emitcode ("mov","b,a");
12476         emitcode ("sjmp","!tlabel",lbl->key+100);
12477         emitcode ("","!tlabeldef",lbl1->key+100);
12478     }
12479     freeAsmop (count, NULL, ic, FALSE);
12480     unsavermask(rsave);
12481 }
12482
12483 /*-----------------------------------------------------------------*/
12484 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12485 /*-----------------------------------------------------------------*/
12486 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12487 {
12488         bitVect *rsave ;
12489         operand *pnum, *result;
12490         int i;
12491     
12492         assert (nparms==1);
12493         /* save registers that need to be saved */
12494         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12495                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12496     
12497         pnum = parms[0]; 
12498         aopOp (pnum, ic, FALSE, FALSE);
12499         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12500         freeAsmop (pnum, NULL, ic, FALSE);
12501         emitcode ("lcall","NatLib_LoadPrimitive");
12502         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12503         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12504             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12505                 for (i = (size-1) ; i >= 0 ; i-- ) {
12506                         emitcode ("push","a%s",javaRet[i]);
12507                 }
12508                 for (i=0; i < size ; i++ ) {
12509                         emitcode ("pop","a%s",
12510                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12511                 }
12512         } else {
12513                 for (i = 0 ; i < size ; i++ ) {
12514                         aopPut(AOP(result),javaRet[i],i);
12515                 }
12516         }    
12517         freeAsmop (result, NULL, ic, FALSE);
12518         unsavermask(rsave);
12519 }
12520
12521 /*-----------------------------------------------------------------*/
12522 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12523 /*-----------------------------------------------------------------*/
12524 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12525 {
12526         bitVect *rsave ;
12527         operand *pnum, *result;
12528         int size = 3;
12529         int i;
12530     
12531         assert (nparms==1);
12532         /* save registers that need to be saved */
12533         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12534                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12535     
12536         pnum = parms[0]; 
12537         aopOp (pnum, ic, FALSE, FALSE);
12538         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12539         freeAsmop (pnum, NULL, ic, FALSE);
12540         emitcode ("lcall","NatLib_LoadPointer");
12541         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12542         if (AOP_TYPE(result)!=AOP_STR) {
12543                 for (i = 0 ; i < size ; i++ ) {
12544                         aopPut(AOP(result),fReturn[i],i);
12545                 }
12546         }    
12547         freeAsmop (result, NULL, ic, FALSE);
12548         unsavermask(rsave);
12549 }
12550
12551 /*-----------------------------------------------------------------*/
12552 /* genNatLibInstallStateBlock -                                    */
12553 /*-----------------------------------------------------------------*/
12554 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12555                                        operand **parms, const char *name)
12556 {
12557         bitVect *rsave ;
12558         operand *psb, *handle;
12559         assert (nparms==2);
12560
12561         /* save registers that need to be saved */
12562         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12563                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12564         psb = parms[0];
12565         handle = parms[1];
12566
12567         /* put pointer to state block into DPTR1 */
12568         aopOp (psb, ic, FALSE, FALSE);
12569         if (AOP_TYPE (psb) == AOP_IMMD) {
12570                 emitcode ("mov","dps,#1");
12571                 emitcode ("mov", "dptr,%s",
12572                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12573                 emitcode ("mov","dps,#0");
12574         } else {
12575                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12576                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12577                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12578         }
12579         freeAsmop (psb, NULL, ic, FALSE);
12580
12581         /* put libraryID into DPTR */
12582         emitcode ("mov","dptr,#LibraryID");
12583
12584         /* put handle into r3:r2 */
12585         aopOp (handle, ic, FALSE, FALSE);
12586         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12587                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12588                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12589                 emitcode ("pop","ar3");
12590                 emitcode ("pop","ar2");
12591         } else {        
12592                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12593                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12594         }
12595         freeAsmop (psb, NULL, ic, FALSE);
12596
12597         /* make the call */
12598         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12599
12600         /* put return value into place*/
12601         _G.accInUse++;
12602         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12603         _G.accInUse--;
12604         aopPut(AOP(IC_RESULT(ic)),"a",0);
12605         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12606         unsavermask(rsave);
12607 }
12608
12609 /*-----------------------------------------------------------------*/
12610 /* genNatLibRemoveStateBlock -                                     */
12611 /*-----------------------------------------------------------------*/
12612 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12613 {
12614         bitVect *rsave ;
12615
12616         assert(nparms==0);
12617
12618         /* save registers that need to be saved */
12619         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12620                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12621
12622         /* put libraryID into DPTR */
12623         emitcode ("mov","dptr,#LibraryID");
12624         /* make the call */
12625         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12626         unsavermask(rsave);
12627 }
12628
12629 /*-----------------------------------------------------------------*/
12630 /* genNatLibGetStateBlock -                                        */
12631 /*-----------------------------------------------------------------*/
12632 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12633                                    operand **parms,const char *name)
12634 {
12635         bitVect *rsave ;
12636         symbol *lbl = newiTempLabel(NULL);
12637         
12638         assert(nparms==0);
12639         /* save registers that need to be saved */
12640         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12641                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12642
12643         /* put libraryID into DPTR */
12644         emitcode ("mov","dptr,#LibraryID");
12645         /* make the call */
12646         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12647         emitcode ("jnz","!tlabel",lbl->key+100);
12648
12649         /* put return value into place */
12650         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12651         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12652                 emitcode ("push","ar3");
12653                 emitcode ("push","ar2");
12654                 emitcode ("pop","%s",
12655                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12656                 emitcode ("pop","%s",
12657                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12658         } else {
12659                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12660                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12661         }
12662         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12663         emitcode ("","!tlabeldef",lbl->key+100);
12664         unsavermask(rsave);
12665 }
12666
12667 /*-----------------------------------------------------------------*/
12668 /* genMMMalloc -                                                   */
12669 /*-----------------------------------------------------------------*/
12670 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12671                          int size, const char *name)
12672 {
12673         bitVect *rsave ;
12674         operand *bsize;
12675         symbol *rsym;
12676         symbol *lbl = newiTempLabel(NULL);
12677
12678         assert (nparms == 1);
12679         /* save registers that need to be saved */
12680         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12681                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12682         
12683         bsize=parms[0];
12684         aopOp (bsize,ic,FALSE,FALSE);
12685
12686         /* put the size in R4-R2 */
12687         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12688                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12689                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12690                 if (size==3) {
12691                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12692                         emitcode("pop","ar4");
12693                 }
12694                 emitcode("pop","ar3");
12695                 emitcode("pop","ar2");          
12696         } else {
12697                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12698                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12699                 if (size==3) {
12700                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12701                 }
12702         }
12703         freeAsmop (bsize, NULL, ic, FALSE);
12704
12705         /* make the call */
12706         emitcode ("lcall","MM_%s",name);
12707         emitcode ("jz","!tlabel",lbl->key+100);
12708         emitcode ("mov","r2,#!constbyte",0xff);
12709         emitcode ("mov","r3,#!constbyte",0xff);
12710         emitcode ("","!tlabeldef",lbl->key+100);
12711         /* we don't care about the pointer : we just save the handle */
12712         rsym = OP_SYMBOL(IC_RESULT(ic));
12713         if (rsym->liveFrom != rsym->liveTo) {
12714                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12715                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12716                         emitcode ("push","ar3");
12717                         emitcode ("push","ar2");
12718                         emitcode ("pop","%s",
12719                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12720                         emitcode ("pop","%s",
12721                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12722                 } else {
12723                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12724                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12725                 }
12726                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12727         }
12728         unsavermask(rsave);
12729 }
12730
12731 /*-----------------------------------------------------------------*/
12732 /* genMMDeref -                                                    */
12733 /*-----------------------------------------------------------------*/
12734 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12735 {
12736         bitVect *rsave ;
12737         operand *handle;
12738
12739         assert (nparms == 1);
12740         /* save registers that need to be saved */
12741         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12742                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12743         
12744         handle=parms[0];
12745         aopOp (handle,ic,FALSE,FALSE);
12746
12747         /* put the size in R4-R2 */
12748         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12749                 emitcode("push","%s",
12750                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12751                 emitcode("push","%s",
12752                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12753                 emitcode("pop","ar3");
12754                 emitcode("pop","ar2");          
12755         } else {
12756                 emitcode ("mov","r2,%s",
12757                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12758                 emitcode ("mov","r3,%s",
12759                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12760         }
12761         freeAsmop (handle, NULL, ic, FALSE);
12762
12763         /* make the call */
12764         emitcode ("lcall","MM_Deref");
12765         
12766         {
12767                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12768                 if (rsym->liveFrom != rsym->liveTo) {                   
12769                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12770                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12771                             _startLazyDPSEvaluation ();
12772                             
12773                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12774                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12775                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12776
12777                             _endLazyDPSEvaluation ();
12778                             
12779                         }
12780                 }
12781         }
12782         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12783         unsavermask(rsave);
12784 }
12785
12786 /*-----------------------------------------------------------------*/
12787 /* genMMUnrestrictedPersist -                                      */
12788 /*-----------------------------------------------------------------*/
12789 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12790 {
12791         bitVect *rsave ;
12792         operand *handle;
12793
12794         assert (nparms == 1);
12795         /* save registers that need to be saved */
12796         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12797                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12798         
12799         handle=parms[0];
12800         aopOp (handle,ic,FALSE,FALSE);
12801
12802         /* put the size in R3-R2 */
12803         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12804                 emitcode("push","%s",
12805                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12806                 emitcode("push","%s",
12807                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12808                 emitcode("pop","ar3");
12809                 emitcode("pop","ar2");          
12810         } else {
12811                 emitcode ("mov","r2,%s",
12812                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12813                 emitcode ("mov","r3,%s",
12814                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12815         }
12816         freeAsmop (handle, NULL, ic, FALSE);
12817
12818         /* make the call */
12819         emitcode ("lcall","MM_UnrestrictedPersist");
12820
12821         {
12822                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12823                 if (rsym->liveFrom != rsym->liveTo) {   
12824                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12825                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12826                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12827                 }
12828         }
12829         unsavermask(rsave);
12830 }
12831
12832 /*-----------------------------------------------------------------*/
12833 /* genSystemExecJavaProcess -                                      */
12834 /*-----------------------------------------------------------------*/
12835 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12836 {
12837         bitVect *rsave ;
12838         operand *handle, *pp;
12839
12840         assert (nparms==2);
12841         /* save registers that need to be saved */
12842         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12843                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12844         
12845         pp = parms[0];
12846         handle = parms[1];
12847         
12848         /* put the handle in R3-R2 */
12849         aopOp (handle,ic,FALSE,FALSE);
12850         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12851                 emitcode("push","%s",
12852                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12853                 emitcode("push","%s",
12854                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12855                 emitcode("pop","ar3");
12856                 emitcode("pop","ar2");          
12857         } else {
12858                 emitcode ("mov","r2,%s",
12859                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12860                 emitcode ("mov","r3,%s",
12861                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12862         }
12863         freeAsmop (handle, NULL, ic, FALSE);
12864         
12865         /* put pointer in DPTR */
12866         aopOp (pp,ic,FALSE,FALSE);
12867         if (AOP_TYPE(pp) == AOP_IMMD) {
12868                 emitcode ("mov", "dptr,%s",
12869                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12870         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12871                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12872                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12873                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12874         }
12875         freeAsmop (handle, NULL, ic, FALSE);
12876
12877         /* make the call */
12878         emitcode ("lcall","System_ExecJavaProcess");
12879         
12880         /* put result in place */
12881         {
12882                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12883                 if (rsym->liveFrom != rsym->liveTo) {   
12884                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12885                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12886                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12887                 }
12888         }
12889         
12890         unsavermask(rsave);
12891 }
12892
12893 /*-----------------------------------------------------------------*/
12894 /* genSystemRTCRegisters -                                         */
12895 /*-----------------------------------------------------------------*/
12896 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12897                                   char *name)
12898 {
12899         bitVect *rsave ;
12900         operand *pp;
12901
12902         assert (nparms==1);
12903         /* save registers that need to be saved */
12904         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12905                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12906         
12907         pp=parms[0];
12908         /* put pointer in DPTR */
12909         aopOp (pp,ic,FALSE,FALSE);
12910         if (AOP_TYPE (pp) == AOP_IMMD) {
12911                 emitcode ("mov","dps,#1");
12912                 emitcode ("mov", "dptr,%s", 
12913                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12914                 emitcode ("mov","dps,#0");
12915         } else {
12916                 emitcode ("mov","dpl1,%s",
12917                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12918                 emitcode ("mov","dph1,%s",
12919                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12920                 emitcode ("mov","dpx1,%s",
12921                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12922         }
12923         freeAsmop (pp, NULL, ic, FALSE);
12924
12925         /* make the call */
12926         emitcode ("lcall","System_%sRTCRegisters",name);
12927
12928         unsavermask(rsave);
12929 }
12930
12931 /*-----------------------------------------------------------------*/
12932 /* genSystemThreadSleep -                                          */
12933 /*-----------------------------------------------------------------*/
12934 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12935 {
12936         bitVect *rsave ;
12937         operand *to, *s;
12938
12939         assert (nparms==1);
12940         /* save registers that need to be saved */
12941         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12942                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12943
12944         to = parms[0];
12945         aopOp(to,ic,FALSE,FALSE);
12946         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12947             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12948                 emitcode ("push","%s",
12949                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12950                 emitcode ("push","%s",
12951                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12952                 emitcode ("push","%s",
12953                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12954                 emitcode ("push","%s",
12955                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12956                 emitcode ("pop","ar3");
12957                 emitcode ("pop","ar2");
12958                 emitcode ("pop","ar1");
12959                 emitcode ("pop","ar0");
12960         } else {
12961                 emitcode ("mov","r0,%s",
12962                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12963                 emitcode ("mov","r1,%s",
12964                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12965                 emitcode ("mov","r2,%s",
12966                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12967                 emitcode ("mov","r3,%s",
12968                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12969         }
12970         freeAsmop (to, NULL, ic, FALSE);
12971
12972         /* suspend in acc */
12973         s = parms[1];
12974         aopOp(s,ic,FALSE,FALSE);
12975         emitcode ("mov","a,%s",
12976                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12977         freeAsmop (s, NULL, ic, FALSE);
12978
12979         /* make the call */
12980         emitcode ("lcall","System_%s",name);
12981
12982         unsavermask(rsave);
12983 }
12984
12985 /*-----------------------------------------------------------------*/
12986 /* genSystemThreadResume -                                         */
12987 /*-----------------------------------------------------------------*/
12988 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12989 {
12990         bitVect *rsave ;
12991         operand *tid,*pid;
12992
12993         assert (nparms==2);
12994         /* save registers that need to be saved */
12995         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12996                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12997         
12998         tid = parms[0];
12999         pid = parms[1];
13000         
13001         /* PID in R0 */
13002         aopOp(pid,ic,FALSE,FALSE);
13003         emitcode ("mov","r0,%s",
13004                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13005         freeAsmop (pid, NULL, ic, FALSE);
13006         
13007         /* tid into ACC */
13008         aopOp(tid,ic,FALSE,FALSE);
13009         emitcode ("mov","a,%s",
13010                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13011         freeAsmop (tid, NULL, ic, FALSE);
13012         
13013         emitcode ("lcall","System_ThreadResume");
13014
13015         /* put result into place */
13016         {
13017                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13018                 if (rsym->liveFrom != rsym->liveTo) {   
13019                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13020                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13021                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13022                 }
13023         }
13024         unsavermask(rsave);
13025 }
13026
13027 /*-----------------------------------------------------------------*/
13028 /* genSystemProcessResume -                                        */
13029 /*-----------------------------------------------------------------*/
13030 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13031 {
13032         bitVect *rsave ;
13033         operand *pid;
13034
13035         assert (nparms==1);
13036         /* save registers that need to be saved */
13037         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13038                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13039         
13040         pid = parms[0];
13041         
13042         /* pid into ACC */
13043         aopOp(pid,ic,FALSE,FALSE);
13044         emitcode ("mov","a,%s",
13045                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13046         freeAsmop (pid, NULL, ic, FALSE);
13047         
13048         emitcode ("lcall","System_ProcessResume");
13049
13050         unsavermask(rsave);
13051 }
13052
13053 /*-----------------------------------------------------------------*/
13054 /* genSystem -                                                     */
13055 /*-----------------------------------------------------------------*/
13056 static void genSystem (iCode *ic,int nparms,char *name)
13057 {
13058         assert(nparms == 0);
13059
13060         emitcode ("lcall","System_%s",name);
13061 }
13062
13063 /*-----------------------------------------------------------------*/
13064 /* genSystemPoll -                                                  */
13065 /*-----------------------------------------------------------------*/
13066 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13067 {
13068         bitVect *rsave ;
13069         operand *fp;
13070
13071         assert (nparms==1);
13072         /* save registers that need to be saved */
13073         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13074                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13075
13076         fp = parms[0];
13077         aopOp (fp,ic,FALSE,FALSE);
13078         if (AOP_TYPE (fp) == AOP_IMMD) {
13079                 emitcode ("mov", "dptr,%s", 
13080                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13081         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13082                 emitcode ("mov","dpl,%s",
13083                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13084                 emitcode ("mov","dph,%s",
13085                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13086                 emitcode ("mov","dpx,%s",
13087                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13088         }
13089         freeAsmop (fp, NULL, ic, FALSE);
13090
13091         emitcode ("lcall","System_%sPoll",name);
13092
13093         /* put result into place */
13094         {
13095                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13096                 if (rsym->liveFrom != rsym->liveTo) {   
13097                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13098                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13099                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13100                 }
13101         }
13102         unsavermask(rsave);
13103 }
13104
13105 /*-----------------------------------------------------------------*/
13106 /* genSystemGetCurrentID -                                         */
13107 /*-----------------------------------------------------------------*/
13108 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13109 {
13110         assert (nparms==0);
13111
13112         emitcode ("lcall","System_GetCurrent%sId",name);
13113         /* put result into place */
13114         {
13115                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13116                 if (rsym->liveFrom != rsym->liveTo) {   
13117                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13118                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13119                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13120                 }
13121         }
13122 }
13123
13124 /*-----------------------------------------------------------------*/
13125 /* genDummyRead - generate code for dummy read of volatiles        */
13126 /*-----------------------------------------------------------------*/
13127 static void
13128 genDummyRead (iCode * ic)
13129 {
13130   operand *op;
13131   int size, offset;
13132
13133   D(emitcode(";     genDummyRead",""));
13134
13135   op = IC_RIGHT (ic);
13136   if (op && IS_SYMOP (op))
13137     {
13138       aopOp (op, ic, FALSE, FALSE);
13139
13140       /* if the result is a bit */
13141       if (AOP_TYPE (op) == AOP_CRY)
13142         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13143       else
13144         {
13145           /* bit variables done */
13146           /* general case */
13147           size = AOP_SIZE (op);
13148           offset = 0;
13149           while (size--)
13150           {
13151             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13152             offset++;
13153           }
13154         }
13155
13156       freeAsmop (op, NULL, ic, TRUE);
13157     }
13158
13159   op = IC_LEFT (ic);
13160   if (op && IS_SYMOP (op))
13161     {
13162       aopOp (op, ic, FALSE, FALSE);
13163
13164       /* if the result is a bit */
13165       if (AOP_TYPE (op) == AOP_CRY)
13166         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13167       else
13168         {
13169           /* bit variables done */
13170           /* general case */
13171           size = AOP_SIZE (op);
13172           offset = 0;
13173           while (size--)
13174           {
13175             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13176             offset++;
13177           }
13178         }
13179
13180       freeAsmop (op, NULL, ic, TRUE);
13181     }
13182     
13183 }
13184
13185 /*-----------------------------------------------------------------*/
13186 /* genCritical - generate code for start of a critical sequence    */
13187 /*-----------------------------------------------------------------*/
13188 static void
13189 genCritical (iCode *ic)
13190 {
13191   symbol *tlbl = newiTempLabel (NULL);
13192
13193   D(emitcode(";     genCritical",""));
13194   
13195   if (IC_RESULT (ic))
13196     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13197
13198   emitcode ("setb", "c");
13199   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13200   emitcode ("clr", "c");
13201   emitcode ("", "%05d$:", (tlbl->key + 100));
13202
13203   if (IC_RESULT (ic))
13204     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13205   else
13206     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13207
13208   if (IC_RESULT (ic))
13209     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13210 }
13211
13212 /*-----------------------------------------------------------------*/
13213 /* genEndCritical - generate code for end of a critical sequence   */
13214 /*-----------------------------------------------------------------*/
13215 static void
13216 genEndCritical (iCode *ic)
13217 {
13218   D(emitcode(";     genEndCritical",""));
13219   
13220   if (IC_RIGHT (ic))
13221     {
13222       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13223       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13224         {
13225           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13226           emitcode ("mov", "ea,c");
13227         }
13228       else
13229         {
13230           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13231           emitcode ("rrc", "a");
13232           emitcode ("mov", "ea,c");
13233         }
13234       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13235     }
13236   else
13237     {
13238       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13239       emitcode ("mov", "ea,c");
13240     }
13241 }
13242
13243
13244
13245 /*-----------------------------------------------------------------*/
13246 /* genBuiltIn - calls the appropriate function to  generating code */
13247 /* for a built in function                                         */
13248 /*-----------------------------------------------------------------*/
13249 static void genBuiltIn (iCode *ic)
13250 {
13251         operand *bi_parms[MAX_BUILTIN_ARGS];
13252         int nbi_parms;
13253         iCode *bi_iCode;
13254         symbol *bif;
13255
13256         /* get all the arguments for a built in function */
13257         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13258
13259         /* which function is it */
13260         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13261         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13262                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13263         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13264                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13265         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13266                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13267         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13268                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13269         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13270                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13271         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13272                 genInp(bi_iCode,nbi_parms,bi_parms);
13273         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13274                 genOutp(bi_iCode,nbi_parms,bi_parms);
13275         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13276                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13277                 /* JavaNative builtIns */               
13278         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13279                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13280         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13281                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13282         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13283                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13284         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13285                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13286         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13287                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13288         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13289                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13290         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13291                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13292         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13293                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13294         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13295                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13296         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13297                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13298         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13299                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13300         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13301                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13302         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13303                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13304         } else if (strcmp(bif->name,"MM_Free")==0) {
13305                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13306         } else if (strcmp(bif->name,"MM_Deref")==0) {
13307                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13308         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13309                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13310         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13311                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13312         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13313                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13314         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13315                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13316         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13317                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13318         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13319                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13320         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13321                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13322         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13323                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13324         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13325                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13326         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13327                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13328         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13329                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13330         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13331                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13332         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13333                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13334         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13335                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13336         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13337                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13338         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13339                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13340         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13341                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13342         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13343                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13344         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13345                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13346         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13347                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13348         } else {
13349                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13350                 return ;
13351         }
13352         return ;    
13353 }
13354
13355 /*-----------------------------------------------------------------*/
13356 /* gen390Code - generate code for Dallas 390 based controllers     */
13357 /*-----------------------------------------------------------------*/
13358 void
13359 gen390Code (iCode * lic)
13360 {
13361   iCode *ic;
13362   int cln = 0;
13363
13364   lineHead = lineCurr = NULL;
13365   dptrn[1][0] = "dpl1";
13366   dptrn[1][1] = "dph1";
13367   dptrn[1][2] = "dpx1";
13368   
13369   if (options.model == MODEL_FLAT24) {
13370     fReturnSizeDS390 = 5;
13371     fReturn = fReturn24;
13372   } else {
13373     fReturnSizeDS390 = 4;
13374     fReturn = fReturn16;
13375     options.stack10bit=0;
13376   }
13377 #if 1
13378   /* print the allocation information */
13379   if (allocInfo && currFunc)
13380     printAllocInfo (currFunc, codeOutFile);
13381 #endif
13382   /* if debug information required */
13383   if (options.debug && currFunc)
13384     {
13385       debugFile->writeFunction (currFunc, lic);
13386     }
13387   /* stack pointer name */
13388   if (options.useXstack)
13389     spname = "_spx";
13390   else
13391     spname = "sp";
13392
13393
13394   for (ic = lic; ic; ic = ic->next)
13395     {
13396
13397       _G.current_iCode = ic;
13398       
13399       if (ic->lineno && cln != ic->lineno)
13400         {
13401           if (options.debug)
13402             {
13403               debugFile->writeCLine (ic);
13404             }
13405           if (!options.noCcodeInAsm) {
13406             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13407                       printCLine(ic->filename, ic->lineno));
13408           }
13409           cln = ic->lineno;
13410         }
13411       if (options.iCodeInAsm) {
13412         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13413       }
13414       /* if the result is marked as
13415          spilt and rematerializable or code for
13416          this has already been generated then
13417          do nothing */
13418       if (resultRemat (ic) || ic->generated)
13419         continue;
13420
13421       /* depending on the operation */
13422       switch (ic->op)
13423         {
13424         case '!':
13425           genNot (ic);
13426           break;
13427
13428         case '~':
13429           genCpl (ic);
13430           break;
13431
13432         case UNARYMINUS:
13433           genUminus (ic);
13434           break;
13435
13436         case IPUSH:
13437           genIpush (ic);
13438           break;
13439
13440         case IPOP:
13441           /* IPOP happens only when trying to restore a
13442              spilt live range, if there is an ifx statement
13443              following this pop then the if statement might
13444              be using some of the registers being popped which
13445              would destory the contents of the register so
13446              we need to check for this condition and handle it */
13447           if (ic->next &&
13448               ic->next->op == IFX &&
13449               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13450             genIfx (ic->next, ic);
13451           else
13452             genIpop (ic);
13453           break;
13454
13455         case CALL:
13456           genCall (ic);
13457           break;
13458
13459         case PCALL:
13460           genPcall (ic);
13461           break;
13462
13463         case FUNCTION:
13464           genFunction (ic);
13465           break;
13466
13467         case ENDFUNCTION:
13468           genEndFunction (ic);
13469           break;
13470
13471         case RETURN:
13472           genRet (ic);
13473           break;
13474
13475         case LABEL:
13476           genLabel (ic);
13477           break;
13478
13479         case GOTO:
13480           genGoto (ic);
13481           break;
13482
13483         case '+':
13484           genPlus (ic);
13485           break;
13486
13487         case '-':
13488           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13489             genMinus (ic);
13490           break;
13491
13492         case '*':
13493           genMult (ic);
13494           break;
13495
13496         case '/':
13497           genDiv (ic);
13498           break;
13499
13500         case '%':
13501           genMod (ic);
13502           break;
13503
13504         case '>':
13505           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13506           break;
13507
13508         case '<':
13509           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13510           break;
13511
13512         case LE_OP:
13513         case GE_OP:
13514         case NE_OP:
13515
13516           /* note these two are xlated by algebraic equivalence
13517              during parsing SDCC.y */
13518           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13519                   "got '>=' or '<=' shouldn't have come here");
13520           break;
13521
13522         case EQ_OP:
13523           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13524           break;
13525
13526         case AND_OP:
13527           genAndOp (ic);
13528           break;
13529
13530         case OR_OP:
13531           genOrOp (ic);
13532           break;
13533
13534         case '^':
13535           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13536           break;
13537
13538         case '|':
13539           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13540           break;
13541
13542         case BITWISEAND:
13543           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13544           break;
13545
13546         case INLINEASM:
13547           genInline (ic);
13548           break;
13549
13550         case RRC:
13551           genRRC (ic);
13552           break;
13553
13554         case RLC:
13555           genRLC (ic);
13556           break;
13557
13558         case GETHBIT:
13559           genGetHbit (ic);
13560           break;
13561
13562         case LEFT_OP:
13563           genLeftShift (ic);
13564           break;
13565
13566         case RIGHT_OP:
13567           genRightShift (ic);
13568           break;
13569
13570         case GET_VALUE_AT_ADDRESS:
13571           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13572           break;
13573
13574         case '=':
13575           if (POINTER_SET (ic))
13576             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13577           else
13578             genAssign (ic);
13579           break;
13580
13581         case IFX:
13582           genIfx (ic, NULL);
13583           break;
13584
13585         case ADDRESS_OF:
13586           genAddrOf (ic);
13587           break;
13588
13589         case JUMPTABLE:
13590           genJumpTab (ic);
13591           break;
13592
13593         case CAST:
13594           genCast (ic);
13595           break;
13596
13597         case RECEIVE:
13598           genReceive (ic);
13599           break;
13600
13601         case SEND:
13602           if (ic->builtinSEND) genBuiltIn(ic);
13603           else addSet (&_G.sendSet, ic);
13604           break;
13605
13606         case DUMMY_READ_VOLATILE:
13607           genDummyRead (ic);
13608           break;
13609
13610         case CRITICAL:
13611           genCritical (ic);
13612           break;
13613
13614         case ENDCRITICAL:
13615           genEndCritical (ic);
13616           break;
13617         
13618         case SWAP:
13619           genSwap (ic);
13620           break;
13621           
13622 #if 0 // obsolete, and buggy for != xdata
13623         case ARRAYINIT:
13624             genArrayInit(ic);
13625             break;
13626 #endif
13627             
13628         default:
13629           ic = ic;
13630         }
13631     }
13632
13633
13634   /* now we are ready to call the
13635      peep hole optimizer */
13636   if (!options.nopeep)
13637     peepHole (&lineHead);
13638
13639   /* now do the actual printing */
13640   printLine (lineHead, codeOutFile);
13641   return;
13642 }