* src/ds390/main.c,
[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 (strcmp (sym1->rname, sym2->rname) == 0)
870     return TRUE;
871
872
873   /* if left is a tmp & right is not */
874   if (IS_ITEMP (op1) &&
875       !IS_ITEMP (op2) &&
876       sym1->isspilt &&
877       (sym1->usl.spillLoc == sym2))
878     return TRUE;
879
880   if (IS_ITEMP (op2) &&
881       !IS_ITEMP (op1) &&
882       sym2->isspilt &&
883       sym1->level > 0 &&
884       (sym2->usl.spillLoc == sym1))
885     return TRUE;
886
887   /* are they spilt to the same location */
888   if (IS_ITEMP (op2) &&
889       IS_ITEMP (op1) &&
890       sym2->isspilt &&
891       sym1->isspilt &&
892       (sym1->usl.spillLoc == sym2->usl.spillLoc))
893     return TRUE;
894     
895   return FALSE;
896 }
897
898 /*-----------------------------------------------------------------*/
899 /* sameRegs - two asmops have the same registers                   */
900 /*-----------------------------------------------------------------*/
901 static bool
902 sameRegs (asmop * aop1, asmop * aop2)
903 {
904   int i;
905
906   if (aop1 == aop2)
907     {
908       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
909         {
910           return FALSE;
911         }
912       return TRUE;
913     }
914
915   if (aop1->type != AOP_REG ||
916       aop2->type != AOP_REG)
917     return FALSE;
918
919   if (aop1->size != aop2->size)
920     return FALSE;
921
922   for (i = 0; i < aop1->size; i++)
923     if (aop1->aopu.aop_reg[i] !=
924         aop2->aopu.aop_reg[i])
925       return FALSE;
926
927   return TRUE;
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* aopOp - allocates an asmop for an operand  :                    */
932 /*-----------------------------------------------------------------*/
933 static void
934 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
935 {
936   asmop *aop;
937   symbol *sym;
938   int i;
939
940   if (!op)
941     return;
942
943   /* if this a literal */
944   if (IS_OP_LITERAL (op))
945     {
946       op->aop = aop = newAsmop (AOP_LIT);
947       aop->aopu.aop_lit = op->operand.valOperand;
948       aop->size = getSize (operandType (op));
949       return;
950     }
951
952   /* if already has a asmop then continue */
953   if (op->aop)
954     {
955       if ((op->aop->type == AOP_DPTR && useDP2)
956           || (op->aop->type == AOP_DPTR2 && !useDP2))
957         op->aop = NULL;
958       else
959         return;
960     }
961
962   /* if the underlying symbol has a aop */
963   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
964     {
965       op->aop = OP_SYMBOL (op)->aop;
966       if ((op->aop->type == AOP_DPTR && useDP2)
967           || (op->aop->type == AOP_DPTR2 && !useDP2))
968         op->aop = NULL;
969       else
970         return;
971     }
972
973   /* if this is a true symbol */
974   if (IS_TRUE_SYMOP (op))
975     {
976       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
977       return;
978     }
979
980   /* this is a temporary : this has
981      only four choices :
982      a) register
983      b) spillocation
984      c) rematerialize
985      d) conditional
986      e) can be a return use only */
987
988   sym = OP_SYMBOL (op);
989
990
991   /* if the type is a conditional */
992   if (sym->regType == REG_CND)
993     {
994       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
995       aop->size = 0;
996       return;
997     }
998
999   /* if it is spilt then two situations
1000      a) is rematerialize
1001      b) has a spill location */
1002   if (sym->isspilt || sym->nRegs == 0)
1003     {
1004
1005       /* rematerialize it NOW */
1006       if (sym->remat)
1007         {
1008           sym->aop = op->aop = aop =
1009             aopForRemat (sym);
1010           aop->size = getSize (sym->type);
1011           return;
1012         }
1013
1014       if (sym->accuse)
1015         {
1016           int i;
1017           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1018           aop->size = getSize (sym->type);
1019           for (i = 0; i < 2; i++)
1020             aop->aopu.aop_str[i] = accUse[i];
1021           return;
1022         }
1023
1024       if (sym->ruonly)
1025         {
1026           int i;
1027
1028           if (useDP2)
1029             {
1030               /* a AOP_STR uses DPTR, but DPTR is already in use;
1031                * we're just hosed.
1032                */
1033                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1034             }
1035
1036           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1037           aop->size = getSize (sym->type);
1038           for (i = 0; i < (int) fReturnSizeDS390; i++)
1039             aop->aopu.aop_str[i] = fReturn[i];
1040           return;
1041         }
1042       
1043       if (sym->dptr) { /* has been allocated to a DPTRn */
1044           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1045           aop->size = getSize (sym->type);
1046           aop->aopu.dptr = sym->dptr;
1047           return ;
1048       }
1049       
1050       if (sym->usl.spillLoc)
1051         {
1052           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1053             {
1054               /* force a new aop if sizes differ */
1055               sym->usl.spillLoc->aop = NULL;
1056             }
1057           sym->aop = op->aop = aop =
1058                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1059           aop->size = getSize (sym->type);
1060           return;
1061         }
1062       
1063       /* else must be a dummy iTemp */
1064       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1065       aop->size = getSize (sym->type);
1066       return;
1067     }
1068
1069   /* must be in a register */
1070   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1071   aop->size = sym->nRegs;
1072   for (i = 0; i < sym->nRegs; i++)
1073     aop->aopu.aop_reg[i] = sym->regs[i];
1074 }
1075
1076 /*-----------------------------------------------------------------*/
1077 /* freeAsmop - free up the asmop given to an operand               */
1078 /*----------------------------------------------------------------*/
1079 static void
1080 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1081 {
1082   asmop *aop;
1083
1084   if (!op)
1085     aop = aaop;
1086   else
1087     aop = op->aop;
1088
1089   if (!aop)
1090     return;
1091
1092   if (aop->freed)
1093     goto dealloc;
1094
1095   aop->freed = 1;
1096
1097   /* depending on the asmop type only three cases need work AOP_RO
1098      , AOP_R1 && AOP_STK */
1099   switch (aop->type)
1100     {
1101     case AOP_R0:
1102       if (_G.r0Pushed)
1103         {
1104           if (pop)
1105             {
1106               emitcode ("pop", "ar0");
1107               _G.r0Pushed--;
1108             }
1109         }
1110       bitVectUnSetBit (ic->rUsed, R0_IDX);
1111       break;
1112
1113     case AOP_R1:
1114       if (_G.r1Pushed)
1115         {
1116           if (pop)
1117             {
1118               emitcode ("pop", "ar1");
1119               _G.r1Pushed--;
1120             }
1121         }
1122       bitVectUnSetBit (ic->rUsed, R1_IDX);
1123       break;
1124
1125     case AOP_STK:
1126       {
1127         int sz = aop->size;
1128         int stk = aop->aopu.aop_stk + aop->size;
1129         bitVectUnSetBit (ic->rUsed, R0_IDX);
1130         bitVectUnSetBit (ic->rUsed, R1_IDX);
1131
1132         getFreePtr (ic, &aop, FALSE);
1133
1134         if (options.stack10bit)
1135           {
1136             /* I'm not sure what to do here yet... */
1137             /* #STUB */
1138             fprintf (stderr,
1139                      "*** Warning: probably generating bad code for "
1140                      "10 bit stack mode.\n");
1141           }
1142
1143         if (stk)
1144           {
1145             emitcode ("mov", "a,_bp");
1146             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1147             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1148           }
1149         else
1150           {
1151             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1152           }
1153
1154         while (sz--)
1155           {
1156             emitcode ("pop", "acc");
1157             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1158             if (!sz)
1159               break;
1160             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1161           }
1162         op->aop = aop;
1163         freeAsmop (op, NULL, ic, TRUE);
1164         if (_G.r0Pushed)
1165           {
1166             emitcode ("pop", "ar0");
1167             _G.r0Pushed--;
1168           }
1169
1170         if (_G.r1Pushed)
1171           {
1172             emitcode ("pop", "ar1");
1173             _G.r1Pushed--;
1174           }
1175       }
1176     case AOP_DPTR2:
1177         if (_G.dptr1InUse) {
1178             emitcode ("pop","dpx1");
1179             emitcode ("pop","dph1");
1180             emitcode ("pop","dpl1");
1181         }
1182         break;
1183     case AOP_DPTR:
1184         if (_G.dptrInUse) {
1185             emitcode ("pop","dpx");
1186             emitcode ("pop","dph");
1187             emitcode ("pop","dpl");
1188         }
1189         break;
1190     }
1191 dealloc:
1192   /* all other cases just dealloc */
1193   if (op)
1194     {
1195       op->aop = NULL;
1196       if (IS_SYMOP (op))
1197         {
1198           OP_SYMBOL (op)->aop = NULL;
1199           /* if the symbol has a spill */
1200           if (SPIL_LOC (op))
1201             SPIL_LOC (op)->aop = NULL;
1202         }
1203     }
1204 }
1205
1206 #define DEFAULT_ACC_WARNING 0
1207 static int saveAccWarn = DEFAULT_ACC_WARNING;
1208
1209 /*-------------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop                            */
1211 /*                                                                   */
1212 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1213 /* in the accumulator. Set it to the name of a free register         */
1214 /* if acc must be preserved; the register will be used to preserve   */
1215 /* acc temporarily and to return the result byte.                    */
1216 /*-------------------------------------------------------------------*/
1217
1218 static char *
1219 aopGet (asmop *aop,
1220         int   offset,
1221         bool  bit16,
1222         bool  dname,
1223         char  *saveAcc)
1224 {
1225   /* offset is greater than
1226      size then zero */
1227   if (offset > (aop->size - 1) &&
1228       aop->type != AOP_LIT)
1229     return zero;
1230
1231   /* depending on type */
1232   switch (aop->type)
1233     {
1234     case AOP_DUMMY:
1235       return zero;
1236
1237     case AOP_R0:
1238     case AOP_R1:
1239       /* if we need to increment it */
1240       while (offset > aop->coff)
1241         {
1242           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1243           aop->coff++;
1244         }
1245
1246       while (offset < aop->coff)
1247         {
1248           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1249           aop->coff--;
1250         }
1251
1252       aop->coff = offset;
1253       if (aop->paged)
1254         {
1255           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1256           return (dname ? "acc" : "a");
1257         }
1258       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1259       return Safe_strdup(buffer);       
1260
1261     case AOP_DPTRn:
1262         assert(offset <= 3);
1263         return dptrn[aop->aopu.dptr][offset];
1264
1265     case AOP_DPTR:
1266     case AOP_DPTR2:
1267
1268       if (aop->type == AOP_DPTR2)
1269         {
1270           genSetDPTR (1);
1271         }
1272         
1273       if (saveAcc)
1274         {
1275             TR_AP("#1");
1276 //          if (aop->type != AOP_DPTR2)
1277 //          {
1278 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1279 //              emitcode(";", "spanky: saveAcc for DPTR");
1280 //          }
1281             
1282             emitcode ("xch", "a, %s", saveAcc);
1283         }
1284
1285       _flushLazyDPS ();
1286
1287       while (offset > aop->coff)
1288         {
1289           emitcode ("inc", "dptr");
1290           aop->coff++;
1291         }
1292
1293       while (offset < aop->coff)
1294         {
1295           emitcode ("lcall", "__decdptr");
1296           aop->coff--;
1297         }
1298
1299       aop->coff = offset;
1300       if (aop->code)
1301         {
1302           emitcode ("clr", "a");
1303           emitcode ("movc", "a,@a+dptr");
1304         }
1305       else
1306         {
1307           emitcode ("movx", "a,@dptr");
1308         }
1309
1310       if (aop->type == AOP_DPTR2)
1311         {
1312           genSetDPTR (0);
1313         }
1314         
1315         if (saveAcc)
1316         {
1317        TR_AP("#2");
1318               emitcode ("xch", "a, %s", saveAcc);
1319 //            if (strcmp(saveAcc, "_ap"))
1320 //            {
1321 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1322 //            }
1323                   
1324               return saveAcc;
1325         }
1326       return (dname ? "acc" : "a");
1327
1328     case AOP_IMMD:
1329       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1330       {
1331           SNPRINTF(buffer, sizeof(buffer), 
1332                    "%s",aop->aopu.aop_immd.aop_immd2);
1333       } 
1334       else if (bit16)
1335       {
1336          SNPRINTF(buffer, sizeof(buffer), 
1337                   "#%s", aop->aopu.aop_immd.aop_immd1);
1338       }
1339       else if (offset) 
1340       {
1341           switch (offset) {
1342           case 1:
1343               tsprintf(buffer, sizeof(buffer),
1344                        "#!his",aop->aopu.aop_immd.aop_immd1);
1345               break;
1346           case 2:
1347               tsprintf(buffer, sizeof(buffer), 
1348                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1349               break;
1350           case 3:
1351               tsprintf(buffer, sizeof(buffer),
1352                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1353               break;
1354           default: /* should not need this (just in case) */
1355               SNPRINTF (buffer, sizeof(buffer), 
1356                         "#(%s >> %d)",
1357                        aop->aopu.aop_immd.aop_immd1,
1358                        offset * 8);
1359           }
1360       }
1361       else
1362       {
1363         SNPRINTF (buffer, sizeof(buffer), 
1364                   "#%s", aop->aopu.aop_immd.aop_immd1);
1365       }
1366       return Safe_strdup(buffer);       
1367
1368     case AOP_DIR:
1369       if (offset)
1370       {
1371         SNPRINTF (buffer, sizeof(buffer),
1372                   "(%s + %d)",
1373                  aop->aopu.aop_dir,
1374                  offset);
1375       }
1376       else
1377       {
1378         SNPRINTF(buffer, sizeof(buffer), 
1379                  "%s", aop->aopu.aop_dir);
1380       }
1381
1382       return Safe_strdup(buffer);
1383
1384     case AOP_REG:
1385       if (dname)
1386         return aop->aopu.aop_reg[offset]->dname;
1387       else
1388         return aop->aopu.aop_reg[offset]->name;
1389
1390     case AOP_CRY:
1391       emitcode ("clr", "a");
1392       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1393       emitcode ("rlc", "a");
1394       return (dname ? "acc" : "a");
1395
1396     case AOP_ACC:
1397       if (!offset && dname)
1398         return "acc";
1399       return aop->aopu.aop_str[offset];
1400
1401     case AOP_LIT:
1402       return aopLiteral (aop->aopu.aop_lit, offset);
1403
1404     case AOP_STR:
1405       aop->coff = offset;
1406       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1407           dname)
1408         return "acc";
1409
1410       return aop->aopu.aop_str[offset];
1411
1412     }
1413
1414   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1415           "aopget got unsupported aop->type");
1416   exit (1);
1417     
1418   return NULL;  // not reached, but makes compiler happy.
1419 }
1420 /*-----------------------------------------------------------------*/
1421 /* aopPut - puts a string for a aop                                */
1422 /*-----------------------------------------------------------------*/
1423 static void
1424 aopPut (asmop * aop, char *s, int offset)
1425 {
1426   if (aop->size && offset > (aop->size - 1))
1427     {
1428       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1429               "aopPut got offset > aop->size");
1430       exit (1);
1431     }
1432
1433   /* will assign value to value */
1434   /* depending on where it is ofcourse */
1435   switch (aop->type)
1436     {
1437     case AOP_DUMMY:
1438       MOVA (s);         /* read s in case it was volatile */
1439       break;
1440       
1441     case AOP_DIR:
1442         if (offset)
1443         {
1444             SNPRINTF (buffer, sizeof(buffer),
1445                       "(%s + %d)",
1446                       aop->aopu.aop_dir, offset);
1447         }
1448         else
1449         {
1450             SNPRINTF (buffer, sizeof(buffer), 
1451                      "%s", aop->aopu.aop_dir);
1452         }
1453         
1454
1455         if (strcmp (buffer, s))
1456         {
1457             emitcode ("mov", "%s,%s", buffer, s);
1458         }
1459       break;
1460
1461     case AOP_REG:
1462       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1463           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1464         {
1465           if (*s == '@' ||
1466               strcmp (s, "r0") == 0 ||
1467               strcmp (s, "r1") == 0 ||
1468               strcmp (s, "r2") == 0 ||
1469               strcmp (s, "r3") == 0 ||
1470               strcmp (s, "r4") == 0 ||
1471               strcmp (s, "r5") == 0 ||
1472               strcmp (s, "r6") == 0 ||
1473               strcmp (s, "r7") == 0)
1474             {
1475                 emitcode ("mov", "%s,%s",
1476                           aop->aopu.aop_reg[offset]->dname, s);
1477             }
1478             else
1479             {
1480                 emitcode ("mov", "%s,%s",
1481                           aop->aopu.aop_reg[offset]->name, s);
1482             }
1483         }
1484       break;
1485
1486     case AOP_DPTRn:
1487         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1488         break;
1489
1490     case AOP_DPTR:
1491     case AOP_DPTR2:
1492
1493       if (aop->type == AOP_DPTR2)
1494         {
1495           genSetDPTR (1);
1496         }
1497       _flushLazyDPS ();
1498
1499       if (aop->code)
1500         {
1501           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1502                   "aopPut writting to code space");
1503           exit (1);
1504         }
1505
1506       while (offset > aop->coff)
1507         {
1508           aop->coff++;
1509           emitcode ("inc", "dptr");
1510         }
1511
1512       while (offset < aop->coff)
1513         {
1514           aop->coff--;
1515           emitcode ("lcall", "__decdptr");
1516         }
1517
1518       aop->coff = offset;
1519
1520       /* if not in accumulater */
1521       MOVA (s);
1522
1523       emitcode ("movx", "@dptr,a");
1524
1525       if (aop->type == AOP_DPTR2)
1526         {
1527           genSetDPTR (0);
1528         }
1529       break;
1530
1531     case AOP_R0:
1532     case AOP_R1:
1533       while (offset > aop->coff)
1534         {
1535           aop->coff++;
1536           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1537         }
1538       while (offset < aop->coff)
1539         {
1540           aop->coff--;
1541           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1542         }
1543       aop->coff = offset;
1544
1545       if (aop->paged)
1546         {
1547           MOVA (s);
1548           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1549
1550         }
1551       else if (*s == '@')
1552         {
1553           MOVA (s);
1554           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1555         }
1556       else if (strcmp (s, "r0") == 0 ||
1557                strcmp (s, "r1") == 0 ||
1558                strcmp (s, "r2") == 0 ||
1559                strcmp (s, "r3") == 0 ||
1560                strcmp (s, "r4") == 0 ||
1561                strcmp (s, "r5") == 0 ||
1562                strcmp (s, "r6") == 0 ||
1563                strcmp (s, "r7") == 0)
1564         {
1565           char buff[10];
1566           SNPRINTF(buff, sizeof(buff), 
1567                    "a%s", s);
1568           emitcode ("mov", "@%s,%s",
1569                     aop->aopu.aop_ptr->name, buff);
1570         }
1571         else
1572         {
1573             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1574         }
1575       break;
1576
1577     case AOP_STK:
1578       if (strcmp (s, "a") == 0)
1579         emitcode ("push", "acc");
1580       else
1581         if (*s=='@') {
1582           MOVA(s);
1583           emitcode ("push", "acc");
1584         } else {
1585           emitcode ("push", s);
1586         }
1587
1588       break;
1589
1590     case AOP_CRY:
1591       /* if bit variable */
1592       if (!aop->aopu.aop_dir)
1593         {
1594           emitcode ("clr", "a");
1595           emitcode ("rlc", "a");
1596         }
1597       else
1598         {
1599           if (s == zero)
1600             emitcode ("clr", "%s", aop->aopu.aop_dir);
1601           else if (s == one)
1602             emitcode ("setb", "%s", aop->aopu.aop_dir);
1603           else if (!strcmp (s, "c"))
1604             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1605           else
1606             {
1607               if (strcmp (s, "a"))
1608                 {
1609                   MOVA (s);
1610                 }
1611               {
1612                 /* set C, if a >= 1 */
1613                 emitcode ("add", "a,#!constbyte",0xff);
1614                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1615               }
1616             }
1617         }
1618       break;
1619
1620     case AOP_STR:
1621       aop->coff = offset;
1622       if (strcmp (aop->aopu.aop_str[offset], s))
1623         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1624       break;
1625
1626     case AOP_ACC:
1627       aop->coff = offset;
1628       if (!offset && (strcmp (s, "acc") == 0))
1629         break;
1630
1631       if (strcmp (aop->aopu.aop_str[offset], s))
1632         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1633       break;
1634
1635     default:
1636       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1637               "aopPut got unsupported aop->type");
1638       exit (1);
1639     }
1640
1641 }
1642
1643
1644 /*--------------------------------------------------------------------*/
1645 /* reAdjustPreg - points a register back to where it should (coff==0) */
1646 /*--------------------------------------------------------------------*/
1647 static void
1648 reAdjustPreg (asmop * aop)
1649 {
1650   if ((aop->coff==0) || (aop->size <= 1)) {
1651     return;
1652   }
1653
1654   switch (aop->type)
1655     {
1656     case AOP_R0:
1657     case AOP_R1:
1658       while (aop->coff--)
1659         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1660       break;
1661     case AOP_DPTR:
1662     case AOP_DPTR2:
1663       if (aop->type == AOP_DPTR2)
1664         {
1665           genSetDPTR (1);
1666           _flushLazyDPS ();
1667         }
1668       while (aop->coff--)
1669         {
1670           emitcode ("lcall", "__decdptr");
1671         }
1672
1673       if (aop->type == AOP_DPTR2)
1674         {
1675           genSetDPTR (0);
1676         }
1677       break;
1678
1679     }
1680   aop->coff=0;
1681 }
1682
1683 #define AOP(op) op->aop
1684 #define AOP_TYPE(op) AOP(op)->type
1685 #define AOP_SIZE(op) AOP(op)->size
1686 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1687                        AOP_TYPE(x) == AOP_R0))
1688
1689 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1690                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1691                          AOP(x)->paged))
1692
1693 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1694                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1695                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1696 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1697 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1698 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1699
1700 // The following two macros can be used even if the aop has not yet been aopOp'd.
1701 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1702 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1703
1704 /* Workaround for DS80C390 bug: div ab may return bogus results
1705  * if A is accessed in instruction immediately before the div.
1706  *
1707  * Will be fixed in B4 rev of processor, Dallas claims.
1708  */
1709
1710 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1711     if (!AOP_NEEDSACC(RIGHT))         \
1712     {               \
1713       /* We can load A first, then B, since     \
1714        * B (the RIGHT operand) won't clobber A,   \
1715        * thus avoiding touching A right before the div. \
1716        */             \
1717       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1718       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1719       MOVA(L);            \
1720       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1721       MOVB(L); \
1722     }               \
1723     else              \
1724     {               \
1725       /* Just stuff in a nop after loading A. */    \
1726       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1727       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1728       MOVA(L);            \
1729       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1730     }
1731
1732
1733 /*-----------------------------------------------------------------*/
1734 /* opIsGptr: returns non-zero if the passed operand is       */
1735 /* a generic pointer type.             */
1736 /*-----------------------------------------------------------------*/
1737 static int
1738 opIsGptr (operand * op)
1739 {
1740   sym_link *type = operandType (op);
1741
1742   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1743     {
1744       return 1;
1745     }
1746   return 0;
1747 }
1748
1749 /*-----------------------------------------------------------------*/
1750 /* getDataSize - get the operand data size                         */
1751 /*-----------------------------------------------------------------*/
1752 static int
1753 getDataSize (operand * op)
1754 {
1755   int size;
1756   size = AOP_SIZE (op);
1757   if (size == GPTRSIZE)
1758     {
1759       sym_link *type = operandType (op);
1760       if (IS_GENPTR (type))
1761         {
1762           /* generic pointer; arithmetic operations
1763            * should ignore the high byte (pointer type).
1764            */
1765           size--;
1766         }
1767     }
1768   return size;
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* outAcc - output Acc                                             */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 outAcc (operand * result)
1776 {
1777   int size, offset;
1778   size = getDataSize (result);
1779   if (size)
1780     {
1781       aopPut (AOP (result), "a", 0);
1782       size--;
1783       offset = 1;
1784       /* unsigned or positive */
1785       while (size--)
1786         {
1787           aopPut (AOP (result), zero, offset++);
1788         }
1789     }
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* outBitC - output a bit C                                        */
1794 /*-----------------------------------------------------------------*/
1795 static void
1796 outBitC (operand * result)
1797 {
1798   /* if the result is bit */
1799   if (AOP_TYPE (result) == AOP_CRY)
1800     {
1801       aopPut (AOP (result), "c", 0);
1802     }
1803   else
1804     {
1805       emitcode ("clr", "a");
1806       emitcode ("rlc", "a");
1807       outAcc (result);
1808     }
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* toBoolean - emit code for orl a,operator(sizeop)                */
1813 /*-----------------------------------------------------------------*/
1814 static void
1815 toBoolean (operand * oper)
1816 {
1817   int   size = AOP_SIZE (oper) - 1;
1818   int   offset = 1;
1819   bool usedB = FALSE;
1820
1821   /* The generic part of a generic pointer should
1822    * not participate in it's truth value.
1823    *
1824    * i.e. 0x10000000 is zero.
1825    */
1826   if (opIsGptr (oper))
1827     {
1828       D (emitcode (";", "toBoolean: generic ptr special case."););
1829       size--;
1830     }
1831
1832   _startLazyDPSEvaluation ();
1833   if (AOP_NEEDSACC (oper) && size)
1834     {
1835       usedB = TRUE;
1836       if (_G.bInUse)
1837       {
1838           emitcode ("push", "b");
1839       }
1840       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1841     }
1842   else
1843     {
1844       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1845     }
1846     
1847   while (size--)
1848     {
1849       if (usedB)
1850         {
1851           emitcode ("orl", "b,%s",
1852                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1853         }
1854       else
1855         {
1856           emitcode ("orl", "a,%s",
1857                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1858         }
1859     }
1860   _endLazyDPSEvaluation ();
1861
1862   if (usedB)
1863     {
1864       emitcode ("mov", "a,b");
1865       if (_G.bInUse)
1866       {
1867           emitcode ("pop", "b");
1868       }
1869         
1870     }
1871 }
1872
1873
1874 /*-----------------------------------------------------------------*/
1875 /* genNot - generate code for ! operation                          */
1876 /*-----------------------------------------------------------------*/
1877 static void
1878 genNot (iCode * ic)
1879 {
1880   symbol *tlbl;
1881
1882   D (emitcode (";", "genNot "););
1883
1884   /* assign asmOps to operand & result */
1885   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1887
1888   /* if in bit space then a special case */
1889   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1890     {
1891       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892       emitcode ("cpl", "c");
1893       outBitC (IC_RESULT (ic));
1894       goto release;
1895     }
1896
1897   toBoolean (IC_LEFT (ic));
1898
1899   tlbl = newiTempLabel (NULL);
1900   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1901   emitcode ("", "!tlabeldef", tlbl->key + 100);
1902   outBitC (IC_RESULT (ic));
1903
1904 release:
1905   /* release the aops */
1906   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1907   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1908 }
1909
1910
1911 /*-----------------------------------------------------------------*/
1912 /* genCpl - generate code for complement                           */
1913 /*-----------------------------------------------------------------*/
1914 static void
1915 genCpl (iCode * ic)
1916 {
1917   int offset = 0;
1918   int size;
1919   symbol *tlbl;
1920
1921   D (emitcode (";", "genCpl "););
1922
1923
1924   /* assign asmOps to operand & result */
1925   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1926   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1927
1928   /* special case if in bit space */
1929   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1930     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1931       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1932       emitcode ("cpl", "c");
1933       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1934       goto release;
1935     }
1936     tlbl=newiTempLabel(NULL);
1937     emitcode ("cjne", "%s,#0x01,%05d$", 
1938               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1939     emitcode ("", "%05d$:", tlbl->key+100);
1940     outBitC (IC_RESULT(ic));
1941     goto release;
1942   }
1943
1944   size = AOP_SIZE (IC_RESULT (ic));
1945   _startLazyDPSEvaluation ();
1946   while (size--)
1947     {
1948       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1949       emitcode ("cpl", "a");
1950       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1951     }
1952   _endLazyDPSEvaluation ();
1953
1954
1955 release:
1956   /* release the aops */
1957   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1958   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1959 }
1960
1961 /*-----------------------------------------------------------------*/
1962 /* genUminusFloat - unary minus for floating points                */
1963 /*-----------------------------------------------------------------*/
1964 static void
1965 genUminusFloat (operand * op, operand * result)
1966 {
1967   int size, offset = 0;
1968     
1969   D(emitcode (";", "genUminusFloat"););
1970   
1971   /* for this we just copy and then flip the bit */
1972     
1973   _startLazyDPSEvaluation ();
1974   size = AOP_SIZE (op) - 1;
1975
1976   while (size--)
1977   {
1978       aopPut (AOP (result),
1979               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1980               offset);
1981       offset++;
1982     }
1983   
1984   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1985
1986   emitcode ("cpl", "acc.7");
1987   aopPut (AOP (result), "a", offset);    
1988   _endLazyDPSEvaluation ();
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* genUminus - unary minus code generation                         */
1993 /*-----------------------------------------------------------------*/
1994 static void
1995 genUminus (iCode * ic)
1996 {
1997   int offset, size;
1998   sym_link *optype;
1999
2000   D (emitcode (";", "genUminus "););
2001
2002   /* assign asmops */
2003   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2004   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2005
2006   /* if both in bit space then special
2007      case */
2008   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2009       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2010     {
2011
2012       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2013       emitcode ("cpl", "c");
2014       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2015       goto release;
2016     }
2017
2018   optype = operandType (IC_LEFT (ic));
2019
2020   /* if float then do float stuff */
2021   if (IS_FLOAT (optype))
2022     {
2023       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2024       goto release;
2025     }
2026
2027   /* otherwise subtract from zero */
2028   size = AOP_SIZE (IC_LEFT (ic));
2029   offset = 0;
2030   _startLazyDPSEvaluation ();
2031   while (size--)
2032     {
2033       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2034       if (!strcmp (l, "a"))
2035         {
2036           if (offset == 0)
2037             SETC;
2038           emitcode ("cpl", "a");
2039           emitcode ("addc", "a,#0");
2040         }
2041       else
2042         {
2043           if (offset == 0)
2044             CLRC;
2045           emitcode ("clr", "a");
2046           emitcode ("subb", "a,%s", l);
2047         }
2048       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2049     }
2050   _endLazyDPSEvaluation ();
2051
2052   /* if any remaining bytes in the result */
2053   /* we just need to propagate the sign   */
2054   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2055     {
2056       emitcode ("rlc", "a");
2057       emitcode ("subb", "a,acc");
2058       while (size--)
2059         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2060     }
2061
2062 release:
2063   /* release the aops */
2064   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2065   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2066 }
2067
2068 /*-----------------------------------------------------------------*/
2069 /* savermask - saves registers in the mask                         */
2070 /*-----------------------------------------------------------------*/
2071 static void savermask(bitVect *rs_mask)
2072 {
2073     int i;
2074     if (options.useXstack) {
2075         if (bitVectBitValue (rs_mask, R0_IDX))
2076             emitcode ("mov", "b,r0");
2077         emitcode ("mov", "r0,%s", spname);
2078         for (i = 0; i < ds390_nRegs; i++) {
2079             if (bitVectBitValue (rs_mask, i)) {
2080                 if (i == R0_IDX)
2081                     emitcode ("mov", "a,b");
2082                 else
2083                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2084                 emitcode ("movx", "@r0,a");
2085                 emitcode ("inc", "r0");
2086             }
2087         }
2088         emitcode ("mov", "%s,r0", spname);
2089         if (bitVectBitValue (rs_mask, R0_IDX))
2090             emitcode ("mov", "r0,b");
2091     } else {
2092         for (i = 0; i < ds390_nRegs; i++) {
2093             if (bitVectBitValue (rs_mask, i))
2094                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2095         }
2096     }
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* saveRegisters - will look for a call and save the registers     */
2101 /*-----------------------------------------------------------------*/
2102 static void
2103 saveRegisters (iCode * lic)
2104 {
2105   iCode *ic;
2106   bitVect *rsave;
2107
2108   /* look for call */
2109   for (ic = lic; ic; ic = ic->next)
2110     if (ic->op == CALL || ic->op == PCALL)
2111       break;
2112
2113   if (!ic)
2114     {
2115       fprintf (stderr, "found parameter push with no function call\n");
2116       return;
2117     }
2118
2119   /* if the registers have been saved already then
2120      do nothing */
2121   if (ic->regsSaved 
2122       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2123     return ;
2124
2125   /* special case if DPTR alive across a function call then must save it 
2126      even though callee saves */
2127   if (IS_SYMOP(IC_LEFT(ic)) &&
2128       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2129       int i;
2130       rsave = newBitVect(ic->rMask->size);
2131       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2132           if (bitVectBitValue(ic->rMask,i))
2133               rsave = bitVectSetBit(rsave,i);
2134       }
2135       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2136   } else {
2137     /* safe the registers in use at this time but skip the
2138        ones for the result */
2139     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2140                            ds390_rUmaskForOp (IC_RESULT(ic)));
2141   }
2142   ic->regsSaved = 1;
2143   savermask(rsave);
2144 }
2145
2146 /*-----------------------------------------------------------------*/
2147 /* usavermask - restore registers with mask                        */
2148 /*-----------------------------------------------------------------*/
2149 static void unsavermask(bitVect *rs_mask)
2150 {
2151     int i;
2152     if (options.useXstack) {
2153         emitcode ("mov", "r0,%s", spname);
2154         for (i = ds390_nRegs; i >= 0; i--) {
2155             if (bitVectBitValue (rs_mask, i)) {
2156                 emitcode ("dec", "r0");
2157                 emitcode ("movx", "a,@r0");
2158                 if (i == R0_IDX)
2159                     emitcode ("mov", "b,a");
2160                 else
2161                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2162             }       
2163         }
2164         emitcode ("mov", "%s,r0", spname);
2165         if (bitVectBitValue (rs_mask, R0_IDX))
2166             emitcode ("mov", "r0,b");
2167     } else {
2168         for (i = ds390_nRegs; i >= 0; i--) {
2169             if (bitVectBitValue (rs_mask, i))
2170                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2171         }
2172     }
2173 }
2174
2175 /*-----------------------------------------------------------------*/
2176 /* unsaveRegisters - pop the pushed registers                      */
2177 /*-----------------------------------------------------------------*/
2178 static void
2179 unsaveRegisters (iCode * ic)
2180 {
2181   bitVect *rsave;
2182
2183   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2184       int i;
2185       rsave = newBitVect(ic->rMask->size);
2186       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2187           if (bitVectBitValue(ic->rMask,i))
2188               rsave = bitVectSetBit(rsave,i);
2189       }
2190       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2191   } else {
2192     /* restore the registers in use at this time but skip the
2193        ones for the result */
2194     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2195                            ds390_rUmaskForOp (IC_RESULT(ic)));
2196   }
2197   unsavermask(rsave);
2198 }
2199
2200
2201 /*-----------------------------------------------------------------*/
2202 /* pushSide -                */
2203 /*-----------------------------------------------------------------*/
2204 static void
2205 pushSide (operand * oper, int size)
2206 {
2207   int offset = 0;
2208   _startLazyDPSEvaluation ();
2209   while (size--)
2210     {
2211       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2212       if (AOP_TYPE (oper) != AOP_REG &&
2213           AOP_TYPE (oper) != AOP_DIR &&
2214           strcmp (l, "a"))
2215         {
2216           emitcode ("mov", "a,%s", l);
2217           emitcode ("push", "acc");
2218         }
2219       else
2220         emitcode ("push", "%s", l);
2221     }
2222   _endLazyDPSEvaluation ();
2223 }
2224
2225 /*-----------------------------------------------------------------*/
2226 /* assignResultValue -               */
2227 /*-----------------------------------------------------------------*/
2228 static void
2229 assignResultValue (operand * oper)
2230 {
2231   int offset = 0;
2232   int size = AOP_SIZE (oper);
2233   bool pushedAcc = FALSE;
2234
2235   if (size == fReturnSizeDS390)
2236   {
2237       /* I don't think this case can ever happen... */
2238       /* ACC is the last part of this. If writing the result
2239        * uses AC, we must preserve it.
2240        */
2241       if (AOP_NEEDSACC(oper))
2242       {
2243           emitcode(";", "assignResultValue special case for ACC.");
2244           emitcode("push", "acc");
2245           pushedAcc = TRUE;
2246           size--;
2247       }
2248   }
2249     
2250     
2251   _startLazyDPSEvaluation ();
2252   while (size--)
2253     {
2254       aopPut (AOP (oper), fReturn[offset], offset);
2255       offset++;
2256     }
2257   _endLazyDPSEvaluation ();
2258     
2259   if (pushedAcc)
2260     {
2261         emitcode("pop", "acc");
2262         aopPut(AOP(oper), "a", offset);
2263     }
2264 }
2265
2266
2267 /*-----------------------------------------------------------------*/
2268 /* genXpush - pushes onto the external stack                       */
2269 /*-----------------------------------------------------------------*/
2270 static void
2271 genXpush (iCode * ic)
2272 {
2273   asmop *aop = newAsmop (0);
2274   regs *r;
2275   int size, offset = 0;
2276
2277   D (emitcode (";", "genXpush ");
2278     );
2279
2280   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2281   r = getFreePtr (ic, &aop, FALSE);
2282
2283
2284   emitcode ("mov", "%s,_spx", r->name);
2285
2286   size = AOP_SIZE (IC_LEFT (ic));
2287   _startLazyDPSEvaluation ();
2288   while (size--)
2289     {
2290
2291       MOVA (aopGet (AOP (IC_LEFT (ic)),
2292                         offset++, FALSE, FALSE, NULL));
2293       emitcode ("movx", "@%s,a", r->name);
2294       emitcode ("inc", "%s", r->name);
2295
2296     }
2297   _endLazyDPSEvaluation ();
2298
2299
2300   emitcode ("mov", "_spx,%s", r->name);
2301
2302   freeAsmop (NULL, aop, ic, TRUE);
2303   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2304 }
2305
2306 /*-----------------------------------------------------------------*/
2307 /* genIpush - generate code for pushing this gets a little complex  */
2308 /*-----------------------------------------------------------------*/
2309 static void
2310 genIpush (iCode * ic)
2311 {
2312   int size, offset = 0;
2313   char *l;
2314
2315   D (emitcode (";", "genIpush ");
2316     );
2317
2318   /* if this is not a parm push : ie. it is spill push
2319      and spill push is always done on the local stack */
2320   if (!ic->parmPush)
2321     {
2322
2323       /* and the item is spilt then do nothing */
2324       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2325         return;
2326
2327       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2328       size = AOP_SIZE (IC_LEFT (ic));
2329       /* push it on the stack */
2330       _startLazyDPSEvaluation ();
2331       while (size--)
2332         {
2333           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2334           if (*l == '#')
2335             {
2336               MOVA (l);
2337               l = "acc";
2338             }
2339           emitcode ("push", "%s", l);
2340         }
2341       _endLazyDPSEvaluation ();
2342       return;
2343     }
2344
2345   /* this is a paramter push: in this case we call
2346      the routine to find the call and save those
2347      registers that need to be saved */
2348   saveRegisters (ic);
2349
2350   /* if use external stack then call the external
2351      stack pushing routine */
2352   if (options.useXstack)
2353     {
2354       genXpush (ic);
2355       return;
2356     }
2357
2358   /* then do the push */
2359   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2360
2361   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2362   size = AOP_SIZE (IC_LEFT (ic));
2363
2364   _startLazyDPSEvaluation ();
2365   while (size--)
2366     {
2367       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2368       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2369           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2370           strcmp (l, "acc"))
2371         {
2372           emitcode ("mov", "a,%s", l);
2373           emitcode ("push", "acc");
2374         }
2375       else
2376         {
2377             emitcode ("push", "%s", l);
2378         }
2379     }
2380   _endLazyDPSEvaluation ();
2381
2382   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2383 }
2384
2385 /*-----------------------------------------------------------------*/
2386 /* genIpop - recover the registers: can happen only for spilling   */
2387 /*-----------------------------------------------------------------*/
2388 static void
2389 genIpop (iCode * ic)
2390 {
2391   int size, offset;
2392
2393   D (emitcode (";", "genIpop ");
2394     );
2395
2396
2397   /* if the temp was not pushed then */
2398   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2399     return;
2400
2401   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2402   size = AOP_SIZE (IC_LEFT (ic));
2403   offset = (size - 1);
2404   _startLazyDPSEvaluation ();
2405   while (size--)
2406     {
2407       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2408                                      FALSE, TRUE, NULL));
2409     }
2410   _endLazyDPSEvaluation ();
2411
2412   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2413 }
2414
2415 /*-----------------------------------------------------------------*/
2416 /* unsaveRBank - restores the resgister bank from stack            */
2417 /*-----------------------------------------------------------------*/
2418 static void
2419 unsaveRBank (int bank, iCode * ic, bool popPsw)
2420 {
2421   int i;
2422   asmop *aop = NULL;
2423   regs *r = NULL;
2424
2425   if (options.useXstack)
2426   {
2427       if (!ic)
2428       {
2429           /* Assume r0 is available for use. */
2430           r = ds390_regWithIdx (R0_IDX);;          
2431       } 
2432       else
2433       {
2434           aop = newAsmop (0);
2435           r = getFreePtr (ic, &aop, FALSE);
2436       }
2437       emitcode ("mov", "%s,_spx", r->name);      
2438   }
2439   
2440   if (popPsw)
2441     {
2442       if (options.useXstack)
2443       {
2444           emitcode ("movx", "a,@%s", r->name);
2445           emitcode ("mov", "psw,a");
2446           emitcode ("dec", "%s", r->name);
2447         }
2448       else
2449       {
2450         emitcode ("pop", "psw");
2451       }
2452     }
2453
2454   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2455     {
2456       if (options.useXstack)
2457         {
2458           emitcode ("movx", "a,@%s", r->name);
2459           emitcode ("mov", "(%s+%d),a",
2460                     regs390[i].base, 8 * bank + regs390[i].offset);
2461           emitcode ("dec", "%s", r->name);
2462
2463         }
2464       else
2465         emitcode ("pop", "(%s+%d)",
2466                   regs390[i].base, 8 * bank + regs390[i].offset);
2467     }
2468
2469   if (options.useXstack)
2470     {
2471       emitcode ("mov", "_spx,%s", r->name);
2472     }
2473     
2474   if (aop)
2475   {
2476       freeAsmop (NULL, aop, ic, TRUE);  
2477   }    
2478 }
2479
2480 /*-----------------------------------------------------------------*/
2481 /* saveRBank - saves an entire register bank on the stack          */
2482 /*-----------------------------------------------------------------*/
2483 static void
2484 saveRBank (int bank, iCode * ic, bool pushPsw)
2485 {
2486   int i;
2487   asmop *aop = NULL;
2488   regs *r = NULL;
2489
2490   if (options.useXstack)
2491     {
2492         if (!ic)
2493         {
2494           /* Assume r0 is available for use. */
2495                   r = ds390_regWithIdx (R0_IDX);;
2496         }
2497         else
2498         {
2499           aop = newAsmop (0);
2500           r = getFreePtr (ic, &aop, FALSE);
2501         }
2502         emitcode ("mov", "%s,_spx", r->name);    
2503     }
2504
2505   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2506     {
2507       if (options.useXstack)
2508         {
2509           emitcode ("inc", "%s", r->name);
2510           emitcode ("mov", "a,(%s+%d)",
2511                     regs390[i].base, 8 * bank + regs390[i].offset);
2512           emitcode ("movx", "@%s,a", r->name);
2513         }
2514       else
2515         emitcode ("push", "(%s+%d)",
2516                   regs390[i].base, 8 * bank + regs390[i].offset);
2517     }
2518
2519   if (pushPsw)
2520     {
2521       if (options.useXstack)
2522         {
2523           emitcode ("mov", "a,psw");
2524           emitcode ("movx", "@%s,a", r->name);
2525           emitcode ("inc", "%s", r->name);
2526           emitcode ("mov", "_spx,%s", r->name);
2527         }
2528       else
2529       {
2530         emitcode ("push", "psw");
2531       }
2532
2533       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2534     }
2535   
2536   if (aop)
2537   {
2538        freeAsmop (NULL, aop, ic, TRUE);
2539   }    
2540     
2541   if (ic)
2542   {  
2543       ic->bankSaved = 1;
2544   }
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genSend - gen code for SEND                                     */
2549 /*-----------------------------------------------------------------*/
2550 static void genSend(set *sendSet)
2551 {
2552     iCode *sic;
2553     int sendCount = 0 ;
2554     static int rb1_count = 0;
2555
2556     for (sic = setFirstItem (sendSet); sic;
2557          sic = setNextItem (sendSet)) {     
2558         int size, offset = 0;
2559         
2560         size=getSize(operandType(IC_LEFT(sic)));
2561         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2562         if (sendCount == 0) { /* first parameter */
2563             // we know that dpl(hxb) is the result, so
2564             rb1_count = 0 ;
2565             _startLazyDPSEvaluation ();
2566             if (size>1) {
2567                 aopOp (IC_LEFT (sic), sic, FALSE, 
2568                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2569             } else {
2570                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2571             }
2572             while (size--) {
2573                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2574                                   FALSE, FALSE, NULL);
2575                 if (strcmp (l, fReturn[offset])) {
2576                     emitcode ("mov", "%s,%s",
2577                               fReturn[offset],
2578                               l);
2579                 }
2580                 offset++;
2581             }
2582             _endLazyDPSEvaluation ();
2583             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2584             rb1_count =0;
2585         } else { /* if more parameter in registers */
2586             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2587             while (size--) {
2588                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2589                                                                 FALSE, FALSE, NULL));
2590             }
2591             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2592         }
2593         sendCount++;
2594     }
2595 }
2596
2597 static void
2598 adjustEsp(const char *reg)
2599 {
2600     emitcode ("anl","%s,#3", reg);
2601     if (TARGET_IS_DS400)
2602     {
2603         emitcode ("orl","%s,#!constbyte",
2604                   reg,
2605                   (options.stack_loc >> 8) & 0xff);
2606     }
2607 }
2608
2609 /*-----------------------------------------------------------------*/
2610 /* genCall - generates a call statement                            */
2611 /*-----------------------------------------------------------------*/
2612 static void
2613 genCall (iCode * ic)
2614 {
2615   sym_link *dtype;
2616   bool restoreBank = FALSE;
2617   bool swapBanks = FALSE;
2618
2619   D (emitcode (";", "genCall "););
2620
2621   /* if we are calling a not _naked function that is not using
2622      the same register bank then we need to save the
2623      destination registers on the stack */
2624   dtype = operandType (IC_LEFT (ic));
2625   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2626       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2627       IFFUNC_ISISR (currFunc->type))
2628   {
2629       if (!ic->bankSaved) 
2630       {
2631            /* This is unexpected; the bank should have been saved in
2632             * genFunction.
2633             */
2634            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2635            restoreBank = TRUE;
2636       }
2637       swapBanks = TRUE;
2638   }
2639   
2640     /* if caller saves & we have not saved then */
2641     if (!ic->regsSaved)
2642       saveRegisters (ic);
2643   
2644   /* if send set is not empty the assign */
2645   /* We've saved all the registers we care about;
2646   * therefore, we may clobber any register not used
2647   * in the calling convention (i.e. anything not in
2648   * fReturn.
2649   */
2650   if (_G.sendSet)
2651     {
2652         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2653             genSend(reverseSet(_G.sendSet));
2654         } else {
2655             genSend(_G.sendSet);
2656         }
2657       _G.sendSet = NULL;
2658     }  
2659     
2660   if (swapBanks)
2661   {
2662         emitcode ("mov", "psw,#!constbyte", 
2663            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2664   }
2665
2666   /* make the call */
2667   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2668                             OP_SYMBOL (IC_LEFT (ic))->rname :
2669                             OP_SYMBOL (IC_LEFT (ic))->name));
2670
2671   if (swapBanks)
2672   {
2673        emitcode ("mov", "psw,#!constbyte", 
2674           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2675   }
2676
2677   /* if we need assign a result value */
2678   if ((IS_ITEMP (IC_RESULT (ic)) &&
2679        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2680         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2681         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2682       IS_TRUE_SYMOP (IC_RESULT (ic)))
2683     {
2684       if (isOperandInFarSpace (IC_RESULT (ic))
2685           && getSize (operandType (IC_RESULT (ic))) <= 2)
2686         {
2687           int size = getSize (operandType (IC_RESULT (ic)));
2688
2689           /* Special case for 1 or 2 byte return in far space. */
2690           MOVA (fReturn[0]);
2691           if (size > 1)
2692             {
2693               emitcode ("mov", "b,%s", fReturn[1]);
2694               _G.bInUse++;
2695             }
2696
2697           _G.accInUse++;
2698           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2699           _G.accInUse--;
2700           
2701           if (size > 1)
2702             _G.bInUse--;
2703
2704           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2705
2706           if (size > 1)
2707             {
2708               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2709             }
2710           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2711         }
2712       else
2713         {
2714           _G.bInUse++;
2715           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2716           _G.bInUse--;
2717
2718           assignResultValue (IC_RESULT (ic));
2719
2720           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2721         }
2722     }
2723
2724   /* adjust the stack for parameters if
2725      required */
2726   if (ic->parmBytes) {
2727       int i;
2728       if (options.stack10bit) {
2729           if (ic->parmBytes <= 10) {
2730               emitcode(";","stack adjustment for parms");
2731               for (i=0; i < ic->parmBytes ; i++) {
2732                   emitcode("pop","acc");
2733               }
2734           } else {            
2735               PROTECT_SP;
2736               emitcode ("clr","c");
2737               emitcode ("mov","a,sp");
2738               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2739               emitcode ("mov","sp,a");
2740               emitcode ("mov","a,esp");
2741               adjustEsp("a");
2742               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2743               emitcode ("mov","esp,a");   
2744               UNPROTECT_SP;
2745           }
2746       } else {
2747           if (ic->parmBytes > 3) {
2748               emitcode ("mov", "a,%s", spname);
2749               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2750               emitcode ("mov", "%s,a", spname);
2751           } else
2752               for (i = 0; i < ic->parmBytes; i++)
2753                   emitcode ("dec", "%s", spname);
2754       }
2755   }
2756
2757   /* if we hade saved some registers then unsave them */
2758   if (ic->regsSaved)
2759     unsaveRegisters (ic);
2760
2761   /* if register bank was saved then pop them */
2762   if (restoreBank)
2763     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2764 }
2765
2766 /*-----------------------------------------------------------------*/
2767 /* genPcall - generates a call by pointer statement                */
2768 /*-----------------------------------------------------------------*/
2769 static void
2770 genPcall (iCode * ic)
2771 {
2772   sym_link *dtype;
2773   symbol *rlbl = newiTempLabel (NULL);
2774   bool restoreBank=FALSE;
2775
2776   D (emitcode (";", "genPcall ");
2777     );
2778
2779
2780   /* if caller saves & we have not saved then */
2781   if (!ic->regsSaved)
2782     saveRegisters (ic);
2783
2784   /* if we are calling a function that is not using
2785      the same register bank then we need to save the
2786      destination registers on the stack */
2787   dtype = operandType (IC_LEFT (ic));
2788   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2789       IFFUNC_ISISR (currFunc->type) &&
2790       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2791     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2792     restoreBank=TRUE;
2793   }
2794
2795   /* push the return address on to the stack */
2796   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2797   emitcode ("push", "acc");
2798   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2799   emitcode ("push", "acc");
2800
2801   if (options.model == MODEL_FLAT24)
2802     {
2803       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2804       emitcode ("push", "acc");
2805     }
2806
2807   /* now push the calling address */
2808   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2809
2810   pushSide (IC_LEFT (ic), FPTRSIZE);
2811
2812   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2813
2814   /* if send set is not empty the assign */
2815   if (_G.sendSet)
2816     {
2817         genSend(reverseSet(_G.sendSet));
2818         _G.sendSet = NULL;
2819     }
2820
2821   emitcode ("ret", "");
2822   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2823
2824
2825   /* if we need assign a result value */
2826   if ((IS_ITEMP (IC_RESULT (ic)) &&
2827        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2828         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2829       IS_TRUE_SYMOP (IC_RESULT (ic)))
2830     {
2831
2832       _G.accInUse++;
2833       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2834       _G.accInUse--;
2835
2836       assignResultValue (IC_RESULT (ic));
2837
2838       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2839     }
2840
2841   /* adjust the stack for parameters if
2842      required */
2843   if (ic->parmBytes)
2844     {
2845       int i;
2846       if (options.stack10bit) {
2847           if (ic->parmBytes <= 10) {
2848               emitcode(";","stack adjustment for parms");
2849               for (i=0; i < ic->parmBytes ; i++) {
2850                   emitcode("pop","acc");
2851               }
2852           } else {            
2853               PROTECT_SP;
2854               emitcode ("clr","c");
2855               emitcode ("mov","a,sp");
2856               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2857               emitcode ("mov","sp,a");
2858               emitcode ("mov","a,esp");
2859               adjustEsp("a");
2860               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2861               emitcode ("mov","esp,a");   
2862               UNPROTECT_SP;
2863           }
2864       } else {
2865           if (ic->parmBytes > 3) {
2866               emitcode ("mov", "a,%s", spname);
2867               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2868               emitcode ("mov", "%s,a", spname);
2869           }
2870           else
2871               for (i = 0; i < ic->parmBytes; i++)
2872                   emitcode ("dec", "%s", spname);
2873           
2874       }
2875     }
2876   /* if register bank was saved then unsave them */
2877   if (restoreBank)
2878     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2879   
2880   /* if we hade saved some registers then
2881      unsave them */
2882   if (ic->regsSaved)
2883     unsaveRegisters (ic);
2884
2885 }
2886
2887 /*-----------------------------------------------------------------*/
2888 /* resultRemat - result  is rematerializable                       */
2889 /*-----------------------------------------------------------------*/
2890 static int
2891 resultRemat (iCode * ic)
2892 {
2893   if (SKIP_IC (ic) || ic->op == IFX)
2894     return 0;
2895
2896   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2897     {
2898       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2899       if (sym->remat && !POINTER_SET (ic))
2900         return 1;
2901     }
2902
2903   return 0;
2904 }
2905
2906 #if defined(__BORLANDC__) || defined(_MSC_VER)
2907 #define STRCASECMP stricmp
2908 #else
2909 #define STRCASECMP strcasecmp
2910 #endif
2911
2912 /*-----------------------------------------------------------------*/
2913 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2914 /*-----------------------------------------------------------------*/
2915 static int
2916 regsCmp(void *p1, void *p2)
2917 {
2918   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2919 }
2920
2921 static bool
2922 inExcludeList (char *s)
2923 {
2924   const char *p = setFirstItem(options.excludeRegsSet);
2925
2926   if (p == NULL || STRCASECMP(p, "none") == 0)
2927     return FALSE;
2928
2929
2930   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2931 }
2932
2933 /*-----------------------------------------------------------------*/
2934 /* genFunction - generated code for function entry                 */
2935 /*-----------------------------------------------------------------*/
2936 static void
2937 genFunction (iCode * ic)
2938 {
2939   symbol *sym;
2940   sym_link *ftype;
2941   bool   switchedPSW = FALSE;
2942
2943   D (emitcode (";", "genFunction "););
2944
2945   _G.nRegsSaved = 0;
2946   /* create the function header */
2947   emitcode (";", "-----------------------------------------");
2948   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2949   emitcode (";", "-----------------------------------------");
2950
2951   emitcode ("", "%s:", sym->rname);
2952   ftype = operandType (IC_LEFT (ic));
2953
2954   if (IFFUNC_ISNAKED(ftype))
2955   {
2956       emitcode(";", "naked function: no prologue.");
2957       return;
2958   }
2959   
2960   if (options.stack_probe) 
2961       emitcode ("lcall","__stack_probe");
2962
2963   /* here we need to generate the equates for the
2964      register bank if required */
2965   if (FUNC_REGBANK (ftype) != rbank)
2966     {
2967       int i;
2968
2969       rbank = FUNC_REGBANK (ftype);
2970       for (i = 0; i < ds390_nRegs; i++)
2971         {
2972           if (regs390[i].print) {
2973               if (strcmp (regs390[i].base, "0") == 0)
2974                   emitcode ("", "%s !equ !constbyte",
2975                             regs390[i].dname,
2976                             8 * rbank + regs390[i].offset);
2977               else
2978                   emitcode ("", "%s !equ %s + !constbyte",
2979                             regs390[i].dname,
2980                             regs390[i].base,
2981                             8 * rbank + regs390[i].offset);
2982           }
2983         }
2984     }
2985
2986   /* if this is an interrupt service routine then
2987      save acc, b, dpl, dph  */
2988   if (IFFUNC_ISISR (sym->type))
2989       { /* is ISR */
2990       if (!inExcludeList ("acc"))
2991         emitcode ("push", "acc");
2992       if (!inExcludeList ("b"))
2993         emitcode ("push", "b");
2994       if (!inExcludeList ("dpl"))
2995         emitcode ("push", "dpl");
2996       if (!inExcludeList ("dph"))
2997         emitcode ("push", "dph");
2998       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2999         {
3000           emitcode ("push", "dpx");
3001           /* Make sure we're using standard DPTR */
3002           emitcode ("push", "dps");
3003           emitcode ("mov", "dps,#0");
3004           if (options.stack10bit)
3005             {
3006               /* This ISR could conceivably use DPTR2. Better save it. */
3007               emitcode ("push", "dpl1");
3008               emitcode ("push", "dph1");
3009               emitcode ("push", "dpx1");
3010               emitcode ("push",  DP2_RESULT_REG);
3011             }
3012         }
3013       /* if this isr has no bank i.e. is going to
3014          run with bank 0 , then we need to save more
3015          registers :-) */
3016       if (!FUNC_REGBANK (sym->type))
3017         {
3018             int i;
3019
3020           /* if this function does not call any other
3021              function then we can be economical and
3022              save only those registers that are used */
3023           if (!IFFUNC_HASFCALL(sym->type))
3024             {
3025
3026               /* if any registers used */
3027               if (sym->regsUsed)
3028                 {
3029                   /* save the registers used */
3030                   for (i = 0; i < sym->regsUsed->size; i++)
3031                     {
3032                       if (bitVectBitValue (sym->regsUsed, i))
3033                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3034                     }
3035                 }
3036             }
3037           else
3038             {
3039               /* this function has  a function call cannot
3040                  determines register usage so we will have to push the
3041                  entire bank */
3042               saveRBank (0, ic, FALSE);
3043               if (options.parms_in_bank1) {
3044                   for (i=0; i < 8 ; i++ ) {
3045                       emitcode ("push","%s",rb1regs[i]);
3046                   }
3047               }
3048             }
3049         }
3050         else
3051         {
3052             /* This ISR uses a non-zero bank.
3053              *
3054              * We assume that the bank is available for our
3055              * exclusive use.
3056              *
3057              * However, if this ISR calls a function which uses some
3058              * other bank, we must save that bank entirely.
3059              */
3060             unsigned long banksToSave = 0;
3061             
3062             if (IFFUNC_HASFCALL(sym->type))
3063             {
3064
3065 #define MAX_REGISTER_BANKS 4
3066
3067                 iCode *i;
3068                 int ix;
3069
3070                 for (i = ic; i; i = i->next)
3071                 {
3072                     if (i->op == ENDFUNCTION)
3073                     {
3074                         /* we got to the end OK. */
3075                         break;
3076                     }
3077                     
3078                     if (i->op == CALL)
3079                     {
3080                         sym_link *dtype;
3081                         
3082                         dtype = operandType (IC_LEFT(i));
3083                         if (dtype 
3084                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3085                         {
3086                              /* Mark this bank for saving. */
3087                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3088                              {
3089                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3090                              }
3091                              else
3092                              {
3093                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3094                              }
3095                              
3096                              /* And note that we don't need to do it in 
3097                               * genCall.
3098                               */
3099                              i->bankSaved = 1;
3100                         }
3101                     }
3102                     if (i->op == PCALL)
3103                     {
3104                         /* This is a mess; we have no idea what
3105                          * register bank the called function might
3106                          * use.
3107                          *
3108                          * The only thing I can think of to do is
3109                          * throw a warning and hope.
3110                          */
3111                         werror(W_FUNCPTR_IN_USING_ISR);   
3112                     }
3113                 }
3114
3115                 if (banksToSave && options.useXstack)
3116                 {
3117                     /* Since we aren't passing it an ic, 
3118                      * saveRBank will assume r0 is available to abuse.
3119                      *
3120                      * So switch to our (trashable) bank now, so
3121                      * the caller's R0 isn't trashed.
3122                      */
3123                     emitcode ("push", "psw");
3124                     emitcode ("mov", "psw,#!constbyte", 
3125                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3126                     switchedPSW = TRUE;
3127                 }
3128                 
3129                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3130                 {
3131                      if (banksToSave & (1 << ix))
3132                      {
3133                          saveRBank(ix, NULL, FALSE);
3134                      }
3135                 }
3136             }
3137             // TODO: this needs a closer look
3138             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3139         }
3140     }
3141   else
3142     {
3143       /* if callee-save to be used for this function
3144          then save the registers being used in this function */
3145       if (IFFUNC_CALLEESAVES(sym->type))
3146         {
3147           int i;
3148
3149           /* if any registers used */
3150           if (sym->regsUsed)
3151             {
3152               /* save the registers used */
3153               for (i = 0; i < sym->regsUsed->size; i++)
3154                 {
3155                   if (bitVectBitValue (sym->regsUsed, i))
3156                     {
3157                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3158                       _G.nRegsSaved++;
3159                     }
3160                 }
3161             }
3162         }
3163     }
3164
3165   /* set the register bank to the desired value */
3166   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3167    && !switchedPSW)
3168     {
3169       emitcode ("push", "psw");
3170       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3171     }
3172
3173   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3174        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3175       if (options.stack10bit) {
3176           emitcode ("push","_bpx");
3177           emitcode ("push","_bpx+1");
3178           emitcode ("mov","_bpx,%s",spname);
3179           emitcode ("mov","_bpx+1,esp");
3180           adjustEsp("_bpx+1");
3181       } else {
3182           if (options.useXstack) {
3183               emitcode ("mov", "r0,%s", spname);
3184               emitcode ("mov", "a,_bp");
3185               emitcode ("movx", "@r0,a");
3186               emitcode ("inc", "%s", spname);
3187           } else {
3188               /* set up the stack */
3189               emitcode ("push", "_bp"); /* save the callers stack  */
3190           }
3191           emitcode ("mov", "_bp,%s", spname);
3192       }
3193   }
3194
3195   /* adjust the stack for the function */
3196   if (sym->stack) {
3197       int i = sym->stack;
3198       if (options.stack10bit) {
3199           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3200           assert (sym->recvSize <= 4);
3201           if (sym->stack <= 8) {
3202               while (i--) emitcode ("push","acc");
3203           } else {
3204               PROTECT_SP;
3205               emitcode ("mov","a,sp");
3206               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3207               emitcode ("mov","sp,a");
3208               emitcode ("mov","a,esp");
3209               adjustEsp("a");
3210               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3211               emitcode ("mov","esp,a");
3212               UNPROTECT_SP;
3213           }
3214       } else {
3215           if (i > 256)
3216               werror (W_STACK_OVERFLOW, sym->name);
3217           
3218           if (i > 3 && sym->recvSize < 4) {
3219               
3220               emitcode ("mov", "a,sp");
3221               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3222               emitcode ("mov", "sp,a");
3223               
3224           } else
3225               while (i--)
3226                   emitcode ("inc", "sp");
3227       }
3228   }
3229
3230   if (sym->xstack)
3231     {
3232
3233       emitcode ("mov", "a,_spx");
3234       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3235       emitcode ("mov", "_spx,a");
3236     }
3237   
3238   /* if critical function then turn interrupts off */
3239   if (IFFUNC_ISCRITICAL (ftype))
3240     {
3241       symbol *tlbl = newiTempLabel (NULL);
3242       emitcode ("setb", "c");
3243       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3244       emitcode ("clr", "c");
3245       emitcode ("", "%05d$:", (tlbl->key + 100));
3246       emitcode ("push", "psw"); /* save old ea via c in psw */
3247     }
3248
3249 }
3250
3251 /*-----------------------------------------------------------------*/
3252 /* genEndFunction - generates epilogue for functions               */
3253 /*-----------------------------------------------------------------*/
3254 static void
3255 genEndFunction (iCode * ic)
3256 {
3257   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3258   lineNode *lnp = lineCurr;
3259   bitVect *regsUsed;
3260   bitVect *regsUsedPrologue;
3261   bitVect *regsUnneeded;
3262   int idx;
3263
3264   D (emitcode (";", "genEndFunction "););
3265
3266   if (IFFUNC_ISNAKED(sym->type))
3267   {
3268       emitcode(";", "naked function: no epilogue.");
3269       if (options.debug && currFunc)
3270         debugFile->writeEndFunction (currFunc, ic, 0);
3271       return;
3272   }
3273
3274   if (IFFUNC_ISCRITICAL (sym->type))
3275     {
3276       emitcode ("pop", "psw"); /* restore ea via c in psw */
3277       emitcode ("mov", "ea,c");
3278     }
3279   
3280   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3281        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3282
3283       if (options.stack10bit) {
3284           PROTECT_SP;     
3285           emitcode ("mov", "sp,_bpx", spname);
3286           emitcode ("mov", "esp,_bpx+1", spname);
3287           UNPROTECT_SP;
3288       } else {
3289           emitcode ("mov", "%s,_bp", spname);
3290       }
3291   }
3292
3293   /* if use external stack but some variables were
3294      added to the local stack then decrement the
3295      local stack */
3296   if (options.useXstack && sym->stack) {
3297       emitcode ("mov", "a,sp");
3298       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3299       emitcode ("mov", "sp,a");
3300   }
3301
3302
3303   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3304        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3305
3306       if (options.useXstack) {
3307           emitcode ("mov", "r0,%s", spname);
3308           emitcode ("movx", "a,@r0");
3309           emitcode ("mov", "_bp,a");
3310           emitcode ("dec", "%s", spname);
3311       } else {
3312           if (options.stack10bit) {
3313               emitcode ("pop", "_bpx+1");
3314               emitcode ("pop", "_bpx");
3315           } else {
3316               emitcode ("pop", "_bp");
3317           }
3318       }
3319   }
3320
3321   /* restore the register bank  */
3322   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3323   {
3324     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3325      || !options.useXstack)
3326     {
3327         /* Special case of ISR using non-zero bank with useXstack
3328          * is handled below.
3329          */
3330         emitcode ("pop", "psw");
3331     }
3332   } 
3333
3334   if (IFFUNC_ISISR (sym->type))
3335       { /* is ISR */  
3336
3337       /* now we need to restore the registers */
3338       /* if this isr has no bank i.e. is going to
3339          run with bank 0 , then we need to save more
3340          registers :-) */
3341       if (!FUNC_REGBANK (sym->type))
3342         {
3343             int i;
3344           /* if this function does not call any other
3345              function then we can be economical and
3346              save only those registers that are used */
3347           if (!IFFUNC_HASFCALL(sym->type))
3348             {
3349
3350               /* if any registers used */
3351               if (sym->regsUsed)
3352                 {
3353                   /* save the registers used */
3354                   for (i = sym->regsUsed->size; i >= 0; i--)
3355                     {
3356                       if (bitVectBitValue (sym->regsUsed, i))
3357                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3358                     }
3359                 }
3360             }
3361           else
3362             {
3363               /* this function has  a function call cannot
3364                  determines register usage so we will have to pop the
3365                  entire bank */
3366               if (options.parms_in_bank1) {
3367                   for (i = 7 ; i >= 0 ; i-- ) {
3368                       emitcode ("pop","%s",rb1regs[i]);
3369                   }
3370               }
3371               unsaveRBank (0, ic, FALSE);
3372             }
3373         }
3374         else
3375         {
3376             /* This ISR uses a non-zero bank.
3377              *
3378              * Restore any register banks saved by genFunction
3379              * in reverse order.
3380              */
3381             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3382             int ix;
3383           
3384             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3385             {
3386                 if (savedBanks & (1 << ix))
3387                 {
3388                     unsaveRBank(ix, NULL, FALSE);
3389                 }
3390             }
3391             
3392             if (options.useXstack)
3393             {
3394                 /* Restore bank AFTER calling unsaveRBank,
3395                  * since it can trash r0.
3396                  */
3397                 emitcode ("pop", "psw");
3398             }
3399         }
3400
3401       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3402         {
3403           if (options.stack10bit)
3404             {
3405               emitcode ("pop", DP2_RESULT_REG);
3406               emitcode ("pop", "dpx1");
3407               emitcode ("pop", "dph1");
3408               emitcode ("pop", "dpl1");
3409             }
3410           emitcode ("pop", "dps");
3411           emitcode ("pop", "dpx");
3412         }
3413       if (!inExcludeList ("dph"))
3414         emitcode ("pop", "dph");
3415       if (!inExcludeList ("dpl"))
3416         emitcode ("pop", "dpl");
3417       if (!inExcludeList ("b"))
3418         emitcode ("pop", "b");
3419       if (!inExcludeList ("acc"))
3420         emitcode ("pop", "acc");
3421
3422       /* if debug then send end of function */
3423       if (options.debug && currFunc) {
3424           debugFile->writeEndFunction (currFunc, ic, 1);
3425         }
3426
3427       emitcode ("reti", "");
3428     }
3429   else
3430     {
3431       if (IFFUNC_CALLEESAVES(sym->type))
3432         {
3433           int i;
3434
3435           /* if any registers used */
3436           if (sym->regsUsed)
3437             {
3438               /* save the registers used */
3439               for (i = sym->regsUsed->size; i >= 0; i--)
3440                 {
3441                   if (bitVectBitValue (sym->regsUsed, i))
3442                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3443                 }
3444             }
3445         }
3446
3447       /* if debug then send end of function */
3448       if (options.debug && currFunc)
3449         {
3450           debugFile->writeEndFunction (currFunc, ic, 1);
3451         }
3452
3453       emitcode ("ret", "");
3454     }
3455
3456   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3457     return;
3458   
3459   /* If this was an interrupt handler using bank 0 that called another */
3460   /* function, then all registers must be saved; nothing to optimized. */
3461   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3462       && !FUNC_REGBANK(sym->type))
3463     return;
3464     
3465   /* There are no push/pops to optimize if not callee-saves or ISR */
3466   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3467     return;
3468   
3469   /* If there were stack parameters, we cannot optimize without also    */
3470   /* fixing all of the stack offsets; this is too dificult to consider. */
3471   if (FUNC_HASSTACKPARM(sym->type))
3472     return;
3473   
3474   /* Compute the registers actually used */
3475   regsUsed = newBitVect (ds390_nRegs);
3476   regsUsedPrologue = newBitVect (ds390_nRegs);
3477   while (lnp)
3478     {
3479       if (lnp->ic && lnp->ic->op == FUNCTION)
3480         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3481       else
3482         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3483       
3484       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3485           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3486         break;
3487       if (!lnp->prev)
3488         break;
3489       lnp = lnp->prev;
3490     }
3491
3492   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3493       && !bitVectBitValue (regsUsed, DPS_IDX))
3494     {
3495       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3496     }
3497     
3498   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3499       && !bitVectBitValue (regsUsed, CND_IDX))
3500     {
3501       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3502       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3503           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3504         bitVectUnSetBit (regsUsed, CND_IDX);
3505     }
3506   else
3507     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3508     
3509   /* If this was an interrupt handler that called another function */
3510   /* function, then assume working registers may be modified by it. */
3511   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3512     {
3513       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3514       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3515       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3516       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3517       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3518       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3519       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3520       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3521       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3522       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3523       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3524     }
3525
3526   /* Remove the unneeded push/pops */
3527   regsUnneeded = newBitVect (ds390_nRegs);
3528   while (lnp)
3529     {
3530       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3531         {
3532           if (!strncmp(lnp->line, "push", 4))
3533             {
3534               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3535               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3536                 {
3537                   connectLine (lnp->prev, lnp->next);
3538                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3539                 }
3540             }
3541           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3542             {
3543               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3544               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3545                 {
3546                   connectLine (lnp->prev, lnp->next);
3547                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3548                 }
3549             }
3550         }
3551       lnp = lnp->next;
3552     }  
3553   
3554   for (idx = 0; idx < regsUnneeded->size; idx++)
3555     if (bitVectBitValue (regsUnneeded, idx))
3556       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3557   
3558   freeBitVect (regsUnneeded);
3559   freeBitVect (regsUsed);
3560   freeBitVect (regsUsedPrologue);
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genJavaNativeRet - generate code for return JavaNative          */
3565 /*-----------------------------------------------------------------*/
3566 static void genJavaNativeRet(iCode *ic)
3567 {
3568     int i, size;
3569
3570     aopOp (IC_LEFT (ic), ic, FALSE, 
3571            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3572     size = AOP_SIZE (IC_LEFT (ic));
3573
3574     assert (size <= 4);
3575
3576     /* it is assigned to GPR0-R3 then push them */
3577     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3578         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3579         for (i = 0 ; i < size ; i++ ) {
3580             emitcode ("push","%s",
3581                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3582         }
3583         for (i = (size-1) ; i >= 0 ; i--) {
3584             emitcode ("pop","a%s",javaRet[i]);
3585         }
3586     } else {
3587         for (i = 0 ; i < size ; i++) 
3588             emitcode ("mov","%s,%s",javaRet[i],
3589                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3590     }
3591     for (i = size ; i < 4 ; i++ )
3592             emitcode ("mov","%s,#0",javaRet[i]);
3593     return;
3594 }
3595
3596 /*-----------------------------------------------------------------*/
3597 /* genRet - generate code for return statement                     */
3598 /*-----------------------------------------------------------------*/
3599 static void
3600 genRet (iCode * ic)
3601 {
3602   int size, offset = 0, pushed = 0;
3603
3604   D (emitcode (";", "genRet "););
3605
3606   /* if we have no return value then
3607      just generate the "ret" */
3608   if (!IC_LEFT (ic))
3609     goto jumpret;
3610
3611   /* if this is a JavaNative function then return 
3612      value in different register */
3613   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3614       genJavaNativeRet(ic);
3615       goto jumpret;
3616   }
3617   /* we have something to return then
3618      move the return value into place */
3619   aopOp (IC_LEFT (ic), ic, FALSE, 
3620          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3621   size = AOP_SIZE (IC_LEFT (ic));
3622
3623   _startLazyDPSEvaluation ();
3624   while (size--)
3625     {
3626       char *l;
3627       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3628         {
3629           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3630                       FALSE, TRUE, NULL);
3631           emitcode ("push", "%s", l);
3632           pushed++;
3633         }
3634       else
3635         {
3636           /* Since A is the last element of fReturn,
3637            * is is OK to clobber it in the aopGet.
3638            */
3639           l = aopGet (AOP (IC_LEFT (ic)), offset,
3640                       FALSE, FALSE, NULL);
3641           if (strcmp (fReturn[offset], l))
3642             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3643         }
3644     }
3645   _endLazyDPSEvaluation ();
3646
3647   if (pushed)
3648     {
3649       while (pushed)
3650         {
3651           pushed--;
3652           if (strcmp (fReturn[pushed], "a"))
3653             emitcode ("pop", fReturn[pushed]);
3654           else
3655             emitcode ("pop", "acc");
3656         }
3657     }
3658   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3659
3660 jumpret:
3661   /* generate a jump to the return label
3662      if the next is not the return statement */
3663   if (!(ic->next && ic->next->op == LABEL &&
3664         IC_LABEL (ic->next) == returnLabel))
3665
3666     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3667
3668 }
3669
3670 /*-----------------------------------------------------------------*/
3671 /* genLabel - generates a label                                    */
3672 /*-----------------------------------------------------------------*/
3673 static void
3674 genLabel (iCode * ic)
3675 {
3676   /* special case never generate */
3677   if (IC_LABEL (ic) == entryLabel)
3678     return;
3679
3680   D (emitcode (";", "genLabel ");
3681     );
3682
3683   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3684 }
3685
3686 /*-----------------------------------------------------------------*/
3687 /* genGoto - generates a ljmp                                      */
3688 /*-----------------------------------------------------------------*/
3689 static void
3690 genGoto (iCode * ic)
3691 {
3692   D (emitcode (";", "genGoto ");
3693     );
3694   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3695 }
3696
3697 /*-----------------------------------------------------------------*/
3698 /* findLabelBackwards: walks back through the iCode chain looking  */
3699 /* for the given label. Returns number of iCode instructions     */
3700 /* between that label and given ic.          */
3701 /* Returns zero if label not found.          */
3702 /*-----------------------------------------------------------------*/
3703 static int
3704 findLabelBackwards (iCode * ic, int key)
3705 {
3706   int count = 0;
3707
3708   while (ic->prev)
3709     {
3710       ic = ic->prev;
3711       count++;
3712
3713       /* If we have any pushes or pops, we cannot predict the distance.
3714          I don't like this at all, this should be dealt with in the 
3715          back-end */
3716       if (ic->op == IPUSH || ic->op == IPOP) {
3717         return 0;
3718       }
3719
3720       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3721         {
3722           /* printf("findLabelBackwards = %d\n", count); */
3723           return count;
3724         }
3725     }
3726
3727   return 0;
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genPlusIncr :- does addition with increment if possible         */
3732 /*-----------------------------------------------------------------*/
3733 static bool
3734 genPlusIncr (iCode * ic)
3735 {
3736   unsigned int icount;
3737   unsigned int size = getDataSize (IC_RESULT (ic));
3738
3739   /* will try to generate an increment */
3740   /* if the right side is not a literal
3741      we cannot */
3742   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3743     return FALSE;
3744
3745   /* if the literal value of the right hand side
3746      is greater than 4 then it is not worth it */
3747   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3748     return FALSE;
3749
3750   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3751       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3752       while (icount--) {
3753           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3754       }
3755       return TRUE;
3756   }
3757   /* if increment 16 bits in register */
3758   if (
3759        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3760        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3761        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3762        (size > 1) &&
3763        (icount == 1))
3764     {
3765       symbol  *tlbl;
3766       int     emitTlbl;
3767       int     labelRange;
3768       char    *l;
3769
3770       /* If the next instruction is a goto and the goto target
3771        * is <= 5 instructions previous to this, we can generate
3772        * jumps straight to that target.
3773        */
3774       if (ic->next && ic->next->op == GOTO
3775           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3776           && labelRange <= 5)
3777         {
3778           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3779           tlbl = IC_LABEL (ic->next);
3780           emitTlbl = 0;
3781         }
3782       else
3783         {
3784           tlbl = newiTempLabel (NULL);
3785           emitTlbl = 1;
3786         }
3787         
3788       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3789       emitcode ("inc", "%s", l);
3790       
3791       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3792           IS_AOP_PREG (IC_RESULT (ic)))
3793       {   
3794         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3795       }
3796       else
3797       {
3798           emitcode ("clr", "a");
3799           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3800       }
3801
3802       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3803       emitcode ("inc", "%s", l);
3804       if (size > 2)
3805         {
3806             if (!strcmp(l, "acc"))
3807             {
3808                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3809             }
3810             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3811                      IS_AOP_PREG (IC_RESULT (ic)))
3812             {
3813                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3814             }
3815             else
3816             {
3817                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3818             }
3819
3820             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3821             emitcode ("inc", "%s", l);
3822         }
3823       if (size > 3)
3824         {
3825             if (!strcmp(l, "acc"))
3826             {
3827                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3828             }
3829             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3830                      IS_AOP_PREG (IC_RESULT (ic)))
3831             {
3832                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3833             }
3834             else
3835             {
3836                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3837             }
3838
3839             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3840             emitcode ("inc", "%s", l);  }
3841
3842       if (emitTlbl)
3843         {
3844           emitcode ("", "!tlabeldef", tlbl->key + 100);
3845         }
3846       return TRUE;
3847     }
3848
3849   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3850       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3851       options.model == MODEL_FLAT24 ) {
3852
3853       switch (size) {
3854       case 3:
3855           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3856       case 2:
3857           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3858       case 1:
3859           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3860           break;
3861       }
3862       while (icount--) emitcode ("inc","dptr");      
3863       return TRUE;
3864   }
3865
3866   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3867       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3868       icount <= 5 ) {
3869       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3870       while (icount--) emitcode ("inc","dptr");
3871       emitcode ("mov","dps,#0");
3872       return TRUE;
3873   }
3874
3875   /* if the sizes are greater than 1 then we cannot */
3876   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3877       AOP_SIZE (IC_LEFT (ic)) > 1)
3878     return FALSE;
3879
3880   /* we can if the aops of the left & result match or
3881      if they are in registers and the registers are the
3882      same */
3883   if (
3884        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3885        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3886        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3887     {
3888
3889       if (icount > 3)
3890         {
3891           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3892           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3893           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3894         }
3895       else
3896         {
3897
3898           _startLazyDPSEvaluation ();
3899           while (icount--)
3900             {
3901               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3902             }
3903           _endLazyDPSEvaluation ();
3904         }
3905
3906       return TRUE;
3907     }
3908
3909   return FALSE;
3910 }
3911
3912 /*-----------------------------------------------------------------*/
3913 /* outBitAcc - output a bit in acc                                 */
3914 /*-----------------------------------------------------------------*/
3915 static void
3916 outBitAcc (operand * result)
3917 {
3918   symbol *tlbl = newiTempLabel (NULL);
3919   /* if the result is a bit */
3920   if (AOP_TYPE (result) == AOP_CRY)
3921     {
3922       aopPut (AOP (result), "a", 0);
3923     }
3924   else
3925     {
3926       emitcode ("jz", "!tlabel", tlbl->key + 100);
3927       emitcode ("mov", "a,%s", one);
3928       emitcode ("", "!tlabeldef", tlbl->key + 100);
3929       outAcc (result);
3930     }
3931 }
3932
3933 /*-----------------------------------------------------------------*/
3934 /* genPlusBits - generates code for addition of two bits           */
3935 /*-----------------------------------------------------------------*/
3936 static void
3937 genPlusBits (iCode * ic)
3938 {
3939   D (emitcode (";", "genPlusBits "););
3940     
3941   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3942     {
3943       symbol *lbl = newiTempLabel (NULL);
3944       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3945       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3946       emitcode ("cpl", "c");
3947       emitcode ("", "!tlabeldef", (lbl->key + 100));
3948       outBitC (IC_RESULT (ic));
3949     }
3950   else
3951     {
3952       emitcode ("clr", "a");
3953       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3954       emitcode ("rlc", "a");
3955       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3956       emitcode ("addc", "a,#0");
3957       outAcc (IC_RESULT (ic));
3958     }
3959 }
3960
3961 static void
3962 adjustArithmeticResult (iCode * ic)
3963 {
3964   if (opIsGptr (IC_RESULT (ic)) &&
3965       opIsGptr (IC_LEFT (ic)) &&
3966       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3967     {
3968       aopPut (AOP (IC_RESULT (ic)),
3969               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3970               GPTRSIZE - 1);
3971     }
3972
3973   if (opIsGptr (IC_RESULT (ic)) &&
3974       opIsGptr (IC_RIGHT (ic)) &&
3975       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3976     {
3977       aopPut (AOP (IC_RESULT (ic)),
3978             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3979               GPTRSIZE - 1);
3980     }
3981
3982   if (opIsGptr (IC_RESULT (ic)) &&
3983       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3984       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3985       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3986       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3987     {
3988       char buff[5];
3989       SNPRINTF (buff, sizeof(buff), 
3990                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3991       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3992     }
3993 }
3994
3995 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3996 // generates the result if possible. If result is generated, returns TRUE; otherwise
3997 // returns false and caller must deal with fact that result isn't aopOp'd.
3998 bool aopOp3(iCode * ic)
3999 {
4000     bool dp1InUse, dp2InUse;
4001     bool useDp2;
4002
4003     // First, generate the right opcode. DPTR may be used if neither left nor result are
4004     // of type AOP_STR.
4005     
4006 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4007 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4008 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4009 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4010 //      );
4011 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4012 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4013 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4014 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4015 //      );
4016     
4017     // Right uses DPTR unless left or result is an AOP_STR; however,
4018     // if right is an AOP_STR, it must use DPTR regardless.
4019     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4020      && !AOP_IS_STR(IC_RIGHT(ic)))
4021     {
4022         useDp2 = TRUE;
4023     }
4024     else
4025     {
4026         useDp2 = FALSE;
4027     }
4028         
4029     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4030     
4031     // if the right used DPTR, left MUST use DPTR2.
4032     // if the right used DPTR2, left MUST use DPTR.
4033     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4034     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4035     // enabling us to assign DPTR to result.
4036      
4037     if (AOP_USESDPTR(IC_RIGHT(ic)))
4038     {
4039         useDp2 = TRUE;
4040     }
4041     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4042     {
4043         useDp2 = FALSE;
4044     }
4045     else
4046     {
4047         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4048         {
4049             useDp2 = TRUE;
4050         }
4051         else
4052         {
4053             useDp2 = FALSE;
4054         }
4055     }
4056
4057     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4058
4059         
4060     // We've op'd the left & right. So, if left or right are the same operand as result, 
4061     // we know aopOp will succeed, and we can just do it & bail.
4062     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4063       {
4064         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4065         return TRUE;
4066       }
4067     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4068       {
4069 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4070         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4071         return TRUE;
4072       }
4073     
4074     // Operands may be equivalent (but not equal) if they share a spill location. If
4075     // so, use the same DPTR or DPTR2.
4076     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4077       {
4078         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4079         return TRUE;
4080       }
4081     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4082       {
4083         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4084         return TRUE;
4085       }
4086     
4087     // Note which dptrs are currently in use.
4088     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4089     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4090     
4091     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
4092     // generate it.
4093     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4094     {
4095         return FALSE;
4096     }
4097     
4098     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4099     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4100     {
4101         return FALSE;
4102     }
4103     
4104     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4105     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4106     {
4107         return FALSE;
4108     }
4109
4110     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4111
4112     // Some sanity checking...
4113     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4114     {
4115         fprintf(stderr,
4116                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4117                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4118         emitcode(";", ">>> unexpected DPTR here.");
4119     }
4120     
4121     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4122     {
4123         fprintf(stderr,
4124                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4125                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4126         emitcode(";", ">>> unexpected DPTR2 here.");
4127     }    
4128     
4129     return TRUE;
4130 }
4131
4132 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4133 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4134 // will be set TRUE. The caller must then handle the case specially, noting
4135 // that the IC_RESULT operand is not aopOp'd.
4136 // 
4137 #define AOP_OP_3_NOFATAL(ic, rc) \
4138             do { rc = !aopOp3(ic); } while (0)
4139
4140 // aopOp the left & right operands of an ic.
4141 #define AOP_OP_2(ic) \
4142     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4143     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4144
4145 // convienience macro.
4146 #define AOP_SET_LOCALS(ic) \
4147     left = IC_LEFT(ic); \
4148     right = IC_RIGHT(ic); \
4149     result = IC_RESULT(ic);
4150
4151
4152 // Given an integer value of pushedSize bytes on the stack,
4153 // adjust it to be resultSize bytes, either by discarding
4154 // the most significant bytes or by zero-padding.
4155 //
4156 // On exit from this macro, pushedSize will have been adjusted to
4157 // equal resultSize, and ACC may be trashed.
4158 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4159       /* If the pushed data is bigger than the result,          \
4160        * simply discard unused bytes. Icky, but works.          \
4161        */                                                       \
4162       while (pushedSize > resultSize)                           \
4163       {                                                         \
4164           D (emitcode (";", "discarding unused result byte."););\
4165           emitcode ("pop", "acc");                              \
4166           pushedSize--;                                         \
4167       }                                                         \
4168       if (pushedSize < resultSize)                              \
4169       {                                                         \
4170           emitcode ("clr", "a");                                \
4171           /* Conversly, we haven't pushed enough here.          \
4172            * just zero-pad, and all is well.                    \
4173            */                                                   \
4174           while (pushedSize < resultSize)                       \
4175           {                                                     \
4176               emitcode("push", "acc");                          \
4177               pushedSize++;                                     \
4178           }                                                     \
4179       }                                                         \
4180       assert(pushedSize == resultSize);
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genPlus - generates code for addition                           */
4184 /*-----------------------------------------------------------------*/
4185 static void
4186 genPlus (iCode * ic)
4187 {
4188   int size, offset = 0;
4189   bool pushResult;
4190   int rSize;
4191
4192   D (emitcode (";", "genPlus "););
4193
4194   /* special cases :- */
4195   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4196       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4197       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4198       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4199       if (size <= 9) {
4200           while (size--) emitcode ("inc","dptr");
4201       } else {
4202           emitcode ("mov","a,dpl");
4203           emitcode ("add","a,#!constbyte",size & 0xff);
4204           emitcode ("mov","dpl,a");
4205           emitcode ("mov","a,dph");
4206           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4207           emitcode ("mov","dph,a");
4208           emitcode ("mov","a,dpx");
4209           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4210           emitcode ("mov","dpx,a");
4211       }
4212       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4213       return ;
4214   }
4215   if ( IS_SYMOP(IC_LEFT(ic)) && 
4216        OP_SYMBOL(IC_LEFT(ic))->remat &&
4217        isOperandInFarSpace(IC_RIGHT(ic))) {
4218       operand *op = IC_RIGHT(ic);
4219       IC_RIGHT(ic) = IC_LEFT(ic);
4220       IC_LEFT(ic) = op;
4221   }
4222                 
4223   AOP_OP_3_NOFATAL (ic, pushResult);
4224     
4225   if (pushResult)
4226     {
4227       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4228     }
4229
4230   if (!pushResult)
4231     {
4232       /* if literal, literal on the right or
4233          if left requires ACC or right is already
4234          in ACC */
4235       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4236        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4237           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4238         {
4239           operand *t = IC_RIGHT (ic);
4240           IC_RIGHT (ic) = IC_LEFT (ic);
4241           IC_LEFT (ic) = t;
4242           emitcode (";", "Swapped plus args.");
4243         }
4244
4245       /* if both left & right are in bit
4246          space */
4247       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4248           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4249         {
4250           genPlusBits (ic);
4251           goto release;
4252         }
4253
4254       /* if left in bit space & right literal */
4255       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4256           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4257         {
4258           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4259           /* if result in bit space */
4260           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4261             {
4262               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4263                 emitcode ("cpl", "c");
4264               outBitC (IC_RESULT (ic));
4265             }
4266           else
4267             {
4268               size = getDataSize (IC_RESULT (ic));
4269               _startLazyDPSEvaluation ();
4270               while (size--)
4271                 {
4272                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4273                   emitcode ("addc", "a,#0");
4274                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4275                 }
4276               _endLazyDPSEvaluation ();
4277             }
4278           goto release;
4279         }
4280
4281       /* if I can do an increment instead
4282          of add then GOOD for ME */
4283       if (genPlusIncr (ic) == TRUE)
4284         {
4285           emitcode (";", "did genPlusIncr");
4286           goto release;
4287         }
4288
4289     }
4290   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4291
4292   _startLazyDPSEvaluation ();
4293   while (size--)
4294     {
4295       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4296         {
4297           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4298           if (offset == 0)
4299             emitcode ("add", "a,%s",
4300                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4301           else
4302             emitcode ("addc", "a,%s",
4303                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4304         }
4305       else
4306         {
4307           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4308           {
4309               /* right is going to use ACC or we would have taken the
4310                * above branch.
4311                */
4312               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4313        TR_AP("#3");
4314               D(emitcode(";", "+ AOP_ACC special case."););
4315               emitcode("xch", "a, %s", DP2_RESULT_REG);
4316           }
4317           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4318           if (offset == 0)
4319           {
4320             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4321             {
4322          TR_AP("#4");
4323                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4324             }
4325             else
4326             {
4327                 emitcode ("add", "a,%s",
4328                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4329                                   DP2_RESULT_REG));
4330             }
4331           }
4332           else
4333           {
4334             emitcode ("addc", "a,%s",
4335                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4336                           DP2_RESULT_REG));
4337           }
4338         }
4339       if (!pushResult)
4340         {
4341           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4342         }
4343       else
4344         {
4345           emitcode ("push", "acc");
4346         }
4347       offset++;
4348     }
4349   _endLazyDPSEvaluation ();
4350
4351   if (pushResult)
4352     {
4353       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4354
4355       size = getDataSize (IC_LEFT (ic));
4356       rSize = getDataSize (IC_RESULT (ic));
4357
4358       ADJUST_PUSHED_RESULT(size, rSize);
4359
4360       _startLazyDPSEvaluation ();
4361       while (size--)
4362         {
4363           emitcode ("pop", "acc");
4364           aopPut (AOP (IC_RESULT (ic)), "a", size);
4365         }
4366       _endLazyDPSEvaluation ();
4367     }
4368
4369   adjustArithmeticResult (ic);
4370
4371 release:
4372   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4373   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4374   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4375 }
4376
4377 /*-----------------------------------------------------------------*/
4378 /* genMinusDec :- does subtraction with deccrement if possible     */
4379 /*-----------------------------------------------------------------*/
4380 static bool
4381 genMinusDec (iCode * ic)
4382 {
4383   unsigned int icount;
4384   unsigned int size = getDataSize (IC_RESULT (ic));
4385
4386   /* will try to generate an increment */
4387   /* if the right side is not a literal
4388      we cannot */
4389   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4390     return FALSE;
4391
4392   /* if the literal value of the right hand side
4393      is greater than 4 then it is not worth it */
4394   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4395     return FALSE;
4396
4397   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4398       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4399       while (icount--) {
4400           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4401       }
4402       return TRUE;
4403   }
4404   /* if decrement 16 bits in register */
4405   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4406       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4407       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4408       (size > 1) &&
4409       (icount == 1))
4410     {
4411       symbol *tlbl;
4412       int    emitTlbl;
4413       int    labelRange;
4414       char   *l;
4415
4416       /* If the next instruction is a goto and the goto target
4417          * is <= 5 instructions previous to this, we can generate
4418          * jumps straight to that target.
4419        */
4420       if (ic->next && ic->next->op == GOTO
4421           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4422           && labelRange <= 5)
4423         {
4424           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4425           tlbl = IC_LABEL (ic->next);
4426           emitTlbl = 0;
4427         }
4428       else
4429         {
4430           tlbl = newiTempLabel (NULL);
4431           emitTlbl = 1;
4432         }
4433
4434       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4435       emitcode ("dec", "%s", l);
4436  
4437       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4438           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4439           IS_AOP_PREG (IC_RESULT (ic)))
4440       {     
4441           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4442       }
4443       else
4444       {
4445           emitcode ("mov", "a,#!constbyte",0xff);
4446           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4447       }
4448       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4449       emitcode ("dec", "%s", l);
4450       if (size > 2)
4451         {
4452             if (!strcmp(l, "acc"))
4453             {
4454                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4455             }
4456             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4457                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4458                      IS_AOP_PREG (IC_RESULT (ic)))
4459             {       
4460                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4461             }
4462             else
4463             {
4464                 emitcode ("mov", "a,#!constbyte",0xff);
4465                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4466             }
4467             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4468             emitcode ("dec", "%s", l);
4469         }
4470       if (size > 3)
4471         {
4472             if (!strcmp(l, "acc"))
4473             {
4474                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4475             }
4476             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4477                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4478                      IS_AOP_PREG (IC_RESULT (ic)))
4479             {       
4480                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4481             }
4482             else
4483             {
4484                 emitcode ("mov", "a,#!constbyte",0xff);
4485                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4486             }       
4487             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4488             emitcode ("dec", "%s", l);
4489         }
4490       if (emitTlbl)
4491         {
4492           emitcode ("", "!tlabeldef", tlbl->key + 100);
4493         }
4494       return TRUE;
4495     }
4496
4497   /* if the sizes are greater than 1 then we cannot */
4498   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4499       AOP_SIZE (IC_LEFT (ic)) > 1)
4500     return FALSE;
4501
4502   /* we can if the aops of the left & result match or
4503      if they are in registers and the registers are the
4504      same */
4505   if (
4506        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4507        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4508        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4509     {
4510
4511       _startLazyDPSEvaluation ();
4512       while (icount--)
4513         {
4514           emitcode ("dec", "%s",
4515                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4516         }
4517       _endLazyDPSEvaluation ();
4518
4519       return TRUE;
4520     }
4521
4522   return FALSE;
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* addSign - complete with sign                                    */
4527 /*-----------------------------------------------------------------*/
4528 static void
4529 addSign (operand * result, int offset, int sign)
4530 {
4531   int size = (getDataSize (result) - offset);
4532   if (size > 0)
4533     {
4534       _startLazyDPSEvaluation();
4535       if (sign)
4536         {
4537           emitcode ("rlc", "a");
4538           emitcode ("subb", "a,acc");
4539           while (size--)
4540           {
4541             aopPut (AOP (result), "a", offset++);
4542           }
4543         }
4544       else
4545       {
4546         while (size--)
4547         {
4548           aopPut (AOP (result), zero, offset++);
4549         }
4550       }
4551       _endLazyDPSEvaluation();
4552     }
4553 }
4554
4555 /*-----------------------------------------------------------------*/
4556 /* genMinusBits - generates code for subtraction  of two bits      */
4557 /*-----------------------------------------------------------------*/
4558 static void
4559 genMinusBits (iCode * ic)
4560 {
4561   symbol *lbl = newiTempLabel (NULL);
4562
4563   D (emitcode (";", "genMinusBits "););
4564
4565   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4566     {
4567       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4568       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4569       emitcode ("cpl", "c");
4570       emitcode ("", "!tlabeldef", (lbl->key + 100));
4571       outBitC (IC_RESULT (ic));
4572     }
4573   else
4574     {
4575       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4576       emitcode ("subb", "a,acc");
4577       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4578       emitcode ("inc", "a");
4579       emitcode ("", "!tlabeldef", (lbl->key + 100));
4580       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4581       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4582     }
4583 }
4584
4585 /*-----------------------------------------------------------------*/
4586 /* genMinus - generates code for subtraction                       */
4587 /*-----------------------------------------------------------------*/
4588 static void
4589 genMinus (iCode * ic)
4590 {
4591     int size, offset = 0;
4592     int rSize;
4593     long lit = 0L;
4594     bool pushResult;
4595
4596     D (emitcode (";", "genMinus "););
4597
4598     AOP_OP_3_NOFATAL(ic, pushResult);   
4599
4600     if (!pushResult)
4601     {
4602       /* special cases :- */
4603       /* if both left & right are in bit space */
4604       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4605           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4606         {
4607           genMinusBits (ic);
4608           goto release;
4609         }
4610
4611       /* if I can do an decrement instead
4612          of subtract then GOOD for ME */
4613       if (genMinusDec (ic) == TRUE)
4614         goto release;
4615
4616     }
4617
4618   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4619
4620   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4621     {
4622       CLRC;
4623     }
4624   else
4625     {
4626       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4627       lit = -lit;
4628     }
4629
4630
4631   /* if literal, add a,#-lit, else normal subb */
4632   _startLazyDPSEvaluation ();
4633   while (size--) {
4634       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4635           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4636               emitcode ("mov","b,%s",
4637                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4638               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4639               emitcode ("subb","a,b");
4640           } else {
4641               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4642               emitcode ("subb", "a,%s",
4643                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4644                                 DP2_RESULT_REG));
4645           }
4646       } else {
4647           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4648           /* first add without previous c */
4649           if (!offset) {
4650               if (!size && lit==-1) {
4651                   emitcode ("dec", "a");
4652               } else {
4653                   emitcode ("add", "a,#!constbyte",
4654                             (unsigned int) (lit & 0x0FFL));
4655               }
4656           } else {
4657               emitcode ("addc", "a,#!constbyte",
4658                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4659           }
4660       }
4661       
4662       if (pushResult) {
4663           emitcode ("push", "acc");
4664       } else {
4665           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4666       }
4667       offset++;
4668   }
4669   _endLazyDPSEvaluation ();
4670   
4671   if (pushResult)
4672     {
4673       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4674
4675       size = getDataSize (IC_LEFT (ic));
4676       rSize = getDataSize (IC_RESULT (ic));
4677
4678       ADJUST_PUSHED_RESULT(size, rSize);
4679
4680       _startLazyDPSEvaluation ();
4681       while (size--)
4682         {
4683           emitcode ("pop", "acc");
4684           aopPut (AOP (IC_RESULT (ic)), "a", size);
4685         }
4686       _endLazyDPSEvaluation ();
4687     }
4688
4689   adjustArithmeticResult (ic);
4690
4691 release:
4692   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4693   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4695 }
4696
4697
4698 /*-----------------------------------------------------------------*/
4699 /* genMultbits :- multiplication of bits                           */
4700 /*-----------------------------------------------------------------*/
4701 static void
4702 genMultbits (operand * left,
4703              operand * right,
4704              operand * result,
4705              iCode   * ic)
4706 {
4707   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4708   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4709   aopOp(result, ic, TRUE, FALSE);
4710   outBitC (result);
4711 }
4712
4713
4714 /*-----------------------------------------------------------------*/
4715 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4716 /*-----------------------------------------------------------------*/
4717 static void
4718 genMultOneByte (operand * left,
4719                 operand * right,
4720                 operand * result,
4721                 iCode   * ic)
4722 {
4723   int size;
4724   symbol *lbl;
4725   bool runtimeSign, compiletimeSign;
4726   bool lUnsigned, rUnsigned;
4727   
4728
4729   /* (if two literals: the value is computed before) */
4730   /* if one literal, literal on the right */
4731   if (AOP_TYPE (left) == AOP_LIT)
4732     {
4733       operand *t = right;
4734       right = left;
4735       left = t;
4736       emitcode (";", "swapped left and right");
4737     }
4738
4739   /* (if two literals: the value is computed before) */
4740   /* if one literal, literal on the right */
4741   if (AOP_TYPE (left) == AOP_LIT)
4742     {
4743       operand *t = right;
4744       right = left;
4745       left = t;
4746       /* emitcode (";", "swapped left and right"); */
4747     }
4748   /* if no literal, unsigned on the right: shorter code */
4749   if (   AOP_TYPE (right) != AOP_LIT
4750       && SPEC_USIGN (getSpec (operandType (left))))
4751     {
4752       operand *t = right;
4753       right = left;
4754       left = t;
4755     }
4756
4757   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4758   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4759
4760   if ((lUnsigned && rUnsigned)
4761 /* sorry, I don't know how to get size
4762    without calling aopOp (result,...);
4763    see Feature Request  */
4764       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4765                    no need to take care about the signedness! */
4766     {
4767       /* just an unsigned 8 * 8 = 8 multiply
4768          or 8u * 8u = 16u */
4769       /* emitcode (";","unsigned"); */
4770       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4771       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4772       emitcode ("mul", "ab");
4773     
4774       _G.accInUse++; _G.bInUse++;
4775       aopOp (result, ic, TRUE, FALSE);
4776       size = AOP_SIZE (result);
4777   
4778       if (size < 1 || size > 2)
4779         {
4780           /* this should never happen */
4781           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4782                    size, __FILE__, lineno);
4783           exit (1);
4784         }
4785   
4786       aopPut (AOP (result), "a", 0);
4787       _G.accInUse--; _G.bInUse--;
4788       if (size == 2) 
4789         aopPut (AOP (result), "b", 1);
4790       return;
4791     }
4792
4793   /* we have to do a signed multiply */
4794   /* emitcode (";", "signed"); */
4795   
4796   /* now sign adjust for both left & right */
4797
4798   /* let's see what's needed: */
4799   /* apply negative sign during runtime */
4800   runtimeSign = FALSE;
4801   /* negative sign from literals */
4802   compiletimeSign = FALSE;
4803
4804   if (!lUnsigned)
4805     {
4806       if (AOP_TYPE(left) == AOP_LIT)
4807         {
4808           /* signed literal */
4809           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4810           if (val < 0)
4811             compiletimeSign = TRUE;
4812         }
4813       else
4814         /* signed but not literal */
4815         runtimeSign = TRUE;
4816     }
4817
4818   if (!rUnsigned)
4819     {
4820       if (AOP_TYPE(right) == AOP_LIT)
4821         {
4822           /* signed literal */
4823           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4824           if (val < 0)
4825             compiletimeSign ^= TRUE;
4826         }
4827       else
4828         /* signed but not literal */
4829         runtimeSign = TRUE;
4830     }
4831
4832   /* initialize F0, which stores the runtime sign */
4833   if (runtimeSign)
4834     {
4835       if (compiletimeSign)
4836         emitcode ("setb", "F0"); /* set sign flag */
4837       else
4838         emitcode ("clr", "F0"); /* reset sign flag */
4839     }
4840   
4841   /* save the signs of the operands */
4842   if (AOP_TYPE(right) == AOP_LIT)
4843     {
4844       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4845
4846       if (!rUnsigned && val < 0)
4847         emitcode ("mov", "b,#!constbyte", -val);
4848       else
4849         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4850     }
4851   else /* ! literal */
4852     {
4853       if (rUnsigned)  /* emitcode (";", "signed"); */
4854         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4855       else
4856         {
4857           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4858           lbl = newiTempLabel (NULL);
4859           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4860           emitcode ("cpl", "F0"); /* complement sign flag */
4861           emitcode ("cpl", "a");  /* 2's complement */
4862           emitcode ("inc", "a");
4863           emitcode ("", "!tlabeldef", lbl->key + 100);
4864           emitcode ("mov", "b,a");
4865         }
4866     }
4867
4868   if (AOP_TYPE(left) == AOP_LIT)
4869     {
4870       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4871
4872       if (!lUnsigned && val < 0)
4873         emitcode ("mov", "a,#!constbyte", -val);
4874       else
4875         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4876     }
4877   else /* ! literal */
4878     {
4879       if (lUnsigned)  /* emitcode (";", "signed"); */
4880
4881         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4882       else
4883         {
4884           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4885           lbl = newiTempLabel (NULL);
4886           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4887           emitcode ("cpl", "F0"); /* complement sign flag */
4888           emitcode ("cpl", "a");  /* 2's complement */
4889           emitcode ("inc", "a");
4890           emitcode ("", "!tlabeldef", lbl->key + 100);
4891         }
4892     }
4893
4894   /* now the multiplication */
4895   emitcode ("mul", "ab");
4896   _G.accInUse++;_G.bInUse++;
4897   aopOp(result, ic, TRUE, FALSE);
4898   size = AOP_SIZE (result);
4899
4900   if (size < 1 || size > 2) 
4901     {
4902       /* this should never happen */
4903       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4904                size, __FILE__, lineno);
4905       exit (1);
4906     }    
4907     
4908   if (runtimeSign || compiletimeSign)
4909     {
4910       lbl = newiTempLabel (NULL);
4911       if (runtimeSign)
4912         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4913       emitcode ("cpl", "a"); /* lsb 2's complement */
4914       if (size != 2)
4915         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4916       else
4917         {
4918           emitcode ("add", "a,#1"); /* this sets carry flag */
4919           emitcode ("xch", "a,b");
4920           emitcode ("cpl", "a"); /* msb 2's complement */
4921           emitcode ("addc", "a,#0");
4922           emitcode ("xch", "a,b");
4923         }
4924       emitcode ("", "!tlabeldef", lbl->key + 100);
4925     }
4926   aopPut (AOP (result), "a", 0);
4927   _G.accInUse--;_G.bInUse--;
4928   if (size == 2)
4929     aopPut (AOP (result), "b", 1);
4930 }
4931
4932 /*-----------------------------------------------------------------*/
4933 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4934 /*-----------------------------------------------------------------*/
4935 static void genMultTwoByte (operand *left, operand *right, 
4936                             operand *result, iCode *ic)
4937 {
4938         sym_link *retype = getSpec(operandType(right));
4939         sym_link *letype = getSpec(operandType(left));
4940         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4941         symbol *lbl;
4942
4943         if (AOP_TYPE (left) == AOP_LIT) {
4944                 operand *t = right;
4945                 right = left;
4946                 left = t;
4947         }
4948         /* save EA bit in F1 */
4949         lbl = newiTempLabel(NULL);
4950         emitcode ("setb","F1");
4951         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4952         emitcode ("clr","F1");
4953         emitcode("","!tlabeldef",lbl->key+100);
4954
4955         /* load up MB with right */
4956         if (!umult) {
4957                 emitcode("clr","F0");
4958                 if (AOP_TYPE(right) == AOP_LIT) {
4959                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4960                         if (val < 0) {
4961                                 emitcode("setb","F0");
4962                                 val = -val;
4963                         }
4964                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4965                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4966                 } else {
4967                         lbl = newiTempLabel(NULL);
4968                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4969                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4970                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4971                         emitcode ("xch", "a,b");
4972                         emitcode ("cpl","a");
4973                         emitcode ("add", "a,#1");
4974                         emitcode ("xch", "a,b");
4975                         emitcode ("cpl", "a"); // msb
4976                         emitcode ("addc", "a,#0");
4977                         emitcode ("setb","F0");
4978                         emitcode ("","!tlabeldef",lbl->key+100);
4979                         emitcode ("mov","mb,b");
4980                         emitcode ("mov","mb,a");
4981                 }
4982         } else {
4983                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4984                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4985         }
4986         /* load up MA with left */
4987         if (!umult) {
4988                 lbl = newiTempLabel(NULL);
4989                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4990                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4991                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4992                 emitcode ("xch", "a,b");
4993                 emitcode ("cpl","a");
4994                 emitcode ("add", "a,#1");
4995                 emitcode ("xch", "a,b");
4996                 emitcode ("cpl", "a"); // msb
4997                 emitcode ("addc","a,#0");
4998                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4999                 emitcode ("setb","F0");
5000                 emitcode ("","!tlabeldef",lbl->key+100);
5001                 emitcode ("mov","ma,b");
5002                 emitcode ("mov","ma,a");
5003         } else {
5004                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5005                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5006         }
5007         /* wait for multiplication to finish */
5008         lbl = newiTempLabel(NULL);
5009         emitcode("","!tlabeldef", lbl->key+100);
5010         emitcode("mov","a,mcnt1");
5011         emitcode("anl","a,#!constbyte",0x80);
5012         emitcode("jnz","!tlabel",lbl->key+100);
5013         
5014         freeAsmop (left, NULL, ic, TRUE);
5015         freeAsmop (right, NULL, ic,TRUE);
5016         aopOp(result, ic, TRUE, FALSE);
5017
5018         /* if unsigned then simple */   
5019         if (umult) {
5020                 emitcode ("mov","a,ma");
5021                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5022                 emitcode ("mov","a,ma");
5023                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5024                 aopPut(AOP(result),"ma",1);
5025                 aopPut(AOP(result),"ma",0);
5026         } else {
5027                 emitcode("push","ma");
5028                 emitcode("push","ma");
5029                 emitcode("push","ma");
5030                 MOVA("ma");
5031                 /* negate result if needed */
5032                 lbl = newiTempLabel(NULL);      
5033                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5034                 emitcode("cpl","a");
5035                 emitcode("add","a,#1");
5036                 emitcode("","!tlabeldef", lbl->key+100);
5037                 if (AOP_TYPE(result) == AOP_ACC)
5038                 {
5039                     D(emitcode(";", "ACC special case."););
5040                     /* We know result is the only live aop, and 
5041                      * it's obviously not a DPTR2, so AP is available.
5042                      */
5043                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5044                 }
5045                 else
5046                 {
5047                     aopPut(AOP(result),"a",0);
5048                 }
5049             
5050                 emitcode("pop","acc");
5051                 lbl = newiTempLabel(NULL);      
5052                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5053                 emitcode("cpl","a");
5054                 emitcode("addc","a,#0");
5055                 emitcode("","!tlabeldef", lbl->key+100);
5056                 aopPut(AOP(result),"a",1);
5057                 emitcode("pop","acc");
5058                 if (AOP_SIZE(result) >= 3) {
5059                         lbl = newiTempLabel(NULL);      
5060                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5061                         emitcode("cpl","a");
5062                         emitcode("addc","a,#0");                        
5063                         emitcode("","!tlabeldef", lbl->key+100);
5064                         aopPut(AOP(result),"a",2);
5065                 }
5066                 emitcode("pop","acc");
5067                 if (AOP_SIZE(result) >= 4) {
5068                         lbl = newiTempLabel(NULL);      
5069                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5070                         emitcode("cpl","a");
5071                         emitcode("addc","a,#0");                        
5072                         emitcode("","!tlabeldef", lbl->key+100);
5073                         aopPut(AOP(result),"a",3);
5074                 }
5075                 if (AOP_TYPE(result) == AOP_ACC)
5076                 {
5077                     /* We stashed the result away above. */
5078                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5079                 }           
5080                 
5081         }
5082         freeAsmop (result, NULL, ic, TRUE);
5083
5084         /* restore EA bit in F1 */
5085         lbl = newiTempLabel(NULL);
5086         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5087         emitcode ("setb","EA");
5088         emitcode("","!tlabeldef",lbl->key+100);
5089         return ;
5090 }
5091
5092 /*-----------------------------------------------------------------*/
5093 /* genMult - generates code for multiplication                     */
5094 /*-----------------------------------------------------------------*/
5095 static void
5096 genMult (iCode * ic)
5097 {
5098   operand *left = IC_LEFT (ic);
5099   operand *right = IC_RIGHT (ic);
5100   operand *result = IC_RESULT (ic);
5101
5102   D (emitcode (";", "genMult "););
5103
5104   /* assign the amsops */
5105   AOP_OP_2 (ic);
5106
5107   /* special cases first */
5108   /* both are bits */
5109   if (AOP_TYPE (left) == AOP_CRY &&
5110       AOP_TYPE (right) == AOP_CRY)
5111     {
5112       genMultbits (left, right, result, ic);
5113       goto release;
5114     }
5115
5116   /* if both are of size == 1 */
5117   if (AOP_SIZE (left) == 1 &&
5118       AOP_SIZE (right) == 1)
5119     {
5120       genMultOneByte (left, right, result, ic);
5121       goto release;
5122     }
5123
5124   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5125           /* use the ds390 ARITHMETIC accel UNIT */
5126           genMultTwoByte (left, right, result, ic);
5127           return ;
5128   }
5129   /* should have been converted to function call */
5130   assert (0);
5131
5132 release:
5133   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135   freeAsmop (result, NULL, ic, TRUE);
5136 }
5137
5138 /*-----------------------------------------------------------------*/
5139 /* genDivbits :- division of bits                                  */
5140 /*-----------------------------------------------------------------*/
5141 static void
5142 genDivbits (operand * left,
5143             operand * right,
5144             operand * result,
5145             iCode   * ic)
5146 {
5147
5148   char *l;
5149
5150   /* the result must be bit */
5151   LOAD_AB_FOR_DIV (left, right, l);
5152   emitcode ("div", "ab");
5153   emitcode ("rrc", "a");
5154   aopOp(result, ic, TRUE, FALSE);
5155     
5156   aopPut (AOP (result), "c", 0);
5157 }
5158
5159 /*-----------------------------------------------------------------*/
5160 /* genDivOneByte : 8 bit division                                  */
5161 /*-----------------------------------------------------------------*/
5162 static void
5163 genDivOneByte (operand * left,
5164                operand * right,
5165                operand * result,
5166                iCode   * ic)
5167 {
5168   bool lUnsigned, rUnsigned;
5169   bool runtimeSign, compiletimeSign;
5170   char *l;
5171   symbol *lbl;
5172   int size, offset;
5173
5174   offset = 1;
5175   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5176   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5177   
5178   /* signed or unsigned */
5179   if (lUnsigned && rUnsigned)
5180     {
5181       /* unsigned is easy */
5182       LOAD_AB_FOR_DIV (left, right, l);
5183       emitcode ("div", "ab");
5184
5185       _G.accInUse++;
5186       aopOp (result, ic, TRUE, FALSE);
5187       aopPut (AOP (result), "a", 0);
5188       _G.accInUse--;
5189
5190       size = AOP_SIZE (result) - 1;
5191       
5192       while (size--)
5193         aopPut (AOP (result), zero, offset++);
5194       return;
5195     }
5196
5197   /* signed is a little bit more difficult */
5198
5199   /* now sign adjust for both left & right */
5200
5201   /* let's see what's needed: */
5202   /* apply negative sign during runtime */
5203   runtimeSign = FALSE;
5204   /* negative sign from literals */
5205   compiletimeSign = FALSE;
5206
5207   if (!lUnsigned)
5208     {
5209       if (AOP_TYPE(left) == AOP_LIT)
5210         {
5211           /* signed literal */
5212           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5213           if (val < 0)
5214             compiletimeSign = TRUE;
5215         }
5216       else
5217         /* signed but not literal */
5218         runtimeSign = TRUE;
5219     }
5220
5221   if (!rUnsigned)
5222     {
5223       if (AOP_TYPE(right) == AOP_LIT)
5224         {
5225           /* signed literal */
5226           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5227           if (val < 0)
5228             compiletimeSign ^= TRUE;
5229         }
5230       else
5231         /* signed but not literal */
5232         runtimeSign = TRUE;
5233     }
5234
5235   /* initialize F0, which stores the runtime sign */
5236   if (runtimeSign)
5237     {
5238       if (compiletimeSign)
5239         emitcode ("setb", "F0"); /* set sign flag */
5240       else
5241         emitcode ("clr", "F0"); /* reset sign flag */
5242     }
5243
5244   /* save the signs of the operands */
5245   if (AOP_TYPE(right) == AOP_LIT)
5246     {
5247       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5248
5249       if (!rUnsigned && val < 0)
5250         emitcode ("mov", "b,#0x%02x", -val);
5251       else
5252         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5253     }
5254   else /* ! literal */
5255     {
5256       if (rUnsigned)
5257         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5258       else
5259         {
5260           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5261           lbl = newiTempLabel (NULL);
5262           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5263           emitcode ("cpl", "F0"); /* complement sign flag */
5264           emitcode ("cpl", "a");  /* 2's complement */
5265           emitcode ("inc", "a");
5266           emitcode ("", "!tlabeldef", lbl->key + 100);
5267           emitcode ("mov", "b,a");
5268         }
5269     }
5270
5271   if (AOP_TYPE(left) == AOP_LIT)
5272     {
5273       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5274
5275       if (!lUnsigned && val < 0)
5276         emitcode ("mov", "a,#0x%02x", -val);
5277       else
5278         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5279     }
5280   else /* ! literal */
5281     {
5282       if (lUnsigned)
5283         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5284       else
5285         {
5286           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5287           lbl = newiTempLabel (NULL);
5288           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5289           emitcode ("cpl", "F0"); /* complement sign flag */
5290           emitcode ("cpl", "a");  /* 2's complement */
5291           emitcode ("inc", "a");
5292           emitcode ("", "!tlabeldef", lbl->key + 100);
5293         }
5294     }
5295   
5296   /* now the division */
5297   emitcode ("nop", "; workaround for DS80C390 div bug.");
5298   emitcode ("div", "ab");
5299   
5300   if (runtimeSign || compiletimeSign)
5301     {
5302       lbl = newiTempLabel (NULL);
5303       if (runtimeSign)
5304         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5305       emitcode ("cpl", "a"); /* lsb 2's complement */
5306       emitcode ("inc", "a");
5307       emitcode ("", "!tlabeldef", lbl->key + 100);
5308
5309       _G.accInUse++;     _G.bInUse++;
5310       aopOp (result, ic, TRUE, FALSE);
5311       size = AOP_SIZE (result) - 1;
5312
5313       if (size > 0)
5314         {
5315           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5316              then the result will be in b, a */
5317           emitcode ("mov", "b,a"); /* 1 */
5318           /* msb is 0x00 or 0xff depending on the sign */
5319           if (runtimeSign)
5320             {
5321               emitcode ("mov",  "c,F0");
5322               emitcode ("subb", "a,acc");
5323               emitcode ("xch",  "a,b"); /* 2 */
5324               while (size--)
5325                 aopPut (AOP (result), "b", offset++); /* write msb's */
5326             }
5327           else /* compiletimeSign */
5328             while (size--)
5329               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5330         }
5331       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5332     }
5333   else
5334     {
5335       _G.accInUse++;     _G.bInUse++;
5336       aopOp(result, ic, TRUE, FALSE);
5337       size = AOP_SIZE (result) - 1;
5338       
5339       aopPut (AOP (result), "a", 0);
5340       while (size--)
5341         aopPut (AOP (result), zero, offset++);
5342     }
5343   _G.accInUse--;     _G.bInUse--;
5344
5345 }
5346
5347 /*-----------------------------------------------------------------*/
5348 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5349 /*-----------------------------------------------------------------*/
5350 static void genDivTwoByte (operand *left, operand *right, 
5351                             operand *result, iCode *ic)
5352 {
5353         sym_link *retype = getSpec(operandType(right));
5354         sym_link *letype = getSpec(operandType(left));
5355         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5356         symbol *lbl;
5357
5358         /* save EA bit in F1 */
5359         lbl = newiTempLabel(NULL);
5360         emitcode ("setb","F1");
5361         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5362         emitcode ("clr","F1");
5363         emitcode("","!tlabeldef",lbl->key+100);
5364
5365         /* load up MA with left */
5366         if (!umult) {
5367                 emitcode("clr","F0");
5368                 lbl = newiTempLabel(NULL);
5369                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5370                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5371                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5372                 emitcode ("xch", "a,b");
5373                 emitcode ("cpl","a");
5374                 emitcode ("add", "a,#1");
5375                 emitcode ("xch", "a,b");
5376                 emitcode ("cpl", "a"); // msb
5377                 emitcode ("addc","a,#0");
5378                 emitcode ("setb","F0");
5379                 emitcode ("","!tlabeldef",lbl->key+100);
5380                 emitcode ("mov","ma,b");
5381                 emitcode ("mov","ma,a");
5382         } else {
5383                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5384                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5385         }
5386
5387         /* load up MB with right */
5388         if (!umult) {
5389                 if (AOP_TYPE(right) == AOP_LIT) {
5390                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5391                         if (val < 0) {
5392                                 lbl = newiTempLabel(NULL);
5393                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5394                                 emitcode("setb","F0");
5395                                 emitcode ("","!tlabeldef",lbl->key+100);
5396                                 val = -val;
5397                         } 
5398                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5399                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5400                 } else {
5401                         lbl = newiTempLabel(NULL);
5402                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5403                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5404                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5405                         emitcode ("xch", "a,b");
5406                         emitcode ("cpl","a");
5407                         emitcode ("add", "a,#1");
5408                         emitcode ("xch", "a,b");
5409                         emitcode ("cpl", "a"); // msb
5410                         emitcode ("addc", "a,#0");
5411                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5412                         emitcode ("setb","F0");
5413                         emitcode ("","!tlabeldef",lbl->key+100);
5414                         emitcode ("mov","mb,b");
5415                         emitcode ("mov","mb,a");
5416                 }
5417         } else {
5418                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5419                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5420         }
5421
5422         /* wait for multiplication to finish */
5423         lbl = newiTempLabel(NULL);
5424         emitcode("","!tlabeldef", lbl->key+100);
5425         emitcode("mov","a,mcnt1");
5426         emitcode("anl","a,#!constbyte",0x80);
5427         emitcode("jnz","!tlabel",lbl->key+100);
5428         
5429         freeAsmop (left, NULL, ic, TRUE);
5430         freeAsmop (right, NULL, ic,TRUE);
5431         aopOp(result, ic, TRUE, FALSE);
5432
5433         /* if unsigned then simple */   
5434         if (umult) {
5435                 aopPut(AOP(result),"ma",1);
5436                 aopPut(AOP(result),"ma",0);
5437         } else {
5438                 emitcode("push","ma");
5439                 MOVA("ma");
5440                 /* negate result if needed */
5441                 lbl = newiTempLabel(NULL);      
5442                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5443                 emitcode("cpl","a");
5444                 emitcode("add","a,#1");
5445                 emitcode("","!tlabeldef", lbl->key+100);
5446                 aopPut(AOP(result),"a",0);
5447                 emitcode("pop","acc");
5448                 lbl = newiTempLabel(NULL);      
5449                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5450                 emitcode("cpl","a");
5451                 emitcode("addc","a,#0");
5452                 emitcode("","!tlabeldef", lbl->key+100);
5453                 aopPut(AOP(result),"a",1);
5454         }
5455         freeAsmop (result, NULL, ic, TRUE);
5456         /* restore EA bit in F1 */
5457         lbl = newiTempLabel(NULL);
5458         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5459         emitcode ("setb","EA");
5460         emitcode("","!tlabeldef",lbl->key+100);
5461         return ;
5462 }
5463
5464 /*-----------------------------------------------------------------*/
5465 /* genDiv - generates code for division                            */
5466 /*-----------------------------------------------------------------*/
5467 static void
5468 genDiv (iCode * ic)
5469 {
5470   operand *left = IC_LEFT (ic);
5471   operand *right = IC_RIGHT (ic);
5472   operand *result = IC_RESULT (ic);
5473
5474   D (emitcode (";", "genDiv "););
5475
5476   /* assign the amsops */
5477   AOP_OP_2 (ic);
5478
5479   /* special cases first */
5480   /* both are bits */
5481   if (AOP_TYPE (left) == AOP_CRY &&
5482       AOP_TYPE (right) == AOP_CRY)
5483     {
5484       genDivbits (left, right, result, ic);
5485       goto release;
5486     }
5487
5488   /* if both are of size == 1 */
5489   if (AOP_SIZE (left) == 1 &&
5490       AOP_SIZE (right) == 1)
5491     {
5492       genDivOneByte (left, right, result, ic);
5493       goto release;
5494     }
5495
5496   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5497           /* use the ds390 ARITHMETIC accel UNIT */
5498           genDivTwoByte (left, right, result, ic);
5499           return ;
5500   }
5501   /* should have been converted to function call */
5502   assert (0);
5503 release:
5504   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5506   freeAsmop (result, NULL, ic, TRUE);
5507 }
5508
5509 /*-----------------------------------------------------------------*/
5510 /* genModbits :- modulus of bits                                   */
5511 /*-----------------------------------------------------------------*/
5512 static void
5513 genModbits (operand * left,
5514             operand * right,
5515             operand * result,
5516             iCode   * ic)
5517 {
5518
5519   char *l;
5520
5521   /* the result must be bit */
5522   LOAD_AB_FOR_DIV (left, right, l);
5523   emitcode ("div", "ab");
5524   emitcode ("mov", "a,b");
5525   emitcode ("rrc", "a");
5526   aopOp(result, ic, TRUE, FALSE);
5527   aopPut (AOP (result), "c", 0);
5528 }
5529
5530 /*-----------------------------------------------------------------*/
5531 /* genModOneByte : 8 bit modulus                                   */
5532 /*-----------------------------------------------------------------*/
5533 static void
5534 genModOneByte (operand * left,
5535                operand * right,
5536                operand * result,
5537                iCode   * ic)
5538 {
5539   bool lUnsigned, rUnsigned;
5540   bool runtimeSign, compiletimeSign;
5541   char *l;
5542   symbol *lbl;
5543   int size, offset;
5544
5545   offset = 1;
5546   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5547   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5548   
5549   /* signed or unsigned */
5550   if (lUnsigned && rUnsigned)
5551     {
5552       /* unsigned is easy */
5553       LOAD_AB_FOR_DIV (left, right, l);
5554       emitcode ("div", "ab");
5555       aopOp (result, ic, TRUE, FALSE);  
5556       aopPut (AOP (result), "b", 0);
5557
5558       for (size = AOP_SIZE (result) - 1; size--;)
5559         aopPut (AOP (result), zero, offset++);
5560       return;
5561     }
5562
5563   /* signed is a little bit more difficult */
5564
5565   /* now sign adjust for both left & right */
5566
5567   /* modulus: sign of the right operand has no influence on the result! */
5568   if (AOP_TYPE(right) == AOP_LIT)
5569     {
5570       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5571
5572       if (!rUnsigned && val < 0)
5573         emitcode ("mov", "b,#0x%02x", -val);
5574       else
5575         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5576     }
5577   else /* ! literal */
5578     {
5579       if (rUnsigned)
5580         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5581       else
5582         {
5583           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5584           lbl = newiTempLabel (NULL);
5585           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5586           emitcode ("cpl", "a");  /* 2's complement */
5587           emitcode ("inc", "a");
5588           emitcode ("", "!tlabeldef", lbl->key + 100);
5589           emitcode ("mov", "b,a");
5590         }
5591     }
5592   
5593   /* let's see what's needed: */
5594   /* apply negative sign during runtime */
5595   runtimeSign = FALSE;
5596   /* negative sign from literals */
5597   compiletimeSign = FALSE;
5598
5599   /* sign adjust left side */
5600   if (AOP_TYPE(left) == AOP_LIT)
5601     {
5602       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5603
5604       if (!lUnsigned && val < 0)
5605         {
5606           compiletimeSign = TRUE; /* set sign flag */
5607           emitcode ("mov", "a,#0x%02x", -val);
5608         }
5609       else
5610         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5611     }
5612   else /* ! literal */
5613     {
5614       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5615       
5616       if (!lUnsigned)
5617         {
5618           runtimeSign = TRUE;
5619           emitcode ("clr", "F0"); /* clear sign flag */
5620           
5621           lbl = newiTempLabel (NULL);
5622           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5623           emitcode ("setb", "F0"); /* set sign flag */
5624           emitcode ("cpl", "a");   /* 2's complement */
5625           emitcode ("inc", "a");
5626           emitcode ("", "!tlabeldef", lbl->key + 100);
5627         }
5628     }
5629   
5630   /* now the modulus */
5631   emitcode ("nop", "; workaround for DS80C390 div bug.");
5632   emitcode ("div", "ab");
5633   
5634   if (runtimeSign || compiletimeSign)
5635     {
5636       emitcode ("mov", "a,b");
5637       lbl = newiTempLabel (NULL);
5638       if (runtimeSign)
5639         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5640       emitcode ("cpl", "a"); /* lsb 2's complement */
5641       emitcode ("inc", "a");
5642       emitcode ("", "!tlabeldef", lbl->key + 100);
5643
5644       _G.accInUse++;     _G.bInUse++;
5645       aopOp (result, ic, TRUE, FALSE);
5646       size = AOP_SIZE (result) - 1;
5647       
5648       if (size > 0)
5649         {
5650           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5651              then the result will be in b, a */
5652           emitcode ("mov", "b,a"); /* 1 */
5653           /* msb is 0x00 or 0xff depending on the sign */
5654           if (runtimeSign)
5655             {
5656               emitcode ("mov",  "c,F0");
5657               emitcode ("subb", "a,acc");
5658               emitcode ("xch",  "a,b"); /* 2 */
5659               while (size--)
5660                 aopPut (AOP (result), "b", offset++); /* write msb's */
5661             }
5662           else /* compiletimeSign */
5663             while (size--)
5664               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5665         }
5666       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5667     }
5668   else
5669     {
5670       _G.accInUse++;     _G.bInUse++;
5671       aopOp(result, ic, TRUE, FALSE);
5672       size = AOP_SIZE (result) - 1;
5673       
5674       aopPut (AOP (result), "b", 0);
5675       while (size--)
5676         aopPut (AOP (result), zero, offset++);
5677     }
5678   _G.accInUse--;     _G.bInUse--;
5679
5680 }
5681
5682 /*-----------------------------------------------------------------*/
5683 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5684 /*-----------------------------------------------------------------*/
5685 static void genModTwoByte (operand *left, operand *right, 
5686                             operand *result, iCode *ic)
5687 {
5688         sym_link *retype = getSpec(operandType(right));
5689         sym_link *letype = getSpec(operandType(left));
5690         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5691         symbol *lbl;
5692
5693         /* load up MA with left */
5694         /* save EA bit in F1 */
5695         lbl = newiTempLabel(NULL);
5696         emitcode ("setb","F1");
5697         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5698         emitcode ("clr","F1");
5699         emitcode("","!tlabeldef",lbl->key+100);
5700
5701         if (!umult) {
5702                 lbl = newiTempLabel(NULL);
5703                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5704                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5705                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5706                 emitcode ("xch", "a,b");
5707                 emitcode ("cpl","a");
5708                 emitcode ("add", "a,#1");
5709                 emitcode ("xch", "a,b");
5710                 emitcode ("cpl", "a"); // msb
5711                 emitcode ("addc","a,#0");
5712                 emitcode ("","!tlabeldef",lbl->key+100);
5713                 emitcode ("mov","ma,b");
5714                 emitcode ("mov","ma,a");
5715         } else {
5716                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5717                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5718         }
5719
5720         /* load up MB with right */
5721         if (!umult) {
5722                 if (AOP_TYPE(right) == AOP_LIT) {
5723                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5724                         if (val < 0) {
5725                                 val = -val;
5726                         } 
5727                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5728                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5729                 } else {
5730                         lbl = newiTempLabel(NULL);
5731                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5732                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5733                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5734                         emitcode ("xch", "a,b");
5735                         emitcode ("cpl","a");
5736                         emitcode ("add", "a,#1");
5737                         emitcode ("xch", "a,b");
5738                         emitcode ("cpl", "a"); // msb
5739                         emitcode ("addc", "a,#0");
5740                         emitcode ("","!tlabeldef",lbl->key+100);
5741                         emitcode ("mov","mb,b");
5742                         emitcode ("mov","mb,a");
5743                 }
5744         } else {
5745                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5746                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5747         }
5748
5749         /* wait for multiplication to finish */
5750         lbl = newiTempLabel(NULL);
5751         emitcode("","!tlabeldef", lbl->key+100);
5752         emitcode("mov","a,mcnt1");
5753         emitcode("anl","a,#!constbyte",0x80);
5754         emitcode("jnz","!tlabel",lbl->key+100);
5755         
5756         freeAsmop (left, NULL, ic, TRUE);
5757         freeAsmop (right, NULL, ic,TRUE);
5758         aopOp(result, ic, TRUE, FALSE);
5759
5760         aopPut(AOP(result),"mb",1);
5761         aopPut(AOP(result),"mb",0);
5762         freeAsmop (result, NULL, ic, TRUE);
5763
5764         /* restore EA bit in F1 */
5765         lbl = newiTempLabel(NULL);
5766         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5767         emitcode ("setb","EA");
5768         emitcode("","!tlabeldef",lbl->key+100);
5769         return ;
5770 }
5771
5772 /*-----------------------------------------------------------------*/
5773 /* genMod - generates code for division                            */
5774 /*-----------------------------------------------------------------*/
5775 static void
5776 genMod (iCode * ic)
5777 {
5778   operand *left = IC_LEFT (ic);
5779   operand *right = IC_RIGHT (ic);
5780   operand *result = IC_RESULT (ic);
5781
5782   D (emitcode (";", "genMod "); );
5783
5784   /* assign the amsops */
5785   AOP_OP_2 (ic);
5786
5787   /* special cases first */
5788   /* both are bits */
5789   if (AOP_TYPE (left) == AOP_CRY &&
5790       AOP_TYPE (right) == AOP_CRY)
5791     {
5792       genModbits (left, right, result, ic);
5793       goto release;
5794     }
5795
5796   /* if both are of size == 1 */
5797   if (AOP_SIZE (left) == 1 &&
5798       AOP_SIZE (right) == 1)
5799     {
5800       genModOneByte (left, right, result, ic);
5801       goto release;
5802     }
5803
5804   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5805           /* use the ds390 ARITHMETIC accel UNIT */
5806           genModTwoByte (left, right, result, ic);
5807           return ;
5808   }
5809
5810   /* should have been converted to function call */
5811   assert (0);
5812
5813 release:
5814   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5816   freeAsmop (result, NULL, ic, TRUE);
5817 }
5818
5819 /*-----------------------------------------------------------------*/
5820 /* genIfxJump :- will create a jump depending on the ifx           */
5821 /*-----------------------------------------------------------------*/
5822 static void
5823 genIfxJump (iCode * ic, char *jval)
5824 {
5825   symbol *jlbl;
5826   symbol *tlbl = newiTempLabel (NULL);
5827   char *inst;
5828
5829   D (emitcode (";", "genIfxJump"););
5830
5831   /* if true label then we jump if condition
5832      supplied is true */
5833   if (IC_TRUE (ic))
5834     {
5835       jlbl = IC_TRUE (ic);
5836       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5837                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5838     }
5839   else
5840     {
5841       /* false label is present */
5842       jlbl = IC_FALSE (ic);
5843       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5844                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5845     }
5846   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5847     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5848   else
5849     emitcode (inst, "!tlabel", tlbl->key + 100);
5850   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5851   emitcode ("", "!tlabeldef", tlbl->key + 100);
5852
5853   /* mark the icode as generated */
5854   ic->generated = 1;
5855 }
5856
5857 /*-----------------------------------------------------------------*/
5858 /* genCmp :- greater or less than comparison                       */
5859 /*-----------------------------------------------------------------*/
5860 static void
5861 genCmp (operand * left, operand * right,
5862         iCode * ic, iCode * ifx, int sign)
5863 {
5864   int size, offset = 0;
5865   unsigned long lit = 0L;
5866   operand *result;
5867
5868   D (emitcode (";", "genCmp"););
5869
5870   result = IC_RESULT (ic);
5871
5872   /* if left & right are bit variables */
5873   if (AOP_TYPE (left) == AOP_CRY &&
5874       AOP_TYPE (right) == AOP_CRY)
5875     {
5876       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5877       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5878     }
5879   else
5880     {
5881       /* subtract right from left if at the
5882          end the carry flag is set then we know that
5883          left is greater than right */
5884       size = max (AOP_SIZE (left), AOP_SIZE (right));
5885
5886       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5887       if ((size == 1) && !sign 
5888           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5889         {
5890           symbol *lbl = newiTempLabel (NULL);
5891           emitcode ("cjne", "%s,%s,!tlabel",
5892                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5893                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5894                     lbl->key + 100);
5895           emitcode ("", "!tlabeldef", lbl->key + 100);
5896         }
5897       else
5898         {
5899           if (AOP_TYPE (right) == AOP_LIT)
5900             {
5901               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5902               /* optimize if(x < 0) or if(x >= 0) */
5903               if (lit == 0L)
5904                 {
5905                   if (!sign)
5906                     {
5907                       CLRC;
5908                     }
5909                   else
5910                     {
5911                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5912
5913                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5914                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5915
5916                       aopOp (result, ic, FALSE, FALSE);
5917
5918                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5919                         {
5920                           freeAsmop (result, NULL, ic, TRUE);
5921                           genIfxJump (ifx, "acc.7");
5922                           return;
5923                         }
5924                       else
5925                         {
5926                           emitcode ("rlc", "a");
5927                         }
5928                       goto release_freedLR;
5929                     }
5930                   goto release;
5931                 }
5932             }
5933           CLRC;
5934           while (size--)
5935             {
5936               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5937               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5938               // emitcode (";", "genCmp #2");
5939               if (sign && (size == 0))
5940                 {
5941                   // emitcode (";", "genCmp #3");
5942                   emitcode ("xrl", "a,#!constbyte",0x80);
5943                   if (AOP_TYPE (right) == AOP_LIT)
5944                     {
5945                       unsigned long lit = (unsigned long)
5946                       floatFromVal (AOP (right)->aopu.aop_lit);
5947                       // emitcode (";", "genCmp #3.1");
5948                       emitcode ("subb", "a,#!constbyte",
5949                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5950                     }
5951                   else
5952                     {
5953                       // emitcode (";", "genCmp #3.2");
5954                       saveAccWarn = 0;  
5955                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5956                       saveAccWarn = DEFAULT_ACC_WARNING;
5957                       emitcode ("xrl", "b,#!constbyte",0x80);
5958                       emitcode ("subb", "a,b");
5959                     }
5960                 }
5961               else
5962                 {
5963                   const char *s;
5964
5965                   // emitcode (";", "genCmp #4");
5966                   saveAccWarn = 0;
5967                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5968                   saveAccWarn = DEFAULT_ACC_WARNING;
5969
5970                   emitcode ("subb", "a,%s", s);
5971                 }
5972             }
5973         }
5974     }
5975
5976 release:
5977 /* Don't need the left & right operands any more; do need the result. */
5978   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5979   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5980
5981   aopOp (result, ic, FALSE, FALSE);
5982
5983 release_freedLR:
5984
5985   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5986     {
5987       outBitC (result);
5988     }
5989   else
5990     {
5991       /* if the result is used in the next
5992          ifx conditional branch then generate
5993          code a little differently */
5994       if (ifx)
5995         {
5996           genIfxJump (ifx, "c");
5997         }
5998       else
5999         {
6000           outBitC (result);
6001         }
6002       /* leave the result in acc */
6003     }
6004   freeAsmop (result, NULL, ic, TRUE);
6005 }
6006
6007 /*-----------------------------------------------------------------*/
6008 /* genCmpGt :- greater than comparison                             */
6009 /*-----------------------------------------------------------------*/
6010 static void
6011 genCmpGt (iCode * ic, iCode * ifx)
6012 {
6013   operand *left, *right;
6014   sym_link *letype, *retype;
6015   int sign;
6016
6017   D (emitcode (";", "genCmpGt ");
6018     );
6019
6020   left = IC_LEFT (ic);
6021   right = IC_RIGHT (ic);
6022
6023   letype = getSpec (operandType (left));
6024   retype = getSpec (operandType (right));
6025   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6026
6027   /* assign the left & right amsops */
6028   AOP_OP_2 (ic);
6029
6030   genCmp (right, left, ic, ifx, sign);
6031 }
6032
6033 /*-----------------------------------------------------------------*/
6034 /* genCmpLt - less than comparisons                                */
6035 /*-----------------------------------------------------------------*/
6036 static void
6037 genCmpLt (iCode * ic, iCode * ifx)
6038 {
6039   operand *left, *right;
6040   sym_link *letype, *retype;
6041   int sign;
6042
6043   D (emitcode (";", "genCmpLt "););
6044
6045   left = IC_LEFT (ic);
6046   right = IC_RIGHT (ic);
6047
6048   letype = getSpec (operandType (left));
6049   retype = getSpec (operandType (right));
6050   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6051
6052   /* assign the left & right amsops */
6053   AOP_OP_2 (ic);
6054
6055   genCmp (left, right, ic, ifx, sign);
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* gencjneshort - compare and jump if not equal                    */
6060 /*-----------------------------------------------------------------*/
6061 static void
6062 gencjneshort (operand * left, operand * right, symbol * lbl)
6063 {
6064   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6065   int offset = 0;
6066   unsigned long lit = 0L;
6067
6068   D (emitcode (";", "gencjneshort");
6069     );
6070
6071   /* if the left side is a literal or
6072      if the right is in a pointer register and left
6073      is not */
6074   if ((AOP_TYPE (left) == AOP_LIT) ||
6075       (AOP_TYPE (left) == AOP_IMMD) ||
6076       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6077     {
6078       operand *t = right;
6079       right = left;
6080       left = t;
6081     }
6082
6083   if (AOP_TYPE (right) == AOP_LIT)
6084     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6085
6086   if (opIsGptr (left) || opIsGptr (right))
6087     {
6088       /* We are comparing a generic pointer to something.
6089        * Exclude the generic type byte from the comparison.
6090        */
6091       size--;
6092       D (emitcode (";", "cjneshort: generic ptr special case."););
6093     }
6094
6095
6096   /* if the right side is a literal then anything goes */
6097   if (AOP_TYPE (right) == AOP_LIT &&
6098       AOP_TYPE (left) != AOP_DIR)
6099     {
6100       while (size--)
6101         {
6102           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6103           emitcode ("cjne", "a,%s,!tlabel",
6104                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6105                     lbl->key + 100);
6106           offset++;
6107         }
6108     }
6109
6110   /* if the right side is in a register or in direct space or
6111      if the left is a pointer register & right is not */
6112   else if (AOP_TYPE (right) == AOP_REG ||
6113            AOP_TYPE (right) == AOP_DIR ||
6114            AOP_TYPE (right) == AOP_LIT ||
6115            AOP_TYPE (right) == AOP_IMMD ||
6116            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6117            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6118     {
6119       while (size--)
6120         {
6121           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6122           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6123               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6124             emitcode ("jnz", "!tlabel", lbl->key + 100);
6125           else
6126             emitcode ("cjne", "a,%s,!tlabel",
6127                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6128                       lbl->key + 100);
6129           offset++;
6130         }
6131     }
6132   else
6133     {
6134       /* right is a pointer reg need both a & b */
6135       while (size--)
6136         {
6137           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6138           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6139           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6140           offset++;
6141         }
6142     }
6143 }
6144
6145 /*-----------------------------------------------------------------*/
6146 /* gencjne - compare and jump if not equal                         */
6147 /*-----------------------------------------------------------------*/
6148 static void
6149 gencjne (operand * left, operand * right, symbol * lbl)
6150 {
6151   symbol *tlbl = newiTempLabel (NULL);
6152
6153   D (emitcode (";", "gencjne");
6154     );
6155
6156   gencjneshort (left, right, lbl);
6157
6158   emitcode ("mov", "a,%s", one);
6159   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6160   emitcode ("", "!tlabeldef", lbl->key + 100);
6161   emitcode ("clr", "a");
6162   emitcode ("", "!tlabeldef", tlbl->key + 100);
6163 }
6164
6165 /*-----------------------------------------------------------------*/
6166 /* genCmpEq - generates code for equal to                          */
6167 /*-----------------------------------------------------------------*/
6168 static void
6169 genCmpEq (iCode * ic, iCode * ifx)
6170 {
6171   operand *left, *right, *result;
6172
6173   D (emitcode (";", "genCmpEq ");
6174     );
6175
6176   AOP_OP_2 (ic);
6177   AOP_SET_LOCALS (ic);
6178
6179   /* if literal, literal on the right or
6180      if the right is in a pointer register and left
6181      is not */
6182   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6183       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6184     {
6185       operand *t = IC_RIGHT (ic);
6186       IC_RIGHT (ic) = IC_LEFT (ic);
6187       IC_LEFT (ic) = t;
6188     }
6189
6190   if (ifx &&                    /* !AOP_SIZE(result) */
6191       OP_SYMBOL (result) &&
6192       OP_SYMBOL (result)->regType == REG_CND)
6193     {
6194       symbol *tlbl;
6195       /* if they are both bit variables */
6196       if (AOP_TYPE (left) == AOP_CRY &&
6197           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6198         {
6199           if (AOP_TYPE (right) == AOP_LIT)
6200             {
6201               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6202               if (lit == 0L)
6203                 {
6204                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6205                   emitcode ("cpl", "c");
6206                 }
6207               else if (lit == 1L)
6208                 {
6209                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6210                 }
6211               else
6212                 {
6213                   emitcode ("clr", "c");
6214                 }
6215               /* AOP_TYPE(right) == AOP_CRY */
6216             }
6217           else
6218             {
6219               symbol *lbl = newiTempLabel (NULL);
6220               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6222               emitcode ("cpl", "c");
6223               emitcode ("", "!tlabeldef", (lbl->key + 100));
6224             }
6225           /* if true label then we jump if condition
6226              supplied is true */
6227           tlbl = newiTempLabel (NULL);
6228           if (IC_TRUE (ifx))
6229             {
6230               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6231               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6232             }
6233           else
6234             {
6235               emitcode ("jc", "!tlabel", tlbl->key + 100);
6236               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6237             }
6238           emitcode ("", "!tlabeldef", tlbl->key + 100);
6239         }
6240       else
6241         {
6242           tlbl = newiTempLabel (NULL);
6243           gencjneshort (left, right, tlbl);
6244           if (IC_TRUE (ifx))
6245             {
6246               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6247               emitcode ("", "!tlabeldef", tlbl->key + 100);
6248             }
6249           else
6250             {
6251               symbol *lbl = newiTempLabel (NULL);
6252               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6253               emitcode ("", "!tlabeldef", tlbl->key + 100);
6254               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6255               emitcode ("", "!tlabeldef", lbl->key + 100);
6256             }
6257         }
6258       /* mark the icode as generated */
6259       ifx->generated = 1;
6260
6261       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6262       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6263       return;
6264     }
6265
6266   /* if they are both bit variables */
6267   if (AOP_TYPE (left) == AOP_CRY &&
6268       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6269     {
6270       if (AOP_TYPE (right) == AOP_LIT)
6271         {
6272           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6273           if (lit == 0L)
6274             {
6275               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6276               emitcode ("cpl", "c");
6277             }
6278           else if (lit == 1L)
6279             {
6280               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6281             }
6282           else
6283             {
6284               emitcode ("clr", "c");
6285             }
6286           /* AOP_TYPE(right) == AOP_CRY */
6287         }
6288       else
6289         {
6290           symbol *lbl = newiTempLabel (NULL);
6291           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6292           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6293           emitcode ("cpl", "c");
6294           emitcode ("", "!tlabeldef", (lbl->key + 100));
6295         }
6296
6297       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6298       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299
6300       aopOp (result, ic, TRUE, FALSE);
6301
6302       /* c = 1 if egal */
6303       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6304         {
6305           outBitC (result);
6306           goto release;
6307         }
6308       if (ifx)
6309         {
6310           genIfxJump (ifx, "c");
6311           goto release;
6312         }
6313       /* if the result is used in an arithmetic operation
6314          then put the result in place */
6315       outBitC (result);
6316     }
6317   else
6318     {
6319       gencjne (left, right, newiTempLabel (NULL));
6320
6321       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323
6324       aopOp (result, ic, TRUE, FALSE);
6325
6326       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6327         {
6328           aopPut (AOP (result), "a", 0);
6329           goto release;
6330         }
6331       if (ifx)
6332         {
6333           genIfxJump (ifx, "a");
6334           goto release;
6335         }
6336       /* if the result is used in an arithmetic operation
6337          then put the result in place */
6338       if (AOP_TYPE (result) != AOP_CRY)
6339         outAcc (result);
6340       /* leave the result in acc */
6341     }
6342
6343 release:
6344   freeAsmop (result, NULL, ic, TRUE);
6345 }
6346
6347 /*-----------------------------------------------------------------*/
6348 /* ifxForOp - returns the icode containing the ifx for operand     */
6349 /*-----------------------------------------------------------------*/
6350 static iCode *
6351 ifxForOp (operand * op, iCode * ic)
6352 {
6353   /* if true symbol then needs to be assigned */
6354   if (IS_TRUE_SYMOP (op))
6355     return NULL;
6356
6357   /* if this has register type condition and
6358      the next instruction is ifx with the same operand
6359      and live to of the operand is upto the ifx only then */
6360   if (ic->next &&
6361       ic->next->op == IFX &&
6362       IC_COND (ic->next)->key == op->key &&
6363       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6364     return ic->next;
6365
6366   return NULL;
6367 }
6368 /*-----------------------------------------------------------------*/
6369 /* hasInc - operand is incremented before any other use            */
6370 /*-----------------------------------------------------------------*/
6371 static iCode *
6372 hasInc (operand *op, iCode *ic, int osize)
6373 {
6374   sym_link *type = operandType(op);
6375   sym_link *retype = getSpec (type);
6376   iCode *lic = ic->next;
6377   int isize ;
6378   
6379   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6380   if (!IS_SYMOP(op)) return NULL;
6381
6382   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6383   if (IS_AGGREGATE(type->next)) return NULL;
6384   if (osize != (isize = getSize(type->next))) return NULL;
6385
6386   while (lic) {
6387       /* if operand of the form op = op + <sizeof *op> */
6388       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6389           isOperandEqual(IC_RESULT(lic),op) && 
6390           isOperandLiteral(IC_RIGHT(lic)) &&
6391           operandLitValue(IC_RIGHT(lic)) == isize) {
6392           return lic;
6393       }
6394       /* if the operand used or deffed */
6395       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6396           return NULL;
6397       }
6398       /* if GOTO or IFX */
6399       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6400       lic = lic->next;
6401   }
6402   return NULL;
6403 }
6404
6405 /*-----------------------------------------------------------------*/
6406 /* genAndOp - for && operation                                     */
6407 /*-----------------------------------------------------------------*/
6408 static void
6409 genAndOp (iCode * ic)
6410 {
6411   operand *left, *right, *result;
6412   symbol *tlbl;
6413
6414   D (emitcode (";", "genAndOp "););
6415
6416   /* note here that && operations that are in an
6417      if statement are taken away by backPatchLabels
6418      only those used in arthmetic operations remain */
6419   AOP_OP_2 (ic);
6420   AOP_SET_LOCALS (ic);
6421
6422   /* if both are bit variables */
6423   if (AOP_TYPE (left) == AOP_CRY &&
6424       AOP_TYPE (right) == AOP_CRY)
6425     {
6426       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6427       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6428       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6429       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6430   
6431       aopOp (result,ic,FALSE, FALSE);
6432       outBitC (result);
6433     }
6434   else
6435     {
6436       tlbl = newiTempLabel (NULL);
6437       toBoolean (left);
6438       emitcode ("jz", "!tlabel", tlbl->key + 100);
6439       toBoolean (right);
6440       emitcode ("", "!tlabeldef", tlbl->key + 100);
6441       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6442       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443   
6444       aopOp (result,ic,FALSE, FALSE);
6445       outBitAcc (result);
6446     }
6447     freeAsmop (result, NULL, ic, TRUE);
6448 }
6449
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genOrOp - for || operation                                      */
6453 /*-----------------------------------------------------------------*/
6454 static void
6455 genOrOp (iCode * ic)
6456 {
6457   operand *left, *right, *result;
6458   symbol *tlbl;
6459
6460   D (emitcode (";", "genOrOp "););
6461
6462   /* note here that || operations that are in an
6463      if statement are taken away by backPatchLabels
6464      only those used in arthmetic operations remain */
6465   AOP_OP_2 (ic);
6466   AOP_SET_LOCALS (ic);
6467
6468   /* if both are bit variables */
6469   if (AOP_TYPE (left) == AOP_CRY &&
6470       AOP_TYPE (right) == AOP_CRY)
6471     {
6472       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6473       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6474       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6476   
6477       aopOp (result,ic,FALSE, FALSE);
6478       
6479       outBitC (result);
6480     }
6481   else
6482     {
6483       tlbl = newiTempLabel (NULL);
6484       toBoolean (left);
6485       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6486       toBoolean (right);
6487       emitcode ("", "!tlabeldef", tlbl->key + 100);
6488       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490   
6491       aopOp (result,ic,FALSE, FALSE);
6492       
6493       outBitAcc (result);
6494     }
6495
6496   freeAsmop (result, NULL, ic, TRUE);
6497 }
6498
6499 /*-----------------------------------------------------------------*/
6500 /* isLiteralBit - test if lit == 2^n                               */
6501 /*-----------------------------------------------------------------*/
6502 static int
6503 isLiteralBit (unsigned long lit)
6504 {
6505   unsigned long pw[32] =
6506   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6507    0x100L, 0x200L, 0x400L, 0x800L,
6508    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6509    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6510    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6511    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6512    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6513   int idx;
6514
6515   for (idx = 0; idx < 32; idx++)
6516     if (lit == pw[idx])
6517       return idx + 1;
6518   return 0;
6519 }
6520
6521 /*-----------------------------------------------------------------*/
6522 /* continueIfTrue -                                                */
6523 /*-----------------------------------------------------------------*/
6524 static void
6525 continueIfTrue (iCode * ic)
6526 {
6527   if (IC_TRUE (ic))
6528     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6529   ic->generated = 1;
6530 }
6531
6532 /*-----------------------------------------------------------------*/
6533 /* jmpIfTrue -                                                     */
6534 /*-----------------------------------------------------------------*/
6535 static void
6536 jumpIfTrue (iCode * ic)
6537 {
6538   if (!IC_TRUE (ic))
6539     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6540   ic->generated = 1;
6541 }
6542
6543 /*-----------------------------------------------------------------*/
6544 /* jmpTrueOrFalse -                                                */
6545 /*-----------------------------------------------------------------*/
6546 static void
6547 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6548 {
6549   // ugly but optimized by peephole
6550   if (IC_TRUE (ic))
6551     {
6552       symbol *nlbl = newiTempLabel (NULL);
6553       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6554       emitcode ("", "!tlabeldef", tlbl->key + 100);
6555       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6556       emitcode ("", "!tlabeldef", nlbl->key + 100);
6557     }
6558   else
6559     {
6560       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6561       emitcode ("", "!tlabeldef", tlbl->key + 100);
6562     }
6563   ic->generated = 1;
6564 }
6565
6566 // Generate code to perform a bit-wise logic operation
6567 // on two operands in far space (assumed to already have been 
6568 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6569 // in far space. This requires pushing the result on the stack
6570 // then popping it into the result.
6571 static void
6572 genFarFarLogicOp(iCode *ic, char *logicOp)
6573 {
6574       int size, resultSize, compSize;
6575       int offset = 0;
6576       
6577       TR_AP("#5");
6578       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6579       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6580                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6581       
6582       _startLazyDPSEvaluation();
6583       for (size = compSize; (size--); offset++)
6584       {
6585           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6586           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6587           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6588           
6589           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6590           emitcode ("push", "acc");
6591       }
6592       _endLazyDPSEvaluation();
6593      
6594       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6595       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6596       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6597      
6598       resultSize = AOP_SIZE(IC_RESULT(ic));
6599
6600       ADJUST_PUSHED_RESULT(compSize, resultSize);
6601
6602       _startLazyDPSEvaluation();
6603       while (compSize--)
6604       {
6605           emitcode ("pop", "acc");
6606           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6607       }
6608       _endLazyDPSEvaluation();
6609       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6610 }
6611
6612
6613 /*-----------------------------------------------------------------*/
6614 /* genAnd  - code for and                                          */
6615 /*-----------------------------------------------------------------*/
6616 static void
6617 genAnd (iCode * ic, iCode * ifx)
6618 {
6619   operand *left, *right, *result;
6620   int size, offset = 0;
6621   unsigned long lit = 0L;
6622   int bytelit;
6623   char buff[10];
6624   bool pushResult;
6625
6626   D (emitcode (";", "genAnd "););
6627
6628   AOP_OP_3_NOFATAL (ic, pushResult);
6629   AOP_SET_LOCALS (ic);
6630
6631   if (pushResult)
6632   {
6633       genFarFarLogicOp(ic, "anl");
6634       return;
6635   }  
6636
6637 #ifdef DEBUG_TYPE
6638   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6639             AOP_TYPE (result),
6640             AOP_TYPE (left), AOP_TYPE (right));
6641   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6642             AOP_SIZE (result),
6643             AOP_SIZE (left), AOP_SIZE (right));
6644 #endif
6645
6646   /* if left is a literal & right is not then exchange them */
6647   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6648 #ifdef LOGIC_OPS_BROKEN      
6649     ||  AOP_NEEDSACC (left)
6650 #endif
6651     )
6652     {
6653       operand *tmp = right;
6654       right = left;
6655       left = tmp;
6656     }
6657
6658   /* if result = right then exchange them */
6659   if (sameRegs (AOP (result), AOP (right)))
6660     {
6661       operand *tmp = right;
6662       right = left;
6663       left = tmp;
6664     }
6665
6666   /* if right is bit then exchange them */
6667   if (AOP_TYPE (right) == AOP_CRY &&
6668       AOP_TYPE (left) != AOP_CRY)
6669     {
6670       operand *tmp = right;
6671       right = left;
6672       left = tmp;
6673     }
6674   if (AOP_TYPE (right) == AOP_LIT)
6675     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6676
6677   size = AOP_SIZE (result);
6678
6679   // if(bit & yy)
6680   // result = bit & yy;
6681   if (AOP_TYPE (left) == AOP_CRY)
6682     {
6683       // c = bit & literal;
6684       if (AOP_TYPE (right) == AOP_LIT)
6685         {
6686           if (lit & 1)
6687             {
6688               if (size && sameRegs (AOP (result), AOP (left)))
6689                 // no change
6690                 goto release;
6691               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6692             }
6693           else
6694             {
6695               // bit(result) = 0;
6696               if (size && (AOP_TYPE (result) == AOP_CRY))
6697                 {
6698                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6699                   goto release;
6700                 }
6701               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6702                 {
6703                   jumpIfTrue (ifx);
6704                   goto release;
6705                 }
6706               emitcode ("clr", "c");
6707             }
6708         }
6709       else
6710         {
6711           if (AOP_TYPE (right) == AOP_CRY)
6712             {
6713               // c = bit & bit;
6714               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6715               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6716             }
6717           else
6718             {
6719               // c = bit & val;
6720               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6721               // c = lsb
6722               emitcode ("rrc", "a");
6723               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6724             }
6725         }
6726       // bit = c
6727       // val = c
6728       if (size)
6729         outBitC (result);
6730       // if(bit & ...)
6731       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6732         genIfxJump (ifx, "c");
6733       goto release;
6734     }
6735
6736   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6737   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6738   if ((AOP_TYPE (right) == AOP_LIT) &&
6739       (AOP_TYPE (result) == AOP_CRY) &&
6740       (AOP_TYPE (left) != AOP_CRY))
6741     {
6742       int posbit = isLiteralBit (lit);
6743       /* left &  2^n */
6744       if (posbit)
6745         {
6746           posbit--;
6747           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6748           // bit = left & 2^n
6749           if (size)
6750             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6751           // if(left &  2^n)
6752           else
6753             {
6754               if (ifx)
6755                 {
6756                   SNPRINTF (buff, sizeof(buff), 
6757                             "acc.%d", posbit & 0x07);
6758                   genIfxJump (ifx, buff);
6759                 }
6760               else 
6761                   {
6762                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6763                   }
6764               goto release;
6765             }
6766         }
6767       else
6768         {
6769           symbol *tlbl = newiTempLabel (NULL);
6770           int sizel = AOP_SIZE (left);
6771           if (size)
6772             emitcode ("setb", "c");
6773           while (sizel--)
6774             {
6775               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6776                 {
6777                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6778                   // byte ==  2^n ?
6779                   if ((posbit = isLiteralBit (bytelit)) != 0)
6780                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6781                   else
6782                     {
6783                       if (bytelit != 0x0FFL)
6784                         emitcode ("anl", "a,%s",
6785                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6786                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6787                     }
6788                 }
6789               offset++;
6790             }
6791           // bit = left & literal
6792           if (size)
6793             {
6794               emitcode ("clr", "c");
6795               emitcode ("", "!tlabeldef", tlbl->key + 100);
6796             }
6797           // if(left & literal)
6798           else
6799             {
6800               if (ifx)
6801                 jmpTrueOrFalse (ifx, tlbl);
6802               else
6803                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6804               goto release;
6805             }
6806         }
6807       outBitC (result);
6808       goto release;
6809     }
6810
6811   /* if left is same as result */
6812   if (sameRegs (AOP (result), AOP (left)))
6813     {
6814       for (; size--; offset++)
6815         {
6816           if (AOP_TYPE (right) == AOP_LIT)
6817             {
6818               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6819                 continue;
6820               else if (bytelit == 0)
6821                 aopPut (AOP (result), zero, offset);
6822               else if (IS_AOP_PREG (result))
6823                 {
6824                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6825                   emitcode ("anl", "a,%s",
6826                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6827                   aopPut (AOP (result), "a", offset);
6828                 }
6829               else
6830                 emitcode ("anl", "%s,%s",
6831                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6832                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6833             }
6834           else
6835             {
6836               if (AOP_TYPE (left) == AOP_ACC)
6837                 emitcode ("anl", "a,%s",
6838                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6839               else
6840                 {
6841                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6842                   if (IS_AOP_PREG (result))
6843                     {
6844                       emitcode ("anl", "a,%s",
6845                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6846                       aopPut (AOP (result), "a", offset);
6847                     }
6848                   else
6849                     emitcode ("anl", "%s,a",
6850                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6851                 }
6852             }
6853         }
6854     }
6855   else
6856     {
6857       // left & result in different registers
6858       if (AOP_TYPE (result) == AOP_CRY)
6859         {
6860           // result = bit
6861           // if(size), result in bit
6862           // if(!size && ifx), conditional oper: if(left & right)
6863           symbol *tlbl = newiTempLabel (NULL);
6864           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6865           if (size)
6866             emitcode ("setb", "c");
6867           while (sizer--)
6868             {
6869               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6870                 emitcode ("anl", "a,%s",
6871                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6872               } else {
6873                 if (AOP_TYPE(left)==AOP_ACC) {
6874                   emitcode("mov", "b,a");
6875                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6876                   emitcode("anl", "a,b");
6877                 }else {
6878                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6879                   emitcode ("anl", "a,%s",
6880                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6881                 }
6882               }
6883               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6884               offset++;
6885             }
6886           if (size)
6887             {
6888               CLRC;
6889               emitcode ("", "!tlabeldef", tlbl->key + 100);
6890               outBitC (result);
6891             }
6892           else if (ifx)
6893             jmpTrueOrFalse (ifx, tlbl);
6894           else
6895             emitcode ("", "!tlabeldef", tlbl->key + 100);
6896         }
6897       else
6898         {
6899           for (; (size--); offset++)
6900             {
6901               // normal case
6902               // result = left & right
6903               if (AOP_TYPE (right) == AOP_LIT)
6904                 {
6905                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6906                     {
6907                       aopPut (AOP (result),
6908                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6909                               offset);
6910                       continue;
6911                     }
6912                   else if (bytelit == 0)
6913                     {
6914                       aopPut (AOP (result), zero, offset);
6915                       continue;
6916                     }
6917                   D (emitcode (";", "better literal AND."););
6918                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6919                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6920                                                     FALSE, FALSE, DP2_RESULT_REG));
6921
6922                 }
6923               else
6924                 {
6925                   // faster than result <- left, anl result,right
6926                   // and better if result is SFR
6927                   if (AOP_TYPE (left) == AOP_ACC)
6928                     {
6929                       emitcode ("anl", "a,%s", 
6930                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6931                     }
6932                   else
6933                     {
6934                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6935                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6936                       {
6937                           emitcode("mov", "b,a");
6938                           rOp = "b";
6939                       }
6940                         
6941                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6942                       emitcode ("anl", "a,%s", rOp);
6943                     }                   
6944                 }
6945               aopPut (AOP (result), "a", offset);
6946             }
6947         }
6948     }
6949
6950 release:
6951   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6952   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6953   freeAsmop (result, NULL, ic, TRUE);
6954 }
6955
6956
6957 /*-----------------------------------------------------------------*/
6958 /* genOr  - code for or                                            */
6959 /*-----------------------------------------------------------------*/
6960 static void
6961 genOr (iCode * ic, iCode * ifx)
6962 {
6963   operand *left, *right, *result;
6964   int size, offset = 0;
6965   unsigned long lit = 0L;
6966   bool     pushResult;
6967
6968   D (emitcode (";", "genOr "););
6969
6970   AOP_OP_3_NOFATAL (ic, pushResult);
6971   AOP_SET_LOCALS (ic);
6972
6973   if (pushResult)
6974   {
6975       genFarFarLogicOp(ic, "orl");
6976       return;
6977   }
6978
6979
6980 #ifdef DEBUG_TYPE
6981   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6982             AOP_TYPE (result),
6983             AOP_TYPE (left), AOP_TYPE (right));
6984   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6985             AOP_SIZE (result),
6986             AOP_SIZE (left), AOP_SIZE (right));
6987 #endif
6988
6989   /* if left is a literal & right is not then exchange them */
6990   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6991 #ifdef LOGIC_OPS_BROKEN
6992    || AOP_NEEDSACC (left) // I think this is a net loss now.
6993 #endif      
6994       )
6995     {
6996       operand *tmp = right;
6997       right = left;
6998       left = tmp;
6999     }
7000
7001   /* if result = right then exchange them */
7002   if (sameRegs (AOP (result), AOP (right)))
7003     {
7004       operand *tmp = right;
7005       right = left;
7006       left = tmp;
7007     }
7008
7009   /* if right is bit then exchange them */
7010   if (AOP_TYPE (right) == AOP_CRY &&
7011       AOP_TYPE (left) != AOP_CRY)
7012     {
7013       operand *tmp = right;
7014       right = left;
7015       left = tmp;
7016     }
7017   if (AOP_TYPE (right) == AOP_LIT)
7018     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7019
7020   size = AOP_SIZE (result);
7021
7022   // if(bit | yy)
7023   // xx = bit | yy;
7024   if (AOP_TYPE (left) == AOP_CRY)
7025     {
7026       if (AOP_TYPE (right) == AOP_LIT)
7027         {
7028           // c = bit & literal;
7029           if (lit)
7030             {
7031               // lit != 0 => result = 1
7032               if (AOP_TYPE (result) == AOP_CRY)
7033                 {
7034                   if (size)
7035                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7036                   else if (ifx)
7037                     continueIfTrue (ifx);
7038                   goto release;
7039                 }
7040               emitcode ("setb", "c");
7041             }
7042           else
7043             {
7044               // lit == 0 => result = left
7045               if (size && sameRegs (AOP (result), AOP (left)))
7046                 goto release;
7047               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7048             }
7049         }
7050       else
7051         {
7052           if (AOP_TYPE (right) == AOP_CRY)
7053             {
7054               // c = bit | bit;
7055               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7056               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7057             }
7058           else
7059             {
7060               // c = bit | val;
7061               symbol *tlbl = newiTempLabel (NULL);
7062               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7063                 emitcode ("setb", "c");
7064               emitcode ("jb", "%s,!tlabel",
7065                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7066               toBoolean (right);
7067               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7068               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7069                 {
7070                   jmpTrueOrFalse (ifx, tlbl);
7071                   goto release;
7072                 }
7073               else
7074                 {
7075                   CLRC;
7076                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7077                 }
7078             }
7079         }
7080       // bit = c
7081       // val = c
7082       if (size)
7083         outBitC (result);
7084       // if(bit | ...)
7085       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7086            genIfxJump (ifx, "c");
7087       goto release;
7088     }
7089
7090   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7091   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7092   if ((AOP_TYPE (right) == AOP_LIT) &&
7093       (AOP_TYPE (result) == AOP_CRY) &&
7094       (AOP_TYPE (left) != AOP_CRY))
7095     {
7096       if (lit)
7097         {
7098           // result = 1
7099           if (size)
7100             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7101           else
7102             continueIfTrue (ifx);
7103           goto release;
7104         }
7105       else
7106         {
7107           // lit = 0, result = boolean(left)
7108           if (size)
7109             emitcode ("setb", "c");
7110           toBoolean (right);
7111           if (size)
7112             {
7113               symbol *tlbl = newiTempLabel (NULL);
7114               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7115               CLRC;
7116               emitcode ("", "!tlabeldef", tlbl->key + 100);
7117             }
7118           else
7119             {
7120               genIfxJump (ifx, "a");
7121               goto release;
7122             }
7123         }
7124       outBitC (result);
7125       goto release;
7126     }
7127
7128   /* if left is same as result */
7129   if (sameRegs (AOP (result), AOP (left)))
7130     {
7131       for (; size--; offset++)
7132         {
7133           if (AOP_TYPE (right) == AOP_LIT)
7134             {
7135               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7136                 {
7137                   continue;
7138                 }
7139               else
7140                 {
7141                   if (IS_AOP_PREG (left))
7142                     {
7143                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7144                       emitcode ("orl", "a,%s",
7145                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7146                       aopPut (AOP (result), "a", offset);
7147                     }
7148                   else
7149                     {
7150                       emitcode ("orl", "%s,%s",
7151                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7152                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7153                     }
7154                 }
7155             }
7156           else
7157             {
7158               if (AOP_TYPE (left) == AOP_ACC)
7159                 {
7160                   emitcode ("orl", "a,%s",
7161                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7162                 }
7163               else
7164                 {
7165                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7166                   if (IS_AOP_PREG (left))
7167                     {
7168                       emitcode ("orl", "a,%s", 
7169                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7170                       aopPut (AOP (result), "a", offset);
7171                     }
7172                   else
7173                     {
7174                       emitcode ("orl", "%s,a",
7175                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7176                     }
7177                 }
7178             }
7179         }
7180     }
7181   else
7182     {
7183       // left & result in different registers
7184       if (AOP_TYPE (result) == AOP_CRY)
7185         {
7186           // result = bit
7187           // if(size), result in bit
7188           // if(!size && ifx), conditional oper: if(left | right)
7189           symbol *tlbl = newiTempLabel (NULL);
7190           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7191           if (size)
7192             emitcode ("setb", "c");
7193           while (sizer--)
7194             {
7195               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7196                 emitcode ("orl", "a,%s",
7197                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7198               } else {
7199                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7200                 emitcode ("orl", "a,%s",
7201                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7202               }
7203               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7204               offset++;
7205             }
7206           if (size)
7207             {
7208               CLRC;
7209               emitcode ("", "!tlabeldef", tlbl->key + 100);
7210               outBitC (result);
7211             }
7212           else if (ifx)
7213             jmpTrueOrFalse (ifx, tlbl);
7214           else
7215             emitcode ("", "!tlabeldef", tlbl->key + 100);
7216         }
7217       else
7218         {
7219             _startLazyDPSEvaluation();
7220           for (; (size--); offset++)
7221             {
7222               // normal case
7223               // result = left & right
7224               if (AOP_TYPE (right) == AOP_LIT)
7225                 {
7226                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7227                     {
7228                       aopPut (AOP (result),
7229                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7230                               offset);
7231                       continue;
7232                     }
7233                   D (emitcode (";", "better literal OR."););
7234                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7235                   emitcode ("orl", "a, %s",
7236                             aopGet (AOP (right), offset,
7237                                     FALSE, FALSE, DP2_RESULT_REG));
7238
7239                 }
7240               else
7241                 {
7242                   // faster than result <- left, anl result,right
7243                   // and better if result is SFR
7244                   if (AOP_TYPE (left) == AOP_ACC)
7245                     {
7246                       emitcode ("orl", "a,%s",
7247                                 aopGet (AOP (right), offset,
7248                                         FALSE, FALSE, DP2_RESULT_REG));
7249                     }
7250                   else
7251                     {
7252                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7253                         
7254                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7255                       {
7256                           emitcode("mov", "b,a");
7257                           rOp = "b";
7258                       }
7259                         
7260                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7261                       emitcode ("orl", "a,%s", rOp);
7262                     }
7263                 }
7264               aopPut (AOP (result), "a", offset);
7265             }
7266             _endLazyDPSEvaluation();
7267         }
7268     }
7269
7270 release:
7271   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7272   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7273   freeAsmop (result, NULL, ic, TRUE);
7274 }
7275
7276 /*-----------------------------------------------------------------*/
7277 /* genXor - code for xclusive or                                   */
7278 /*-----------------------------------------------------------------*/
7279 static void
7280 genXor (iCode * ic, iCode * ifx)
7281 {
7282   operand *left, *right, *result;
7283   int size, offset = 0;
7284   unsigned long lit = 0L;
7285   bool pushResult;
7286
7287   D (emitcode (";", "genXor "););
7288
7289   AOP_OP_3_NOFATAL (ic, pushResult);
7290   AOP_SET_LOCALS (ic);
7291
7292   if (pushResult)
7293   {
7294       genFarFarLogicOp(ic, "xrl");
7295       return;
7296   }  
7297
7298 #ifdef DEBUG_TYPE
7299   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7300             AOP_TYPE (result),
7301             AOP_TYPE (left), AOP_TYPE (right));
7302   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7303             AOP_SIZE (result),
7304             AOP_SIZE (left), AOP_SIZE (right));
7305 #endif
7306
7307   /* if left is a literal & right is not ||
7308      if left needs acc & right does not */
7309   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
7310 #ifdef LOGIC_OPS_BROKEN      
7311       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7312 #endif
7313      )
7314     {
7315       operand *tmp = right;
7316       right = left;
7317       left = tmp;
7318     }
7319
7320   /* if result = right then exchange them */
7321   if (sameRegs (AOP (result), AOP (right)))
7322     {
7323       operand *tmp = right;
7324       right = left;
7325       left = tmp;
7326     }
7327
7328   /* if right is bit then exchange them */
7329   if (AOP_TYPE (right) == AOP_CRY &&
7330       AOP_TYPE (left) != AOP_CRY)
7331     {
7332       operand *tmp = right;
7333       right = left;
7334       left = tmp;
7335     }
7336   if (AOP_TYPE (right) == AOP_LIT)
7337     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7338
7339   size = AOP_SIZE (result);
7340
7341   // if(bit ^ yy)
7342   // xx = bit ^ yy;
7343   if (AOP_TYPE (left) == AOP_CRY)
7344     {
7345       if (AOP_TYPE (right) == AOP_LIT)
7346         {
7347           // c = bit & literal;
7348           if (lit >> 1)
7349             {
7350               // lit>>1  != 0 => result = 1
7351               if (AOP_TYPE (result) == AOP_CRY)
7352                 {
7353                   if (size)
7354                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7355                   else if (ifx)
7356                     continueIfTrue (ifx);
7357                   goto release;
7358                 }
7359               emitcode ("setb", "c");
7360             }
7361           else
7362             {
7363               // lit == (0 or 1)
7364               if (lit == 0)
7365                 {
7366                   // lit == 0, result = left
7367                   if (size && sameRegs (AOP (result), AOP (left)))
7368                     goto release;
7369                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7370                 }
7371               else
7372                 {
7373                   // lit == 1, result = not(left)
7374                   if (size && sameRegs (AOP (result), AOP (left)))
7375                     {
7376                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7377                       goto release;
7378                     }
7379                   else
7380                     {
7381                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7382                       emitcode ("cpl", "c");
7383                     }
7384                 }
7385             }
7386
7387         }
7388       else
7389         {
7390           // right != literal
7391           symbol *tlbl = newiTempLabel (NULL);
7392           if (AOP_TYPE (right) == AOP_CRY)
7393             {
7394               // c = bit ^ bit;
7395               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7396             }
7397           else
7398             {
7399               int sizer = AOP_SIZE (right);
7400               // c = bit ^ val
7401               // if val>>1 != 0, result = 1
7402               emitcode ("setb", "c");
7403               while (sizer)
7404                 {
7405                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7406                   if (sizer == 1)
7407                     // test the msb of the lsb
7408                     emitcode ("anl", "a,#!constbyte",0xfe);
7409                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7410                   sizer--;
7411                 }
7412               // val = (0,1)
7413               emitcode ("rrc", "a");
7414             }
7415           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7416           emitcode ("cpl", "c");
7417           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7418         }
7419       // bit = c
7420       // val = c
7421       if (size)
7422         outBitC (result);
7423       // if(bit | ...)
7424       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7425         genIfxJump (ifx, "c");
7426       goto release;
7427     }
7428
7429   if (sameRegs (AOP (result), AOP (left)))
7430     {
7431       /* if left is same as result */
7432       for (; size--; offset++)
7433         {
7434           if (AOP_TYPE (right) == AOP_LIT)
7435             {
7436               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7437                 continue;
7438               else if (IS_AOP_PREG (left))
7439                 {
7440                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7441                   emitcode ("xrl", "a,%s",
7442                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7443                   aopPut (AOP (result), "a", offset);
7444                 }
7445               else
7446                 emitcode ("xrl", "%s,%s",
7447                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7448                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7449             }
7450           else
7451             {
7452               if (AOP_TYPE (left) == AOP_ACC)
7453                 emitcode ("xrl", "a,%s",
7454                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7455               else
7456                 {
7457                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7458                   if (IS_AOP_PREG (left))
7459                     {
7460                       emitcode ("xrl", "a,%s",
7461                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7462                       aopPut (AOP (result), "a", offset);
7463                     }
7464                   else
7465                     emitcode ("xrl", "%s,a",
7466                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7467                 }
7468             }
7469         }
7470     }
7471   else
7472     {
7473       // left & result in different registers
7474       if (AOP_TYPE (result) == AOP_CRY)
7475         {
7476           // result = bit
7477           // if(size), result in bit
7478           // if(!size && ifx), conditional oper: if(left ^ right)
7479           symbol *tlbl = newiTempLabel (NULL);
7480           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7481                   
7482           if (size)
7483             emitcode ("setb", "c");
7484           while (sizer--)
7485             {
7486               if ((AOP_TYPE (right) == AOP_LIT) &&
7487                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7488                 {
7489                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7490                 }
7491               else
7492                 {
7493                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7494                     emitcode ("xrl", "a,%s",
7495                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7496                   } else {
7497                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7498                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7499                       {
7500                           emitcode("mov", "b,a");
7501                           rOp = "b";
7502                       }
7503                         
7504                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7505                       emitcode ("xrl", "a,%s", rOp);                  
7506                   }
7507                 }
7508               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7509               offset++;
7510             }
7511           if (size)
7512             {
7513               CLRC;
7514               emitcode ("", "!tlabeldef", tlbl->key + 100);
7515               outBitC (result);
7516             }
7517           else if (ifx)
7518             jmpTrueOrFalse (ifx, tlbl);
7519         }
7520       else
7521         {
7522         for (; (size--); offset++)
7523           {
7524             // normal case
7525             // result = left & right
7526             if (AOP_TYPE (right) == AOP_LIT)
7527               {
7528                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7529                   {
7530                     aopPut (AOP (result),
7531                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7532                             offset);
7533                     continue;
7534                   }
7535                 D (emitcode (";", "better literal XOR."););
7536                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7537                 emitcode ("xrl", "a, %s",
7538                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7539               }
7540             else
7541               {
7542                 // faster than result <- left, anl result,right
7543                 // and better if result is SFR
7544                 if (AOP_TYPE (left) == AOP_ACC)
7545                   {
7546                     emitcode ("xrl", "a,%s",
7547                               aopGet (AOP (right), offset,
7548                                       FALSE, FALSE, DP2_RESULT_REG));
7549                   }
7550                 else
7551                   {
7552                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7553                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7554                       {
7555                           emitcode("mov", "b,a");
7556                           rOp = "b";
7557                       }
7558                         
7559                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7560                       emitcode ("xrl", "a,%s", rOp);
7561                   }
7562               }
7563             aopPut (AOP (result), "a", offset);
7564           }
7565         }
7566         
7567     }
7568
7569 release:
7570   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7571   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7572   freeAsmop (result, NULL, ic, TRUE);
7573 }
7574
7575 /*-----------------------------------------------------------------*/
7576 /* genInline - write the inline code out                           */
7577 /*-----------------------------------------------------------------*/
7578 static void
7579 genInline (iCode * ic)
7580 {
7581   char *buffer, *bp, *bp1;
7582
7583   D (emitcode (";", "genInline "); );
7584
7585   _G.inLine += (!options.asmpeep);
7586
7587   buffer = Safe_strdup(IC_INLINE(ic));
7588   bp = buffer;
7589   bp1 = buffer;
7590
7591   /* emit each line as a code */
7592   while (*bp)
7593     {
7594       if (*bp == '\n')
7595         {
7596           *bp++ = '\0';
7597           emitcode (bp1, "");
7598           bp1 = bp;
7599         }
7600       else
7601         {
7602           if (*bp == ':')
7603             {
7604               bp++;
7605               *bp = '\0';
7606               bp++;
7607               emitcode (bp1, "");
7608               bp1 = bp;
7609             }
7610           else
7611             bp++;
7612         }
7613     }
7614   if (bp1 != bp)
7615     emitcode (bp1, "");
7616   /*     emitcode("",buffer); */
7617   _G.inLine -= (!options.asmpeep);
7618 }
7619
7620 /*-----------------------------------------------------------------*/
7621 /* genRRC - rotate right with carry                                */
7622 /*-----------------------------------------------------------------*/
7623 static void
7624 genRRC (iCode * ic)
7625 {
7626   operand *left, *result;
7627   int     size, offset;
7628
7629   D (emitcode (";", "genRRC "););
7630
7631   /* rotate right with carry */
7632   left = IC_LEFT (ic);
7633   result = IC_RESULT (ic);
7634   aopOp (left, ic, FALSE, FALSE);
7635   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7636
7637   /* move it to the result */
7638   size = AOP_SIZE (result);
7639   offset = size - 1;
7640   CLRC;
7641
7642   _startLazyDPSEvaluation ();
7643   while (size--)
7644     {
7645       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7646       emitcode ("rrc", "a");
7647       if (AOP_SIZE (result) > 1)
7648         aopPut (AOP (result), "a", offset--);
7649     }
7650   _endLazyDPSEvaluation ();
7651
7652   /* now we need to put the carry into the
7653      highest order byte of the result */
7654   if (AOP_SIZE (result) > 1)
7655     {
7656       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7657     }
7658   emitcode ("mov", "acc.7,c");
7659   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7660   freeAsmop (left, NULL, ic, TRUE);
7661   freeAsmop (result, NULL, ic, TRUE);
7662 }
7663
7664 /*-----------------------------------------------------------------*/
7665 /* genRLC - generate code for rotate left with carry               */
7666 /*-----------------------------------------------------------------*/
7667 static void
7668 genRLC (iCode * ic)
7669 {
7670   operand *left, *result;
7671   int size, offset;
7672   char *l;
7673
7674   D (emitcode (";", "genRLC "););
7675
7676   /* rotate right with carry */
7677   left = IC_LEFT (ic);
7678   result = IC_RESULT (ic);
7679   aopOp (left, ic, FALSE, FALSE);
7680   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7681
7682   /* move it to the result */
7683   size = AOP_SIZE (result);
7684   offset = 0;
7685   if (size--)
7686     {
7687       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7688       MOVA (l);
7689       emitcode ("add", "a,acc");
7690       if (AOP_SIZE (result) > 1)
7691         {
7692           aopPut (AOP (result), "a", offset++);
7693         }
7694
7695       _startLazyDPSEvaluation ();
7696       while (size--)
7697         {
7698           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7699           MOVA (l);
7700           emitcode ("rlc", "a");
7701           if (AOP_SIZE (result) > 1)
7702             aopPut (AOP (result), "a", offset++);
7703         }
7704       _endLazyDPSEvaluation ();
7705     }
7706   /* now we need to put the carry into the
7707      highest order byte of the result */
7708   if (AOP_SIZE (result) > 1)
7709     {
7710       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7711       MOVA (l);
7712     }
7713   emitcode ("mov", "acc.0,c");
7714   aopPut (AOP (result), "a", 0);
7715   freeAsmop (left, NULL, ic, TRUE);
7716   freeAsmop (result, NULL, ic, TRUE);
7717 }
7718
7719 /*-----------------------------------------------------------------*/
7720 /* genGetHbit - generates code get highest order bit               */
7721 /*-----------------------------------------------------------------*/
7722 static void
7723 genGetHbit (iCode * ic)
7724 {
7725   operand *left, *result;
7726   left = IC_LEFT (ic);
7727   result = IC_RESULT (ic);
7728   aopOp (left, ic, FALSE, FALSE);
7729   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7730
7731   D (emitcode (";", "genGetHbit "););
7732
7733   /* get the highest order byte into a */
7734   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7735   if (AOP_TYPE (result) == AOP_CRY)
7736     {
7737       emitcode ("rlc", "a");
7738       outBitC (result);
7739     }
7740   else
7741     {
7742       emitcode ("rl", "a");
7743       emitcode ("anl", "a,#1");
7744       outAcc (result);
7745     }
7746
7747
7748   freeAsmop (left, NULL, ic, TRUE);
7749   freeAsmop (result, NULL, ic, TRUE);
7750 }
7751
7752 /*-----------------------------------------------------------------*/
7753 /* genSwap - generates code to swap nibbles or bytes               */
7754 /*-----------------------------------------------------------------*/
7755 static void
7756 genSwap (iCode * ic)
7757 {
7758   operand *left, *result;
7759
7760   D(emitcode (";     genSwap",""));
7761
7762   left = IC_LEFT (ic);
7763   result = IC_RESULT (ic);
7764   aopOp (left, ic, FALSE, FALSE);
7765   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7766   
7767   _startLazyDPSEvaluation ();
7768   switch (AOP_SIZE (left))
7769     {
7770     case 1: /* swap nibbles in byte */
7771       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7772       emitcode ("swap", "a");
7773       aopPut (AOP (result), "a", 0);
7774       break;
7775     case 2: /* swap bytes in word */
7776       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7777         {
7778           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7779           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7780           aopPut (AOP (result), "a", 1);
7781         }
7782       else if (operandsEqu (left, result))
7783         {
7784           char * reg = "a";
7785           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7786           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7787             {
7788               emitcode ("mov", "b,a");
7789               reg = "b";
7790               _G.bInUse=1;
7791             }
7792           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7793           aopPut (AOP (result), reg, 1);
7794           _G.bInUse=0;
7795         }
7796       else
7797         {
7798           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7799           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7800         }
7801       break;
7802     default:
7803       wassertl(FALSE, "unsupported SWAP operand size");
7804     }
7805   _endLazyDPSEvaluation ();
7806   
7807   freeAsmop (left, NULL, ic, TRUE);
7808   freeAsmop (result, NULL, ic, TRUE);
7809 }
7810
7811 /*-----------------------------------------------------------------*/
7812 /* AccRol - rotate left accumulator by known count                 */
7813 /*-----------------------------------------------------------------*/
7814 static void
7815 AccRol (int shCount)
7816 {
7817   shCount &= 0x0007;            // shCount : 0..7
7818
7819   switch (shCount)
7820     {
7821     case 0:
7822       break;
7823     case 1:
7824       emitcode ("rl", "a");
7825       break;
7826     case 2:
7827       emitcode ("rl", "a");
7828       emitcode ("rl", "a");
7829       break;
7830     case 3:
7831       emitcode ("swap", "a");
7832       emitcode ("rr", "a");
7833       break;
7834     case 4:
7835       emitcode ("swap", "a");
7836       break;
7837     case 5:
7838       emitcode ("swap", "a");
7839       emitcode ("rl", "a");
7840       break;
7841     case 6:
7842       emitcode ("rr", "a");
7843       emitcode ("rr", "a");
7844       break;
7845     case 7:
7846       emitcode ("rr", "a");
7847       break;
7848     }
7849 }
7850
7851 /*-----------------------------------------------------------------*/
7852 /* AccLsh - left shift accumulator by known count                  */
7853 /*-----------------------------------------------------------------*/
7854 static void
7855 AccLsh (int shCount)
7856 {
7857   if (shCount != 0)
7858     {
7859       if (shCount == 1)
7860         emitcode ("add", "a,acc");
7861       else if (shCount == 2)
7862         {
7863           emitcode ("add", "a,acc");
7864           emitcode ("add", "a,acc");
7865         }
7866       else
7867         {
7868           /* rotate left accumulator */
7869           AccRol (shCount);
7870           /* and kill the lower order bits */
7871           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7872         }
7873     }
7874 }
7875
7876 /*-----------------------------------------------------------------*/
7877 /* AccRsh - right shift accumulator by known count                 */
7878 /*-----------------------------------------------------------------*/
7879 static void
7880 AccRsh (int shCount)
7881 {
7882   if (shCount != 0)
7883     {
7884       if (shCount == 1)
7885         {
7886           CLRC;
7887           emitcode ("rrc", "a");
7888         }
7889       else
7890         {
7891           /* rotate right accumulator */
7892           AccRol (8 - shCount);
7893           /* and kill the higher order bits */
7894           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7895         }
7896     }
7897 }
7898
7899 #ifdef BETTER_LITERAL_SHIFT
7900 /*-----------------------------------------------------------------*/
7901 /* AccSRsh - signed right shift accumulator by known count                 */
7902 /*-----------------------------------------------------------------*/
7903 static void
7904 AccSRsh (int shCount)
7905 {
7906   symbol *tlbl;
7907   if (shCount != 0)
7908     {
7909       if (shCount == 1)
7910         {
7911           emitcode ("mov", "c,acc.7");
7912           emitcode ("rrc", "a");
7913         }
7914       else if (shCount == 2)
7915         {
7916           emitcode ("mov", "c,acc.7");
7917           emitcode ("rrc", "a");
7918           emitcode ("mov", "c,acc.7");
7919           emitcode ("rrc", "a");
7920         }
7921       else
7922         {
7923           tlbl = newiTempLabel (NULL);
7924           /* rotate right accumulator */
7925           AccRol (8 - shCount);
7926           /* and kill the higher order bits */
7927           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7928           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7929           emitcode ("orl", "a,#!constbyte",
7930                     (unsigned char) ~SRMask[shCount]);
7931           emitcode ("", "!tlabeldef", tlbl->key + 100);
7932         }
7933     }
7934 }
7935 #endif
7936
7937 #ifdef BETTER_LITERAL_SHIFT
7938 /*-----------------------------------------------------------------*/
7939 /* shiftR1Left2Result - shift right one byte from left to result   */
7940 /*-----------------------------------------------------------------*/
7941 static void
7942 shiftR1Left2Result (operand * left, int offl,
7943                     operand * result, int offr,
7944                     int shCount, int sign)
7945 {
7946   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7947   /* shift right accumulator */
7948   if (sign)
7949     AccSRsh (shCount);
7950   else
7951     AccRsh (shCount);
7952   aopPut (AOP (result), "a", offr);
7953 }
7954 #endif
7955
7956 #ifdef BETTER_LITERAL_SHIFT
7957 /*-----------------------------------------------------------------*/
7958 /* shiftL1Left2Result - shift left one byte from left to result    */
7959 /*-----------------------------------------------------------------*/
7960 static void
7961 shiftL1Left2Result (operand * left, int offl,
7962                     operand * result, int offr, int shCount)
7963 {
7964   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7965   /* shift left accumulator */
7966   AccLsh (shCount);
7967   aopPut (AOP (result), "a", offr);
7968 }
7969 #endif
7970
7971 #ifdef BETTER_LITERAL_SHIFT
7972 /*-----------------------------------------------------------------*/
7973 /* movLeft2Result - move byte from left to result                  */
7974 /*-----------------------------------------------------------------*/
7975 static void
7976 movLeft2Result (operand * left, int offl,
7977                 operand * result, int offr, int sign)
7978 {
7979   char *l;
7980   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7981   {
7982       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7983
7984       if (*l == '@' && (IS_AOP_PREG (result)))
7985       {
7986           emitcode ("mov", "a,%s", l);
7987           aopPut (AOP (result), "a", offr);
7988       }
7989       else
7990       {
7991           if (!sign)
7992           {
7993             aopPut (AOP (result), l, offr);
7994           }
7995           else
7996             {
7997               /* MSB sign in acc.7 ! */
7998               if (getDataSize (left) == offl + 1)
7999                 {
8000                   emitcode ("mov", "a,%s", l);
8001                   aopPut (AOP (result), "a", offr);
8002                 }
8003             }
8004       }
8005   }
8006 }
8007 #endif
8008
8009 #ifdef BETTER_LITERAL_SHIFT
8010 /*-----------------------------------------------------------------*/
8011 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8012 /*-----------------------------------------------------------------*/
8013 static void
8014 AccAXRrl1 (char *x)
8015 {
8016   emitcode ("rrc", "a");
8017   emitcode ("xch", "a,%s", x);
8018   emitcode ("rrc", "a");
8019   emitcode ("xch", "a,%s", x);
8020 }
8021 #endif
8022
8023 #ifdef BETTER_LITERAL_SHIFT
8024 //REMOVE ME!!!
8025 /*-----------------------------------------------------------------*/
8026 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8027 /*-----------------------------------------------------------------*/
8028 static void
8029 AccAXLrl1 (char *x)
8030 {
8031   emitcode ("xch", "a,%s", x);
8032   emitcode ("rlc", "a");
8033   emitcode ("xch", "a,%s", x);
8034   emitcode ("rlc", "a");
8035 }
8036 #endif
8037
8038 #ifdef BETTER_LITERAL_SHIFT
8039 /*-----------------------------------------------------------------*/
8040 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8041 /*-----------------------------------------------------------------*/
8042 static void
8043 AccAXLsh1 (char *x)
8044 {
8045   emitcode ("xch", "a,%s", x);
8046   emitcode ("add", "a,acc");
8047   emitcode ("xch", "a,%s", x);
8048   emitcode ("rlc", "a");
8049 }
8050 #endif
8051
8052 #ifdef BETTER_LITERAL_SHIFT
8053 /*-----------------------------------------------------------------*/
8054 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8055 /*-----------------------------------------------------------------*/
8056 static void
8057 AccAXLsh (char *x, int shCount)
8058 {
8059   switch (shCount)
8060     {
8061     case 0:
8062       break;
8063     case 1:
8064       AccAXLsh1 (x);
8065       break;
8066     case 2:
8067       AccAXLsh1 (x);
8068       AccAXLsh1 (x);
8069       break;
8070     case 3:
8071     case 4:
8072     case 5:                     // AAAAABBB:CCCCCDDD
8073
8074       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8075
8076       emitcode ("anl", "a,#!constbyte",
8077                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8078
8079       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8080
8081       AccRol (shCount);         // DDDCCCCC:BBB00000
8082
8083       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8084
8085       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8086
8087       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8088
8089       emitcode ("anl", "a,#!constbyte",
8090                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8091
8092       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8093
8094       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8095
8096       break;
8097     case 6:                     // AAAAAABB:CCCCCCDD
8098       emitcode ("anl", "a,#!constbyte",
8099                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8100       emitcode ("mov", "c,acc.0");      // c = B
8101       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8102 #if 0
8103       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8104       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8105 #else
8106       emitcode("rrc","a"); 
8107       emitcode("xch","a,%s", x); 
8108       emitcode("rrc","a"); 
8109       emitcode("mov","c,acc.0"); //<< get correct bit 
8110       emitcode("xch","a,%s", x); 
8111
8112       emitcode("rrc","a"); 
8113       emitcode("xch","a,%s", x); 
8114       emitcode("rrc","a"); 
8115       emitcode("xch","a,%s", x); 
8116 #endif
8117       break;
8118     case 7:                     // a:x <<= 7
8119
8120       emitcode ("anl", "a,#!constbyte",
8121                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8122
8123       emitcode ("mov", "c,acc.0");      // c = B
8124
8125       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8126
8127       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8128
8129       break;
8130     default:
8131       break;
8132     }
8133 }
8134 #endif
8135
8136 #ifdef BETTER_LITERAL_SHIFT
8137 //REMOVE ME!!!
8138 /*-----------------------------------------------------------------*/
8139 /* AccAXRsh - right shift a:x known count (0..7)                   */
8140 /*-----------------------------------------------------------------*/
8141 static void
8142 AccAXRsh (char *x, int shCount)
8143 {
8144   switch (shCount)
8145     {
8146     case 0:
8147       break;
8148     case 1:
8149       CLRC;
8150       AccAXRrl1 (x);            // 0->a:x
8151
8152       break;
8153     case 2:
8154       CLRC;
8155       AccAXRrl1 (x);            // 0->a:x
8156
8157       CLRC;
8158       AccAXRrl1 (x);            // 0->a:x
8159
8160       break;
8161     case 3:
8162     case 4:
8163     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8164
8165       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8166
8167       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8168
8169       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8170
8171       emitcode ("anl", "a,#!constbyte",
8172                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8173
8174       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8175
8176       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8177
8178       emitcode ("anl", "a,#!constbyte",
8179                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8180
8181       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8182
8183       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8184
8185       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8186
8187       break;
8188     case 6:                     // AABBBBBB:CCDDDDDD
8189
8190       emitcode ("mov", "c,acc.7");
8191       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8192
8193       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8194
8195       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8196
8197       emitcode ("anl", "a,#!constbyte",
8198                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8199
8200       break;
8201     case 7:                     // ABBBBBBB:CDDDDDDD
8202
8203       emitcode ("mov", "c,acc.7");      // c = A
8204
8205       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8206
8207       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8208
8209       emitcode ("anl", "a,#!constbyte",
8210                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8211
8212       break;
8213     default:
8214       break;
8215     }
8216 }
8217 #endif
8218
8219 #ifdef BETTER_LITERAL_SHIFT
8220 /*-----------------------------------------------------------------*/
8221 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8222 /*-----------------------------------------------------------------*/
8223 static void
8224 AccAXRshS (char *x, int shCount)
8225 {
8226   symbol *tlbl;
8227   switch (shCount)
8228     {
8229     case 0:
8230       break;
8231     case 1:
8232       emitcode ("mov", "c,acc.7");
8233       AccAXRrl1 (x);            // s->a:x
8234
8235       break;
8236     case 2:
8237       emitcode ("mov", "c,acc.7");
8238       AccAXRrl1 (x);            // s->a:x
8239
8240       emitcode ("mov", "c,acc.7");
8241       AccAXRrl1 (x);            // s->a:x
8242
8243       break;
8244     case 3:
8245     case 4:
8246     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8247
8248       tlbl = newiTempLabel (NULL);
8249       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8250
8251       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8252
8253       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8254
8255       emitcode ("anl", "a,#!constbyte",
8256                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8257
8258       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8259
8260       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8261
8262       emitcode ("anl", "a,#!constbyte",
8263                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8264
8265       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8266
8267       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8268
8269       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8270
8271       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8272       emitcode ("orl", "a,#!constbyte",
8273                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8274
8275       emitcode ("", "!tlabeldef", tlbl->key + 100);
8276       break;                    // SSSSAAAA:BBBCCCCC
8277
8278     case 6:                     // AABBBBBB:CCDDDDDD
8279
8280       tlbl = newiTempLabel (NULL);
8281       emitcode ("mov", "c,acc.7");
8282       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8283
8284       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8285
8286       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8287
8288       emitcode ("anl", "a,#!constbyte",
8289                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8290
8291       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8292       emitcode ("orl", "a,#!constbyte",
8293                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8294
8295       emitcode ("", "!tlabeldef", tlbl->key + 100);
8296       break;
8297     case 7:                     // ABBBBBBB:CDDDDDDD
8298
8299       tlbl = newiTempLabel (NULL);
8300       emitcode ("mov", "c,acc.7");      // c = A
8301
8302       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8303
8304       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8305
8306       emitcode ("anl", "a,#!constbyte",
8307                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8308
8309       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8310       emitcode ("orl", "a,#!constbyte",
8311                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8312
8313       emitcode ("", "!tlabeldef", tlbl->key + 100);
8314       break;
8315     default:
8316       break;
8317     }
8318 }
8319 #endif
8320
8321 #ifdef BETTER_LITERAL_SHIFT
8322 static void
8323 _loadLeftIntoAx(char    **lsb, 
8324                 operand *left, 
8325                 operand *result,
8326                 int     offl,
8327                 int     offr)
8328 {
8329   // Get the initial value from left into a pair of registers.
8330   // MSB must be in A, LSB can be any register.
8331   //
8332   // If the result is held in registers, it is an optimization
8333   // if the LSB can be held in the register which will hold the,
8334   // result LSB since this saves us from having to copy it into
8335   // the result following AccAXLsh.
8336   //
8337   // If the result is addressed indirectly, this is not a gain.
8338   if (AOP_NEEDSACC(result))
8339   {
8340        char *leftByte;
8341        
8342        _startLazyDPSEvaluation();
8343       if (AOP_TYPE(left) == AOP_DPTR2)
8344        {
8345            // Get MSB in A.
8346            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8347            // get LSB in DP2_RESULT_REG.
8348            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8349            assert(!strcmp(leftByte, DP2_RESULT_REG));
8350        }
8351        else
8352        {
8353            // get LSB into DP2_RESULT_REG
8354            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8355            if (strcmp(leftByte, DP2_RESULT_REG))
8356            {
8357                TR_AP("#7");
8358                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8359            }
8360            // And MSB in A.
8361            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8362            assert(strcmp(leftByte, DP2_RESULT_REG));
8363            MOVA(leftByte);
8364        }
8365        _endLazyDPSEvaluation();
8366        *lsb = DP2_RESULT_REG;
8367   }
8368   else
8369   {
8370       if (sameRegs (AOP (result), AOP (left)) &&
8371         ((offl + MSB16) == offr))
8372       {
8373           /* don't crash result[offr] */
8374           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8375           emitcode ("xch", "a,%s", 
8376                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8377       }
8378       else
8379       {
8380           movLeft2Result (left, offl, result, offr, 0);
8381           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8382       }
8383       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8384       assert(strcmp(*lsb,"a"));      
8385   }
8386 }
8387
8388 static void
8389 _storeAxResults(char    *lsb,
8390                 operand *result,
8391                 int     offr)
8392 {
8393   _startLazyDPSEvaluation();
8394   if (AOP_NEEDSACC(result))
8395   {
8396       /* We have to explicitly update the result LSB.
8397        */
8398       emitcode("xch","a,%s", lsb);
8399       aopPut(AOP(result), "a", offr);
8400       emitcode("mov","a,%s", lsb);
8401   }
8402   if (getDataSize (result) > 1)
8403   {
8404       aopPut (AOP (result), "a", offr + MSB16);
8405   }
8406   _endLazyDPSEvaluation();
8407 }
8408
8409 /*-----------------------------------------------------------------*/
8410 /* shiftL2Left2Result - shift left two bytes from left to result   */
8411 /*-----------------------------------------------------------------*/
8412 static void
8413 shiftL2Left2Result (operand * left, int offl,
8414                     operand * result, int offr, int shCount)
8415 {
8416   char *lsb;
8417
8418   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8419   
8420   AccAXLsh (lsb, shCount);
8421   
8422   _storeAxResults(lsb, result, offr);
8423 }
8424 #endif
8425
8426 #ifdef BETTER_LITERAL_SHIFT
8427 /*-----------------------------------------------------------------*/
8428 /* shiftR2Left2Result - shift right two bytes from left to result  */
8429 /*-----------------------------------------------------------------*/
8430 static void
8431 shiftR2Left2Result (operand * left, int offl,
8432                     operand * result, int offr,
8433                     int shCount, int sign)
8434 {
8435   char *lsb;
8436   
8437   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8438   
8439   /* a:x >> shCount (x = lsb(result)) */
8440   if (sign)
8441   {
8442      AccAXRshS(lsb, shCount);
8443   }
8444   else
8445   {
8446     AccAXRsh(lsb, shCount);
8447   }
8448   
8449   _storeAxResults(lsb, result, offr);
8450 }
8451 #endif
8452
8453 /*-----------------------------------------------------------------*/
8454 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8455 /*-----------------------------------------------------------------*/
8456 static void
8457 shiftLLeftOrResult (operand * left, int offl,
8458                     operand * result, int offr, int shCount)
8459 {
8460   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8461   /* shift left accumulator */
8462   AccLsh (shCount);
8463   /* or with result */
8464   emitcode ("orl", "a,%s",
8465             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8466   /* back to result */
8467   aopPut (AOP (result), "a", offr);
8468 }
8469
8470 #if 0
8471 //REMOVE ME!!!
8472 /*-----------------------------------------------------------------*/
8473 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8474 /*-----------------------------------------------------------------*/
8475 static void
8476 shiftRLeftOrResult (operand * left, int offl,
8477                     operand * result, int offr, int shCount)
8478 {
8479   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8480   /* shift right accumulator */
8481   AccRsh (shCount);
8482   /* or with result */
8483   emitcode ("orl", "a,%s",
8484             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8485   /* back to result */
8486   aopPut (AOP (result), "a", offr);
8487 }
8488 #endif
8489
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* genlshOne - left shift a one byte quantity by known count       */
8493 /*-----------------------------------------------------------------*/
8494 static void
8495 genlshOne (operand * result, operand * left, int shCount)
8496 {
8497   D (emitcode (";", "genlshOne "););
8498   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8499 }
8500 #endif
8501
8502 #ifdef BETTER_LITERAL_SHIFT
8503 /*-----------------------------------------------------------------*/
8504 /* genlshTwo - left shift two bytes by known amount != 0           */
8505 /*-----------------------------------------------------------------*/
8506 static void
8507 genlshTwo (operand * result, operand * left, int shCount)
8508 {
8509   int size;
8510
8511   D (emitcode (";", "genlshTwo "););
8512
8513   size = getDataSize (result);
8514
8515   /* if shCount >= 8 */
8516   if (shCount >= 8)
8517   {
8518       shCount -= 8;
8519
8520       _startLazyDPSEvaluation();
8521
8522       if (size > 1)
8523         {
8524           if (shCount)
8525           {
8526             _endLazyDPSEvaluation();
8527             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8528             aopPut (AOP (result), zero, LSB);       
8529           }
8530           else
8531           {
8532             movLeft2Result (left, LSB, result, MSB16, 0);
8533             aopPut (AOP (result), zero, LSB);
8534             _endLazyDPSEvaluation();
8535           }
8536         }
8537         else
8538         {
8539           aopPut (AOP (result), zero, LSB);
8540           _endLazyDPSEvaluation();
8541         }
8542   }
8543
8544   /*  1 <= shCount <= 7 */
8545   else
8546     {
8547       if (size == 1)
8548       {
8549         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8550       }
8551       else
8552       {
8553         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8554       }
8555     }
8556 }
8557 #endif
8558
8559 #if 0
8560 //REMOVE ME!!!
8561 /*-----------------------------------------------------------------*/
8562 /* shiftLLong - shift left one long from left to result            */
8563 /* offl = LSB or MSB16                                             */
8564 /*-----------------------------------------------------------------*/
8565 static void
8566 shiftLLong (operand * left, operand * result, int offr)
8567 {
8568   char *l;
8569   int size = AOP_SIZE (result);
8570
8571   if (size >= LSB + offr)
8572     {
8573       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8574       MOVA (l);
8575       emitcode ("add", "a,acc");
8576       if (sameRegs (AOP (left), AOP (result)) &&
8577           size >= MSB16 + offr && offr != LSB)
8578         emitcode ("xch", "a,%s",
8579                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8580       else
8581         aopPut (AOP (result), "a", LSB + offr);
8582     }
8583
8584   if (size >= MSB16 + offr)
8585     {
8586       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8587         {
8588           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8589         }
8590       emitcode ("rlc", "a");
8591       if (sameRegs (AOP (left), AOP (result)) &&
8592           size >= MSB24 + offr && offr != LSB)
8593         emitcode ("xch", "a,%s",
8594                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8595       else
8596         aopPut (AOP (result), "a", MSB16 + offr);
8597     }
8598
8599   if (size >= MSB24 + offr)
8600     {
8601       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8602         {
8603           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8604         }
8605       emitcode ("rlc", "a");
8606       if (sameRegs (AOP (left), AOP (result)) &&
8607           size >= MSB32 + offr && offr != LSB)
8608         emitcode ("xch", "a,%s",
8609                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8610       else
8611         aopPut (AOP (result), "a", MSB24 + offr);
8612     }
8613
8614   if (size > MSB32 + offr)
8615     {
8616       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8617         {
8618           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8619         }
8620       emitcode ("rlc", "a");
8621       aopPut (AOP (result), "a", MSB32 + offr);
8622     }
8623   if (offr != LSB)
8624     aopPut (AOP (result), zero, LSB);
8625 }
8626 #endif
8627
8628 #if 0
8629 //REMOVE ME!!!
8630 /*-----------------------------------------------------------------*/
8631 /* genlshFour - shift four byte by a known amount != 0             */
8632 /*-----------------------------------------------------------------*/
8633 static void
8634 genlshFour (operand * result, operand * left, int shCount)
8635 {
8636   int size;
8637
8638   D (emitcode (";", "genlshFour ");
8639     );
8640
8641   size = AOP_SIZE (result);
8642
8643   /* if shifting more that 3 bytes */
8644   if (shCount >= 24)
8645     {
8646       shCount -= 24;
8647       if (shCount)
8648         /* lowest order of left goes to the highest
8649            order of the destination */
8650         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8651       else
8652         movLeft2Result (left, LSB, result, MSB32, 0);
8653       aopPut (AOP (result), zero, LSB);
8654       aopPut (AOP (result), zero, MSB16);
8655       aopPut (AOP (result), zero, MSB24);
8656       return;
8657     }
8658
8659   /* more than two bytes */
8660   else if (shCount >= 16)
8661     {
8662       /* lower order two bytes goes to higher order two bytes */
8663       shCount -= 16;
8664       /* if some more remaining */
8665       if (shCount)
8666         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8667       else
8668         {
8669           movLeft2Result (left, MSB16, result, MSB32, 0);
8670           movLeft2Result (left, LSB, result, MSB24, 0);
8671         }
8672       aopPut (AOP (result), zero, MSB16);
8673       aopPut (AOP (result), zero, LSB);
8674       return;
8675     }
8676
8677   /* if more than 1 byte */
8678   else if (shCount >= 8)
8679     {
8680       /* lower order three bytes goes to higher order  three bytes */
8681       shCount -= 8;
8682       if (size == 2)
8683         {
8684           if (shCount)
8685             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8686           else
8687             movLeft2Result (left, LSB, result, MSB16, 0);
8688         }
8689       else
8690         {                       /* size = 4 */
8691           if (shCount == 0)
8692             {
8693               movLeft2Result (left, MSB24, result, MSB32, 0);
8694               movLeft2Result (left, MSB16, result, MSB24, 0);
8695               movLeft2Result (left, LSB, result, MSB16, 0);
8696               aopPut (AOP (result), zero, LSB);
8697             }
8698           else if (shCount == 1)
8699             shiftLLong (left, result, MSB16);
8700           else
8701             {
8702               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8703               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8704               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8705               aopPut (AOP (result), zero, LSB);
8706             }
8707         }
8708     }
8709
8710   /* 1 <= shCount <= 7 */
8711   else if (shCount <= 2)
8712     {
8713       shiftLLong (left, result, LSB);
8714       if (shCount == 2)
8715         shiftLLong (result, result, LSB);
8716     }
8717   /* 3 <= shCount <= 7, optimize */
8718   else
8719     {
8720       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8721       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8722       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8723     }
8724 }
8725 #endif
8726
8727 #ifdef BETTER_LITERAL_SHIFT
8728 /*-----------------------------------------------------------------*/
8729 /* genLeftShiftLiteral - left shifting by known count              */
8730 /*-----------------------------------------------------------------*/
8731 static bool
8732 genLeftShiftLiteral (operand * left,
8733                      operand * right,
8734                      operand * result,
8735                      iCode * ic)
8736 {
8737   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8738   int size;
8739
8740   size = getSize (operandType (result));
8741
8742   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8743
8744   /* We only handle certain easy cases so far. */
8745   if ((shCount != 0)
8746    && (shCount < (size * 8))
8747    && (size != 1)
8748    && (size != 2))
8749   {
8750       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8751       return FALSE;
8752   }
8753
8754   freeAsmop (right, NULL, ic, TRUE);
8755
8756   aopOp(left, ic, FALSE, FALSE);
8757   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8758
8759 #if 0 // debug spew
8760   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8761   {
8762         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8763         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8764         {
8765            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8766         }
8767   }
8768   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8769   {
8770         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8771         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8772         {
8773            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8774         }       
8775   }  
8776 #endif
8777   
8778 #if VIEW_SIZE
8779   emitcode ("; shift left ", "result %d, left %d", size,
8780             AOP_SIZE (left));
8781 #endif
8782
8783   /* I suppose that the left size >= result size */
8784   if (shCount == 0)
8785   {
8786         _startLazyDPSEvaluation();
8787         while (size--)
8788         {
8789           movLeft2Result (left, size, result, size, 0);
8790         }
8791         _endLazyDPSEvaluation();
8792   }
8793   else if (shCount >= (size * 8))
8794   {
8795     _startLazyDPSEvaluation();
8796     while (size--)
8797     {
8798       aopPut (AOP (result), zero, size);
8799     }
8800     _endLazyDPSEvaluation();
8801   }
8802   else
8803   {
8804       switch (size)
8805         {
8806         case 1:
8807           genlshOne (result, left, shCount);
8808           break;
8809
8810         case 2:
8811           genlshTwo (result, left, shCount);
8812           break;
8813 #if 0
8814         case 4:
8815           genlshFour (result, left, shCount);
8816           break;
8817 #endif
8818         default:
8819           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8820           break;
8821         }
8822     }
8823   freeAsmop (left, NULL, ic, TRUE);
8824   freeAsmop (result, NULL, ic, TRUE);
8825   return TRUE;
8826 }
8827 #endif
8828
8829 /*-----------------------------------------------------------------*/
8830 /* genLeftShift - generates code for left shifting                 */
8831 /*-----------------------------------------------------------------*/
8832 static void
8833 genLeftShift (iCode * ic)
8834 {
8835   operand *left, *right, *result;
8836   int size, offset;
8837   char *l;
8838   symbol *tlbl, *tlbl1;
8839
8840   D (emitcode (";", "genLeftShift "););
8841
8842   right = IC_RIGHT (ic);
8843   left = IC_LEFT (ic);
8844   result = IC_RESULT (ic);
8845
8846   aopOp (right, ic, FALSE, FALSE);
8847
8848
8849 #ifdef BETTER_LITERAL_SHIFT
8850   /* if the shift count is known then do it
8851      as efficiently as possible */
8852   if (AOP_TYPE (right) == AOP_LIT)
8853     {
8854       if (genLeftShiftLiteral (left, right, result, ic))
8855       {
8856         return;
8857       }
8858     }
8859 #endif
8860
8861   /* shift count is unknown then we have to form
8862      a loop get the loop count in B : Note: we take
8863      only the lower order byte since shifting
8864      more that 32 bits make no sense anyway, ( the
8865      largest size of an object can be only 32 bits ) */
8866
8867   if (AOP_TYPE (right) == AOP_LIT)
8868   {
8869       /* Really should be handled by genLeftShiftLiteral,
8870        * but since I'm too lazy to fix that today, at least we can make
8871        * some small improvement.
8872        */
8873        emitcode("mov", "b,#!constbyte",
8874                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8875   }
8876   else
8877   {
8878       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8879       emitcode ("inc", "b");
8880   }
8881   freeAsmop (right, NULL, ic, TRUE);
8882   aopOp (left, ic, FALSE, FALSE);
8883   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8884
8885   /* now move the left to the result if they are not the
8886      same */
8887   if (!sameRegs (AOP (left), AOP (result)) &&
8888       AOP_SIZE (result) > 1)
8889     {
8890
8891       size = AOP_SIZE (result);
8892       offset = 0;
8893       _startLazyDPSEvaluation ();
8894       while (size--)
8895         {
8896           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8897           if (*l == '@' && (IS_AOP_PREG (result)))
8898             {
8899
8900               emitcode ("mov", "a,%s", l);
8901               aopPut (AOP (result), "a", offset);
8902             }
8903           else
8904             aopPut (AOP (result), l, offset);
8905           offset++;
8906         }
8907       _endLazyDPSEvaluation ();
8908     }
8909
8910   tlbl = newiTempLabel (NULL);
8911   size = AOP_SIZE (result);
8912   offset = 0;
8913   tlbl1 = newiTempLabel (NULL);
8914
8915   /* if it is only one byte then */
8916   if (size == 1)
8917     {
8918       symbol *tlbl1 = newiTempLabel (NULL);
8919
8920       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8921       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8922       emitcode ("", "!tlabeldef", tlbl->key + 100);
8923       emitcode ("add", "a,acc");
8924       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8925       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8926       aopPut (AOP (result), "a", 0);
8927       goto release;
8928     }
8929
8930   reAdjustPreg (AOP (result));
8931
8932   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8933   emitcode ("", "!tlabeldef", tlbl->key + 100);
8934   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8935   emitcode ("add", "a,acc");
8936   aopPut (AOP (result), "a", offset++);
8937   _startLazyDPSEvaluation ();
8938   while (--size)
8939     {
8940       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8941       emitcode ("rlc", "a");
8942       aopPut (AOP (result), "a", offset++);
8943     }
8944   _endLazyDPSEvaluation ();
8945   reAdjustPreg (AOP (result));
8946
8947   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949 release:
8950   freeAsmop (left, NULL, ic, TRUE);
8951   freeAsmop (result, NULL, ic, TRUE);
8952 }
8953
8954 #ifdef BETTER_LITERAL_SHIFT
8955 /*-----------------------------------------------------------------*/
8956 /* genrshOne - right shift a one byte quantity by known count      */
8957 /*-----------------------------------------------------------------*/
8958 static void
8959 genrshOne (operand * result, operand * left,
8960            int shCount, int sign)
8961 {
8962   D (emitcode (";", "genrshOne"););
8963   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8964 }
8965 #endif
8966
8967 #ifdef BETTER_LITERAL_SHIFT
8968 /*-----------------------------------------------------------------*/
8969 /* genrshTwo - right shift two bytes by known amount != 0          */
8970 /*-----------------------------------------------------------------*/
8971 static void
8972 genrshTwo (operand * result, operand * left,
8973            int shCount, int sign)
8974 {
8975   D (emitcode (";", "genrshTwo"););
8976
8977   /* if shCount >= 8 */
8978   if (shCount >= 8)
8979     {
8980       shCount -= 8;
8981       _startLazyDPSEvaluation();
8982       if (shCount)
8983       {
8984         shiftR1Left2Result (left, MSB16, result, LSB,
8985                             shCount, sign);
8986       }                     
8987       else
8988       {
8989         movLeft2Result (left, MSB16, result, LSB, sign);
8990       }
8991       addSign (result, MSB16, sign);
8992       _endLazyDPSEvaluation();
8993     }
8994
8995   /*  1 <= shCount <= 7 */
8996   else
8997   {
8998     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8999   }
9000 }
9001 #endif
9002
9003 /*-----------------------------------------------------------------*/
9004 /* shiftRLong - shift right one long from left to result           */
9005 /* offl = LSB or MSB16                                             */
9006 /*-----------------------------------------------------------------*/
9007 static void
9008 shiftRLong (operand * left, int offl,
9009             operand * result, int sign)
9010 {
9011   int isSameRegs=sameRegs(AOP(left),AOP(result));
9012
9013   if (isSameRegs && offl>1) {
9014     // we are in big trouble, but this shouldn't happen
9015     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9016   }
9017
9018   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9019   
9020   if (offl==MSB16) {
9021     // shift is > 8
9022     if (sign) {
9023       emitcode ("rlc", "a");
9024       emitcode ("subb", "a,acc");
9025       emitcode ("xch", "a,%s",
9026                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9027     } else {
9028       aopPut (AOP(result), zero, MSB32);
9029     }
9030   }
9031
9032   if (!sign) {
9033     emitcode ("clr", "c");
9034   } else {
9035     emitcode ("mov", "c,acc.7");
9036   }
9037
9038   emitcode ("rrc", "a");
9039
9040   if (isSameRegs && offl==MSB16) {
9041     emitcode ("xch",
9042               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9043   } else {
9044     aopPut (AOP (result), "a", MSB32);
9045     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9046   }
9047
9048   emitcode ("rrc", "a");
9049   if (isSameRegs && offl==1) {
9050     emitcode ("xch", "a,%s",
9051               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9052   } else {
9053     aopPut (AOP (result), "a", MSB24);
9054     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9055   }
9056   emitcode ("rrc", "a");
9057   aopPut (AOP (result), "a", MSB16 - offl);
9058
9059   if (offl == LSB)
9060     {
9061       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9062       emitcode ("rrc", "a");
9063       aopPut (AOP (result), "a", LSB);
9064     }
9065 }
9066
9067 /*-----------------------------------------------------------------*/
9068 /* genrshFour - shift four byte by a known amount != 0             */
9069 /*-----------------------------------------------------------------*/
9070 static void
9071 genrshFour (operand * result, operand * left,
9072             int shCount, int sign)
9073 {
9074   D (emitcode (";", "genrshFour"););
9075
9076   /* if shifting more that 3 bytes */
9077   if (shCount >= 24)
9078     {
9079       shCount -= 24;
9080       _startLazyDPSEvaluation();
9081       if (shCount)
9082         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9083       else
9084         movLeft2Result (left, MSB32, result, LSB, sign);
9085       addSign (result, MSB16, sign);
9086       _endLazyDPSEvaluation();
9087     }
9088   else if (shCount >= 16)
9089     {
9090       shCount -= 16;
9091       _startLazyDPSEvaluation();
9092       if (shCount)
9093         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9094       else
9095         {
9096           movLeft2Result (left, MSB24, result, LSB, 0);
9097           movLeft2Result (left, MSB32, result, MSB16, sign);
9098         }
9099       addSign (result, MSB24, sign);
9100       _endLazyDPSEvaluation();
9101     }
9102   else if (shCount >= 8)
9103     {
9104       shCount -= 8;
9105       _startLazyDPSEvaluation();
9106       if (shCount == 1)
9107         {
9108             shiftRLong (left, MSB16, result, sign);
9109         }
9110       else if (shCount == 0)
9111         {
9112           movLeft2Result (left, MSB16, result, LSB, 0);
9113           movLeft2Result (left, MSB24, result, MSB16, 0);
9114           movLeft2Result (left, MSB32, result, MSB24, sign);
9115           addSign (result, MSB32, sign);
9116         }
9117       else
9118         {
9119           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9120           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9121           /* the last shift is signed */
9122           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9123           addSign (result, MSB32, sign);
9124         }
9125         _endLazyDPSEvaluation();
9126     }
9127   else
9128     {   
9129         /* 1 <= shCount <= 7 */
9130       if (shCount <= 2)
9131         {
9132           shiftRLong (left, LSB, result, sign);
9133           if (shCount == 2)
9134             shiftRLong (result, LSB, result, sign);
9135         }
9136       else
9137         {
9138           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9139           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9140           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9141         }
9142     }
9143 }
9144
9145 #ifdef BETTER_LITERAL_SHIFT
9146 /*-----------------------------------------------------------------*/
9147 /* genRightShiftLiteral - right shifting by known count            */
9148 /*-----------------------------------------------------------------*/
9149 static bool
9150 genRightShiftLiteral (operand * left,
9151                       operand * right,
9152                       operand * result,
9153                       iCode * ic,
9154                       int sign)
9155 {
9156   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9157   int size;
9158
9159   size = getSize (operandType (result));
9160
9161   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9162
9163   /* We only handle certain easy cases so far. */
9164   if ((shCount != 0)
9165    && (shCount < (size * 8))
9166    && (size != 1)
9167    && (size != 2)
9168    && (size != 4))
9169   {
9170       D(emitcode (";", "genRightShiftLiteral wimping out"););
9171       return FALSE;
9172   }
9173
9174   freeAsmop (right, NULL, ic, TRUE);
9175
9176   aopOp (left, ic, FALSE, FALSE);
9177   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9178
9179 #if VIEW_SIZE
9180   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9181             AOP_SIZE (left));
9182 #endif
9183
9184   /* test the LEFT size !!! */
9185
9186   /* I suppose that the left size >= result size */
9187   if (shCount == 0)
9188   {
9189       size = getDataSize (result);
9190       _startLazyDPSEvaluation();
9191       while (size--)
9192       {
9193         movLeft2Result (left, size, result, size, 0);
9194       }
9195       _endLazyDPSEvaluation();
9196   }
9197   else if (shCount >= (size * 8))
9198     {
9199       if (sign)
9200       {
9201         /* get sign in acc.7 */
9202         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9203       }
9204       addSign (result, LSB, sign);
9205     }
9206   else
9207     {
9208       switch (size)
9209         {
9210         case 1:
9211           genrshOne (result, left, shCount, sign);
9212           break;
9213
9214         case 2:
9215           genrshTwo (result, left, shCount, sign);
9216           break;
9217 #if 1
9218         case 4:
9219           genrshFour (result, left, shCount, sign);
9220           break;
9221 #endif    
9222         default:
9223           break;
9224         }
9225     }
9226   freeAsmop (left, NULL, ic, TRUE);
9227   freeAsmop (result, NULL, ic, TRUE);
9228   
9229   return TRUE;
9230 }
9231 #endif
9232
9233 /*-----------------------------------------------------------------*/
9234 /* genSignedRightShift - right shift of signed number              */
9235 /*-----------------------------------------------------------------*/
9236 static void
9237 genSignedRightShift (iCode * ic)
9238 {
9239   operand *right, *left, *result;
9240   int size, offset;
9241   char *l;
9242   symbol *tlbl, *tlbl1;
9243
9244   D (emitcode (";", "genSignedRightShift "););
9245
9246   /* we do it the hard way put the shift count in b
9247      and loop thru preserving the sign */
9248
9249   right = IC_RIGHT (ic);
9250   left = IC_LEFT (ic);
9251   result = IC_RESULT (ic);
9252
9253   aopOp (right, ic, FALSE, FALSE);
9254
9255 #ifdef BETTER_LITERAL_SHIFT
9256   if (AOP_TYPE (right) == AOP_LIT)
9257     {
9258       if (genRightShiftLiteral (left, right, result, ic, 1))
9259       {
9260         return;
9261       }
9262     }
9263 #endif
9264   /* shift count is unknown then we have to form
9265      a loop get the loop count in B : Note: we take
9266      only the lower order byte since shifting
9267      more that 32 bits make no sense anyway, ( the
9268      largest size of an object can be only 32 bits ) */
9269
9270   if (AOP_TYPE (right) == AOP_LIT)
9271   {
9272       /* Really should be handled by genRightShiftLiteral,
9273        * but since I'm too lazy to fix that today, at least we can make
9274        * some small improvement.
9275        */
9276        emitcode("mov", "b,#!constbyte",
9277                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9278   }
9279   else
9280   {
9281         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9282         emitcode ("inc", "b");
9283   }
9284   freeAsmop (right, NULL, ic, TRUE);
9285   aopOp (left, ic, FALSE, FALSE);
9286   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
9287
9288   /* now move the left to the result if they are not the
9289      same */
9290   if (!sameRegs (AOP (left), AOP (result)) &&
9291       AOP_SIZE (result) > 1)
9292     {
9293
9294       size = AOP_SIZE (result);
9295       offset = 0;
9296       _startLazyDPSEvaluation ();
9297       while (size--)
9298         {
9299           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9300           if (*l == '@' && IS_AOP_PREG (result))
9301             {
9302
9303               emitcode ("mov", "a,%s", l);
9304               aopPut (AOP (result), "a", offset);
9305             }
9306           else
9307             aopPut (AOP (result), l, offset);
9308           offset++;
9309         }
9310       _endLazyDPSEvaluation ();
9311     }
9312
9313   /* mov the highest order bit to OVR */
9314   tlbl = newiTempLabel (NULL);
9315   tlbl1 = newiTempLabel (NULL);
9316
9317   size = AOP_SIZE (result);
9318   offset = size - 1;
9319   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9320   emitcode ("rlc", "a");
9321   emitcode ("mov", "ov,c");
9322   /* if it is only one byte then */
9323   if (size == 1)
9324     {
9325       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9326       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9327       emitcode ("", "!tlabeldef", tlbl->key + 100);
9328       emitcode ("mov", "c,ov");
9329       emitcode ("rrc", "a");
9330       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9331       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9332       aopPut (AOP (result), "a", 0);
9333       goto release;
9334     }
9335
9336   reAdjustPreg (AOP (result));
9337   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9338   emitcode ("", "!tlabeldef", tlbl->key + 100);
9339   emitcode ("mov", "c,ov");
9340   _startLazyDPSEvaluation ();
9341   while (size--)
9342     {
9343       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9344       emitcode ("rrc", "a");
9345       aopPut (AOP (result), "a", offset--);
9346     }
9347   _endLazyDPSEvaluation ();
9348   reAdjustPreg (AOP (result));
9349   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9350   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9351
9352 release:
9353   freeAsmop (left, NULL, ic, TRUE);
9354   freeAsmop (result, NULL, ic, TRUE);
9355 }
9356
9357 /*-----------------------------------------------------------------*/
9358 /* genRightShift - generate code for right shifting                */
9359 /*-----------------------------------------------------------------*/
9360 static void
9361 genRightShift (iCode * ic)
9362 {
9363   operand *right, *left, *result;
9364   sym_link *letype;
9365   int size, offset;
9366   char *l;
9367   symbol *tlbl, *tlbl1;
9368
9369   D (emitcode (";", "genRightShift "););
9370
9371   /* if signed then we do it the hard way preserve the
9372      sign bit moving it inwards */
9373   letype = getSpec (operandType (IC_LEFT (ic)));
9374
9375   if (!SPEC_USIGN (letype))
9376     {
9377       genSignedRightShift (ic);
9378       return;
9379     }
9380
9381   /* signed & unsigned types are treated the same : i.e. the
9382      signed is NOT propagated inwards : quoting from the
9383      ANSI - standard : "for E1 >> E2, is equivalent to division
9384      by 2**E2 if unsigned or if it has a non-negative value,
9385      otherwise the result is implementation defined ", MY definition
9386      is that the sign does not get propagated */
9387
9388   right = IC_RIGHT (ic);
9389   left = IC_LEFT (ic);
9390   result = IC_RESULT (ic);
9391
9392   aopOp (right, ic, FALSE, FALSE);
9393
9394 #ifdef BETTER_LITERAL_SHIFT
9395   /* if the shift count is known then do it
9396      as efficiently as possible */
9397   if (AOP_TYPE (right) == AOP_LIT)
9398     {
9399       if (genRightShiftLiteral (left, right, result, ic, 0))
9400       {
9401         return;
9402       }
9403     }
9404 #endif
9405
9406   /* shift count is unknown then we have to form
9407      a loop get the loop count in B : Note: we take
9408      only the lower order byte since shifting
9409      more that 32 bits make no sense anyway, ( the
9410      largest size of an object can be only 32 bits ) */
9411   
9412   if (AOP_TYPE (right) == AOP_LIT)
9413   {
9414       /* Really should be handled by genRightShiftLiteral,
9415        * but since I'm too lazy to fix that today, at least we can make
9416        * some small improvement.
9417        */
9418        emitcode("mov", "b,#!constbyte",
9419                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9420   }
9421   else
9422   {
9423       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9424       emitcode ("inc", "b");
9425   }
9426   freeAsmop (right, NULL, ic, TRUE);
9427   aopOp (left, ic, FALSE, FALSE);
9428   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9429
9430   /* now move the left to the result if they are not the
9431      same */
9432   if (!sameRegs (AOP (left), AOP (result)) &&
9433       AOP_SIZE (result) > 1)
9434     {
9435
9436       size = AOP_SIZE (result);
9437       offset = 0;
9438       _startLazyDPSEvaluation ();
9439       while (size--)
9440         {
9441           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9442           if (*l == '@' && IS_AOP_PREG (result))
9443             {
9444
9445               emitcode ("mov", "a,%s", l);
9446               aopPut (AOP (result), "a", offset);
9447             }
9448           else
9449             aopPut (AOP (result), l, offset);
9450           offset++;
9451         }
9452       _endLazyDPSEvaluation ();
9453     }
9454
9455   tlbl = newiTempLabel (NULL);
9456   tlbl1 = newiTempLabel (NULL);
9457   size = AOP_SIZE (result);
9458   offset = size - 1;
9459
9460   /* if it is only one byte then */
9461   if (size == 1)
9462     {
9463       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9464       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9465       emitcode ("", "!tlabeldef", tlbl->key + 100);
9466       CLRC;
9467       emitcode ("rrc", "a");
9468       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9469       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9470       aopPut (AOP (result), "a", 0);
9471       goto release;
9472     }
9473
9474   reAdjustPreg (AOP (result));
9475   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9476   emitcode ("", "!tlabeldef", tlbl->key + 100);
9477   CLRC;
9478   _startLazyDPSEvaluation ();
9479   while (size--)
9480     {
9481       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9482       emitcode ("rrc", "a");
9483       aopPut (AOP (result), "a", offset--);
9484     }
9485   _endLazyDPSEvaluation ();
9486   reAdjustPreg (AOP (result));
9487
9488   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9489   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9490
9491 release:
9492   freeAsmop (left, NULL, ic, TRUE);
9493   freeAsmop (result, NULL, ic, TRUE);
9494 }
9495
9496
9497 /*-----------------------------------------------------------------*/
9498 /* emitPtrByteGet - emits code to get a byte into A through a      */
9499 /*                  pointer register (R0, R1, or DPTR). The        */
9500 /*                  original value of A can be preserved in B.     */
9501 /*-----------------------------------------------------------------*/
9502 static void
9503 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9504 {
9505   switch (p_type)
9506     {
9507     case IPOINTER:
9508     case POINTER:
9509       if (preserveAinB)
9510         emitcode ("mov", "b,a");
9511       emitcode ("mov", "a,@%s", rname);
9512       break;
9513
9514     case PPOINTER:
9515       if (preserveAinB)
9516         emitcode ("mov", "b,a");
9517       emitcode ("movx", "a,@%s", rname);
9518       break;
9519       
9520     case FPOINTER:
9521       if (preserveAinB)
9522         emitcode ("mov", "b,a");
9523       emitcode ("movx", "a,@dptr");
9524       break;
9525
9526     case CPOINTER:
9527       if (preserveAinB)
9528         emitcode ("mov", "b,a");
9529       emitcode ("clr", "a");
9530       emitcode ("movc", "a,@a+dptr");
9531       break;
9532
9533     case GPOINTER:
9534       if (preserveAinB)
9535         {
9536           emitcode ("push", "b");
9537           emitcode ("push", "acc");
9538         }
9539       emitcode ("lcall", "__gptrget");
9540       if (preserveAinB)
9541         emitcode ("pop", "b");
9542       break;
9543     }
9544 }
9545
9546 /*-----------------------------------------------------------------*/
9547 /* emitPtrByteSet - emits code to set a byte from src through a    */
9548 /*                  pointer register (R0, R1, or DPTR).            */
9549 /*-----------------------------------------------------------------*/
9550 static void
9551 emitPtrByteSet (char *rname, int p_type, char *src)
9552 {
9553   switch (p_type)
9554     {
9555     case IPOINTER:
9556     case POINTER:
9557       if (*src=='@')
9558         {
9559           MOVA (src);
9560           emitcode ("mov", "@%s,a", rname);
9561         }
9562       else
9563         emitcode ("mov", "@%s,%s", rname, src);
9564       break;
9565
9566     case PPOINTER:
9567       MOVA (src);
9568       emitcode ("movx", "@%s,a", rname);
9569       break;
9570       
9571     case FPOINTER:
9572       MOVA (src);
9573       emitcode ("movx", "@dptr,a");
9574       break;
9575
9576     case GPOINTER:
9577       MOVA (src);
9578       emitcode ("lcall", "__gptrput");
9579       break;
9580     }
9581 }
9582
9583 /*-----------------------------------------------------------------*/
9584 /* genUnpackBits - generates code for unpacking bits               */
9585 /*-----------------------------------------------------------------*/
9586 static void
9587 genUnpackBits (operand * result, char *rname, int ptype)
9588 {
9589   int offset = 0;       /* result byte offset */
9590   int rsize;            /* result size */
9591   int rlen = 0;         /* remaining bitfield length */
9592   sym_link *etype;      /* bitfield type information */
9593   int blen;             /* bitfield length */
9594   int bstr;             /* bitfield starting bit within byte */
9595
9596   D(emitcode (";     genUnpackBits",""));
9597
9598   etype = getSpec (operandType (result));
9599   rsize = getSize (operandType (result));
9600   blen = SPEC_BLEN (etype);
9601   bstr = SPEC_BSTR (etype);
9602
9603   /* If the bitfield length is less than a byte */
9604   if (blen < 8)
9605     {
9606       emitPtrByteGet (rname, ptype, FALSE);
9607       AccRsh (bstr);
9608       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9609       aopPut (AOP (result), "a", offset++);
9610       goto finish;
9611     }
9612
9613   /* Bit field did not fit in a byte. Copy all
9614      but the partial byte at the end.  */
9615   for (rlen=blen;rlen>=8;rlen-=8)
9616     {
9617       emitPtrByteGet (rname, ptype, FALSE);
9618       aopPut (AOP (result), "a", offset++);
9619       if (rlen>8)
9620         emitcode ("inc", "%s", rname);
9621     }
9622
9623   /* Handle the partial byte at the end */
9624   if (rlen)
9625     {
9626       emitPtrByteGet (rname, ptype, FALSE);
9627       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9628       aopPut (AOP (result), "a", offset++);
9629     }
9630
9631 finish:
9632   if (offset < rsize)
9633     {
9634       rsize -= offset;
9635       while (rsize--)
9636         aopPut (AOP (result), zero, offset++);
9637     }
9638 }
9639
9640
9641 /*-----------------------------------------------------------------*/
9642 /* genDataPointerGet - generates code when ptr offset is known     */
9643 /*-----------------------------------------------------------------*/
9644 static void
9645 genDataPointerGet (operand * left,
9646                    operand * result,
9647                    iCode * ic)
9648 {
9649   char *l;
9650   char buff[256];
9651   int size, offset = 0;
9652   aopOp (result, ic, TRUE, FALSE);
9653
9654   /* get the string representation of the name */
9655   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9656   size = AOP_SIZE (result);
9657   _startLazyDPSEvaluation ();
9658   while (size--)
9659     {
9660         if (offset)
9661         {
9662             SNPRINTF (buff, sizeof(buff), 
9663                       "(%s + %d)", l + 1, offset);
9664         }
9665         else
9666         {
9667             SNPRINTF (buff, sizeof(buff), 
9668                       "%s", l + 1);
9669         }
9670       aopPut (AOP (result), buff, offset++);
9671     }
9672   _endLazyDPSEvaluation ();
9673
9674   freeAsmop (left, NULL, ic, TRUE);
9675   freeAsmop (result, NULL, ic, TRUE);
9676 }
9677
9678 /*-----------------------------------------------------------------*/
9679 /* genNearPointerGet - emitcode for near pointer fetch             */
9680 /*-----------------------------------------------------------------*/
9681 static void
9682 genNearPointerGet (operand * left,
9683                    operand * result,
9684                    iCode * ic,
9685                    iCode *pi)
9686 {
9687   asmop *aop = NULL;
9688   regs *preg;
9689   char *rname;
9690   sym_link *rtype, *retype, *letype;
9691   sym_link *ltype = operandType (left);
9692   char buff[80];
9693
9694   rtype = operandType (result);
9695   retype = getSpec (rtype);
9696   letype = getSpec (ltype);
9697
9698   aopOp (left, ic, FALSE, FALSE);
9699
9700   /* if left is rematerialisable and
9701      result is not bitfield variable type and
9702      the left is pointer to data space i.e
9703      lower 128 bytes of space */
9704   if (AOP_TYPE (left) == AOP_IMMD &&
9705       !IS_BITFIELD (retype) &&
9706       !IS_BITFIELD (letype) &&
9707       DCL_TYPE (ltype) == POINTER)
9708     {
9709       genDataPointerGet (left, result, ic);
9710       return;
9711     }
9712
9713   /* if the value is already in a pointer register
9714      then don't need anything more */
9715   if (!AOP_INPREG (AOP (left)))
9716     {
9717       /* otherwise get a free pointer register */
9718       aop = newAsmop (0);
9719       preg = getFreePtr (ic, &aop, FALSE);
9720       emitcode ("mov", "%s,%s",
9721                 preg->name,
9722                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9723       rname = preg->name;
9724     }
9725   else
9726     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9727
9728   freeAsmop (left, NULL, ic, TRUE);
9729   aopOp (result, ic, FALSE, FALSE);
9730
9731   /* if bitfield then unpack the bits */
9732   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9733     genUnpackBits (result, rname, POINTER);
9734   else
9735     {
9736       /* we have can just get the values */
9737       int size = AOP_SIZE (result);
9738       int offset = 0;
9739
9740       while (size--)
9741         {
9742           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9743             {
9744
9745               emitcode ("mov", "a,@%s", rname);
9746               aopPut (AOP (result), "a", offset);
9747             }
9748           else
9749             {
9750               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9751               aopPut (AOP (result), buff, offset);
9752             }
9753           offset++;
9754           if (size || pi)
9755             {
9756                 emitcode ("inc", "%s", rname);
9757             }
9758         }
9759     }
9760
9761   /* now some housekeeping stuff */
9762   if (aop)
9763     {
9764       /* we had to allocate for this iCode */
9765       if (pi) { /* post increment present */
9766         aopPut(AOP ( left ),rname,0);
9767       }
9768       freeAsmop (NULL, aop, ic, TRUE);
9769     }
9770   else
9771     {
9772       /* we did not allocate which means left
9773          already in a pointer register, then
9774          if size > 0 && this could be used again
9775          we have to point it back to where it
9776          belongs */
9777       if (AOP_SIZE (result) > 1 &&
9778           !OP_SYMBOL (left)->remat &&
9779           (OP_SYMBOL (left)->liveTo > ic->seq ||
9780            ic->depth) &&
9781           !pi)
9782         {
9783           int size = AOP_SIZE (result) - 1;
9784           while (size--)
9785             emitcode ("dec", "%s", rname);
9786         }
9787     }
9788
9789   /* done */
9790   freeAsmop (result, NULL, ic, TRUE);
9791   if (pi) pi->generated = 1;
9792 }
9793
9794 /*-----------------------------------------------------------------*/
9795 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9796 /*-----------------------------------------------------------------*/
9797 static void
9798 genPagedPointerGet (operand * left,
9799                     operand * result,
9800                     iCode * ic,
9801                     iCode * pi)
9802 {
9803   asmop *aop = NULL;
9804   regs *preg;
9805   char *rname;
9806   sym_link *rtype, *retype, *letype;
9807
9808   rtype = operandType (result);
9809   retype = getSpec (rtype);
9810   letype = getSpec (operandType (left));
9811   aopOp (left, ic, FALSE, FALSE);
9812
9813   /* if the value is already in a pointer register
9814      then don't need anything more */
9815   if (!AOP_INPREG (AOP (left)))
9816     {
9817       /* otherwise get a free pointer register */
9818       aop = newAsmop (0);
9819       preg = getFreePtr (ic, &aop, FALSE);
9820       emitcode ("mov", "%s,%s",
9821                 preg->name,
9822                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9823       rname = preg->name;
9824     }
9825   else
9826     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9827
9828   freeAsmop (left, NULL, ic, TRUE);
9829   aopOp (result, ic, FALSE, FALSE);
9830
9831   /* if bitfield then unpack the bits */
9832   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9833     genUnpackBits (result, rname, PPOINTER);
9834   else
9835     {
9836       /* we have can just get the values */
9837       int size = AOP_SIZE (result);
9838       int offset = 0;
9839
9840       while (size--)
9841         {
9842
9843           emitcode ("movx", "a,@%s", rname);
9844           aopPut (AOP (result), "a", offset);
9845
9846           offset++;
9847
9848           if (size || pi)
9849             emitcode ("inc", "%s", rname);
9850         }
9851     }
9852
9853   /* now some housekeeping stuff */
9854   if (aop)
9855     {
9856       /* we had to allocate for this iCode */
9857       if (pi) aopPut ( AOP (left), rname, 0);
9858       freeAsmop (NULL, aop, ic, TRUE);
9859     }
9860   else
9861     {
9862       /* we did not allocate which means left
9863          already in a pointer register, then
9864          if size > 0 && this could be used again
9865          we have to point it back to where it
9866          belongs */
9867       if (AOP_SIZE (result) > 1 &&
9868           !OP_SYMBOL (left)->remat &&
9869           (OP_SYMBOL (left)->liveTo > ic->seq ||
9870            ic->depth) &&
9871           !pi)
9872         {
9873           int size = AOP_SIZE (result) - 1;
9874           while (size--)
9875             emitcode ("dec", "%s", rname);
9876         }
9877     }
9878
9879   /* done */
9880   freeAsmop (result, NULL, ic, TRUE);
9881   if (pi) pi->generated = 1;
9882 }
9883
9884 /*-----------------------------------------------------------------*/
9885 /* genFarPointerGet - gget value from far space                    */
9886 /*-----------------------------------------------------------------*/
9887 static void
9888 genFarPointerGet (operand * left,
9889                   operand * result, iCode * ic, iCode *pi)
9890 {
9891     int size, offset, dopi=1;
9892   sym_link *retype = getSpec (operandType (result));
9893   sym_link *letype = getSpec (operandType (left));
9894   D (emitcode (";", "genFarPointerGet"););
9895
9896   aopOp (left, ic, FALSE, FALSE);
9897
9898   /* if the operand is already in dptr
9899      then we do nothing else we move the value to dptr */
9900   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9901     {
9902       /* if this is remateriazable */
9903       if (AOP_TYPE (left) == AOP_IMMD)
9904         {
9905           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9906         }
9907       else
9908         {
9909           /* we need to get it byte by byte */
9910           _startLazyDPSEvaluation ();
9911           if (AOP_TYPE (left) != AOP_DPTR)
9912             {
9913               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9914               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9915               if (options.model == MODEL_FLAT24)
9916                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9917             }
9918           else
9919             {
9920               /* We need to generate a load to DPTR indirect through DPTR. */
9921               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9922               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9923               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9924               if (options.model == MODEL_FLAT24)
9925                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9926               emitcode ("pop", "dph");
9927               emitcode ("pop", "dpl");
9928               dopi =0;
9929             }
9930           _endLazyDPSEvaluation ();
9931         }
9932     }
9933   /* so dptr know contains the address */
9934   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9935
9936   /* if bit then unpack */
9937   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9938       if (AOP_INDPTRn(left)) {
9939           genSetDPTR(AOP(left)->aopu.dptr);
9940       }
9941       genUnpackBits (result, "dptr", FPOINTER);
9942       if (AOP_INDPTRn(left)) {
9943           genSetDPTR(0);
9944       }
9945   } else
9946     {
9947       size = AOP_SIZE (result);
9948       offset = 0;
9949
9950       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9951           while (size--) {
9952               genSetDPTR(AOP(left)->aopu.dptr);
9953               emitcode ("movx", "a,@dptr");
9954               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9955                   emitcode ("inc", "dptr");
9956               genSetDPTR (0);
9957               aopPut (AOP (result), "a", offset++);
9958           }
9959       } else {
9960           _startLazyDPSEvaluation ();
9961           while (size--) {
9962               if (AOP_INDPTRn(left)) {
9963                   genSetDPTR(AOP(left)->aopu.dptr);
9964               } else {
9965                   genSetDPTR (0);
9966               }
9967               _flushLazyDPS ();
9968               
9969               emitcode ("movx", "a,@dptr");
9970               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9971                   emitcode ("inc", "dptr");
9972               
9973               aopPut (AOP (result), "a", offset++);
9974           }
9975           _endLazyDPSEvaluation ();
9976       }
9977     }
9978   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9979       if (!AOP_INDPTRn(left)) {
9980           _startLazyDPSEvaluation ();
9981           aopPut ( AOP (left), "dpl", 0);
9982           aopPut ( AOP (left), "dph", 1);
9983           if (options.model == MODEL_FLAT24)
9984               aopPut ( AOP (left), "dpx", 2);
9985           _endLazyDPSEvaluation ();
9986       }
9987     pi->generated = 1;
9988   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9989              AOP_SIZE(result) > 1 &&
9990              IS_SYMOP(left) &&
9991              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9992       
9993       size = AOP_SIZE (result) - 1;
9994       if (AOP_INDPTRn(left)) {
9995           genSetDPTR(AOP(left)->aopu.dptr);
9996       }
9997       while (size--) emitcode ("lcall","__decdptr");
9998       if (AOP_INDPTRn(left)) {
9999           genSetDPTR(0);
10000       }
10001   }
10002
10003   freeAsmop (left, NULL, ic, TRUE);
10004   freeAsmop (result, NULL, ic, TRUE);
10005 }
10006
10007 /*-----------------------------------------------------------------*/
10008 /* genCodePointerGet - get value from code space                  */
10009 /*-----------------------------------------------------------------*/
10010 static void
10011 genCodePointerGet (operand * left,
10012                     operand * result, iCode * ic, iCode *pi)
10013 {
10014   int size, offset, dopi=1;
10015   sym_link *retype = getSpec (operandType (result));
10016
10017   aopOp (left, ic, FALSE, FALSE);
10018
10019   /* if the operand is already in dptr
10020      then we do nothing else we move the value to dptr */
10021   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10022     {
10023       /* if this is remateriazable */
10024       if (AOP_TYPE (left) == AOP_IMMD)
10025         {
10026           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10027         }
10028       else
10029         {                       /* we need to get it byte by byte */
10030           _startLazyDPSEvaluation ();
10031           if (AOP_TYPE (left) != AOP_DPTR)
10032             {
10033               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10034               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10035               if (options.model == MODEL_FLAT24)
10036                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10037             }
10038           else
10039             {
10040               /* We need to generate a load to DPTR indirect through DPTR. */
10041               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10042               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10043               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10044               if (options.model == MODEL_FLAT24)
10045                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10046               emitcode ("pop", "dph");
10047               emitcode ("pop", "dpl");
10048               dopi=0;
10049             }
10050           _endLazyDPSEvaluation ();
10051         }
10052     }
10053   /* so dptr know contains the address */
10054   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10055
10056   /* if bit then unpack */
10057   if (IS_BITFIELD (retype)) {
10058       if (AOP_INDPTRn(left)) {
10059           genSetDPTR(AOP(left)->aopu.dptr);
10060       }
10061       genUnpackBits (result, "dptr", CPOINTER);
10062       if (AOP_INDPTRn(left)) {
10063           genSetDPTR(0);
10064       }
10065   } else
10066     {
10067       size = AOP_SIZE (result);
10068       offset = 0;
10069       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10070           while (size--) {
10071               genSetDPTR(AOP(left)->aopu.dptr);
10072               emitcode ("clr", "a");
10073               emitcode ("movc", "a,@a+dptr");
10074               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10075                   emitcode ("inc", "dptr");
10076               genSetDPTR (0);
10077               aopPut (AOP (result), "a", offset++);
10078           }
10079       } else {
10080           _startLazyDPSEvaluation ();
10081           while (size--)
10082               {
10083                   if (AOP_INDPTRn(left)) {
10084                       genSetDPTR(AOP(left)->aopu.dptr);
10085                   } else {
10086                       genSetDPTR (0);
10087                   }
10088                   _flushLazyDPS ();
10089                   
10090                   emitcode ("clr", "a");
10091                   emitcode ("movc", "a,@a+dptr");
10092                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10093                       emitcode ("inc", "dptr");
10094                   aopPut (AOP (result), "a", offset++);
10095               }
10096           _endLazyDPSEvaluation ();
10097       }
10098     }
10099   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10100       if (!AOP_INDPTRn(left)) {
10101           _startLazyDPSEvaluation ();
10102           
10103           aopPut ( AOP (left), "dpl", 0);
10104           aopPut ( AOP (left), "dph", 1);
10105           if (options.model == MODEL_FLAT24)
10106               aopPut ( AOP (left), "dpx", 2);
10107
10108           _endLazyDPSEvaluation ();
10109       }
10110       pi->generated = 1;
10111   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
10112              AOP_SIZE(result) > 1 &&
10113              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10114       
10115       size = AOP_SIZE (result) - 1;
10116       if (AOP_INDPTRn(left)) {
10117           genSetDPTR(AOP(left)->aopu.dptr);
10118       }
10119       while (size--) emitcode ("lcall","__decdptr");
10120       if (AOP_INDPTRn(left)) {
10121           genSetDPTR(0);
10122       }
10123   }
10124   
10125   freeAsmop (left, NULL, ic, TRUE);
10126   freeAsmop (result, NULL, ic, TRUE);
10127 }
10128
10129 /*-----------------------------------------------------------------*/
10130 /* genGenPointerGet - gget value from generic pointer space        */
10131 /*-----------------------------------------------------------------*/
10132 static void
10133 genGenPointerGet (operand * left,
10134                   operand * result, iCode * ic, iCode * pi)
10135 {
10136   int size, offset;
10137   sym_link *retype = getSpec (operandType (result));
10138   sym_link *letype = getSpec (operandType (left));
10139
10140   D (emitcode (";", "genGenPointerGet "); );
10141
10142   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10143
10144   /* if the operand is already in dptr
10145      then we do nothing else we move the value to dptr */
10146   if (AOP_TYPE (left) != AOP_STR)
10147     {
10148       /* if this is remateriazable */
10149       if (AOP_TYPE (left) == AOP_IMMD)
10150         {
10151           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10152           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
10153             {
10154                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10155             }
10156             else
10157             {
10158                 emitcode ("mov", "b,#%d", pointerCode (retype));
10159             }
10160         }
10161       else
10162         {                       /* we need to get it byte by byte */
10163             _startLazyDPSEvaluation ();
10164             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10165             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10166             if (options.model == MODEL_FLAT24) {
10167                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10168                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10169             } else {
10170                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10171             }
10172             _endLazyDPSEvaluation ();
10173         }
10174     }
10175
10176   /* so dptr-b now contains the address */
10177   _G.bInUse++;
10178   aopOp (result, ic, FALSE, TRUE);
10179   _G.bInUse--;
10180
10181   /* if bit then unpack */
10182   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10183   {
10184     genUnpackBits (result, "dptr", GPOINTER);
10185   }
10186   else
10187     {
10188         size = AOP_SIZE (result);
10189         offset = 0;
10190
10191         while (size--)
10192         {
10193             if (size)
10194             {
10195                 // Get two bytes at a time, results in _AP & A.
10196                 // dptr will be incremented ONCE by __gptrgetWord.
10197                 //
10198                 // Note: any change here must be coordinated
10199                 // with the implementation of __gptrgetWord
10200                 // in device/lib/_gptrget.c
10201                 emitcode ("lcall", "__gptrgetWord");
10202                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10203                 aopPut (AOP (result), "a", offset++);
10204                 size--;
10205             }
10206             else
10207             {
10208                 // Only one byte to get.
10209                 emitcode ("lcall", "__gptrget");
10210                 aopPut (AOP (result), "a", offset++);
10211             }
10212             
10213             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10214             {
10215                 emitcode ("inc", "dptr");
10216             }
10217         }
10218     }
10219
10220   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10221     _startLazyDPSEvaluation ();
10222       
10223     aopPut ( AOP (left), "dpl", 0);
10224     aopPut ( AOP (left), "dph", 1);
10225     if (options.model == MODEL_FLAT24) {
10226         aopPut ( AOP (left), "dpx", 2);
10227         aopPut ( AOP (left), "b", 3);   
10228     } else  aopPut ( AOP (left), "b", 2);       
10229     
10230     _endLazyDPSEvaluation ();
10231       
10232     pi->generated = 1;
10233   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10234              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10235       
10236       size = AOP_SIZE (result) - 1;
10237       while (size--) emitcode ("lcall","__decdptr");
10238   }
10239
10240   freeAsmop (left, NULL, ic, TRUE);
10241   freeAsmop (result, NULL, ic, TRUE);
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genPointerGet - generate code for pointer get                   */
10246 /*-----------------------------------------------------------------*/
10247 static void
10248 genPointerGet (iCode * ic, iCode *pi)
10249 {
10250   operand *left, *result;
10251   sym_link *type, *etype;
10252   int p_type;
10253
10254   D (emitcode (";", "genPointerGet ");
10255     );
10256
10257   left = IC_LEFT (ic);
10258   result = IC_RESULT (ic);
10259
10260   /* depending on the type of pointer we need to
10261      move it to the correct pointer register */
10262   type = operandType (left);
10263   etype = getSpec (type);
10264   /* if left is of type of pointer then it is simple */
10265   if (IS_PTR (type) && !IS_FUNC (type->next))
10266     p_type = DCL_TYPE (type);
10267   else
10268     {
10269       /* we have to go by the storage class */
10270       p_type = PTR_TYPE (SPEC_OCLS (etype));
10271     }
10272   /* special case when cast remat */
10273   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10274       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10275           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10276           type = operandType (left);
10277           p_type = DCL_TYPE (type);
10278   }
10279   /* now that we have the pointer type we assign
10280      the pointer values */
10281   switch (p_type)
10282     {
10283
10284     case POINTER:
10285     case IPOINTER:
10286       genNearPointerGet (left, result, ic, pi);
10287       break;
10288
10289     case PPOINTER:
10290       genPagedPointerGet (left, result, ic, pi);
10291       break;
10292
10293     case FPOINTER:
10294       genFarPointerGet (left, result, ic, pi);
10295       break;
10296
10297     case CPOINTER:
10298       genCodePointerGet (left, result, ic, pi);
10299       break;
10300
10301     case GPOINTER:
10302       genGenPointerGet (left, result, ic, pi);
10303       break;
10304     }
10305
10306 }
10307
10308 /*-----------------------------------------------------------------*/
10309 /* genPackBits - generates code for packed bit storage             */
10310 /*-----------------------------------------------------------------*/
10311 static void
10312 genPackBits (sym_link * etype,
10313              operand * right,
10314              char *rname, int p_type)
10315 {
10316   int offset = 0;       /* source byte offset */
10317   int rlen = 0;         /* remaining bitfield length */
10318   int blen;             /* bitfield length */
10319   int bstr;             /* bitfield starting bit within byte */
10320   int litval;           /* source literal value (if AOP_LIT) */
10321   unsigned char mask;   /* bitmask within current byte */
10322
10323   D(emitcode (";     genPackBits",""));
10324
10325   blen = SPEC_BLEN (etype);
10326   bstr = SPEC_BSTR (etype);
10327
10328   /* If the bitfield length is less than a byte */
10329   if (blen < 8)
10330     {
10331       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10332               (unsigned char) (0xFF >> (8 - bstr)));
10333
10334       if (AOP_TYPE (right) == AOP_LIT)
10335         {
10336           /* Case with a bitfield length <8 and literal source
10337           */
10338           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10339           litval <<= bstr;
10340           litval &= (~mask) & 0xff;
10341           emitPtrByteGet (rname, p_type, FALSE);
10342           if ((mask|litval)!=0xff)
10343             emitcode ("anl","a,#!constbyte", mask);
10344           if (litval)
10345             emitcode ("orl","a,#!constbyte", litval);
10346         }
10347       else
10348         {
10349           if ((blen==1) && (p_type!=GPOINTER))
10350             {
10351               /* Case with a bitfield length == 1 and no generic pointer
10352               */
10353               if (AOP_TYPE (right) == AOP_CRY)
10354                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10355               else
10356                 {
10357                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10358                   emitcode ("rrc","a");
10359                 }
10360               emitPtrByteGet (rname, p_type, FALSE);
10361               emitcode ("mov","acc.%d,c",bstr);
10362             }
10363           else
10364             {
10365               /* Case with a bitfield length < 8 and arbitrary source
10366               */
10367               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10368               /* shift and mask source value */
10369               AccLsh (bstr);
10370               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10371
10372               /* transfer A to B and get next byte */
10373               emitPtrByteGet (rname, p_type, TRUE);
10374
10375               emitcode ("anl", "a,#!constbyte", mask);
10376               emitcode ("orl", "a,b");
10377               if (p_type == GPOINTER)
10378                 emitcode ("pop", "b");
10379            }
10380         }
10381
10382       emitPtrByteSet (rname, p_type, "a");
10383       return;
10384     }
10385
10386   /* Bit length is greater than 7 bits. In this case, copy  */
10387   /* all except the partial byte at the end                 */
10388   for (rlen=blen;rlen>=8;rlen-=8)
10389     {
10390       emitPtrByteSet (rname, p_type, 
10391                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10392       if (rlen>8)
10393         emitcode ("inc", "%s", rname);
10394     }
10395
10396   /* If there was a partial byte at the end */
10397   if (rlen)
10398     {
10399       mask = (((unsigned char) -1 << rlen) & 0xff);
10400       
10401       if (AOP_TYPE (right) == AOP_LIT)
10402         {
10403           /* Case with partial byte and literal source
10404           */
10405           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10406           litval >>= (blen-rlen);
10407           litval &= (~mask) & 0xff;
10408           emitPtrByteGet (rname, p_type, FALSE);
10409           if ((mask|litval)!=0xff)
10410             emitcode ("anl","a,#!constbyte", mask);
10411           if (litval)
10412             emitcode ("orl","a,#!constbyte", litval);
10413         }
10414       else
10415         {
10416           /* Case with partial byte and arbitrary source
10417           */
10418           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10419           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10420
10421           /* transfer A to B and get next byte */
10422           emitPtrByteGet (rname, p_type, TRUE);
10423
10424           emitcode ("anl", "a,#!constbyte", mask);
10425           emitcode ("orl", "a,b");
10426           if (p_type == GPOINTER)
10427             emitcode ("pop", "b");
10428         }
10429       emitPtrByteSet (rname, p_type, "a");
10430     }
10431
10432 }
10433
10434
10435 /*-----------------------------------------------------------------*/
10436 /* genDataPointerSet - remat pointer to data space                 */
10437 /*-----------------------------------------------------------------*/
10438 static void
10439 genDataPointerSet (operand * right,
10440                    operand * result,
10441                    iCode * ic)
10442 {
10443   int size, offset = 0;
10444   char *l, buff[256];
10445
10446   aopOp (right, ic, FALSE, FALSE);
10447
10448   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10449   size = AOP_SIZE (right);
10450   while (size--)
10451     {
10452       if (offset)
10453         {
10454             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10455         }
10456       else
10457         {
10458             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10459         }
10460         
10461       emitcode ("mov", "%s,%s", buff,
10462                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10463     }
10464
10465   freeAsmop (right, NULL, ic, TRUE);
10466   freeAsmop (result, NULL, ic, TRUE);
10467 }
10468
10469 /*-----------------------------------------------------------------*/
10470 /* genNearPointerSet - emitcode for near pointer put                */
10471 /*-----------------------------------------------------------------*/
10472 static void
10473 genNearPointerSet (operand * right,
10474                    operand * result,
10475                    iCode * ic,
10476                    iCode * pi)
10477 {
10478   asmop *aop = NULL;
10479   char *rname, *l;
10480   sym_link *retype, *letype;
10481   sym_link *ptype = operandType (result);
10482
10483   retype = getSpec (operandType (right));
10484   letype = getSpec (ptype);
10485
10486   aopOp (result, ic, FALSE, FALSE);
10487
10488   /* if the result is rematerializable &
10489      in data space & not a bit variable */
10490   if (AOP_TYPE (result) == AOP_IMMD &&
10491       DCL_TYPE (ptype) == POINTER &&
10492       !IS_BITVAR (retype) &&
10493       !IS_BITVAR (letype))
10494     {
10495       genDataPointerSet (right, result, ic);
10496       return;
10497     }
10498
10499   /* if the value is already in a pointer register
10500      then don't need anything more */
10501   if (!AOP_INPREG (AOP (result)))
10502     {
10503       /* otherwise get a free pointer register */
10504       regs *preg;
10505         
10506       aop = newAsmop (0);
10507       preg = getFreePtr (ic, &aop, FALSE);
10508       emitcode ("mov", "%s,%s",
10509                 preg->name,
10510                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10511       rname = preg->name;
10512     }
10513   else
10514     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10515
10516   aopOp (right, ic, FALSE, FALSE);
10517
10518   /* if bitfield then unpack the bits */
10519   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10520     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10521   else
10522     {
10523       /* we have can just get the values */
10524       int size = AOP_SIZE (right);
10525       int offset = 0;
10526
10527       while (size--)
10528         {
10529           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10530           if (*l == '@')
10531             {
10532               MOVA (l);
10533               emitcode ("mov", "@%s,a", rname);
10534             }
10535           else
10536             emitcode ("mov", "@%s,%s", rname, l);
10537           if (size || pi)
10538             emitcode ("inc", "%s", rname);
10539           offset++;
10540         }
10541     }
10542
10543   /* now some housekeeping stuff */
10544   if (aop)
10545     {
10546       /* we had to allocate for this iCode */
10547       if (pi) aopPut (AOP (result),rname,0);
10548       freeAsmop (NULL, aop, ic, TRUE);
10549     }
10550   else
10551     {
10552       /* we did not allocate which means left
10553          already in a pointer register, then
10554          if size > 0 && this could be used again
10555          we have to point it back to where it
10556          belongs */
10557       if (AOP_SIZE (right) > 1 &&
10558           !OP_SYMBOL (result)->remat &&
10559           (OP_SYMBOL (result)->liveTo > ic->seq ||
10560            ic->depth) &&
10561           !pi)
10562         {
10563           int size = AOP_SIZE (right) - 1;
10564           while (size--)
10565             emitcode ("dec", "%s", rname);
10566         }
10567     }
10568
10569   /* done */
10570   if (pi) pi->generated = 1;
10571   freeAsmop (result, NULL, ic, TRUE);
10572   freeAsmop (right, NULL, ic, TRUE);
10573
10574
10575 }
10576
10577 /*-----------------------------------------------------------------*/
10578 /* genPagedPointerSet - emitcode for Paged pointer put             */
10579 /*-----------------------------------------------------------------*/
10580 static void
10581 genPagedPointerSet (operand * right,
10582                     operand * result,
10583                     iCode * ic,
10584                     iCode *pi)
10585 {
10586   asmop *aop = NULL;
10587   char *rname;
10588   sym_link *retype, *letype;
10589
10590   retype = getSpec (operandType (right));
10591   letype = getSpec (operandType (result));
10592
10593   aopOp (result, ic, FALSE, FALSE);
10594
10595   /* if the value is already in a pointer register
10596      then don't need anything more */
10597   if (!AOP_INPREG (AOP (result)))
10598     {
10599       /* otherwise get a free pointer register */
10600       regs *preg;
10601         
10602       aop = newAsmop (0);
10603       preg = getFreePtr (ic, &aop, FALSE);
10604       emitcode ("mov", "%s,%s",
10605                 preg->name,
10606                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10607       rname = preg->name;
10608     }
10609   else
10610     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10611
10612   aopOp (right, ic, FALSE, FALSE);
10613
10614   /* if bitfield then unpack the bits */
10615   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10616     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10617   else
10618     {
10619       /* we have can just get the values */
10620       int size = AOP_SIZE (right);
10621       int offset = 0;
10622
10623       while (size--)
10624         {
10625           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10626
10627           emitcode ("movx", "@%s,a", rname);
10628
10629           if (size || pi)
10630             emitcode ("inc", "%s", rname);
10631
10632           offset++;
10633         }
10634     }
10635
10636   /* now some housekeeping stuff */
10637   if (aop)
10638     {
10639       if (pi) aopPut (AOP (result),rname,0);
10640       /* we had to allocate for this iCode */
10641       freeAsmop (NULL, aop, ic, TRUE);
10642     }
10643   else
10644     {
10645       /* we did not allocate which means left
10646          already in a pointer register, then
10647          if size > 0 && this could be used again
10648          we have to point it back to where it
10649          belongs */
10650       if (AOP_SIZE (right) > 1 &&
10651           !OP_SYMBOL (result)->remat &&
10652           (OP_SYMBOL (result)->liveTo > ic->seq ||
10653            ic->depth) &&
10654           !pi)
10655         {
10656           int size = AOP_SIZE (right) - 1;
10657           while (size--)
10658             emitcode ("dec", "%s", rname);
10659         }
10660     }
10661
10662   /* done */
10663   if (pi) pi->generated = 1;
10664   freeAsmop (result, NULL, ic, TRUE);
10665   freeAsmop (right, NULL, ic, TRUE);
10666
10667
10668 }
10669
10670 /*-----------------------------------------------------------------*/
10671 /* genFarPointerSet - set value from far space                     */
10672 /*-----------------------------------------------------------------*/
10673 static void
10674 genFarPointerSet (operand * right,
10675                   operand * result, iCode * ic, iCode *pi)
10676 {
10677   int size, offset, dopi=1;
10678   sym_link *retype = getSpec (operandType (right));
10679   sym_link *letype = getSpec (operandType (result));
10680
10681   aopOp (result, ic, FALSE, FALSE);
10682
10683   /* if the operand is already in dptr
10684      then we do nothing else we move the value to dptr */
10685   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10686     {
10687       /* if this is remateriazable */
10688       if (AOP_TYPE (result) == AOP_IMMD)
10689         emitcode ("mov", "dptr,%s", 
10690                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10691       else
10692         {
10693           /* we need to get it byte by byte */
10694           _startLazyDPSEvaluation ();
10695           if (AOP_TYPE (result) != AOP_DPTR)
10696             {
10697               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10698               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10699               if (options.model == MODEL_FLAT24)
10700                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10701             }
10702           else
10703             {
10704               /* We need to generate a load to DPTR indirect through DPTR. */
10705               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10706                 
10707               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10708               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10709               if (options.model == MODEL_FLAT24)
10710                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10711               emitcode ("pop", "dph");
10712               emitcode ("pop", "dpl");
10713               dopi=0;
10714             }
10715           _endLazyDPSEvaluation ();
10716         }
10717     }
10718   /* so dptr know contains the address */
10719   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10720
10721   /* if bit then unpack */
10722   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10723       if (AOP_INDPTRn(result)) {
10724           genSetDPTR(AOP(result)->aopu.dptr);
10725       }
10726       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10727       if (AOP_INDPTRn(result)) {
10728           genSetDPTR(0);
10729       }
10730   } else {
10731       size = AOP_SIZE (right);
10732       offset = 0;
10733       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10734           while (size--) {
10735               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10736               
10737               genSetDPTR(AOP(result)->aopu.dptr);
10738               emitcode ("movx", "@dptr,a");
10739               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10740                   emitcode ("inc", "dptr");
10741               genSetDPTR (0);
10742           }
10743       } else {
10744           _startLazyDPSEvaluation ();
10745           while (size--) {
10746               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10747               
10748               if (AOP_INDPTRn(result)) {
10749                   genSetDPTR(AOP(result)->aopu.dptr);
10750               } else {
10751                   genSetDPTR (0);
10752               }
10753               _flushLazyDPS ();
10754               
10755               emitcode ("movx", "@dptr,a");
10756               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10757                   emitcode ("inc", "dptr");
10758           }
10759           _endLazyDPSEvaluation ();
10760       }
10761   }
10762   
10763   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10764       if (!AOP_INDPTRn(result)) {
10765           _startLazyDPSEvaluation ();
10766           
10767           aopPut (AOP(result),"dpl",0);
10768           aopPut (AOP(result),"dph",1);
10769           if (options.model == MODEL_FLAT24)
10770               aopPut (AOP(result),"dpx",2);
10771
10772           _endLazyDPSEvaluation ();
10773       }
10774       pi->generated=1;
10775   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10776              AOP_SIZE(right) > 1 &&
10777              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10778       
10779       size = AOP_SIZE (right) - 1;
10780       if (AOP_INDPTRn(result)) {
10781           genSetDPTR(AOP(result)->aopu.dptr);
10782       } 
10783       while (size--) emitcode ("lcall","__decdptr");
10784       if (AOP_INDPTRn(result)) {
10785           genSetDPTR(0);
10786       }
10787   }
10788   freeAsmop (result, NULL, ic, TRUE);
10789   freeAsmop (right, NULL, ic, TRUE);
10790 }
10791
10792 /*-----------------------------------------------------------------*/
10793 /* genGenPointerSet - set value from generic pointer space         */
10794 /*-----------------------------------------------------------------*/
10795 static void
10796 genGenPointerSet (operand * right,
10797                   operand * result, iCode * ic, iCode *pi)
10798 {
10799   int size, offset;
10800   sym_link *retype = getSpec (operandType (right));
10801   sym_link *letype = getSpec (operandType (result));
10802
10803   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10804
10805   /* if the operand is already in dptr
10806      then we do nothing else we move the value to dptr */
10807   if (AOP_TYPE (result) != AOP_STR)
10808     {
10809       _startLazyDPSEvaluation ();
10810       /* if this is remateriazable */
10811       if (AOP_TYPE (result) == AOP_IMMD)
10812         {
10813           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10814           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10815           {
10816               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10817           }
10818           else
10819           {
10820               emitcode ("mov", 
10821                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10822           }
10823         }
10824       else
10825         {                       /* we need to get it byte by byte */
10826           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10827           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10828           if (options.model == MODEL_FLAT24) {
10829             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10830             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10831           } else {
10832             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10833           }
10834         }
10835       _endLazyDPSEvaluation ();
10836     }
10837   /* so dptr + b now contains the address */
10838   _G.bInUse++;
10839   aopOp (right, ic, FALSE, TRUE);
10840   _G.bInUse--;
10841     
10842
10843   /* if bit then unpack */
10844   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10845     {
10846         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10847     }
10848   else
10849     {
10850         size = AOP_SIZE (right);
10851         offset = 0;
10852
10853         _startLazyDPSEvaluation ();
10854         while (size--)
10855         {
10856             if (size)
10857             {
10858                 // Set two bytes at a time, passed in _AP & A.
10859                 // dptr will be incremented ONCE by __gptrputWord.
10860                 //
10861                 // Note: any change here must be coordinated
10862                 // with the implementation of __gptrputWord
10863                 // in device/lib/_gptrput.c
10864                 emitcode("mov", "_ap, %s", 
10865                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10866                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10867                 
10868                 genSetDPTR (0);
10869                 _flushLazyDPS ();
10870                 emitcode ("lcall", "__gptrputWord");
10871                 size--;
10872             }
10873             else
10874             {
10875                 // Only one byte to put.
10876                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10877
10878                 genSetDPTR (0);
10879                 _flushLazyDPS ();               
10880                 emitcode ("lcall", "__gptrput");
10881             }
10882             
10883             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10884             {
10885                 emitcode ("inc", "dptr");
10886             }
10887         }
10888         _endLazyDPSEvaluation ();
10889     }
10890
10891   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10892       _startLazyDPSEvaluation ();
10893       
10894       aopPut (AOP(result),"dpl",0);
10895       aopPut (AOP(result),"dph",1);
10896       if (options.model == MODEL_FLAT24) {
10897           aopPut (AOP(result),"dpx",2);
10898           aopPut (AOP(result),"b",3);
10899       } else {
10900           aopPut (AOP(result),"b",2);
10901       }
10902       _endLazyDPSEvaluation ();
10903       
10904       pi->generated=1;
10905   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10906              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10907       
10908       size = AOP_SIZE (right) - 1;
10909       while (size--) emitcode ("lcall","__decdptr");
10910   }
10911   freeAsmop (result, NULL, ic, TRUE);
10912   freeAsmop (right, NULL, ic, TRUE);
10913 }
10914
10915 /*-----------------------------------------------------------------*/
10916 /* genPointerSet - stores the value into a pointer location        */
10917 /*-----------------------------------------------------------------*/
10918 static void
10919 genPointerSet (iCode * ic, iCode *pi)
10920 {
10921   operand *right, *result;
10922   sym_link *type, *etype;
10923   int p_type;
10924
10925   D (emitcode (";", "genPointerSet "););
10926
10927   right = IC_RIGHT (ic);
10928   result = IC_RESULT (ic);
10929
10930   /* depending on the type of pointer we need to
10931      move it to the correct pointer register */
10932   type = operandType (result);
10933   etype = getSpec (type);
10934   /* if left is of type of pointer then it is simple */
10935   if (IS_PTR (type) && !IS_FUNC (type->next))
10936     {
10937       p_type = DCL_TYPE (type);
10938     }
10939   else
10940     {
10941       /* we have to go by the storage class */
10942       p_type = PTR_TYPE (SPEC_OCLS (etype));
10943     }
10944   /* special case when cast remat */
10945   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10946       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10947           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10948           type = operandType (result);
10949           p_type = DCL_TYPE (type);
10950   }
10951
10952   /* now that we have the pointer type we assign
10953      the pointer values */
10954   switch (p_type)
10955     {
10956
10957     case POINTER:
10958     case IPOINTER:
10959       genNearPointerSet (right, result, ic, pi);
10960       break;
10961
10962     case PPOINTER:
10963       genPagedPointerSet (right, result, ic, pi);
10964       break;
10965
10966     case FPOINTER:
10967       genFarPointerSet (right, result, ic, pi);
10968       break;
10969
10970     case GPOINTER:
10971       genGenPointerSet (right, result, ic, pi);
10972       break;
10973
10974     default:
10975       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10976               "genPointerSet: illegal pointer type");
10977     }
10978
10979 }
10980
10981 /*-----------------------------------------------------------------*/
10982 /* genIfx - generate code for Ifx statement                        */
10983 /*-----------------------------------------------------------------*/
10984 static void
10985 genIfx (iCode * ic, iCode * popIc)
10986 {
10987   operand *cond = IC_COND (ic);
10988   int isbit = 0;
10989
10990   D (emitcode (";", "genIfx "););
10991
10992   aopOp (cond, ic, FALSE, FALSE);
10993
10994   /* get the value into acc */
10995   if (AOP_TYPE (cond) != AOP_CRY)
10996     {
10997         toBoolean (cond);
10998     }
10999   else
11000     {
11001         isbit = 1;
11002     }
11003     
11004   /* the result is now in the accumulator */
11005   freeAsmop (cond, NULL, ic, TRUE);
11006
11007   /* if there was something to be popped then do it */
11008   if (popIc)
11009     genIpop (popIc);
11010
11011   /* if the condition is  a bit variable */
11012   if (isbit && IS_ITEMP (cond) &&
11013       SPIL_LOC (cond))
11014     {
11015         genIfxJump (ic, SPIL_LOC (cond)->rname);
11016     }
11017   else if (isbit && !IS_ITEMP (cond))
11018     {
11019         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11020     }
11021   else
11022     {
11023         genIfxJump (ic, "a");
11024     }
11025
11026   ic->generated = 1;
11027 }
11028
11029 /*-----------------------------------------------------------------*/
11030 /* genAddrOf - generates code for address of                       */
11031 /*-----------------------------------------------------------------*/
11032 static void
11033 genAddrOf (iCode * ic)
11034 {
11035   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11036   int size, offset;
11037
11038   D (emitcode (";", "genAddrOf ");
11039     );
11040
11041   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11042
11043   /* if the operand is on the stack then we
11044      need to get the stack offset of this
11045      variable */
11046   if (sym->onStack) {
11047       
11048       /* if 10 bit stack */
11049       if (options.stack10bit) {
11050           char buff[10];
11051           int  offset;
11052           
11053           tsprintf(buff, sizeof(buff), 
11054                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11055           /* if it has an offset then we need to compute it */
11056 /*        emitcode ("subb", "a,#!constbyte", */
11057 /*                  -((sym->stack < 0) ? */
11058 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11059 /*                    ((short) sym->stack)) & 0xff); */
11060 /*        emitcode ("mov","b,a"); */
11061 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11062 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11063 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11064           if (sym->stack) {
11065               emitcode ("mov", "a,_bpx");
11066               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
11067                                              ((char) (sym->stack - _G.nRegsSaved)) :
11068                                              ((char) sym->stack )) & 0xff);
11069               emitcode ("mov", "b,a");
11070               emitcode ("mov", "a,_bpx+1");
11071               
11072               offset = (((sym->stack < 0) ? 
11073                          ((short) (sym->stack - _G.nRegsSaved)) :
11074                          ((short) sym->stack )) >> 8) & 0xff;
11075           
11076               emitcode ("addc","a,#!constbyte", offset);
11077
11078               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11079               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11080               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11081           } else {
11082               /* we can just move _bp */
11083               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11084               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11085               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11086           }       
11087       } else {
11088           /* if it has an offset then we need to compute it */
11089           if (sym->stack) {
11090               emitcode ("mov", "a,_bp");
11091               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11092               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11093           } else {
11094               /* we can just move _bp */
11095               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11096           }
11097           /* fill the result with zero */
11098           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11099           
11100           
11101           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11102               fprintf (stderr,
11103                        "*** warning: pointer to stack var truncated.\n");
11104           }
11105
11106           offset = 1;
11107           while (size--) {
11108               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11109           }      
11110       }
11111       goto release;
11112   }
11113
11114   /* object not on stack then we need the name */
11115   size = AOP_SIZE (IC_RESULT (ic));
11116   offset = 0;
11117
11118   while (size--)
11119     {
11120       char s[SDCC_NAME_MAX];
11121       if (offset) {
11122           switch (offset) {
11123           case 1:
11124               tsprintf(s, sizeof(s), "#!his",sym->rname);
11125               break;
11126           case 2:
11127               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11128               break;
11129           case 3:
11130               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11131               break;
11132           default: /* should not need this (just in case) */
11133               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11134                        sym->rname,
11135                        offset * 8);
11136           }
11137       } 
11138       else
11139       {
11140           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11141       }
11142         
11143       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11144     }
11145
11146 release:
11147   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11148
11149 }
11150
11151 #if 0 // obsolete, and buggy for != xdata
11152 /*-----------------------------------------------------------------*/
11153 /* genArrayInit - generates code for address of                       */
11154 /*-----------------------------------------------------------------*/
11155 static void
11156 genArrayInit (iCode * ic)
11157 {
11158     literalList *iLoop;
11159     int         ix, count;
11160     int         elementSize = 0, eIndex;
11161     unsigned    val, lastVal;
11162     sym_link    *type;
11163     operand     *left=IC_LEFT(ic);
11164     
11165     D (emitcode (";", "genArrayInit "););
11166
11167     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11168     
11169     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11170     {
11171         // Load immediate value into DPTR.
11172         emitcode("mov", "dptr, %s",
11173              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11174     }
11175     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11176     {
11177 #if 0
11178       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11179               "Unexpected operand to genArrayInit.\n");
11180       exit(1);
11181 #else
11182       // a regression because of SDCCcse.c:1.52
11183       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11184       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11185       if (options.model == MODEL_FLAT24)
11186         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11187 #endif
11188     }
11189     
11190     type = operandType(IC_LEFT(ic));
11191     
11192     if (type && type->next)
11193     {
11194         elementSize = getSize(type->next);
11195     }
11196     else
11197     {
11198         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11199                                 "can't determine element size in genArrayInit.\n");
11200         exit(1);
11201     }
11202     
11203     iLoop = IC_ARRAYILIST(ic);
11204     lastVal = 0xffff;
11205     
11206     while (iLoop)
11207     {
11208         bool firstpass = TRUE;
11209         
11210         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
11211                  iLoop->count, (int)iLoop->literalValue, elementSize);
11212         
11213         ix = iLoop->count;
11214         
11215         while (ix)
11216         {
11217             symbol *tlbl = NULL;
11218             
11219             count = ix > 256 ? 256 : ix;
11220             
11221             if (count > 1)
11222             {
11223                 tlbl = newiTempLabel (NULL);
11224                 if (firstpass || (count & 0xff))
11225                 {
11226                     emitcode("mov", "b, #!constbyte", count & 0xff);
11227                 }
11228                 
11229                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11230             }
11231             
11232             firstpass = FALSE;
11233                 
11234             for (eIndex = 0; eIndex < elementSize; eIndex++)
11235             {
11236                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11237                 if (val != lastVal)
11238                 {
11239                     emitcode("mov", "a, #!constbyte", val);
11240                     lastVal = val;
11241                 }
11242                 
11243                 emitcode("movx", "@dptr, a");
11244                 emitcode("inc", "dptr");
11245             }
11246             
11247             if (count > 1)
11248             {
11249                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11250             }
11251             
11252             ix -= count;
11253         }
11254         
11255         iLoop = iLoop->next;
11256     }
11257     
11258     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11259 }
11260 #endif
11261
11262 /*-----------------------------------------------------------------*/
11263 /* genFarFarAssign - assignment when both are in far space         */
11264 /*-----------------------------------------------------------------*/
11265 static void
11266 genFarFarAssign (operand * result, operand * right, iCode * ic)
11267 {
11268   int size = AOP_SIZE (right);
11269   int offset = 0;
11270   symbol *rSym = NULL;
11271
11272   if (size == 1)
11273   {
11274       /* quick & easy case. */
11275       D(emitcode(";","genFarFarAssign (1 byte case)"););      
11276       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11277       freeAsmop (right, NULL, ic, FALSE);
11278       /* now assign DPTR to result */
11279       _G.accInUse++;
11280       aopOp(result, ic, FALSE, FALSE);
11281       _G.accInUse--;
11282       aopPut(AOP(result), "a", 0);
11283       freeAsmop(result, NULL, ic, FALSE);
11284       return;
11285   }
11286   
11287   /* See if we've got an underlying symbol to abuse. */
11288   if (IS_SYMOP(result) && OP_SYMBOL(result))
11289   {
11290       if (IS_TRUE_SYMOP(result))
11291       {
11292           rSym = OP_SYMBOL(result);
11293       }
11294       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11295       {
11296           rSym = OP_SYMBOL(result)->usl.spillLoc;
11297       }
11298   }
11299              
11300   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11301   {
11302       /* We can use the '390 auto-toggle feature to good effect here. */
11303       
11304       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11305       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11306       emitcode ("mov", "dptr,#%s", rSym->rname); 
11307       /* DP2 = result, DP1 = right, DP1 is current. */
11308       while (size)
11309       {
11310           emitcode("movx", "a,@dptr");
11311           emitcode("movx", "@dptr,a");
11312           if (--size)
11313           {
11314                emitcode("inc", "dptr");
11315                emitcode("inc", "dptr");
11316           }
11317       }
11318       emitcode("mov", "dps,#0");
11319       freeAsmop (right, NULL, ic, FALSE);
11320 #if 0
11321 some alternative code for processors without auto-toggle
11322 no time to test now, so later well put in...kpb
11323         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11324         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11325         emitcode ("mov", "dptr,#%s", rSym->rname); 
11326         /* DP2 = result, DP1 = right, DP1 is current. */
11327         while (size)
11328         {
11329           --size;
11330           emitcode("movx", "a,@dptr");
11331           if (size)
11332             emitcode("inc", "dptr");
11333           emitcode("inc", "dps");
11334           emitcode("movx", "@dptr,a");
11335           if (size)
11336             emitcode("inc", "dptr");
11337           emitcode("inc", "dps");
11338         }
11339         emitcode("mov", "dps,#0");
11340         freeAsmop (right, NULL, ic, FALSE);
11341 #endif
11342   }
11343   else
11344   {
11345       D (emitcode (";", "genFarFarAssign"););
11346       aopOp (result, ic, TRUE, TRUE);
11347
11348       _startLazyDPSEvaluation ();
11349       
11350       while (size--)
11351         {
11352           aopPut (AOP (result),
11353                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11354           offset++;
11355         }
11356       _endLazyDPSEvaluation ();
11357       freeAsmop (result, NULL, ic, FALSE);
11358       freeAsmop (right, NULL, ic, FALSE);
11359   }
11360 }
11361
11362 /*-----------------------------------------------------------------*/
11363 /* genAssign - generate code for assignment                        */
11364 /*-----------------------------------------------------------------*/
11365 static void
11366 genAssign (iCode * ic)
11367 {
11368   operand *result, *right;
11369   int size, offset;
11370   unsigned long lit = 0L;
11371
11372   D (emitcode (";", "genAssign ");
11373     );
11374
11375   result = IC_RESULT (ic);
11376   right = IC_RIGHT (ic);
11377
11378   /* if they are the same */
11379   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11380     return;
11381
11382   aopOp (right, ic, FALSE, FALSE);
11383
11384   emitcode (";", "genAssign: resultIsFar = %s",
11385             isOperandInFarSpace (result) ?
11386             "TRUE" : "FALSE");
11387
11388   /* special case both in far space */
11389   if ((AOP_TYPE (right) == AOP_DPTR ||
11390        AOP_TYPE (right) == AOP_DPTR2) &&
11391   /* IS_TRUE_SYMOP(result)       && */
11392       isOperandInFarSpace (result))
11393     {
11394       genFarFarAssign (result, right, ic);
11395       return;
11396     }
11397
11398   aopOp (result, ic, TRUE, FALSE);
11399
11400   /* if they are the same registers */
11401   if (sameRegs (AOP (right), AOP (result)))
11402     goto release;
11403
11404   /* if the result is a bit */
11405   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11406     {
11407       /* if the right size is a literal then
11408          we know what the value is */
11409       if (AOP_TYPE (right) == AOP_LIT)
11410         {
11411           if (((int) operandLitValue (right)))
11412             aopPut (AOP (result), one, 0);
11413           else
11414             aopPut (AOP (result), zero, 0);
11415           goto release;
11416         }
11417
11418       /* the right is also a bit variable */
11419       if (AOP_TYPE (right) == AOP_CRY)
11420         {
11421           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11422           aopPut (AOP (result), "c", 0);
11423           goto release;
11424         }
11425
11426       /* we need to or */
11427       toBoolean (right);
11428       aopPut (AOP (result), "a", 0);
11429       goto release;
11430     }
11431
11432   /* bit variables done */
11433   /* general case */
11434   size = AOP_SIZE (result);
11435   offset = 0;
11436   if (AOP_TYPE (right) == AOP_LIT)
11437     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11438
11439   if ((size > 1) &&
11440       (AOP_TYPE (result) != AOP_REG) &&
11441       (AOP_TYPE (right) == AOP_LIT) &&
11442       !IS_FLOAT (operandType (right)))
11443     {
11444       _startLazyDPSEvaluation ();
11445       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11446         {
11447           aopPut (AOP (result),
11448                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11449                   offset);
11450           offset++;
11451           size--;
11452         }
11453       /* And now fill the rest with zeros. */
11454       if (size)
11455         {
11456           emitcode ("clr", "a");
11457         }
11458       while (size--)
11459         {
11460           aopPut (AOP (result), "a", offset++);
11461         }
11462       _endLazyDPSEvaluation ();
11463     }
11464   else
11465     {
11466       _startLazyDPSEvaluation ();
11467       while (size--)
11468         {
11469           aopPut (AOP (result),
11470                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11471                   offset);
11472           offset++;
11473         }
11474       _endLazyDPSEvaluation ();
11475     }
11476
11477 release:
11478   freeAsmop (right, NULL, ic, FALSE);
11479   freeAsmop (result, NULL, ic, TRUE);
11480 }
11481
11482 /*-----------------------------------------------------------------*/
11483 /* genJumpTab - generates code for jump table                      */
11484 /*-----------------------------------------------------------------*/
11485 static void
11486 genJumpTab (iCode * ic)
11487 {
11488   symbol *jtab;
11489   char *l;
11490
11491   D (emitcode (";", "genJumpTab ");
11492     );
11493
11494   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11495   /* get the condition into accumulator */
11496   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11497   MOVA (l);
11498   /* multiply by four! */
11499   emitcode ("add", "a,acc");
11500   emitcode ("add", "a,acc");
11501   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11502
11503   jtab = newiTempLabel (NULL);
11504   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11505   emitcode ("jmp", "@a+dptr");
11506   emitcode ("", "!tlabeldef", jtab->key + 100);
11507   /* now generate the jump labels */
11508   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11509        jtab = setNextItem (IC_JTLABELS (ic)))
11510     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11511
11512 }
11513
11514 /*-----------------------------------------------------------------*/
11515 /* genCast - gen code for casting                                  */
11516 /*-----------------------------------------------------------------*/
11517 static void
11518 genCast (iCode * ic)
11519 {
11520   operand *result = IC_RESULT (ic);
11521   sym_link *ctype = operandType (IC_LEFT (ic));
11522   sym_link *rtype = operandType (IC_RIGHT (ic));
11523   operand *right = IC_RIGHT (ic);
11524   int size, offset;
11525
11526   D (emitcode (";", "genCast "););
11527
11528   /* if they are equivalent then do nothing */
11529   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11530     return;
11531
11532   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11533   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11534
11535   /* if the result is a bit */
11536   if (IS_BITVAR (OP_SYMBOL (result)->type)
11537       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11538     {
11539       /* if the right size is a literal then
11540          we know what the value is */
11541       if (AOP_TYPE (right) == AOP_LIT)
11542         {
11543           if (((int) operandLitValue (right)))
11544             aopPut (AOP (result), one, 0);
11545           else
11546             aopPut (AOP (result), zero, 0);
11547
11548           goto release;
11549         }
11550
11551       /* the right is also a bit variable */
11552       if (AOP_TYPE (right) == AOP_CRY)
11553         {
11554           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11555           aopPut (AOP (result), "c", 0);
11556           goto release;
11557         }
11558
11559       /* we need to or */
11560       toBoolean (right);
11561       aopPut (AOP (result), "a", 0);
11562       goto release;
11563     }
11564
11565   /* if they are the same size : or less */
11566   if (AOP_SIZE (result) <= AOP_SIZE (right))
11567     {
11568
11569       /* if they are in the same place */
11570       if (sameRegs (AOP (right), AOP (result)))
11571         goto release;
11572
11573       /* if they in different places then copy */
11574       size = AOP_SIZE (result);
11575       offset = 0;
11576       _startLazyDPSEvaluation ();
11577       while (size--)
11578         {
11579           aopPut (AOP (result),
11580                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11581                   offset);
11582           offset++;
11583         }
11584       _endLazyDPSEvaluation ();
11585       goto release;
11586     }
11587
11588
11589   /* if the result is of type pointer */
11590   if (IS_PTR (ctype))
11591     {
11592
11593       int p_type;
11594       sym_link *type = operandType (right);
11595
11596       /* pointer to generic pointer */
11597       if (IS_GENPTR (ctype))
11598         {
11599           if (IS_PTR (type))
11600             {
11601               p_type = DCL_TYPE (type);
11602             }
11603           else
11604             {
11605 #if OLD_CAST_BEHAVIOR
11606               /* KV: we are converting a non-pointer type to
11607                * a generic pointer. This (ifdef'd out) code
11608                * says that the resulting generic pointer
11609                * should have the same class as the storage
11610                * location of the non-pointer variable.
11611                *
11612                * For example, converting an int (which happens
11613                * to be stored in DATA space) to a pointer results
11614                * in a DATA generic pointer; if the original int
11615                * in XDATA space, so will be the resulting pointer.
11616                *
11617                * I don't like that behavior, and thus this change:
11618                * all such conversions will be forced to XDATA and
11619                * throw a warning. If you want some non-XDATA
11620                * type, or you want to suppress the warning, you
11621                * must go through an intermediate cast, like so:
11622                *
11623                * char _generic *gp = (char _xdata *)(intVar);
11624                */
11625               sym_link *etype = getSpec (type);
11626
11627               /* we have to go by the storage class */
11628               if (SPEC_OCLS (etype) != generic)
11629                 {
11630                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11631                 }
11632               else
11633 #endif
11634                 {
11635                   /* Converting unknown class (i.e. register variable)
11636                    * to generic pointer. This is not good, but
11637                    * we'll make a guess (and throw a warning).
11638                    */
11639                   p_type = FPOINTER;
11640                   werror (W_INT_TO_GEN_PTR_CAST);
11641                 }
11642             }
11643
11644           /* the first two bytes are known */
11645           size = GPTRSIZE - 1;
11646           offset = 0;
11647           _startLazyDPSEvaluation ();
11648           while (size--)
11649             {
11650               aopPut (AOP (result),
11651                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11652                       offset);
11653               offset++;
11654             }
11655           _endLazyDPSEvaluation ();
11656
11657           /* the last byte depending on type */
11658             {
11659                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11660                 char gpValStr[10];
11661             
11662                 if (gpVal == -1)
11663                 {
11664                     // pointerTypeToGPByte will have bitched.
11665                     exit(1);
11666                 }
11667             
11668                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11669                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11670             }
11671           goto release;
11672         }
11673
11674       /* just copy the pointers */
11675       size = AOP_SIZE (result);
11676       offset = 0;
11677       _startLazyDPSEvaluation ();
11678       while (size--)
11679         {
11680           aopPut (AOP (result),
11681                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11682                   offset);
11683           offset++;
11684         }
11685       _endLazyDPSEvaluation ();
11686       goto release;
11687     }
11688
11689   /* so we now know that the size of destination is greater
11690      than the size of the source */
11691   /* we move to result for the size of source */
11692   size = AOP_SIZE (right);
11693   offset = 0;
11694   _startLazyDPSEvaluation ();
11695   while (size--)
11696     {
11697       aopPut (AOP (result),
11698               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11699               offset);
11700       offset++;
11701     }
11702   _endLazyDPSEvaluation ();
11703
11704   /* now depending on the sign of the source && destination */
11705   size = AOP_SIZE (result) - AOP_SIZE (right);
11706   /* if unsigned or not an integral type */
11707   /* also, if the source is a bit, we don't need to sign extend, because
11708    * it can't possibly have set the sign bit.
11709    */
11710   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11711     {
11712       while (size--)
11713         {
11714           aopPut (AOP (result), zero, offset++);
11715         }
11716     }
11717   else
11718     {
11719       /* we need to extend the sign :{ */
11720       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11721                         FALSE, FALSE, NULL));
11722       emitcode ("rlc", "a");
11723       emitcode ("subb", "a,acc");
11724       while (size--)
11725         aopPut (AOP (result), "a", offset++);
11726     }
11727
11728   /* we are done hurray !!!! */
11729
11730 release:
11731   freeAsmop (right, NULL, ic, TRUE);
11732   freeAsmop (result, NULL, ic, TRUE);
11733
11734 }
11735
11736 /*-----------------------------------------------------------------*/
11737 /* genDjnz - generate decrement & jump if not zero instrucion      */
11738 /*-----------------------------------------------------------------*/
11739 static int
11740 genDjnz (iCode * ic, iCode * ifx)
11741 {
11742   symbol *lbl, *lbl1;
11743   if (!ifx)
11744     return 0;
11745
11746   /* if the if condition has a false label
11747      then we cannot save */
11748   if (IC_FALSE (ifx))
11749     return 0;
11750
11751   /* if the minus is not of the form
11752      a = a - 1 */
11753   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11754       !IS_OP_LITERAL (IC_RIGHT (ic)))
11755     return 0;
11756
11757   if (operandLitValue (IC_RIGHT (ic)) != 1)
11758     return 0;
11759
11760   /* if the size of this greater than one then no
11761      saving */
11762   if (getSize (operandType (IC_RESULT (ic))) > 1)
11763     return 0;
11764
11765   /* otherwise we can save BIG */
11766   D(emitcode(";", "genDjnz"););
11767
11768   lbl = newiTempLabel (NULL);
11769   lbl1 = newiTempLabel (NULL);
11770
11771   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11772
11773   if (AOP_NEEDSACC(IC_RESULT(ic)))
11774   {
11775       /* If the result is accessed indirectly via
11776        * the accumulator, we must explicitly write
11777        * it back after the decrement.
11778        */
11779       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11780       
11781       if (strcmp(rByte, "a"))
11782       {
11783            /* Something is hopelessly wrong */
11784            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11785                    __FILE__, __LINE__);
11786            /* We can just give up; the generated code will be inefficient,
11787             * but what the hey.
11788             */
11789            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11790            return 0;
11791       }
11792       emitcode ("dec", "%s", rByte);
11793       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11794       emitcode ("jnz", "!tlabel", lbl->key + 100);
11795   }
11796   else if (IS_AOP_PREG (IC_RESULT (ic)))
11797     {
11798       emitcode ("dec", "%s",
11799                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11800       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11801       emitcode ("jnz", "!tlabel", lbl->key + 100);
11802     }
11803   else
11804     {
11805       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11806                 lbl->key + 100);
11807     }
11808   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11809   emitcode ("", "!tlabeldef", lbl->key + 100);
11810   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11811   emitcode ("", "!tlabeldef", lbl1->key + 100);
11812
11813   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11814   ifx->generated = 1;
11815   return 1;
11816 }
11817
11818 /*-----------------------------------------------------------------*/
11819 /* genReceive - generate code for a receive iCode                  */
11820 /*-----------------------------------------------------------------*/
11821 static void
11822 genReceive (iCode * ic)
11823 {
11824     int size = getSize (operandType (IC_RESULT (ic)));
11825     int offset = 0;
11826     int rb1off ;
11827     
11828     D (emitcode (";", "genReceive "););
11829
11830     if (ic->argreg == 1) 
11831     {
11832         /* first parameter */
11833         if (AOP_IS_STR(IC_RESULT(ic)))
11834         {
11835             /* Nothing to do: it's already in the proper place. */
11836             return;
11837         }
11838         else
11839         {
11840             bool useDp2;
11841             
11842             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11843                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11844                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11845             
11846             _G.accInUse++;
11847             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11848             _G.accInUse--; 
11849             
11850             /* Sanity checking... */
11851             if (AOP_USESDPTR(IC_RESULT(ic)))
11852             {
11853                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11854                         "genReceive got unexpected DPTR.");
11855             }
11856             assignResultValue (IC_RESULT (ic));
11857         }
11858     } 
11859     else 
11860     { 
11861         /* second receive onwards */
11862         /* this gets a little tricky since unused recevies will be
11863          eliminated, we have saved the reg in the type field . and
11864          we use that to figure out which register to use */
11865         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11866         rb1off = ic->argreg;
11867         while (size--) 
11868         {
11869             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11870         }
11871     }
11872     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11873 }
11874
11875 /*-----------------------------------------------------------------*/
11876 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11877 /*-----------------------------------------------------------------*/
11878 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11879 {
11880     operand *from , *to , *count;
11881     symbol *lbl;
11882     bitVect *rsave;
11883     int i;
11884
11885     /* we know it has to be 3 parameters */
11886     assert (nparms == 3);
11887     
11888     rsave = newBitVect(16);
11889     /* save DPTR if it needs to be saved */
11890     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891             if (bitVectBitValue(ic->rMask,i))
11892                     rsave = bitVectSetBit(rsave,i);
11893     }
11894     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11896     savermask(rsave);
11897     
11898     to = parms[0];
11899     from = parms[1];
11900     count = parms[2];
11901
11902     aopOp (from, ic->next, FALSE, FALSE);
11903
11904     /* get from into DPTR1 */
11905     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11906     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11907     if (options.model == MODEL_FLAT24) {
11908         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11909     }
11910
11911     freeAsmop (from, NULL, ic, FALSE);
11912     aopOp (to, ic, FALSE, FALSE);
11913     /* get "to" into DPTR */
11914     /* if the operand is already in dptr
11915        then we do nothing else we move the value to dptr */
11916     if (AOP_TYPE (to) != AOP_STR) {
11917         /* if already in DPTR then we need to push */
11918         if (AOP_TYPE(to) == AOP_DPTR) {
11919             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11920             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11921             if (options.model == MODEL_FLAT24)
11922                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11923             emitcode ("pop", "dph");
11924             emitcode ("pop", "dpl");        
11925         } else {
11926             _startLazyDPSEvaluation ();
11927             /* if this is remateriazable */
11928             if (AOP_TYPE (to) == AOP_IMMD) {
11929                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11930             } else {                    /* we need to get it byte by byte */
11931                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11932                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11933                 if (options.model == MODEL_FLAT24) {
11934                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11935                 }
11936             }
11937             _endLazyDPSEvaluation ();
11938         }
11939     }
11940     freeAsmop (to, NULL, ic, FALSE);
11941     _G.dptrInUse = _G.dptr1InUse = 1;
11942     aopOp (count, ic->next->next, FALSE,FALSE);
11943     lbl =newiTempLabel(NULL);
11944
11945     /* now for the actual copy */
11946     if (AOP_TYPE(count) == AOP_LIT && 
11947         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11948         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11949         if (fromc) {
11950             emitcode ("lcall","__bi_memcpyc2x_s");
11951         } else {
11952             emitcode ("lcall","__bi_memcpyx2x_s");
11953         }
11954         freeAsmop (count, NULL, ic, FALSE);
11955     } else {
11956         symbol *lbl1 = newiTempLabel(NULL);
11957         
11958         emitcode (";"," Auto increment but no djnz");
11959         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11960         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11961         freeAsmop (count, NULL, ic, FALSE);
11962         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11963         emitcode ("","!tlabeldef",lbl->key+100);
11964         if (fromc) {
11965             emitcode ("clr","a");
11966             emitcode ("movc", "a,@a+dptr");
11967         } else 
11968             emitcode ("movx", "a,@dptr");
11969         emitcode ("movx", "@dptr,a");
11970         emitcode ("inc", "dptr");
11971         emitcode ("inc", "dptr");
11972         emitcode ("mov","a,b");
11973         emitcode ("orl","a,_ap");
11974         emitcode ("jz","!tlabel",lbl1->key+100);
11975         emitcode ("mov","a,_ap");
11976         emitcode ("add","a,#!constbyte",0xFF);
11977         emitcode ("mov","_ap,a");
11978         emitcode ("mov","a,b");
11979         emitcode ("addc","a,#!constbyte",0xFF);
11980         emitcode ("mov","b,a");
11981         emitcode ("sjmp","!tlabel",lbl->key+100);
11982         emitcode ("","!tlabeldef",lbl1->key+100);
11983     }
11984     emitcode ("mov", "dps,#0"); 
11985     _G.dptrInUse = _G.dptr1InUse = 0;
11986     unsavermask(rsave);
11987
11988 }
11989
11990 /*-----------------------------------------------------------------*/
11991 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11992 /*-----------------------------------------------------------------*/
11993 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11994 {
11995     operand *from , *to , *count;
11996     symbol *lbl,*lbl2;
11997     bitVect *rsave;
11998     int i;
11999
12000     /* we know it has to be 3 parameters */
12001     assert (nparms == 3);
12002     
12003     rsave = newBitVect(16);
12004     /* save DPTR if it needs to be saved */
12005     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12006             if (bitVectBitValue(ic->rMask,i))
12007                     rsave = bitVectSetBit(rsave,i);
12008     }
12009     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12010                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12011     savermask(rsave);
12012     
12013     to = parms[0];
12014     from = parms[1];
12015     count = parms[2];
12016
12017     aopOp (from, ic->next, FALSE, FALSE);
12018
12019     /* get from into DPTR1 */
12020     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12021     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12022     if (options.model == MODEL_FLAT24) {
12023         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12024     }
12025
12026     freeAsmop (from, NULL, ic, FALSE);
12027     aopOp (to, ic, FALSE, FALSE);
12028     /* get "to" into DPTR */
12029     /* if the operand is already in dptr
12030        then we do nothing else we move the value to dptr */
12031     if (AOP_TYPE (to) != AOP_STR) {
12032         /* if already in DPTR then we need to push */
12033         if (AOP_TYPE(to) == AOP_DPTR) {
12034             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12035             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12036             if (options.model == MODEL_FLAT24)
12037                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12038             emitcode ("pop", "dph");
12039             emitcode ("pop", "dpl");        
12040         } else {
12041             _startLazyDPSEvaluation ();
12042             /* if this is remateriazable */
12043             if (AOP_TYPE (to) == AOP_IMMD) {
12044                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12045             } else {                    /* we need to get it byte by byte */
12046                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12047                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12048                 if (options.model == MODEL_FLAT24) {
12049                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12050                 }
12051             }
12052             _endLazyDPSEvaluation ();
12053         }
12054     }
12055     freeAsmop (to, NULL, ic, FALSE);
12056     _G.dptrInUse = _G.dptr1InUse = 1;
12057     aopOp (count, ic->next->next, FALSE,FALSE);
12058     lbl =newiTempLabel(NULL);
12059     lbl2 =newiTempLabel(NULL);
12060
12061     /* now for the actual compare */
12062     if (AOP_TYPE(count) == AOP_LIT && 
12063         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12064         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12065         if (fromc)
12066             emitcode("lcall","__bi_memcmpc2x_s");
12067         else
12068             emitcode("lcall","__bi_memcmpx2x_s");
12069         freeAsmop (count, NULL, ic, FALSE);
12070         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12071         aopPut(AOP(IC_RESULT(ic)),"a",0);
12072         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12073     } else {
12074         symbol *lbl1 = newiTempLabel(NULL);
12075
12076         emitcode("push","ar0");         
12077         emitcode (";"," Auto increment but no djnz");
12078         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12079         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12080         freeAsmop (count, NULL, ic, FALSE);
12081         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12082         emitcode ("","!tlabeldef",lbl->key+100);
12083         if (fromc) {
12084             emitcode ("clr","a");
12085             emitcode ("movc", "a,@a+dptr");
12086         } else 
12087             emitcode ("movx", "a,@dptr");
12088         emitcode ("mov","r0,a");
12089         emitcode ("movx", "a,@dptr");
12090         emitcode ("clr","c");
12091         emitcode ("subb","a,r0");
12092         emitcode ("jnz","!tlabel",lbl2->key+100);
12093         emitcode ("inc", "dptr");
12094         emitcode ("inc", "dptr");
12095         emitcode ("mov","a,b");
12096         emitcode ("orl","a,_ap");
12097         emitcode ("jz","!tlabel",lbl1->key+100);
12098         emitcode ("mov","a,_ap");
12099         emitcode ("add","a,#!constbyte",0xFF);
12100         emitcode ("mov","_ap,a");
12101         emitcode ("mov","a,b");
12102         emitcode ("addc","a,#!constbyte",0xFF);
12103         emitcode ("mov","b,a");
12104         emitcode ("sjmp","!tlabel",lbl->key+100);
12105         emitcode ("","!tlabeldef",lbl1->key+100);
12106         emitcode ("clr","a");
12107         emitcode ("","!tlabeldef",lbl2->key+100);
12108         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12109         aopPut(AOP(IC_RESULT(ic)),"a",0);
12110         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12111         emitcode("pop","ar0");
12112         emitcode ("mov", "dps,#0");      
12113     }
12114     _G.dptrInUse = _G.dptr1InUse = 0;
12115     unsavermask(rsave);
12116
12117 }
12118
12119 /*-----------------------------------------------------------------*/
12120 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12121 /* port, first parameter output area second parameter pointer to   */
12122 /* port third parameter count                                      */
12123 /*-----------------------------------------------------------------*/
12124 static void genInp( iCode *ic, int nparms, operand **parms)
12125 {
12126     operand *from , *to , *count;
12127     symbol *lbl;
12128     bitVect *rsave;
12129     int i;
12130
12131     /* we know it has to be 3 parameters */
12132     assert (nparms == 3);
12133     
12134     rsave = newBitVect(16);
12135     /* save DPTR if it needs to be saved */
12136     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12137             if (bitVectBitValue(ic->rMask,i))
12138                     rsave = bitVectSetBit(rsave,i);
12139     }
12140     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12141                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12142     savermask(rsave);
12143     
12144     to = parms[0];
12145     from = parms[1];
12146     count = parms[2];
12147
12148     aopOp (from, ic->next, FALSE, FALSE);
12149
12150     /* get from into DPTR1 */
12151     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12152     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12153     if (options.model == MODEL_FLAT24) {
12154         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12155     }
12156
12157     freeAsmop (from, NULL, ic, FALSE);
12158     aopOp (to, ic, FALSE, FALSE);
12159     /* get "to" into DPTR */
12160     /* if the operand is already in dptr
12161        then we do nothing else we move the value to dptr */
12162     if (AOP_TYPE (to) != AOP_STR) {
12163         /* if already in DPTR then we need to push */
12164         if (AOP_TYPE(to) == AOP_DPTR) {
12165             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12166             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12167             if (options.model == MODEL_FLAT24)
12168                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12169             emitcode ("pop", "dph");
12170             emitcode ("pop", "dpl");        
12171         } else {
12172             _startLazyDPSEvaluation ();
12173             /* if this is remateriazable */
12174             if (AOP_TYPE (to) == AOP_IMMD) {
12175                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12176             } else {                    /* we need to get it byte by byte */
12177                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12178                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12179                 if (options.model == MODEL_FLAT24) {
12180                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12181                 }
12182             }
12183             _endLazyDPSEvaluation ();
12184         }
12185     }
12186     freeAsmop (to, NULL, ic, FALSE);
12187
12188     _G.dptrInUse = _G.dptr1InUse = 1;
12189     aopOp (count, ic->next->next, FALSE,FALSE);
12190     lbl =newiTempLabel(NULL);
12191
12192     /* now for the actual copy */
12193     if (AOP_TYPE(count) == AOP_LIT && 
12194         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12195         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12196         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12197         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12198         freeAsmop (count, NULL, ic, FALSE);
12199         emitcode ("","!tlabeldef",lbl->key+100);
12200         emitcode ("movx", "a,@dptr");   /* read data from port */
12201         emitcode ("dec","dps");         /* switch to DPTR */
12202         emitcode ("movx", "@dptr,a");   /* save into location */
12203         emitcode ("inc", "dptr");       /* point to next area */
12204         emitcode ("inc","dps");         /* switch to DPTR2 */
12205         emitcode ("djnz","b,!tlabel",lbl->key+100);
12206     } else {
12207         symbol *lbl1 = newiTempLabel(NULL);
12208         
12209         emitcode (";"," Auto increment but no djnz");
12210         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12211         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12212         freeAsmop (count, NULL, ic, FALSE);
12213         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12214         emitcode ("","!tlabeldef",lbl->key+100);
12215         emitcode ("movx", "a,@dptr");
12216         emitcode ("dec","dps");         /* switch to DPTR */
12217         emitcode ("movx", "@dptr,a");
12218         emitcode ("inc", "dptr");
12219         emitcode ("inc","dps");         /* switch to DPTR2 */
12220 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12221 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12222         emitcode ("mov","a,b");
12223         emitcode ("orl","a,_ap");
12224         emitcode ("jz","!tlabel",lbl1->key+100);
12225         emitcode ("mov","a,_ap");
12226         emitcode ("add","a,#!constbyte",0xFF);
12227         emitcode ("mov","_ap,a");
12228         emitcode ("mov","a,b");
12229         emitcode ("addc","a,#!constbyte",0xFF);
12230         emitcode ("mov","b,a");
12231         emitcode ("sjmp","!tlabel",lbl->key+100);
12232         emitcode ("","!tlabeldef",lbl1->key+100);
12233     }
12234     emitcode ("mov", "dps,#0"); 
12235     _G.dptrInUse = _G.dptr1InUse = 0;
12236     unsavermask(rsave);
12237
12238 }
12239
12240 /*-----------------------------------------------------------------*/
12241 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12242 /* port, first parameter output area second parameter pointer to   */
12243 /* port third parameter count                                      */
12244 /*-----------------------------------------------------------------*/
12245 static void genOutp( iCode *ic, int nparms, operand **parms)
12246 {
12247     operand *from , *to , *count;
12248     symbol *lbl;
12249     bitVect *rsave;
12250     int i;
12251
12252     /* we know it has to be 3 parameters */
12253     assert (nparms == 3);
12254     
12255     rsave = newBitVect(16);
12256     /* save DPTR if it needs to be saved */
12257     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12258             if (bitVectBitValue(ic->rMask,i))
12259                     rsave = bitVectSetBit(rsave,i);
12260     }
12261     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12262                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12263     savermask(rsave);
12264     
12265     to = parms[0];
12266     from = parms[1];
12267     count = parms[2];
12268
12269     aopOp (from, ic->next, FALSE, FALSE);
12270
12271     /* get from into DPTR1 */
12272     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12273     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12274     if (options.model == MODEL_FLAT24) {
12275         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12276     }
12277
12278     freeAsmop (from, NULL, ic, FALSE);
12279     aopOp (to, ic, FALSE, FALSE);
12280     /* get "to" into DPTR */
12281     /* if the operand is already in dptr
12282        then we do nothing else we move the value to dptr */
12283     if (AOP_TYPE (to) != AOP_STR) {
12284         /* if already in DPTR then we need to push */
12285         if (AOP_TYPE(to) == AOP_DPTR) {
12286             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12287             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12288             if (options.model == MODEL_FLAT24)
12289                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12290             emitcode ("pop", "dph");
12291             emitcode ("pop", "dpl");        
12292         } else {
12293             _startLazyDPSEvaluation ();
12294             /* if this is remateriazable */
12295             if (AOP_TYPE (to) == AOP_IMMD) {
12296                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12297             } else {                    /* we need to get it byte by byte */
12298                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12299                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12300                 if (options.model == MODEL_FLAT24) {
12301                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12302                 }
12303             }
12304             _endLazyDPSEvaluation ();
12305         }
12306     }
12307     freeAsmop (to, NULL, ic, FALSE);
12308
12309     _G.dptrInUse = _G.dptr1InUse = 1;
12310     aopOp (count, ic->next->next, FALSE,FALSE);
12311     lbl =newiTempLabel(NULL);
12312
12313     /* now for the actual copy */
12314     if (AOP_TYPE(count) == AOP_LIT && 
12315         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12316         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12317         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12318         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12319         emitcode ("","!tlabeldef",lbl->key+100);
12320         emitcode ("movx", "a,@dptr");   /* read data from port */
12321         emitcode ("inc","dps");         /* switch to DPTR2 */
12322         emitcode ("movx", "@dptr,a");   /* save into location */
12323         emitcode ("inc", "dptr");       /* point to next area */
12324         emitcode ("dec","dps");         /* switch to DPTR */
12325         emitcode ("djnz","b,!tlabel",lbl->key+100);
12326         freeAsmop (count, NULL, ic, FALSE);
12327     } else {
12328         symbol *lbl1 = newiTempLabel(NULL);
12329         
12330         emitcode (";"," Auto increment but no djnz");
12331         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12332         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12333         freeAsmop (count, NULL, ic, FALSE);
12334         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12335         emitcode ("","!tlabeldef",lbl->key+100);
12336         emitcode ("movx", "a,@dptr");
12337         emitcode ("inc", "dptr");
12338         emitcode ("inc","dps");         /* switch to DPTR2 */
12339         emitcode ("movx", "@dptr,a");
12340         emitcode ("dec","dps");         /* switch to DPTR */
12341         emitcode ("mov","a,b");
12342         emitcode ("orl","a,_ap");
12343         emitcode ("jz","!tlabel",lbl1->key+100);
12344         emitcode ("mov","a,_ap");
12345         emitcode ("add","a,#!constbyte",0xFF);
12346         emitcode ("mov","_ap,a");
12347         emitcode ("mov","a,b");
12348         emitcode ("addc","a,#!constbyte",0xFF);
12349         emitcode ("mov","b,a");
12350         emitcode ("sjmp","!tlabel",lbl->key+100);
12351         emitcode ("","!tlabeldef",lbl1->key+100);
12352     }
12353     emitcode ("mov", "dps,#0"); 
12354     _G.dptrInUse = _G.dptr1InUse = 0;
12355     unsavermask(rsave);
12356
12357 }
12358
12359 /*-----------------------------------------------------------------*/
12360 /* genSwapW - swap lower & high order bytes                        */
12361 /*-----------------------------------------------------------------*/
12362 static void genSwapW(iCode *ic, int nparms, operand **parms)
12363 {
12364     operand *dest;
12365     operand *src;
12366     assert (nparms==1);
12367
12368     src = parms[0];
12369     dest=IC_RESULT(ic);
12370
12371     assert(getSize(operandType(src))==2);
12372
12373     aopOp (src, ic, FALSE, FALSE);
12374     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12375     _G.accInUse++;
12376     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12377     _G.accInUse--;
12378     freeAsmop (src, NULL, ic, FALSE);
12379     
12380     aopOp (dest,ic, FALSE, FALSE);
12381     aopPut(AOP(dest),"b",0);
12382     aopPut(AOP(dest),"a",1);
12383     freeAsmop (dest, NULL, ic, FALSE);    
12384 }
12385
12386 /*-----------------------------------------------------------------*/
12387 /* genMemsetX - gencode for memSetX data                           */
12388 /*-----------------------------------------------------------------*/
12389 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12390 {
12391     operand *to , *val , *count;
12392     symbol *lbl;
12393     char *l;
12394     int i;
12395     bitVect *rsave;
12396
12397     /* we know it has to be 3 parameters */
12398     assert (nparms == 3);
12399     
12400     to = parms[0];
12401     val = parms[1];
12402     count = parms[2];
12403         
12404     /* save DPTR if it needs to be saved */
12405     rsave = newBitVect(16);
12406     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12407             if (bitVectBitValue(ic->rMask,i))
12408                     rsave = bitVectSetBit(rsave,i);
12409     }
12410     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12411                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12412     savermask(rsave);
12413
12414     aopOp (to, ic, FALSE, FALSE);
12415     /* get "to" into DPTR */
12416     /* if the operand is already in dptr
12417        then we do nothing else we move the value to dptr */
12418     if (AOP_TYPE (to) != AOP_STR) {
12419         /* if already in DPTR then we need to push */
12420         if (AOP_TYPE(to) == AOP_DPTR) {
12421             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12422             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12423             if (options.model == MODEL_FLAT24)
12424                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12425             emitcode ("pop", "dph");
12426             emitcode ("pop", "dpl");        
12427         } else {
12428             _startLazyDPSEvaluation ();
12429             /* if this is remateriazable */
12430             if (AOP_TYPE (to) == AOP_IMMD) {
12431                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12432             } else {                    /* we need to get it byte by byte */
12433                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12434                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12435                 if (options.model == MODEL_FLAT24) {
12436                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12437                 }
12438             }
12439             _endLazyDPSEvaluation ();
12440         }
12441     }
12442     freeAsmop (to, NULL, ic, FALSE);
12443
12444     aopOp (val, ic->next->next, FALSE,FALSE);
12445     aopOp (count, ic->next->next, FALSE,FALSE);    
12446     lbl =newiTempLabel(NULL);
12447     /* now for the actual copy */
12448     if (AOP_TYPE(count) == AOP_LIT && 
12449         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12450         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12451         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12452         MOVA(l);
12453         emitcode ("","!tlabeldef",lbl->key+100);
12454         emitcode ("movx", "@dptr,a");
12455         emitcode ("inc", "dptr");
12456         emitcode ("djnz","b,!tlabel",lbl->key+100);
12457     } else {
12458         symbol *lbl1 = newiTempLabel(NULL);
12459         
12460         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12461         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12462         emitcode ("","!tlabeldef",lbl->key+100);
12463         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12464         emitcode ("movx", "@dptr,a");
12465         emitcode ("inc", "dptr");
12466         emitcode ("mov","a,b");
12467         emitcode ("orl","a,_ap");
12468         emitcode ("jz","!tlabel",lbl1->key+100);
12469         emitcode ("mov","a,_ap");
12470         emitcode ("add","a,#!constbyte",0xFF);
12471         emitcode ("mov","_ap,a");
12472         emitcode ("mov","a,b");
12473         emitcode ("addc","a,#!constbyte",0xFF);
12474         emitcode ("mov","b,a");
12475         emitcode ("sjmp","!tlabel",lbl->key+100);
12476         emitcode ("","!tlabeldef",lbl1->key+100);
12477     }
12478     freeAsmop (count, NULL, ic, FALSE);
12479     unsavermask(rsave);
12480 }
12481
12482 /*-----------------------------------------------------------------*/
12483 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12484 /*-----------------------------------------------------------------*/
12485 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12486 {
12487         bitVect *rsave ;
12488         operand *pnum, *result;
12489         int i;
12490     
12491         assert (nparms==1);
12492         /* save registers that need to be saved */
12493         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12494                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12495     
12496         pnum = parms[0]; 
12497         aopOp (pnum, ic, FALSE, FALSE);
12498         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12499         freeAsmop (pnum, NULL, ic, FALSE);
12500         emitcode ("lcall","NatLib_LoadPrimitive");
12501         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12502         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12503             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12504                 for (i = (size-1) ; i >= 0 ; i-- ) {
12505                         emitcode ("push","a%s",javaRet[i]);
12506                 }
12507                 for (i=0; i < size ; i++ ) {
12508                         emitcode ("pop","a%s",
12509                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12510                 }
12511         } else {
12512                 for (i = 0 ; i < size ; i++ ) {
12513                         aopPut(AOP(result),javaRet[i],i);
12514                 }
12515         }    
12516         freeAsmop (result, NULL, ic, FALSE);
12517         unsavermask(rsave);
12518 }
12519
12520 /*-----------------------------------------------------------------*/
12521 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12522 /*-----------------------------------------------------------------*/
12523 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12524 {
12525         bitVect *rsave ;
12526         operand *pnum, *result;
12527         int size = 3;
12528         int i;
12529     
12530         assert (nparms==1);
12531         /* save registers that need to be saved */
12532         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12533                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12534     
12535         pnum = parms[0]; 
12536         aopOp (pnum, ic, FALSE, FALSE);
12537         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12538         freeAsmop (pnum, NULL, ic, FALSE);
12539         emitcode ("lcall","NatLib_LoadPointer");
12540         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12541         if (AOP_TYPE(result)!=AOP_STR) {
12542                 for (i = 0 ; i < size ; i++ ) {
12543                         aopPut(AOP(result),fReturn[i],i);
12544                 }
12545         }    
12546         freeAsmop (result, NULL, ic, FALSE);
12547         unsavermask(rsave);
12548 }
12549
12550 /*-----------------------------------------------------------------*/
12551 /* genNatLibInstallStateBlock -                                    */
12552 /*-----------------------------------------------------------------*/
12553 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12554                                        operand **parms, const char *name)
12555 {
12556         bitVect *rsave ;
12557         operand *psb, *handle;
12558         assert (nparms==2);
12559
12560         /* save registers that need to be saved */
12561         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12562                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12563         psb = parms[0];
12564         handle = parms[1];
12565
12566         /* put pointer to state block into DPTR1 */
12567         aopOp (psb, ic, FALSE, FALSE);
12568         if (AOP_TYPE (psb) == AOP_IMMD) {
12569                 emitcode ("mov","dps,#1");
12570                 emitcode ("mov", "dptr,%s",
12571                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12572                 emitcode ("mov","dps,#0");
12573         } else {
12574                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12575                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12576                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12577         }
12578         freeAsmop (psb, NULL, ic, FALSE);
12579
12580         /* put libraryID into DPTR */
12581         emitcode ("mov","dptr,#LibraryID");
12582
12583         /* put handle into r3:r2 */
12584         aopOp (handle, ic, FALSE, FALSE);
12585         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12586                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12587                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12588                 emitcode ("pop","ar3");
12589                 emitcode ("pop","ar2");
12590         } else {        
12591                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12592                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12593         }
12594         freeAsmop (psb, NULL, ic, FALSE);
12595
12596         /* make the call */
12597         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12598
12599         /* put return value into place*/
12600         _G.accInUse++;
12601         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12602         _G.accInUse--;
12603         aopPut(AOP(IC_RESULT(ic)),"a",0);
12604         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12605         unsavermask(rsave);
12606 }
12607
12608 /*-----------------------------------------------------------------*/
12609 /* genNatLibRemoveStateBlock -                                     */
12610 /*-----------------------------------------------------------------*/
12611 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12612 {
12613         bitVect *rsave ;
12614
12615         assert(nparms==0);
12616
12617         /* save registers that need to be saved */
12618         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12619                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12620
12621         /* put libraryID into DPTR */
12622         emitcode ("mov","dptr,#LibraryID");
12623         /* make the call */
12624         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12625         unsavermask(rsave);
12626 }
12627
12628 /*-----------------------------------------------------------------*/
12629 /* genNatLibGetStateBlock -                                        */
12630 /*-----------------------------------------------------------------*/
12631 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12632                                    operand **parms,const char *name)
12633 {
12634         bitVect *rsave ;
12635         symbol *lbl = newiTempLabel(NULL);
12636         
12637         assert(nparms==0);
12638         /* save registers that need to be saved */
12639         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12640                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12641
12642         /* put libraryID into DPTR */
12643         emitcode ("mov","dptr,#LibraryID");
12644         /* make the call */
12645         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12646         emitcode ("jnz","!tlabel",lbl->key+100);
12647
12648         /* put return value into place */
12649         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12650         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12651                 emitcode ("push","ar3");
12652                 emitcode ("push","ar2");
12653                 emitcode ("pop","%s",
12654                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12655                 emitcode ("pop","%s",
12656                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12657         } else {
12658                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12659                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12660         }
12661         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12662         emitcode ("","!tlabeldef",lbl->key+100);
12663         unsavermask(rsave);
12664 }
12665
12666 /*-----------------------------------------------------------------*/
12667 /* genMMMalloc -                                                   */
12668 /*-----------------------------------------------------------------*/
12669 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12670                          int size, const char *name)
12671 {
12672         bitVect *rsave ;
12673         operand *bsize;
12674         symbol *rsym;
12675         symbol *lbl = newiTempLabel(NULL);
12676
12677         assert (nparms == 1);
12678         /* save registers that need to be saved */
12679         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12680                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12681         
12682         bsize=parms[0];
12683         aopOp (bsize,ic,FALSE,FALSE);
12684
12685         /* put the size in R4-R2 */
12686         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12687                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12688                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12689                 if (size==3) {
12690                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12691                         emitcode("pop","ar4");
12692                 }
12693                 emitcode("pop","ar3");
12694                 emitcode("pop","ar2");          
12695         } else {
12696                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12697                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12698                 if (size==3) {
12699                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12700                 }
12701         }
12702         freeAsmop (bsize, NULL, ic, FALSE);
12703
12704         /* make the call */
12705         emitcode ("lcall","MM_%s",name);
12706         emitcode ("jz","!tlabel",lbl->key+100);
12707         emitcode ("mov","r2,#!constbyte",0xff);
12708         emitcode ("mov","r3,#!constbyte",0xff);
12709         emitcode ("","!tlabeldef",lbl->key+100);
12710         /* we don't care about the pointer : we just save the handle */
12711         rsym = OP_SYMBOL(IC_RESULT(ic));
12712         if (rsym->liveFrom != rsym->liveTo) {
12713                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12714                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12715                         emitcode ("push","ar3");
12716                         emitcode ("push","ar2");
12717                         emitcode ("pop","%s",
12718                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12719                         emitcode ("pop","%s",
12720                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12721                 } else {
12722                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12723                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12724                 }
12725                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12726         }
12727         unsavermask(rsave);
12728 }
12729
12730 /*-----------------------------------------------------------------*/
12731 /* genMMDeref -                                                    */
12732 /*-----------------------------------------------------------------*/
12733 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12734 {
12735         bitVect *rsave ;
12736         operand *handle;
12737
12738         assert (nparms == 1);
12739         /* save registers that need to be saved */
12740         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12741                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12742         
12743         handle=parms[0];
12744         aopOp (handle,ic,FALSE,FALSE);
12745
12746         /* put the size in R4-R2 */
12747         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12748                 emitcode("push","%s",
12749                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12750                 emitcode("push","%s",
12751                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12752                 emitcode("pop","ar3");
12753                 emitcode("pop","ar2");          
12754         } else {
12755                 emitcode ("mov","r2,%s",
12756                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12757                 emitcode ("mov","r3,%s",
12758                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12759         }
12760         freeAsmop (handle, NULL, ic, FALSE);
12761
12762         /* make the call */
12763         emitcode ("lcall","MM_Deref");
12764         
12765         {
12766                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12767                 if (rsym->liveFrom != rsym->liveTo) {                   
12768                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12769                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12770                             _startLazyDPSEvaluation ();
12771                             
12772                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12773                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12774                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12775
12776                             _endLazyDPSEvaluation ();
12777                             
12778                         }
12779                 }
12780         }
12781         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12782         unsavermask(rsave);
12783 }
12784
12785 /*-----------------------------------------------------------------*/
12786 /* genMMUnrestrictedPersist -                                      */
12787 /*-----------------------------------------------------------------*/
12788 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12789 {
12790         bitVect *rsave ;
12791         operand *handle;
12792
12793         assert (nparms == 1);
12794         /* save registers that need to be saved */
12795         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12796                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12797         
12798         handle=parms[0];
12799         aopOp (handle,ic,FALSE,FALSE);
12800
12801         /* put the size in R3-R2 */
12802         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12803                 emitcode("push","%s",
12804                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12805                 emitcode("push","%s",
12806                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12807                 emitcode("pop","ar3");
12808                 emitcode("pop","ar2");          
12809         } else {
12810                 emitcode ("mov","r2,%s",
12811                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12812                 emitcode ("mov","r3,%s",
12813                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12814         }
12815         freeAsmop (handle, NULL, ic, FALSE);
12816
12817         /* make the call */
12818         emitcode ("lcall","MM_UnrestrictedPersist");
12819
12820         {
12821                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12822                 if (rsym->liveFrom != rsym->liveTo) {   
12823                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12824                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12825                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12826                 }
12827         }
12828         unsavermask(rsave);
12829 }
12830
12831 /*-----------------------------------------------------------------*/
12832 /* genSystemExecJavaProcess -                                      */
12833 /*-----------------------------------------------------------------*/
12834 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12835 {
12836         bitVect *rsave ;
12837         operand *handle, *pp;
12838
12839         assert (nparms==2);
12840         /* save registers that need to be saved */
12841         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12842                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12843         
12844         pp = parms[0];
12845         handle = parms[1];
12846         
12847         /* put the handle in R3-R2 */
12848         aopOp (handle,ic,FALSE,FALSE);
12849         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12850                 emitcode("push","%s",
12851                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12852                 emitcode("push","%s",
12853                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12854                 emitcode("pop","ar3");
12855                 emitcode("pop","ar2");          
12856         } else {
12857                 emitcode ("mov","r2,%s",
12858                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12859                 emitcode ("mov","r3,%s",
12860                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12861         }
12862         freeAsmop (handle, NULL, ic, FALSE);
12863         
12864         /* put pointer in DPTR */
12865         aopOp (pp,ic,FALSE,FALSE);
12866         if (AOP_TYPE(pp) == AOP_IMMD) {
12867                 emitcode ("mov", "dptr,%s",
12868                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12869         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12870                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12871                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12872                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12873         }
12874         freeAsmop (handle, NULL, ic, FALSE);
12875
12876         /* make the call */
12877         emitcode ("lcall","System_ExecJavaProcess");
12878         
12879         /* put result in place */
12880         {
12881                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12882                 if (rsym->liveFrom != rsym->liveTo) {   
12883                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12884                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12885                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12886                 }
12887         }
12888         
12889         unsavermask(rsave);
12890 }
12891
12892 /*-----------------------------------------------------------------*/
12893 /* genSystemRTCRegisters -                                         */
12894 /*-----------------------------------------------------------------*/
12895 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12896                                   char *name)
12897 {
12898         bitVect *rsave ;
12899         operand *pp;
12900
12901         assert (nparms==1);
12902         /* save registers that need to be saved */
12903         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12904                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12905         
12906         pp=parms[0];
12907         /* put pointer in DPTR */
12908         aopOp (pp,ic,FALSE,FALSE);
12909         if (AOP_TYPE (pp) == AOP_IMMD) {
12910                 emitcode ("mov","dps,#1");
12911                 emitcode ("mov", "dptr,%s", 
12912                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12913                 emitcode ("mov","dps,#0");
12914         } else {
12915                 emitcode ("mov","dpl1,%s",
12916                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12917                 emitcode ("mov","dph1,%s",
12918                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12919                 emitcode ("mov","dpx1,%s",
12920                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12921         }
12922         freeAsmop (pp, NULL, ic, FALSE);
12923
12924         /* make the call */
12925         emitcode ("lcall","System_%sRTCRegisters",name);
12926
12927         unsavermask(rsave);
12928 }
12929
12930 /*-----------------------------------------------------------------*/
12931 /* genSystemThreadSleep -                                          */
12932 /*-----------------------------------------------------------------*/
12933 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12934 {
12935         bitVect *rsave ;
12936         operand *to, *s;
12937
12938         assert (nparms==1);
12939         /* save registers that need to be saved */
12940         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12941                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12942
12943         to = parms[0];
12944         aopOp(to,ic,FALSE,FALSE);
12945         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12946             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12947                 emitcode ("push","%s",
12948                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12949                 emitcode ("push","%s",
12950                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12951                 emitcode ("push","%s",
12952                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12953                 emitcode ("push","%s",
12954                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12955                 emitcode ("pop","ar3");
12956                 emitcode ("pop","ar2");
12957                 emitcode ("pop","ar1");
12958                 emitcode ("pop","ar0");
12959         } else {
12960                 emitcode ("mov","r0,%s",
12961                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12962                 emitcode ("mov","r1,%s",
12963                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12964                 emitcode ("mov","r2,%s",
12965                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12966                 emitcode ("mov","r3,%s",
12967                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12968         }
12969         freeAsmop (to, NULL, ic, FALSE);
12970
12971         /* suspend in acc */
12972         s = parms[1];
12973         aopOp(s,ic,FALSE,FALSE);
12974         emitcode ("mov","a,%s",
12975                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12976         freeAsmop (s, NULL, ic, FALSE);
12977
12978         /* make the call */
12979         emitcode ("lcall","System_%s",name);
12980
12981         unsavermask(rsave);
12982 }
12983
12984 /*-----------------------------------------------------------------*/
12985 /* genSystemThreadResume -                                         */
12986 /*-----------------------------------------------------------------*/
12987 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12988 {
12989         bitVect *rsave ;
12990         operand *tid,*pid;
12991
12992         assert (nparms==2);
12993         /* save registers that need to be saved */
12994         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12995                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12996         
12997         tid = parms[0];
12998         pid = parms[1];
12999         
13000         /* PID in R0 */
13001         aopOp(pid,ic,FALSE,FALSE);
13002         emitcode ("mov","r0,%s",
13003                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13004         freeAsmop (pid, NULL, ic, FALSE);
13005         
13006         /* tid into ACC */
13007         aopOp(tid,ic,FALSE,FALSE);
13008         emitcode ("mov","a,%s",
13009                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13010         freeAsmop (tid, NULL, ic, FALSE);
13011         
13012         emitcode ("lcall","System_ThreadResume");
13013
13014         /* put result into place */
13015         {
13016                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13017                 if (rsym->liveFrom != rsym->liveTo) {   
13018                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13019                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13020                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13021                 }
13022         }
13023         unsavermask(rsave);
13024 }
13025
13026 /*-----------------------------------------------------------------*/
13027 /* genSystemProcessResume -                                        */
13028 /*-----------------------------------------------------------------*/
13029 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13030 {
13031         bitVect *rsave ;
13032         operand *pid;
13033
13034         assert (nparms==1);
13035         /* save registers that need to be saved */
13036         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13037                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13038         
13039         pid = parms[0];
13040         
13041         /* pid into ACC */
13042         aopOp(pid,ic,FALSE,FALSE);
13043         emitcode ("mov","a,%s",
13044                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13045         freeAsmop (pid, NULL, ic, FALSE);
13046         
13047         emitcode ("lcall","System_ProcessResume");
13048
13049         unsavermask(rsave);
13050 }
13051
13052 /*-----------------------------------------------------------------*/
13053 /* genSystem -                                                     */
13054 /*-----------------------------------------------------------------*/
13055 static void genSystem (iCode *ic,int nparms,char *name)
13056 {
13057         assert(nparms == 0);
13058
13059         emitcode ("lcall","System_%s",name);
13060 }
13061
13062 /*-----------------------------------------------------------------*/
13063 /* genSystemPoll -                                                  */
13064 /*-----------------------------------------------------------------*/
13065 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13066 {
13067         bitVect *rsave ;
13068         operand *fp;
13069
13070         assert (nparms==1);
13071         /* save registers that need to be saved */
13072         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13073                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13074
13075         fp = parms[0];
13076         aopOp (fp,ic,FALSE,FALSE);
13077         if (AOP_TYPE (fp) == AOP_IMMD) {
13078                 emitcode ("mov", "dptr,%s", 
13079                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13080         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13081                 emitcode ("mov","dpl,%s",
13082                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13083                 emitcode ("mov","dph,%s",
13084                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13085                 emitcode ("mov","dpx,%s",
13086                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13087         }
13088         freeAsmop (fp, NULL, ic, FALSE);
13089
13090         emitcode ("lcall","System_%sPoll",name);
13091
13092         /* put result into place */
13093         {
13094                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13095                 if (rsym->liveFrom != rsym->liveTo) {   
13096                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13097                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13098                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13099                 }
13100         }
13101         unsavermask(rsave);
13102 }
13103
13104 /*-----------------------------------------------------------------*/
13105 /* genSystemGetCurrentID -                                         */
13106 /*-----------------------------------------------------------------*/
13107 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13108 {
13109         assert (nparms==0);
13110
13111         emitcode ("lcall","System_GetCurrent%sId",name);
13112         /* put result into place */
13113         {
13114                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13115                 if (rsym->liveFrom != rsym->liveTo) {   
13116                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13117                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13118                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13119                 }
13120         }
13121 }
13122
13123 /*-----------------------------------------------------------------*/
13124 /* genDummyRead - generate code for dummy read of volatiles        */
13125 /*-----------------------------------------------------------------*/
13126 static void
13127 genDummyRead (iCode * ic)
13128 {
13129   operand *op;
13130   int size, offset;
13131
13132   D(emitcode(";     genDummyRead",""));
13133
13134   op = IC_RIGHT (ic);
13135   if (op && IS_SYMOP (op))
13136     {
13137       aopOp (op, ic, FALSE, FALSE);
13138
13139       /* if the result is a bit */
13140       if (AOP_TYPE (op) == AOP_CRY)
13141         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13142       else
13143         {
13144           /* bit variables done */
13145           /* general case */
13146           size = AOP_SIZE (op);
13147           offset = 0;
13148           while (size--)
13149           {
13150             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13151             offset++;
13152           }
13153         }
13154
13155       freeAsmop (op, NULL, ic, TRUE);
13156     }
13157
13158   op = IC_LEFT (ic);
13159   if (op && IS_SYMOP (op))
13160     {
13161       aopOp (op, ic, FALSE, FALSE);
13162
13163       /* if the result is a bit */
13164       if (AOP_TYPE (op) == AOP_CRY)
13165         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13166       else
13167         {
13168           /* bit variables done */
13169           /* general case */
13170           size = AOP_SIZE (op);
13171           offset = 0;
13172           while (size--)
13173           {
13174             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13175             offset++;
13176           }
13177         }
13178
13179       freeAsmop (op, NULL, ic, TRUE);
13180     }
13181     
13182 }
13183
13184 /*-----------------------------------------------------------------*/
13185 /* genCritical - generate code for start of a critical sequence    */
13186 /*-----------------------------------------------------------------*/
13187 static void
13188 genCritical (iCode *ic)
13189 {
13190   symbol *tlbl = newiTempLabel (NULL);
13191
13192   D(emitcode(";     genCritical",""));
13193   
13194   if (IC_RESULT (ic))
13195     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13196
13197   emitcode ("setb", "c");
13198   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13199   emitcode ("clr", "c");
13200   emitcode ("", "%05d$:", (tlbl->key + 100));
13201
13202   if (IC_RESULT (ic))
13203     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13204   else
13205     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13206
13207   if (IC_RESULT (ic))
13208     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13209 }
13210
13211 /*-----------------------------------------------------------------*/
13212 /* genEndCritical - generate code for end of a critical sequence   */
13213 /*-----------------------------------------------------------------*/
13214 static void
13215 genEndCritical (iCode *ic)
13216 {
13217   D(emitcode(";     genEndCritical",""));
13218   
13219   if (IC_RIGHT (ic))
13220     {
13221       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13222       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13223         {
13224           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13225           emitcode ("mov", "ea,c");
13226         }
13227       else
13228         {
13229           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13230           emitcode ("rrc", "a");
13231           emitcode ("mov", "ea,c");
13232         }
13233       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13234     }
13235   else
13236     {
13237       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13238       emitcode ("mov", "ea,c");
13239     }
13240 }
13241
13242
13243
13244 /*-----------------------------------------------------------------*/
13245 /* genBuiltIn - calls the appropriate function to  generating code */
13246 /* for a built in function                                         */
13247 /*-----------------------------------------------------------------*/
13248 static void genBuiltIn (iCode *ic)
13249 {
13250         operand *bi_parms[MAX_BUILTIN_ARGS];
13251         int nbi_parms;
13252         iCode *bi_iCode;
13253         symbol *bif;
13254
13255         /* get all the arguments for a built in function */
13256         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13257
13258         /* which function is it */
13259         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13260         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13261                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13262         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13263                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13264         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13265                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13266         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13267                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13268         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13269                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13270         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13271                 genInp(bi_iCode,nbi_parms,bi_parms);
13272         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13273                 genOutp(bi_iCode,nbi_parms,bi_parms);
13274         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13275                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13276                 /* JavaNative builtIns */               
13277         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13278                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13279         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13280                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13281         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13282                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13283         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13284                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13285         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13286                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13287         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13288                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13289         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13290                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13291         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13292                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13293         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13294                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13295         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13296                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13297         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13298                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13299         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13300                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13301         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13302                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13303         } else if (strcmp(bif->name,"MM_Free")==0) {
13304                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13305         } else if (strcmp(bif->name,"MM_Deref")==0) {
13306                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13307         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13308                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13309         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13310                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13311         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13312                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13313         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13314                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13315         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13316                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13317         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13318                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13319         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13320                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13321         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13322                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13323         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13324                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13325         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13326                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13327         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13328                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13329         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13330                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13331         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13332                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13333         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13334                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13335         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13336                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13337         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13338                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13339         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13340                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13341         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13342                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13343         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13344                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13345         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13346                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13347         } else {
13348                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13349                 return ;
13350         }
13351         return ;    
13352 }
13353
13354 /*-----------------------------------------------------------------*/
13355 /* gen390Code - generate code for Dallas 390 based controllers     */
13356 /*-----------------------------------------------------------------*/
13357 void
13358 gen390Code (iCode * lic)
13359 {
13360   iCode *ic;
13361   int cln = 0;
13362
13363   lineHead = lineCurr = NULL;
13364   dptrn[1][0] = "dpl1";
13365   dptrn[1][1] = "dph1";
13366   dptrn[1][2] = "dpx1";
13367   
13368   if (options.model == MODEL_FLAT24) {
13369     fReturnSizeDS390 = 5;
13370     fReturn = fReturn24;
13371   } else {
13372     fReturnSizeDS390 = 4;
13373     fReturn = fReturn16;
13374     options.stack10bit=0;
13375   }
13376 #if 1
13377   /* print the allocation information */
13378   if (allocInfo && currFunc)
13379     printAllocInfo (currFunc, codeOutFile);
13380 #endif
13381   /* if debug information required */
13382   if (options.debug && currFunc)
13383     {
13384       debugFile->writeFunction (currFunc, lic);
13385     }
13386   /* stack pointer name */
13387   if (options.useXstack)
13388     spname = "_spx";
13389   else
13390     spname = "sp";
13391
13392
13393   for (ic = lic; ic; ic = ic->next)
13394     {
13395
13396       _G.current_iCode = ic;
13397       
13398       if (ic->lineno && cln != ic->lineno)
13399         {
13400           if (options.debug)
13401             {
13402               debugFile->writeCLine (ic);
13403             }
13404           if (!options.noCcodeInAsm) {
13405             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13406                       printCLine(ic->filename, ic->lineno));
13407           }
13408           cln = ic->lineno;
13409         }
13410       if (options.iCodeInAsm) {
13411         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13412       }
13413       /* if the result is marked as
13414          spilt and rematerializable or code for
13415          this has already been generated then
13416          do nothing */
13417       if (resultRemat (ic) || ic->generated)
13418         continue;
13419
13420       /* depending on the operation */
13421       switch (ic->op)
13422         {
13423         case '!':
13424           genNot (ic);
13425           break;
13426
13427         case '~':
13428           genCpl (ic);
13429           break;
13430
13431         case UNARYMINUS:
13432           genUminus (ic);
13433           break;
13434
13435         case IPUSH:
13436           genIpush (ic);
13437           break;
13438
13439         case IPOP:
13440           /* IPOP happens only when trying to restore a
13441              spilt live range, if there is an ifx statement
13442              following this pop then the if statement might
13443              be using some of the registers being popped which
13444              would destory the contents of the register so
13445              we need to check for this condition and handle it */
13446           if (ic->next &&
13447               ic->next->op == IFX &&
13448               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13449             genIfx (ic->next, ic);
13450           else
13451             genIpop (ic);
13452           break;
13453
13454         case CALL:
13455           genCall (ic);
13456           break;
13457
13458         case PCALL:
13459           genPcall (ic);
13460           break;
13461
13462         case FUNCTION:
13463           genFunction (ic);
13464           break;
13465
13466         case ENDFUNCTION:
13467           genEndFunction (ic);
13468           break;
13469
13470         case RETURN:
13471           genRet (ic);
13472           break;
13473
13474         case LABEL:
13475           genLabel (ic);
13476           break;
13477
13478         case GOTO:
13479           genGoto (ic);
13480           break;
13481
13482         case '+':
13483           genPlus (ic);
13484           break;
13485
13486         case '-':
13487           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13488             genMinus (ic);
13489           break;
13490
13491         case '*':
13492           genMult (ic);
13493           break;
13494
13495         case '/':
13496           genDiv (ic);
13497           break;
13498
13499         case '%':
13500           genMod (ic);
13501           break;
13502
13503         case '>':
13504           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13505           break;
13506
13507         case '<':
13508           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13509           break;
13510
13511         case LE_OP:
13512         case GE_OP:
13513         case NE_OP:
13514
13515           /* note these two are xlated by algebraic equivalence
13516              during parsing SDCC.y */
13517           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13518                   "got '>=' or '<=' shouldn't have come here");
13519           break;
13520
13521         case EQ_OP:
13522           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13523           break;
13524
13525         case AND_OP:
13526           genAndOp (ic);
13527           break;
13528
13529         case OR_OP:
13530           genOrOp (ic);
13531           break;
13532
13533         case '^':
13534           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13535           break;
13536
13537         case '|':
13538           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13539           break;
13540
13541         case BITWISEAND:
13542           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13543           break;
13544
13545         case INLINEASM:
13546           genInline (ic);
13547           break;
13548
13549         case RRC:
13550           genRRC (ic);
13551           break;
13552
13553         case RLC:
13554           genRLC (ic);
13555           break;
13556
13557         case GETHBIT:
13558           genGetHbit (ic);
13559           break;
13560
13561         case LEFT_OP:
13562           genLeftShift (ic);
13563           break;
13564
13565         case RIGHT_OP:
13566           genRightShift (ic);
13567           break;
13568
13569         case GET_VALUE_AT_ADDRESS:
13570           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13571           break;
13572
13573         case '=':
13574           if (POINTER_SET (ic))
13575             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13576           else
13577             genAssign (ic);
13578           break;
13579
13580         case IFX:
13581           genIfx (ic, NULL);
13582           break;
13583
13584         case ADDRESS_OF:
13585           genAddrOf (ic);
13586           break;
13587
13588         case JUMPTABLE:
13589           genJumpTab (ic);
13590           break;
13591
13592         case CAST:
13593           genCast (ic);
13594           break;
13595
13596         case RECEIVE:
13597           genReceive (ic);
13598           break;
13599
13600         case SEND:
13601           if (ic->builtinSEND) genBuiltIn(ic);
13602           else addSet (&_G.sendSet, ic);
13603           break;
13604
13605         case DUMMY_READ_VOLATILE:
13606           genDummyRead (ic);
13607           break;
13608
13609         case CRITICAL:
13610           genCritical (ic);
13611           break;
13612
13613         case ENDCRITICAL:
13614           genEndCritical (ic);
13615           break;
13616         
13617         case SWAP:
13618           genSwap (ic);
13619           break;
13620           
13621 #if 0 // obsolete, and buggy for != xdata
13622         case ARRAYINIT:
13623             genArrayInit(ic);
13624             break;
13625 #endif
13626             
13627         default:
13628           ic = ic;
13629         }
13630     }
13631
13632
13633   /* now we are ready to call the
13634      peep hole optimizer */
13635   if (!options.nopeep)
13636     peepHole (&lineHead);
13637
13638   /* now do the actual printing */
13639   printLine (lineHead, codeOutFile);
13640   return;
13641 }