* src/ds390/ralloc.h,
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #define BETTER_LITERAL_SHIFT
40
41 char *aopLiteral (value * val, int offset);
42 extern int allocInfo;
43
44 /* this is the down and dirty file with all kinds of
45    kludgy & hacky stuff. This is what it is all about
46    CODE GENERATION for a specific MCU . some of the
47    routines may be reusable, will have to see */
48
49 static char *zero = "#0";
50 static char *one = "#1";
51 static char *spname;
52
53 #define D(x) x
54
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
57
58 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
65 {"a", "b"};
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
69
70 static struct
71   {
72     short r0Pushed;
73     short r1Pushed;
74     short accInUse;
75     short bInUse;
76     short inLine;
77     short debugLine;
78     short nRegsSaved;
79     short dptrInUse;
80     short dptr1InUse;
81     set *sendSet;
82     iCode *current_iCode;
83   }
84 _G;
85
86 static char *rb1regs[] = {
87     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
88 };
89
90 static void saveRBank (int, iCode *, bool);
91
92 #define RESULTONSTACK(x) \
93                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
94                          IC_RESULT(x)->aop->type == AOP_STK )
95
96 #define MOVA(x) _movA(x)
97 #define MOVB(x) _movB(x)
98                 
99 #define CLRC    emitcode("clr","c")
100 #define SETC    emitcode("setb","c")
101
102 // A scratch register which will be used to hold
103 // result bytes from operands in far space via DPTR2.
104 #define DP2_RESULT_REG  "_ap"
105
106 static lineNode *lineHead = NULL;
107 static lineNode *lineCurr = NULL;
108
109 static unsigned char SLMask[] =
110 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
111  0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char SRMask[] =
113 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
114  0x07, 0x03, 0x01, 0x00};
115
116 #define LSB     0
117 #define MSB16   1
118 #define MSB24   2
119 #define MSB32   3
120 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
121                                 symbol *lbl = newiTempLabel(NULL);              \
122                                 emitcode ("setb","F1");                         \
123                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
124                                 emitcode ("clr","F1");                          \
125                                 emitcode ("","!tlabeldef",lbl->key+100);        \
126                         }}
127 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
128                                 symbol *lbl = newiTempLabel(NULL);              \
129                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
130                                 emitcode ("setb","EA");                         \
131                                 emitcode ("","!tlabeldef",lbl->key+100);        \
132                         }}
133
134 static int _currentDPS;         /* Current processor DPS. */
135 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
136 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
137
138 /*-----------------------------------------------------------------*/
139 /* emitcode - writes the code into a file : for now it is simple    */
140 /*-----------------------------------------------------------------*/
141 static void
142 emitcode (char *inst, char *fmt,...)
143 {
144     va_list ap;
145     char lb[INITIAL_INLINEASM];
146     char *lbp = lb;
147     
148     va_start (ap, fmt);
149     
150     if (inst && *inst)
151     {
152         if (fmt && *fmt)
153         {
154             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
155         }
156         else
157         {
158             SNPRINTF (lb, sizeof(lb), "%s", inst);
159         }
160         
161         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
162                    fmt, ap);
163     }
164     else
165     {
166         tvsprintf (lb, sizeof(lb), fmt, ap);
167     }
168     
169
170     while (isspace (*lbp))
171     {
172         lbp++;
173     }
174
175     if (lbp && *lbp)
176     {
177         lineCurr = (lineCurr ?
178                     connectLine (lineCurr, newLineNode (lb)) :
179                     (lineHead = newLineNode (lb)));
180     }
181     
182     lineCurr->isInline = _G.inLine;
183     lineCurr->isDebug = _G.debugLine;
184     lineCurr->ic = _G.current_iCode;
185     lineCurr->aln = ds390newAsmLineNode(_currentDPS);
186     va_end (ap);
187 }
188
189 //
190 // Move the passed value into A unless it is already there.
191 // 
192 static void
193 _movA(const char *s)
194 {
195     if (strcmp(s,"a") && strcmp(s,"acc"))
196     { 
197         emitcode("mov","a,%s",s);
198     } 
199 }
200
201 //
202 // Move the passed value into B unless it is already there.
203 // 
204 static void
205 _movB(const char *s)
206 {
207     if (strcmp(s,"b"))
208     { 
209         emitcode("mov","b,%s",s);
210     } 
211 }
212
213 /*-----------------------------------------------------------------*/
214 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
215 /*-----------------------------------------------------------------*/
216 static regs *
217 getFreePtr (iCode * ic, asmop ** aopp, bool result)
218 {
219   bool r0iu, r1iu;
220   bool r0ou, r1ou;
221
222   /* the logic: if r0 & r1 used in the instruction
223      then we are in trouble otherwise */
224
225   /* first check if r0 & r1 are used by this
226      instruction, in which case we are in trouble */
227   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
228   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
229   if (r0iu && r1iu) {
230       goto endOfWorld;
231     }
232
233   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
234   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
235
236   /* if no usage of r0 then return it */
237   if (!r0iu && !r0ou)
238     {
239       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
240       (*aopp)->type = AOP_R0;
241
242       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
243     }
244
245   /* if no usage of r1 then return it */
246   if (!r1iu && !r1ou)
247     {
248       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
249       (*aopp)->type = AOP_R1;
250
251       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
252     }
253
254   /* now we know they both have usage */
255   /* if r0 not used in this instruction */
256   if (!r0iu)
257     {
258       /* push it if not already pushed */
259       if (!_G.r0Pushed)
260         {
261           emitcode ("push", "%s",
262                     ds390_regWithIdx (R0_IDX)->dname);
263           _G.r0Pushed++;
264         }
265
266       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
267       (*aopp)->type = AOP_R0;
268
269       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
270     }
271
272   /* if r1 not used then */
273
274   if (!r1iu)
275     {
276       /* push it if not already pushed */
277       if (!_G.r1Pushed)
278         {
279           emitcode ("push", "%s",
280                     ds390_regWithIdx (R1_IDX)->dname);
281           _G.r1Pushed++;
282         }
283
284       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
285       (*aopp)->type = AOP_R1;
286       return ds390_regWithIdx (R1_IDX);
287     }
288
289 endOfWorld:
290   /* I said end of world but not quite end of world yet */
291   /* if this is a result then we can push it on the stack */
292   if (result)
293     {
294       (*aopp)->type = AOP_STK;
295       return NULL;
296     }
297
298   /* other wise this is true end of the world */
299   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300           "getFreePtr should never reach here");
301   exit (1);
302     
303   return NULL; // notreached, but makes compiler happy.
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp                                  */
308 /*-----------------------------------------------------------------*/
309 static asmop *
310 newAsmop (short type)
311 {
312   asmop *aop;
313
314   aop = Safe_calloc (1, sizeof (asmop));
315   aop->type = type;
316   return aop;
317 }
318
319
320 /*-----------------------------------------------------------------*/
321 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
322 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
323 /* alternate DPTR (DPL1/DPH1/DPX1).          */
324 /*-----------------------------------------------------------------*/
325 static void
326 genSetDPTR (int n)
327 {
328
329   /* If we are doing lazy evaluation, simply note the desired
330    * change, but don't emit any code yet.
331    */
332   if (_lazyDPS)
333     {
334       _desiredDPS = n;
335       return;
336     }
337
338   if (!n)
339     {
340       emitcode ("mov", "dps,#0");
341     }
342   else
343     {
344       TR_DPTR("#1");
345       emitcode ("mov", "dps,#1");
346     }
347 }
348
349 /*-----------------------------------------------------------------*/
350 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
351 /*                   */
352 /* Any code that operates on DPTR (NB: not on the individual     */
353 /* components, like DPH) *must* call _flushLazyDPS() before using  */
354 /* DPTR within a lazy DPS evaluation block.        */
355 /*                   */
356 /* Note that aopPut and aopGet already contain the proper calls to */
357 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
358 /* DPS evaluation block.             */
359 /*                   */
360 /* Also, _flushLazyDPS must be called before any flow control      */
361 /* operations that could potentially branch out of the block.    */
362 /*                         */
363 /* Lazy DPS evaluation is simply an optimization (though an      */
364 /* important one), so if in doubt, leave it out.       */
365 /*-----------------------------------------------------------------*/
366 static void
367 _startLazyDPSEvaluation (void)
368 {
369   _currentDPS = 0;
370   _desiredDPS = 0;
371 #ifdef BETTER_LITERAL_SHIFT  
372   _lazyDPS++;
373 #else
374   _lazyDPS = 1;
375 #endif  
376 }
377
378 /*-----------------------------------------------------------------*/
379 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
380 /* desired one. Call before using DPTR within a lazy DPS evaluation */
381 /* block.                */
382 /*-----------------------------------------------------------------*/
383 static void
384 _flushLazyDPS (void)
385 {
386   if (!_lazyDPS)
387     {
388       /* nothing to do. */
389       return;
390     }
391
392   if (_desiredDPS != _currentDPS)
393     {
394       if (_desiredDPS)
395         {
396           emitcode ("inc", "dps");
397         }
398       else
399         {
400           emitcode ("dec", "dps");
401         }
402       _currentDPS = _desiredDPS;
403     }
404 }
405
406 /*-----------------------------------------------------------------*/
407 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
408 /*                   */
409 /* Forces us back to the safe state (standard DPTR selected).    */
410 /*-----------------------------------------------------------------*/
411 static void
412 _endLazyDPSEvaluation (void)
413 {
414 #ifdef BETTER_LITERAL_SHIFT  
415   _lazyDPS--;
416 #else
417   _lazyDPS = 0;
418 #endif    
419   if (!_lazyDPS)
420   {
421     if (_currentDPS)
422     {
423       genSetDPTR (0);
424       _flushLazyDPS ();
425     }
426     _currentDPS = 0;
427     _desiredDPS = 0;
428   }
429 }
430
431
432
433 /*-----------------------------------------------------------------*/
434 /* pointerCode - returns the code for a pointer type               */
435 /*-----------------------------------------------------------------*/
436 static int
437 pointerCode (sym_link * etype)
438 {
439
440   return PTR_TYPE (SPEC_OCLS (etype));
441
442 }
443
444 /*-----------------------------------------------------------------*/
445 /* leftRightUseAcc - returns size of accumulator use by operands   */
446 /*-----------------------------------------------------------------*/
447 static int
448 leftRightUseAcc(iCode *ic)
449 {
450   operand *op;
451   int size;
452   int accuseSize = 0;
453   int accuse = 0;
454   
455   if (!ic)
456     {
457       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
458               "null iCode pointer");
459       return 0;
460     }
461
462   if (ic->op == IFX)
463     {
464       op = IC_COND (ic);
465       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
466         {
467           accuse = 1;
468           size = getSize (OP_SYMBOL (op)->type);
469           if (size>accuseSize)
470             accuseSize = size;
471         }
472     }
473   else if (ic->op == JUMPTABLE)
474     {
475       op = IC_JTCOND (ic);
476       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
477         {
478           accuse = 1;
479           size = getSize (OP_SYMBOL (op)->type);
480           if (size>accuseSize)
481             accuseSize = size;
482         }
483     }
484   else
485     {
486       op = IC_LEFT (ic);
487       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488         {
489           accuse = 1;
490           size = getSize (OP_SYMBOL (op)->type);
491           if (size>accuseSize)
492             accuseSize = size;
493         }
494       op = IC_RIGHT (ic);
495       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
496         {
497           accuse = 1;
498           size = getSize (OP_SYMBOL (op)->type);
499           if (size>accuseSize)
500             accuseSize = size;
501         }
502     }
503   
504   if (accuseSize)
505     return accuseSize;
506   else
507     return accuse;
508 }
509
510 /*-----------------------------------------------------------------*/
511 /* aopForSym - for a true symbol                                   */
512 /*-----------------------------------------------------------------*/
513 static asmop *
514 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
515 {
516   asmop *aop;
517   memmap *space = SPEC_OCLS (sym->etype);
518   int accuse = leftRightUseAcc (ic);
519
520   /* if already has one */
521   if (sym->aop)
522     {
523       if ((sym->aop->type == AOP_DPTR && useDP2)
524           || (sym->aop->type == AOP_DPTR2 && !useDP2))
525         sym->aop = NULL;
526       else
527         return sym->aop;
528     }
529
530   /* assign depending on the storage class */
531   /* if it is on the stack or indirectly addressable */
532   /* space we need to assign either r0 or r1 to it   */
533   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
534     {
535       sym->aop = aop = newAsmop (0);
536       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
537       aop->size = getSize (sym->type);
538
539       /* now assign the address of the variable to
540          the pointer register */
541       if (aop->type != AOP_STK)
542         {
543
544           if (sym->onStack)
545             {
546               if (_G.accInUse || accuse)
547                 emitcode ("push", "acc");
548
549               if (_G.bInUse || (accuse>1))
550                 emitcode ("push", "b");
551
552               emitcode ("mov", "a,_bp");
553               emitcode ("add", "a,#!constbyte",
554                         ((sym->stack < 0) ?
555                          ((char) (sym->stack - _G.nRegsSaved)) :
556                          ((char) sym->stack)) & 0xff);
557               emitcode ("mov", "%s,a",
558                         aop->aopu.aop_ptr->name);
559
560               if (_G.bInUse || (accuse>1))
561                 emitcode ("pop", "b");
562
563               if (_G.accInUse || accuse)
564                 emitcode ("pop", "acc");
565             }
566           else
567             emitcode ("mov", "%s,#%s",
568                       aop->aopu.aop_ptr->name,
569                       sym->rname);
570           aop->paged = space->paged;
571         }
572       else
573         aop->aopu.aop_stk = sym->stack;
574       return aop;
575     }
576
577   if (sym->onStack && options.stack10bit)
578     {
579         short stack_val = -((sym->stack < 0) ?
580                             ((short) (sym->stack - _G.nRegsSaved)) :
581                             ((short) sym->stack)) ;
582         if (useDP2 && _G.dptr1InUse) {
583             emitcode ("push","dpl1");
584             emitcode ("push","dph1");
585             emitcode ("push","dpx1");
586         } else if (_G.dptrInUse ) {
587             emitcode ("push","dpl");
588             emitcode ("push","dph");
589             emitcode ("push","dpx");
590         }
591       /* It's on the 10 bit stack, which is located in
592        * far data space.
593        */           
594         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
595             if (useDP2) {
596                 if (options.model == MODEL_FLAT24)
597                 {
598                     emitcode ("mov", "dpx1,#!constbyte",
599                               (options.stack_loc >> 16) & 0xff);
600                 }
601                 emitcode ("mov", "dph1,_bpx+1");
602                 
603                 emitcode ("mov", "dpl1,_bpx");
604                 emitcode ("mov","dps,#1");
605             } else {
606                 if (options.model == MODEL_FLAT24)
607                 {
608                     emitcode ("mov", "dpx,#!constbyte",
609                               (options.stack_loc >> 16) & 0xff);
610                 }
611                 emitcode ("mov", "dph,_bpx+1");
612                 emitcode ("mov", "dpl,_bpx");
613             }
614             stack_val = -stack_val;
615             while (stack_val--) {
616                 emitcode ("inc","dptr");
617             }
618             if (useDP2) {
619                 emitcode("mov","dps,#0");
620             }
621         }  else {
622             if (_G.accInUse || accuse)
623                 emitcode ("push", "acc");
624             
625             if (_G.bInUse || (accuse>1))
626                 emitcode ("push", "b");
627         
628             emitcode ("mov", "a,_bpx");
629             emitcode ("clr","c");
630             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
631             emitcode ("mov","b,a");
632             emitcode ("mov","a,_bpx+1");
633             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
634             if (useDP2) {
635                 if (options.model == MODEL_FLAT24)
636                 {
637                     emitcode ("mov", "dpx1,#!constbyte",
638                               (options.stack_loc >> 16) & 0xff);
639                 }
640                 emitcode ("mov", "dph1,a");
641                 emitcode ("mov", "dpl1,b");
642             } else {
643                 if (options.model == MODEL_FLAT24)
644                 {
645                     emitcode ("mov", "dpx,#!constbyte",
646                               (options.stack_loc >> 16) & 0xff);
647                 }
648                 emitcode ("mov", "dph,a");
649                 emitcode ("mov", "dpl,b");
650             }
651             
652             if (_G.bInUse || (accuse>1))
653                 emitcode ("pop", "b");
654             
655             if (_G.accInUse || accuse)
656                 emitcode ("pop", "acc");
657         }
658         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
659         aop->size = getSize (sym->type);
660         return aop;
661     }
662
663   /* if in bit space */
664   if (IN_BITSPACE (space))
665     {
666       sym->aop = aop = newAsmop (AOP_CRY);
667       aop->aopu.aop_dir = sym->rname;
668       aop->size = getSize (sym->type);
669       return aop;
670     }
671   /* if it is in direct space */
672   if (IN_DIRSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_DIR);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679
680   /* special case for a function */
681   if (IS_FUNC (sym->type) && !(sym->isitmp))
682     {
683       sym->aop = aop = newAsmop (AOP_IMMD);
684       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
685       aop->size = FPTRSIZE;
686       return aop;
687     }
688
689   /* only remaining is far space */
690   /* in which case DPTR gets the address */
691   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
692   if (useDP2)
693     {
694       genSetDPTR (1);
695       _flushLazyDPS ();
696       emitcode ("mov", "dptr,#%s", sym->rname);
697       genSetDPTR (0);
698     }
699   else
700     {
701       emitcode ("mov", "dptr,#%s", sym->rname);
702     }
703   aop->size = getSize (sym->type);
704
705   /* if it is in code space */
706   if (IN_CODESPACE (space))
707     aop->code = 1;
708
709   return aop;
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* aopForRemat - rematerialzes an object                           */
714 /*-----------------------------------------------------------------*/
715 static asmop *
716 aopForRemat (symbol * sym)
717 {
718   iCode *ic = sym->rematiCode;
719   asmop *aop = newAsmop (AOP_IMMD);
720   int ptr_type =0;
721   int val = 0;
722
723   for (;;)
724     {
725       if (ic->op == '+')
726         val += (int) operandLitValue (IC_RIGHT (ic));
727       else if (ic->op == '-')
728         val -= (int) operandLitValue (IC_RIGHT (ic));
729       else if (IS_CAST_ICODE(ic)) {
730               sym_link *from_type = operandType(IC_RIGHT(ic));
731               aop->aopu.aop_immd.from_cast_remat = 1;
732               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
733               ptr_type = DCL_TYPE(from_type);
734               if (ptr_type == IPOINTER) {
735                 // bug #481053
736                 ptr_type = POINTER;
737               }
738               continue ;
739       } else break;
740       
741       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
742     }
743
744   if (val)
745   {
746       SNPRINTF (buffer, sizeof(buffer),
747                 "(%s %c 0x%04x)",
748                 OP_SYMBOL (IC_LEFT (ic))->rname,
749                 val >= 0 ? '+' : '-',
750                 abs (val) & 0xffffff);
751   }
752   else 
753   {
754       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
755       {
756           SNPRINTF(buffer, sizeof(buffer), 
757                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
758       }
759       else
760       {
761           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
762       }
763   }
764
765   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
766   /* set immd2 field if required */
767   if (aop->aopu.aop_immd.from_cast_remat) 
768   {
769       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
770       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
771   }
772
773   return aop;
774 }
775
776 /*-----------------------------------------------------------------*/
777 /* aopHasRegs - returns true if aop has regs between from-to       */
778 /*-----------------------------------------------------------------*/
779 static int aopHasRegs(asmop *aop, int from, int to)
780 {
781     int size =0;
782
783     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
784
785     for (; size < aop->size ; size++) {
786         int reg;
787         for (reg = from ; reg <= to ; reg++)
788             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
789     }
790     return 0;
791 }
792
793 /*-----------------------------------------------------------------*/
794 /* regsInCommon - two operands have some registers in common       */
795 /*-----------------------------------------------------------------*/
796 static bool
797 regsInCommon (operand * op1, operand * op2)
798 {
799   symbol *sym1, *sym2;
800   int i;
801
802   /* if they have registers in common */
803   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
804     return FALSE;
805
806   sym1 = OP_SYMBOL (op1);
807   sym2 = OP_SYMBOL (op2);
808
809   if (sym1->nRegs == 0 || sym2->nRegs == 0)
810     return FALSE;
811
812   for (i = 0; i < sym1->nRegs; i++)
813     {
814       int j;
815       if (!sym1->regs[i])
816         continue;
817
818       for (j = 0; j < sym2->nRegs; j++)
819         {
820           if (!sym2->regs[j])
821             continue;
822
823           if (sym2->regs[j] == sym1->regs[i])
824             return TRUE;
825         }
826     }
827
828   return FALSE;
829 }
830
831 /*-----------------------------------------------------------------*/
832 /* operandsEqu - equivalent                                        */
833 /*-----------------------------------------------------------------*/
834 static bool
835 operandsEqu (operand * op1, operand * op2)
836 {
837   symbol *sym1, *sym2;
838
839   /* if they not symbols */
840   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
841     return FALSE;
842
843   sym1 = OP_SYMBOL (op1);
844   sym2 = OP_SYMBOL (op2);
845
846   /* if both are itemps & one is spilt
847      and the other is not then false */
848   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
849       sym1->isspilt != sym2->isspilt)
850     return FALSE;
851
852   /* if they are the same */
853   if (sym1 == sym2)
854     return TRUE;
855
856   if (strcmp (sym1->rname, sym2->rname) == 0)
857     return TRUE;
858
859
860   /* if left is a tmp & right is not */
861   if (IS_ITEMP (op1) &&
862       !IS_ITEMP (op2) &&
863       sym1->isspilt &&
864       (sym1->usl.spillLoc == sym2))
865     return TRUE;
866
867   if (IS_ITEMP (op2) &&
868       !IS_ITEMP (op1) &&
869       sym2->isspilt &&
870       sym1->level > 0 &&
871       (sym2->usl.spillLoc == sym1))
872     return TRUE;
873
874   /* are they spilt to the same location */
875   if (IS_ITEMP (op2) &&
876       IS_ITEMP (op1) &&
877       sym2->isspilt &&
878       sym1->isspilt &&
879       (sym1->usl.spillLoc == sym2->usl.spillLoc))
880     return TRUE;
881     
882   return FALSE;
883 }
884
885 /*-----------------------------------------------------------------*/
886 /* sameRegs - two asmops have the same registers                   */
887 /*-----------------------------------------------------------------*/
888 static bool
889 sameRegs (asmop * aop1, asmop * aop2)
890 {
891   int i;
892
893   if (aop1 == aop2)
894     {
895       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
896         {
897           return FALSE;
898         }
899       return TRUE;
900     }
901
902   if (aop1->type != AOP_REG ||
903       aop2->type != AOP_REG)
904     return FALSE;
905
906   if (aop1->size != aop2->size)
907     return FALSE;
908
909   for (i = 0; i < aop1->size; i++)
910     if (aop1->aopu.aop_reg[i] !=
911         aop2->aopu.aop_reg[i])
912       return FALSE;
913
914   return TRUE;
915 }
916
917 /*-----------------------------------------------------------------*/
918 /* aopOp - allocates an asmop for an operand  :                    */
919 /*-----------------------------------------------------------------*/
920 static void
921 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
922 {
923   asmop *aop;
924   symbol *sym;
925   int i;
926
927   if (!op)
928     return;
929
930   /* if this a literal */
931   if (IS_OP_LITERAL (op))
932     {
933       op->aop = aop = newAsmop (AOP_LIT);
934       aop->aopu.aop_lit = op->operand.valOperand;
935       aop->size = getSize (operandType (op));
936       return;
937     }
938
939   /* if already has a asmop then continue */
940   if (op->aop)
941     {
942       if ((op->aop->type == AOP_DPTR && useDP2)
943           || (op->aop->type == AOP_DPTR2 && !useDP2))
944         op->aop = NULL;
945       else
946         return;
947     }
948
949   /* if the underlying symbol has a aop */
950   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
951     {
952       op->aop = OP_SYMBOL (op)->aop;
953       if ((op->aop->type == AOP_DPTR && useDP2)
954           || (op->aop->type == AOP_DPTR2 && !useDP2))
955         op->aop = NULL;
956       else
957         return;
958     }
959
960   /* if this is a true symbol */
961   if (IS_TRUE_SYMOP (op))
962     {
963       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
964       return;
965     }
966
967   /* this is a temporary : this has
968      only four choices :
969      a) register
970      b) spillocation
971      c) rematerialize
972      d) conditional
973      e) can be a return use only */
974
975   sym = OP_SYMBOL (op);
976
977
978   /* if the type is a conditional */
979   if (sym->regType == REG_CND)
980     {
981       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
982       aop->size = 0;
983       return;
984     }
985
986   /* if it is spilt then two situations
987      a) is rematerialize
988      b) has a spill location */
989   if (sym->isspilt || sym->nRegs == 0)
990     {
991
992       /* rematerialize it NOW */
993       if (sym->remat)
994         {
995           sym->aop = op->aop = aop =
996             aopForRemat (sym);
997           aop->size = getSize (sym->type);
998           return;
999         }
1000
1001       if (sym->accuse)
1002         {
1003           int i;
1004           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1005           aop->size = getSize (sym->type);
1006           for (i = 0; i < 2; i++)
1007             aop->aopu.aop_str[i] = accUse[i];
1008           return;
1009         }
1010
1011       if (sym->ruonly)
1012         {
1013           int i;
1014
1015           if (useDP2)
1016             {
1017               /* a AOP_STR uses DPTR, but DPTR is already in use;
1018                * we're just hosed.
1019                */
1020                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1021             }
1022
1023           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1024           aop->size = getSize (sym->type);
1025           for (i = 0; i < (int) fReturnSizeDS390; i++)
1026             aop->aopu.aop_str[i] = fReturn[i];
1027           return;
1028         }
1029       
1030       if (sym->dptr) { /* has been allocated to a DPTRn */
1031           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1032           aop->size = getSize (sym->type);
1033           aop->aopu.dptr = sym->dptr;
1034           return ;
1035       }
1036       
1037       if (sym->usl.spillLoc)
1038         {
1039           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1040             {
1041               /* force a new aop if sizes differ */
1042               sym->usl.spillLoc->aop = NULL;
1043             }
1044           sym->aop = op->aop = aop =
1045                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1046           aop->size = getSize (sym->type);
1047           return;
1048         }
1049       
1050       /* else must be a dummy iTemp */
1051       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1052       aop->size = getSize (sym->type);
1053       return;
1054     }
1055
1056   /* must be in a register */
1057   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1058   aop->size = sym->nRegs;
1059   for (i = 0; i < sym->nRegs; i++)
1060     aop->aopu.aop_reg[i] = sym->regs[i];
1061 }
1062
1063 /*-----------------------------------------------------------------*/
1064 /* freeAsmop - free up the asmop given to an operand               */
1065 /*----------------------------------------------------------------*/
1066 static void
1067 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1068 {
1069   asmop *aop;
1070
1071   if (!op)
1072     aop = aaop;
1073   else
1074     aop = op->aop;
1075
1076   if (!aop)
1077     return;
1078
1079   if (aop->freed)
1080     goto dealloc;
1081
1082   aop->freed = 1;
1083
1084   /* depending on the asmop type only three cases need work AOP_RO
1085      , AOP_R1 && AOP_STK */
1086   switch (aop->type)
1087     {
1088     case AOP_R0:
1089       if (_G.r0Pushed)
1090         {
1091           if (pop)
1092             {
1093               emitcode ("pop", "ar0");
1094               _G.r0Pushed--;
1095             }
1096         }
1097       bitVectUnSetBit (ic->rUsed, R0_IDX);
1098       break;
1099
1100     case AOP_R1:
1101       if (_G.r1Pushed)
1102         {
1103           if (pop)
1104             {
1105               emitcode ("pop", "ar1");
1106               _G.r1Pushed--;
1107             }
1108         }
1109       bitVectUnSetBit (ic->rUsed, R1_IDX);
1110       break;
1111
1112     case AOP_STK:
1113       {
1114         int sz = aop->size;
1115         int stk = aop->aopu.aop_stk + aop->size;
1116         bitVectUnSetBit (ic->rUsed, R0_IDX);
1117         bitVectUnSetBit (ic->rUsed, R1_IDX);
1118
1119         getFreePtr (ic, &aop, FALSE);
1120
1121         if (options.stack10bit)
1122           {
1123             /* I'm not sure what to do here yet... */
1124             /* #STUB */
1125             fprintf (stderr,
1126                      "*** Warning: probably generating bad code for "
1127                      "10 bit stack mode.\n");
1128           }
1129
1130         if (stk)
1131           {
1132             emitcode ("mov", "a,_bp");
1133             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1134             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1135           }
1136         else
1137           {
1138             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1139           }
1140
1141         while (sz--)
1142           {
1143             emitcode ("pop", "acc");
1144             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1145             if (!sz)
1146               break;
1147             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1148           }
1149         op->aop = aop;
1150         freeAsmop (op, NULL, ic, TRUE);
1151         if (_G.r0Pushed)
1152           {
1153             emitcode ("pop", "ar0");
1154             _G.r0Pushed--;
1155           }
1156
1157         if (_G.r1Pushed)
1158           {
1159             emitcode ("pop", "ar1");
1160             _G.r1Pushed--;
1161           }
1162       }
1163     case AOP_DPTR2:
1164         if (_G.dptr1InUse) {
1165             emitcode ("pop","dpx1");
1166             emitcode ("pop","dph1");
1167             emitcode ("pop","dpl1");
1168         }
1169         break;
1170     case AOP_DPTR:
1171         if (_G.dptrInUse) {
1172             emitcode ("pop","dpx");
1173             emitcode ("pop","dph");
1174             emitcode ("pop","dpl");
1175         }
1176         break;
1177     }
1178 dealloc:
1179   /* all other cases just dealloc */
1180   if (op)
1181     {
1182       op->aop = NULL;
1183       if (IS_SYMOP (op))
1184         {
1185           OP_SYMBOL (op)->aop = NULL;
1186           /* if the symbol has a spill */
1187           if (SPIL_LOC (op))
1188             SPIL_LOC (op)->aop = NULL;
1189         }
1190     }
1191 }
1192
1193 #define DEFAULT_ACC_WARNING 0
1194 static int saveAccWarn = DEFAULT_ACC_WARNING;
1195
1196 /*-------------------------------------------------------------------*/
1197 /* aopGet - for fetching value of the aop                            */
1198 /*                                                                   */
1199 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1200 /* in the accumulator. Set it to the name of a free register         */
1201 /* if acc must be preserved; the register will be used to preserve   */
1202 /* acc temporarily and to return the result byte.                    */
1203 /*-------------------------------------------------------------------*/
1204
1205 static char *
1206 aopGet (asmop *aop,
1207         int   offset,
1208         bool  bit16,
1209         bool  dname,
1210         char  *saveAcc)
1211 {
1212   /* offset is greater than
1213      size then zero */
1214   if (offset > (aop->size - 1) &&
1215       aop->type != AOP_LIT)
1216     return zero;
1217
1218   /* depending on type */
1219   switch (aop->type)
1220     {
1221     case AOP_DUMMY:
1222       return zero;
1223
1224     case AOP_R0:
1225     case AOP_R1:
1226       /* if we need to increment it */
1227       while (offset > aop->coff)
1228         {
1229           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1230           aop->coff++;
1231         }
1232
1233       while (offset < aop->coff)
1234         {
1235           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1236           aop->coff--;
1237         }
1238
1239       aop->coff = offset;
1240       if (aop->paged)
1241         {
1242           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1243           return (dname ? "acc" : "a");
1244         }
1245       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1246       return Safe_strdup(buffer);       
1247
1248     case AOP_DPTRn:
1249         assert(offset <= 3);
1250         return dptrn[aop->aopu.dptr][offset];
1251
1252     case AOP_DPTR:
1253     case AOP_DPTR2:
1254
1255       if (aop->type == AOP_DPTR2)
1256         {
1257           genSetDPTR (1);
1258         }
1259         
1260       if (saveAcc)
1261         {
1262             TR_AP("#1");
1263 //          if (aop->type != AOP_DPTR2)
1264 //          {
1265 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1266 //              emitcode(";", "spanky: saveAcc for DPTR");
1267 //          }
1268             
1269             emitcode ("xch", "a, %s", saveAcc);
1270         }
1271
1272       _flushLazyDPS ();
1273
1274       while (offset > aop->coff)
1275         {
1276           emitcode ("inc", "dptr");
1277           aop->coff++;
1278         }
1279
1280       while (offset < aop->coff)
1281         {
1282           emitcode ("lcall", "__decdptr");
1283           aop->coff--;
1284         }
1285
1286       aop->coff = offset;
1287       if (aop->code)
1288         {
1289           emitcode ("clr", "a");
1290           emitcode ("movc", "a,@a+dptr");
1291         }
1292       else
1293         {
1294           emitcode ("movx", "a,@dptr");
1295         }
1296
1297       if (aop->type == AOP_DPTR2)
1298         {
1299           genSetDPTR (0);
1300         }
1301         
1302         if (saveAcc)
1303         {
1304        TR_AP("#2");
1305               emitcode ("xch", "a, %s", saveAcc);
1306 //            if (strcmp(saveAcc, "_ap"))
1307 //            {
1308 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1309 //            }
1310                   
1311               return saveAcc;
1312         }
1313       return (dname ? "acc" : "a");
1314
1315     case AOP_IMMD:
1316       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1317       {
1318           SNPRINTF(buffer, sizeof(buffer), 
1319                    "%s",aop->aopu.aop_immd.aop_immd2);
1320       } 
1321       else if (bit16)
1322       {
1323          SNPRINTF(buffer, sizeof(buffer), 
1324                   "#%s", aop->aopu.aop_immd.aop_immd1);
1325       }
1326       else if (offset) 
1327       {
1328           switch (offset) {
1329           case 1:
1330               tsprintf(buffer, sizeof(buffer),
1331                        "#!his",aop->aopu.aop_immd.aop_immd1);
1332               break;
1333           case 2:
1334               tsprintf(buffer, sizeof(buffer), 
1335                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1336               break;
1337           case 3:
1338               tsprintf(buffer, sizeof(buffer),
1339                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1340               break;
1341           default: /* should not need this (just in case) */
1342               SNPRINTF (buffer, sizeof(buffer), 
1343                         "#(%s >> %d)",
1344                        aop->aopu.aop_immd.aop_immd1,
1345                        offset * 8);
1346           }
1347       }
1348       else
1349       {
1350         SNPRINTF (buffer, sizeof(buffer), 
1351                   "#%s", aop->aopu.aop_immd.aop_immd1);
1352       }
1353       return Safe_strdup(buffer);       
1354
1355     case AOP_DIR:
1356       if (offset)
1357       {
1358         SNPRINTF (buffer, sizeof(buffer),
1359                   "(%s + %d)",
1360                  aop->aopu.aop_dir,
1361                  offset);
1362       }
1363       else
1364       {
1365         SNPRINTF(buffer, sizeof(buffer), 
1366                  "%s", aop->aopu.aop_dir);
1367       }
1368
1369       return Safe_strdup(buffer);
1370
1371     case AOP_REG:
1372       if (dname)
1373         return aop->aopu.aop_reg[offset]->dname;
1374       else
1375         return aop->aopu.aop_reg[offset]->name;
1376
1377     case AOP_CRY:
1378       emitcode ("clr", "a");
1379       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1380       emitcode ("rlc", "a");
1381       return (dname ? "acc" : "a");
1382
1383     case AOP_ACC:
1384       if (!offset && dname)
1385         return "acc";
1386       return aop->aopu.aop_str[offset];
1387
1388     case AOP_LIT:
1389       return aopLiteral (aop->aopu.aop_lit, offset);
1390
1391     case AOP_STR:
1392       aop->coff = offset;
1393       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1394           dname)
1395         return "acc";
1396
1397       return aop->aopu.aop_str[offset];
1398
1399     }
1400
1401   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1402           "aopget got unsupported aop->type");
1403   exit (1);
1404     
1405   return NULL;  // not reached, but makes compiler happy.
1406 }
1407 /*-----------------------------------------------------------------*/
1408 /* aopPut - puts a string for a aop                                */
1409 /*-----------------------------------------------------------------*/
1410 static void
1411 aopPut (asmop * aop, char *s, int offset)
1412 {
1413   if (aop->size && offset > (aop->size - 1))
1414     {
1415       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1416               "aopPut got offset > aop->size");
1417       exit (1);
1418     }
1419
1420   /* will assign value to value */
1421   /* depending on where it is ofcourse */
1422   switch (aop->type)
1423     {
1424     case AOP_DUMMY:
1425       MOVA (s);         /* read s in case it was volatile */
1426       break;
1427       
1428     case AOP_DIR:
1429         if (offset)
1430         {
1431             SNPRINTF (buffer, sizeof(buffer),
1432                       "(%s + %d)",
1433                       aop->aopu.aop_dir, offset);
1434         }
1435         else
1436         {
1437             SNPRINTF (buffer, sizeof(buffer), 
1438                      "%s", aop->aopu.aop_dir);
1439         }
1440         
1441
1442         if (strcmp (buffer, s))
1443         {
1444             emitcode ("mov", "%s,%s", buffer, s);
1445         }
1446       break;
1447
1448     case AOP_REG:
1449       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1450           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1451         {
1452           if (*s == '@' ||
1453               strcmp (s, "r0") == 0 ||
1454               strcmp (s, "r1") == 0 ||
1455               strcmp (s, "r2") == 0 ||
1456               strcmp (s, "r3") == 0 ||
1457               strcmp (s, "r4") == 0 ||
1458               strcmp (s, "r5") == 0 ||
1459               strcmp (s, "r6") == 0 ||
1460               strcmp (s, "r7") == 0)
1461             {
1462                 emitcode ("mov", "%s,%s",
1463                           aop->aopu.aop_reg[offset]->dname, s);
1464             }
1465             else
1466             {
1467                 emitcode ("mov", "%s,%s",
1468                           aop->aopu.aop_reg[offset]->name, s);
1469             }
1470         }
1471       break;
1472
1473     case AOP_DPTRn:
1474         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1475         break;
1476
1477     case AOP_DPTR:
1478     case AOP_DPTR2:
1479
1480       if (aop->type == AOP_DPTR2)
1481         {
1482           genSetDPTR (1);
1483         }
1484       _flushLazyDPS ();
1485
1486       if (aop->code)
1487         {
1488           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1489                   "aopPut writting to code space");
1490           exit (1);
1491         }
1492
1493       while (offset > aop->coff)
1494         {
1495           aop->coff++;
1496           emitcode ("inc", "dptr");
1497         }
1498
1499       while (offset < aop->coff)
1500         {
1501           aop->coff--;
1502           emitcode ("lcall", "__decdptr");
1503         }
1504
1505       aop->coff = offset;
1506
1507       /* if not in accumulater */
1508       MOVA (s);
1509
1510       emitcode ("movx", "@dptr,a");
1511
1512       if (aop->type == AOP_DPTR2)
1513         {
1514           genSetDPTR (0);
1515         }
1516       break;
1517
1518     case AOP_R0:
1519     case AOP_R1:
1520       while (offset > aop->coff)
1521         {
1522           aop->coff++;
1523           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1524         }
1525       while (offset < aop->coff)
1526         {
1527           aop->coff--;
1528           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1529         }
1530       aop->coff = offset;
1531
1532       if (aop->paged)
1533         {
1534           MOVA (s);
1535           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1536
1537         }
1538       else if (*s == '@')
1539         {
1540           MOVA (s);
1541           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1542         }
1543       else if (strcmp (s, "r0") == 0 ||
1544                strcmp (s, "r1") == 0 ||
1545                strcmp (s, "r2") == 0 ||
1546                strcmp (s, "r3") == 0 ||
1547                strcmp (s, "r4") == 0 ||
1548                strcmp (s, "r5") == 0 ||
1549                strcmp (s, "r6") == 0 ||
1550                strcmp (s, "r7") == 0)
1551         {
1552           char buff[10];
1553           SNPRINTF(buff, sizeof(buff), 
1554                    "a%s", s);
1555           emitcode ("mov", "@%s,%s",
1556                     aop->aopu.aop_ptr->name, buff);
1557         }
1558         else
1559         {
1560             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1561         }
1562       break;
1563
1564     case AOP_STK:
1565       if (strcmp (s, "a") == 0)
1566         emitcode ("push", "acc");
1567       else
1568         if (*s=='@') {
1569           MOVA(s);
1570           emitcode ("push", "acc");
1571         } else {
1572           emitcode ("push", s);
1573         }
1574
1575       break;
1576
1577     case AOP_CRY:
1578       /* if bit variable */
1579       if (!aop->aopu.aop_dir)
1580         {
1581           emitcode ("clr", "a");
1582           emitcode ("rlc", "a");
1583         }
1584       else
1585         {
1586           if (s == zero)
1587             emitcode ("clr", "%s", aop->aopu.aop_dir);
1588           else if (s == one)
1589             emitcode ("setb", "%s", aop->aopu.aop_dir);
1590           else if (!strcmp (s, "c"))
1591             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1592           else
1593             {
1594               if (strcmp (s, "a"))
1595                 {
1596                   MOVA (s);
1597                 }
1598               {
1599                 /* set C, if a >= 1 */
1600                 emitcode ("add", "a,#!constbyte",0xff);
1601                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1602               }
1603             }
1604         }
1605       break;
1606
1607     case AOP_STR:
1608       aop->coff = offset;
1609       if (strcmp (aop->aopu.aop_str[offset], s))
1610         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1611       break;
1612
1613     case AOP_ACC:
1614       aop->coff = offset;
1615       if (!offset && (strcmp (s, "acc") == 0))
1616         break;
1617
1618       if (strcmp (aop->aopu.aop_str[offset], s))
1619         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1620       break;
1621
1622     default:
1623       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1624               "aopPut got unsupported aop->type");
1625       exit (1);
1626     }
1627
1628 }
1629
1630
1631 /*--------------------------------------------------------------------*/
1632 /* reAdjustPreg - points a register back to where it should (coff==0) */
1633 /*--------------------------------------------------------------------*/
1634 static void
1635 reAdjustPreg (asmop * aop)
1636 {
1637   if ((aop->coff==0) || (aop->size <= 1)) {
1638     return;
1639   }
1640
1641   switch (aop->type)
1642     {
1643     case AOP_R0:
1644     case AOP_R1:
1645       while (aop->coff--)
1646         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1647       break;
1648     case AOP_DPTR:
1649     case AOP_DPTR2:
1650       if (aop->type == AOP_DPTR2)
1651         {
1652           genSetDPTR (1);
1653           _flushLazyDPS ();
1654         }
1655       while (aop->coff--)
1656         {
1657           emitcode ("lcall", "__decdptr");
1658         }
1659
1660       if (aop->type == AOP_DPTR2)
1661         {
1662           genSetDPTR (0);
1663         }
1664       break;
1665
1666     }
1667   aop->coff=0;
1668 }
1669
1670 #define AOP(op) op->aop
1671 #define AOP_TYPE(op) AOP(op)->type
1672 #define AOP_SIZE(op) AOP(op)->size
1673 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1674                        AOP_TYPE(x) == AOP_R0))
1675
1676 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1677                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1678                          AOP(x)->paged))
1679
1680 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1681                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1682                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1683 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1684 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1685 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1686
1687 // The following two macros can be used even if the aop has not yet been aopOp'd.
1688 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1689 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1690
1691 /* Workaround for DS80C390 bug: div ab may return bogus results
1692  * if A is accessed in instruction immediately before the div.
1693  *
1694  * Will be fixed in B4 rev of processor, Dallas claims.
1695  */
1696
1697 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1698     if (!AOP_NEEDSACC(RIGHT))         \
1699     {               \
1700       /* We can load A first, then B, since     \
1701        * B (the RIGHT operand) won't clobber A,   \
1702        * thus avoiding touching A right before the div. \
1703        */             \
1704       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1705       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1706       MOVA(L);            \
1707       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1708       MOVB(L); \
1709     }               \
1710     else              \
1711     {               \
1712       /* Just stuff in a nop after loading A. */    \
1713       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1714       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1715       MOVA(L);            \
1716       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1717     }
1718
1719
1720 /*-----------------------------------------------------------------*/
1721 /* opIsGptr: returns non-zero if the passed operand is       */
1722 /* a generic pointer type.             */
1723 /*-----------------------------------------------------------------*/
1724 static int
1725 opIsGptr (operand * op)
1726 {
1727   sym_link *type = operandType (op);
1728
1729   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1730     {
1731       return 1;
1732     }
1733   return 0;
1734 }
1735
1736 /*-----------------------------------------------------------------*/
1737 /* getDataSize - get the operand data size                         */
1738 /*-----------------------------------------------------------------*/
1739 static int
1740 getDataSize (operand * op)
1741 {
1742   int size;
1743   size = AOP_SIZE (op);
1744   if (size == GPTRSIZE)
1745     {
1746       sym_link *type = operandType (op);
1747       if (IS_GENPTR (type))
1748         {
1749           /* generic pointer; arithmetic operations
1750            * should ignore the high byte (pointer type).
1751            */
1752           size--;
1753         }
1754     }
1755   return size;
1756 }
1757
1758 /*-----------------------------------------------------------------*/
1759 /* outAcc - output Acc                                             */
1760 /*-----------------------------------------------------------------*/
1761 static void
1762 outAcc (operand * result)
1763 {
1764   int size, offset;
1765   size = getDataSize (result);
1766   if (size)
1767     {
1768       aopPut (AOP (result), "a", 0);
1769       size--;
1770       offset = 1;
1771       /* unsigned or positive */
1772       while (size--)
1773         {
1774           aopPut (AOP (result), zero, offset++);
1775         }
1776     }
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* outBitC - output a bit C                                        */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 outBitC (operand * result)
1784 {
1785   /* if the result is bit */
1786   if (AOP_TYPE (result) == AOP_CRY)
1787     {
1788       aopPut (AOP (result), "c", 0);
1789     }
1790   else
1791     {
1792       emitcode ("clr", "a");
1793       emitcode ("rlc", "a");
1794       outAcc (result);
1795     }
1796 }
1797
1798 /*-----------------------------------------------------------------*/
1799 /* toBoolean - emit code for orl a,operator(sizeop)                */
1800 /*-----------------------------------------------------------------*/
1801 static void
1802 toBoolean (operand * oper)
1803 {
1804   int   size = AOP_SIZE (oper) - 1;
1805   int   offset = 1;
1806   bool usedB = FALSE;
1807
1808   /* The generic part of a generic pointer should
1809    * not participate in it's truth value.
1810    *
1811    * i.e. 0x10000000 is zero.
1812    */
1813   if (opIsGptr (oper))
1814     {
1815       D (emitcode (";", "toBoolean: generic ptr special case."););
1816       size--;
1817     }
1818
1819   _startLazyDPSEvaluation ();
1820   if (AOP_NEEDSACC (oper) && size)
1821     {
1822       usedB = TRUE;
1823       if (_G.bInUse)
1824       {
1825           emitcode ("push", "b");
1826       }
1827       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1828     }
1829   else
1830     {
1831       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1832     }
1833     
1834   while (size--)
1835     {
1836       if (usedB)
1837         {
1838           emitcode ("orl", "b,%s",
1839                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1840         }
1841       else
1842         {
1843           emitcode ("orl", "a,%s",
1844                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1845         }
1846     }
1847   _endLazyDPSEvaluation ();
1848
1849   if (usedB)
1850     {
1851       emitcode ("mov", "a,b");
1852       if (_G.bInUse)
1853       {
1854           emitcode ("pop", "b");
1855       }
1856         
1857     }
1858 }
1859
1860
1861 /*-----------------------------------------------------------------*/
1862 /* genNot - generate code for ! operation                          */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 genNot (iCode * ic)
1866 {
1867   symbol *tlbl;
1868
1869   D (emitcode (";", "genNot "););
1870
1871   /* assign asmOps to operand & result */
1872   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1873   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1874
1875   /* if in bit space then a special case */
1876   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1877     {
1878       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1879       emitcode ("cpl", "c");
1880       outBitC (IC_RESULT (ic));
1881       goto release;
1882     }
1883
1884   toBoolean (IC_LEFT (ic));
1885
1886   tlbl = newiTempLabel (NULL);
1887   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1888   emitcode ("", "!tlabeldef", tlbl->key + 100);
1889   outBitC (IC_RESULT (ic));
1890
1891 release:
1892   /* release the aops */
1893   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1894   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1895 }
1896
1897
1898 /*-----------------------------------------------------------------*/
1899 /* genCpl - generate code for complement                           */
1900 /*-----------------------------------------------------------------*/
1901 static void
1902 genCpl (iCode * ic)
1903 {
1904   int offset = 0;
1905   int size;
1906   symbol *tlbl;
1907
1908   D (emitcode (";", "genCpl "););
1909
1910
1911   /* assign asmOps to operand & result */
1912   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1913   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1914
1915   /* special case if in bit space */
1916   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1917     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1918       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1919       emitcode ("cpl", "c");
1920       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1921       goto release;
1922     }
1923     tlbl=newiTempLabel(NULL);
1924     emitcode ("cjne", "%s,#0x01,%05d$", 
1925               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1926     emitcode ("", "%05d$:", tlbl->key+100);
1927     outBitC (IC_RESULT(ic));
1928     goto release;
1929   }
1930
1931   size = AOP_SIZE (IC_RESULT (ic));
1932   _startLazyDPSEvaluation ();
1933   while (size--)
1934     {
1935       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1936       emitcode ("cpl", "a");
1937       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1938     }
1939   _endLazyDPSEvaluation ();
1940
1941
1942 release:
1943   /* release the aops */
1944   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1945   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1946 }
1947
1948 /*-----------------------------------------------------------------*/
1949 /* genUminusFloat - unary minus for floating points                */
1950 /*-----------------------------------------------------------------*/
1951 static void
1952 genUminusFloat (operand * op, operand * result)
1953 {
1954   int size, offset = 0;
1955     
1956   D(emitcode (";", "genUminusFloat"););
1957   
1958   /* for this we just copy and then flip the bit */
1959     
1960   _startLazyDPSEvaluation ();
1961   size = AOP_SIZE (op) - 1;
1962
1963   while (size--)
1964   {
1965       aopPut (AOP (result),
1966               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1967               offset);
1968       offset++;
1969     }
1970   
1971   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1972
1973   emitcode ("cpl", "acc.7");
1974   aopPut (AOP (result), "a", offset);    
1975   _endLazyDPSEvaluation ();
1976 }
1977
1978 /*-----------------------------------------------------------------*/
1979 /* genUminus - unary minus code generation                         */
1980 /*-----------------------------------------------------------------*/
1981 static void
1982 genUminus (iCode * ic)
1983 {
1984   int offset, size;
1985   sym_link *optype;
1986
1987   D (emitcode (";", "genUminus "););
1988
1989   /* assign asmops */
1990   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1991   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1992
1993   /* if both in bit space then special
1994      case */
1995   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1996       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1997     {
1998
1999       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2000       emitcode ("cpl", "c");
2001       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2002       goto release;
2003     }
2004
2005   optype = operandType (IC_LEFT (ic));
2006
2007   /* if float then do float stuff */
2008   if (IS_FLOAT (optype))
2009     {
2010       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2011       goto release;
2012     }
2013
2014   /* otherwise subtract from zero */
2015   size = AOP_SIZE (IC_LEFT (ic));
2016   offset = 0;
2017   _startLazyDPSEvaluation ();
2018   while (size--)
2019     {
2020       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2021       if (!strcmp (l, "a"))
2022         {
2023           if (offset == 0)
2024             SETC;
2025           emitcode ("cpl", "a");
2026           emitcode ("addc", "a,#0");
2027         }
2028       else
2029         {
2030           if (offset == 0)
2031             CLRC;
2032           emitcode ("clr", "a");
2033           emitcode ("subb", "a,%s", l);
2034         }
2035       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2036     }
2037   _endLazyDPSEvaluation ();
2038
2039   /* if any remaining bytes in the result */
2040   /* we just need to propagate the sign   */
2041   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2042     {
2043       emitcode ("rlc", "a");
2044       emitcode ("subb", "a,acc");
2045       while (size--)
2046         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2047     }
2048
2049 release:
2050   /* release the aops */
2051   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2052   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2053 }
2054
2055 /*-----------------------------------------------------------------*/
2056 /* savermask - saves registers in the mask                         */
2057 /*-----------------------------------------------------------------*/
2058 static void savermask(bitVect *rs_mask)
2059 {
2060     int i;
2061     if (options.useXstack) {
2062         if (bitVectBitValue (rs_mask, R0_IDX))
2063             emitcode ("mov", "b,r0");
2064         emitcode ("mov", "r0,%s", spname);
2065         for (i = 0; i < ds390_nRegs; i++) {
2066             if (bitVectBitValue (rs_mask, i)) {
2067                 if (i == R0_IDX)
2068                     emitcode ("mov", "a,b");
2069                 else
2070                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2071                 emitcode ("movx", "@r0,a");
2072                 emitcode ("inc", "r0");
2073             }
2074         }
2075         emitcode ("mov", "%s,r0", spname);
2076         if (bitVectBitValue (rs_mask, R0_IDX))
2077             emitcode ("mov", "r0,b");
2078     } else {
2079         for (i = 0; i < ds390_nRegs; i++) {
2080             if (bitVectBitValue (rs_mask, i))
2081                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2082         }
2083     }
2084 }
2085
2086 /*-----------------------------------------------------------------*/
2087 /* saveRegisters - will look for a call and save the registers     */
2088 /*-----------------------------------------------------------------*/
2089 static void
2090 saveRegisters (iCode * lic)
2091 {
2092   iCode *ic;
2093   bitVect *rsave;
2094
2095   /* look for call */
2096   for (ic = lic; ic; ic = ic->next)
2097     if (ic->op == CALL || ic->op == PCALL)
2098       break;
2099
2100   if (!ic)
2101     {
2102       fprintf (stderr, "found parameter push with no function call\n");
2103       return;
2104     }
2105
2106   /* if the registers have been saved already then
2107      do nothing */
2108   if (ic->regsSaved 
2109       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2110     return ;
2111
2112   /* special case if DPTR alive across a function call then must save it 
2113      even though callee saves */
2114   if (IS_SYMOP(IC_LEFT(ic)) &&
2115       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2116       int i;
2117       rsave = newBitVect(ic->rMask->size);
2118       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2119           if (bitVectBitValue(ic->rMask,i))
2120               rsave = bitVectSetBit(rsave,i);
2121       }
2122       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2123   } else {
2124     /* safe the registers in use at this time but skip the
2125        ones for the result */
2126     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2127                            ds390_rUmaskForOp (IC_RESULT(ic)));
2128   }
2129   ic->regsSaved = 1;
2130   savermask(rsave);
2131 }
2132
2133 /*-----------------------------------------------------------------*/
2134 /* usavermask - restore registers with mask                        */
2135 /*-----------------------------------------------------------------*/
2136 static void unsavermask(bitVect *rs_mask)
2137 {
2138     int i;
2139     if (options.useXstack) {
2140         emitcode ("mov", "r0,%s", spname);
2141         for (i = ds390_nRegs; i >= 0; i--) {
2142             if (bitVectBitValue (rs_mask, i)) {
2143                 emitcode ("dec", "r0");
2144                 emitcode ("movx", "a,@r0");
2145                 if (i == R0_IDX)
2146                     emitcode ("mov", "b,a");
2147                 else
2148                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2149             }       
2150         }
2151         emitcode ("mov", "%s,r0", spname);
2152         if (bitVectBitValue (rs_mask, R0_IDX))
2153             emitcode ("mov", "r0,b");
2154     } else {
2155         for (i = ds390_nRegs; i >= 0; i--) {
2156             if (bitVectBitValue (rs_mask, i))
2157                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2158         }
2159     }
2160 }
2161
2162 /*-----------------------------------------------------------------*/
2163 /* unsaveRegisters - pop the pushed registers                      */
2164 /*-----------------------------------------------------------------*/
2165 static void
2166 unsaveRegisters (iCode * ic)
2167 {
2168   bitVect *rsave;
2169
2170   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2171       int i;
2172       rsave = newBitVect(ic->rMask->size);
2173       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2174           if (bitVectBitValue(ic->rMask,i))
2175               rsave = bitVectSetBit(rsave,i);
2176       }
2177       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2178   } else {
2179     /* restore the registers in use at this time but skip the
2180        ones for the result */
2181     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2182                            ds390_rUmaskForOp (IC_RESULT(ic)));
2183   }
2184   unsavermask(rsave);
2185 }
2186
2187
2188 /*-----------------------------------------------------------------*/
2189 /* pushSide -                */
2190 /*-----------------------------------------------------------------*/
2191 static void
2192 pushSide (operand * oper, int size)
2193 {
2194   int offset = 0;
2195   _startLazyDPSEvaluation ();
2196   while (size--)
2197     {
2198       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2199       if (AOP_TYPE (oper) != AOP_REG &&
2200           AOP_TYPE (oper) != AOP_DIR &&
2201           strcmp (l, "a"))
2202         {
2203           emitcode ("mov", "a,%s", l);
2204           emitcode ("push", "acc");
2205         }
2206       else
2207         emitcode ("push", "%s", l);
2208     }
2209   _endLazyDPSEvaluation ();
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* assignResultValue -               */
2214 /*-----------------------------------------------------------------*/
2215 static void
2216 assignResultValue (operand * oper)
2217 {
2218   int offset = 0;
2219   int size = AOP_SIZE (oper);
2220   bool pushedAcc = FALSE;
2221
2222   if (size == fReturnSizeDS390)
2223   {
2224       /* I don't think this case can ever happen... */
2225       /* ACC is the last part of this. If writing the result
2226        * uses AC, we must preserve it.
2227        */
2228       if (AOP_NEEDSACC(oper))
2229       {
2230           emitcode(";", "assignResultValue special case for ACC.");
2231           emitcode("push", "acc");
2232           pushedAcc = TRUE;
2233           size--;
2234       }
2235   }
2236     
2237     
2238   _startLazyDPSEvaluation ();
2239   while (size--)
2240     {
2241       aopPut (AOP (oper), fReturn[offset], offset);
2242       offset++;
2243     }
2244   _endLazyDPSEvaluation ();
2245     
2246   if (pushedAcc)
2247     {
2248         emitcode("pop", "acc");
2249         aopPut(AOP(oper), "a", offset);
2250     }
2251 }
2252
2253
2254 /*-----------------------------------------------------------------*/
2255 /* genXpush - pushes onto the external stack                       */
2256 /*-----------------------------------------------------------------*/
2257 static void
2258 genXpush (iCode * ic)
2259 {
2260   asmop *aop = newAsmop (0);
2261   regs *r;
2262   int size, offset = 0;
2263
2264   D (emitcode (";", "genXpush ");
2265     );
2266
2267   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2268   r = getFreePtr (ic, &aop, FALSE);
2269
2270
2271   emitcode ("mov", "%s,_spx", r->name);
2272
2273   size = AOP_SIZE (IC_LEFT (ic));
2274   _startLazyDPSEvaluation ();
2275   while (size--)
2276     {
2277
2278       MOVA (aopGet (AOP (IC_LEFT (ic)),
2279                         offset++, FALSE, FALSE, NULL));
2280       emitcode ("movx", "@%s,a", r->name);
2281       emitcode ("inc", "%s", r->name);
2282
2283     }
2284   _endLazyDPSEvaluation ();
2285
2286
2287   emitcode ("mov", "_spx,%s", r->name);
2288
2289   freeAsmop (NULL, aop, ic, TRUE);
2290   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2291 }
2292
2293 /*-----------------------------------------------------------------*/
2294 /* genIpush - generate code for pushing this gets a little complex  */
2295 /*-----------------------------------------------------------------*/
2296 static void
2297 genIpush (iCode * ic)
2298 {
2299   int size, offset = 0;
2300   char *l;
2301
2302   D (emitcode (";", "genIpush ");
2303     );
2304
2305   /* if this is not a parm push : ie. it is spill push
2306      and spill push is always done on the local stack */
2307   if (!ic->parmPush)
2308     {
2309
2310       /* and the item is spilt then do nothing */
2311       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2312         return;
2313
2314       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315       size = AOP_SIZE (IC_LEFT (ic));
2316       /* push it on the stack */
2317       _startLazyDPSEvaluation ();
2318       while (size--)
2319         {
2320           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2321           if (*l == '#')
2322             {
2323               MOVA (l);
2324               l = "acc";
2325             }
2326           emitcode ("push", "%s", l);
2327         }
2328       _endLazyDPSEvaluation ();
2329       return;
2330     }
2331
2332   /* this is a paramter push: in this case we call
2333      the routine to find the call and save those
2334      registers that need to be saved */
2335   saveRegisters (ic);
2336
2337   /* if use external stack then call the external
2338      stack pushing routine */
2339   if (options.useXstack)
2340     {
2341       genXpush (ic);
2342       return;
2343     }
2344
2345   /* then do the push */
2346   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2347
2348   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2349   size = AOP_SIZE (IC_LEFT (ic));
2350
2351   _startLazyDPSEvaluation ();
2352   while (size--)
2353     {
2354       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2355       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2356           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2357           strcmp (l, "acc"))
2358         {
2359           emitcode ("mov", "a,%s", l);
2360           emitcode ("push", "acc");
2361         }
2362       else
2363         {
2364             emitcode ("push", "%s", l);
2365         }
2366     }
2367   _endLazyDPSEvaluation ();
2368
2369   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2370 }
2371
2372 /*-----------------------------------------------------------------*/
2373 /* genIpop - recover the registers: can happen only for spilling   */
2374 /*-----------------------------------------------------------------*/
2375 static void
2376 genIpop (iCode * ic)
2377 {
2378   int size, offset;
2379
2380   D (emitcode (";", "genIpop ");
2381     );
2382
2383
2384   /* if the temp was not pushed then */
2385   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2386     return;
2387
2388   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2389   size = AOP_SIZE (IC_LEFT (ic));
2390   offset = (size - 1);
2391   _startLazyDPSEvaluation ();
2392   while (size--)
2393     {
2394       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2395                                      FALSE, TRUE, NULL));
2396     }
2397   _endLazyDPSEvaluation ();
2398
2399   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2400 }
2401
2402 /*-----------------------------------------------------------------*/
2403 /* unsaveRBank - restores the resgister bank from stack            */
2404 /*-----------------------------------------------------------------*/
2405 static void
2406 unsaveRBank (int bank, iCode * ic, bool popPsw)
2407 {
2408   int i;
2409   asmop *aop = NULL;
2410   regs *r = NULL;
2411
2412   if (options.useXstack)
2413   {
2414       if (!ic)
2415       {
2416           /* Assume r0 is available for use. */
2417           r = ds390_regWithIdx (R0_IDX);;          
2418       } 
2419       else
2420       {
2421           aop = newAsmop (0);
2422           r = getFreePtr (ic, &aop, FALSE);
2423       }
2424       emitcode ("mov", "%s,_spx", r->name);      
2425   }
2426   
2427   if (popPsw)
2428     {
2429       if (options.useXstack)
2430       {
2431           emitcode ("movx", "a,@%s", r->name);
2432           emitcode ("mov", "psw,a");
2433           emitcode ("dec", "%s", r->name);
2434         }
2435       else
2436       {
2437         emitcode ("pop", "psw");
2438       }
2439     }
2440
2441   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2442     {
2443       if (options.useXstack)
2444         {
2445           emitcode ("movx", "a,@%s", r->name);
2446           emitcode ("mov", "(%s+%d),a",
2447                     regs390[i].base, 8 * bank + regs390[i].offset);
2448           emitcode ("dec", "%s", r->name);
2449
2450         }
2451       else
2452         emitcode ("pop", "(%s+%d)",
2453                   regs390[i].base, 8 * bank + regs390[i].offset);
2454     }
2455
2456   if (options.useXstack)
2457     {
2458       emitcode ("mov", "_spx,%s", r->name);
2459     }
2460     
2461   if (aop)
2462   {
2463       freeAsmop (NULL, aop, ic, TRUE);  
2464   }    
2465 }
2466
2467 /*-----------------------------------------------------------------*/
2468 /* saveRBank - saves an entire register bank on the stack          */
2469 /*-----------------------------------------------------------------*/
2470 static void
2471 saveRBank (int bank, iCode * ic, bool pushPsw)
2472 {
2473   int i;
2474   asmop *aop = NULL;
2475   regs *r = NULL;
2476
2477   if (options.useXstack)
2478     {
2479         if (!ic)
2480         {
2481           /* Assume r0 is available for use. */
2482                   r = ds390_regWithIdx (R0_IDX);;
2483         }
2484         else
2485         {
2486           aop = newAsmop (0);
2487           r = getFreePtr (ic, &aop, FALSE);
2488         }
2489         emitcode ("mov", "%s,_spx", r->name);    
2490     }
2491
2492   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2493     {
2494       if (options.useXstack)
2495         {
2496           emitcode ("inc", "%s", r->name);
2497           emitcode ("mov", "a,(%s+%d)",
2498                     regs390[i].base, 8 * bank + regs390[i].offset);
2499           emitcode ("movx", "@%s,a", r->name);
2500         }
2501       else
2502         emitcode ("push", "(%s+%d)",
2503                   regs390[i].base, 8 * bank + regs390[i].offset);
2504     }
2505
2506   if (pushPsw)
2507     {
2508       if (options.useXstack)
2509         {
2510           emitcode ("mov", "a,psw");
2511           emitcode ("movx", "@%s,a", r->name);
2512           emitcode ("inc", "%s", r->name);
2513           emitcode ("mov", "_spx,%s", r->name);
2514         }
2515       else
2516       {
2517         emitcode ("push", "psw");
2518       }
2519
2520       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2521     }
2522   
2523   if (aop)
2524   {
2525        freeAsmop (NULL, aop, ic, TRUE);
2526   }    
2527     
2528   if (ic)
2529   {  
2530       ic->bankSaved = 1;
2531   }
2532 }
2533
2534 /*-----------------------------------------------------------------*/
2535 /* genSend - gen code for SEND                                     */
2536 /*-----------------------------------------------------------------*/
2537 static void genSend(set *sendSet)
2538 {
2539     iCode *sic;
2540     int sendCount = 0 ;
2541     static int rb1_count = 0;
2542
2543     for (sic = setFirstItem (sendSet); sic;
2544          sic = setNextItem (sendSet)) {     
2545         int size, offset = 0;
2546         
2547         size=getSize(operandType(IC_LEFT(sic)));
2548         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2549         if (sendCount == 0) { /* first parameter */
2550             // we know that dpl(hxb) is the result, so
2551             rb1_count = 0 ;
2552             _startLazyDPSEvaluation ();
2553             if (size>1) {
2554                 aopOp (IC_LEFT (sic), sic, FALSE, 
2555                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2556             } else {
2557                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2558             }
2559             while (size--) {
2560                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2561                                   FALSE, FALSE, NULL);
2562                 if (strcmp (l, fReturn[offset])) {
2563                     emitcode ("mov", "%s,%s",
2564                               fReturn[offset],
2565                               l);
2566                 }
2567                 offset++;
2568             }
2569             _endLazyDPSEvaluation ();
2570             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2571             rb1_count =0;
2572         } else { /* if more parameter in registers */
2573             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2574             while (size--) {
2575                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2576                                                                 FALSE, FALSE, NULL));
2577             }
2578             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2579         }
2580         sendCount++;
2581     }
2582 }
2583
2584 static void
2585 adjustEsp(const char *reg)
2586 {
2587     emitcode ("anl","%s,#3", reg);
2588     if (TARGET_IS_DS400)
2589     {
2590         emitcode ("orl","%s,#!constbyte",
2591                   reg,
2592                   (options.stack_loc >> 8) & 0xff);
2593     }
2594 }
2595
2596 /*-----------------------------------------------------------------*/
2597 /* genCall - generates a call statement                            */
2598 /*-----------------------------------------------------------------*/
2599 static void
2600 genCall (iCode * ic)
2601 {
2602   sym_link *dtype;
2603   bool restoreBank = FALSE;
2604   bool swapBanks = FALSE;
2605
2606   D (emitcode (";", "genCall "););
2607
2608   /* if we are calling a not _naked function that is not using
2609      the same register bank then we need to save the
2610      destination registers on the stack */
2611   dtype = operandType (IC_LEFT (ic));
2612   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2613       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2614       IFFUNC_ISISR (currFunc->type))
2615   {
2616       if (!ic->bankSaved) 
2617       {
2618            /* This is unexpected; the bank should have been saved in
2619             * genFunction.
2620             */
2621            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2622            restoreBank = TRUE;
2623       }
2624       swapBanks = TRUE;
2625   }
2626   
2627     /* if caller saves & we have not saved then */
2628     if (!ic->regsSaved)
2629       saveRegisters (ic);
2630   
2631   /* if send set is not empty the assign */
2632   /* We've saved all the registers we care about;
2633   * therefore, we may clobber any register not used
2634   * in the calling convention (i.e. anything not in
2635   * fReturn.
2636   */
2637   if (_G.sendSet)
2638     {
2639         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2640             genSend(reverseSet(_G.sendSet));
2641         } else {
2642             genSend(_G.sendSet);
2643         }
2644       _G.sendSet = NULL;
2645     }  
2646     
2647   if (swapBanks)
2648   {
2649         emitcode ("mov", "psw,#!constbyte", 
2650            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2651   }
2652
2653   /* make the call */
2654   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2655                             OP_SYMBOL (IC_LEFT (ic))->rname :
2656                             OP_SYMBOL (IC_LEFT (ic))->name));
2657
2658   if (swapBanks)
2659   {
2660        emitcode ("mov", "psw,#!constbyte", 
2661           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2662   }
2663
2664   /* if we need assign a result value */
2665   if ((IS_ITEMP (IC_RESULT (ic)) &&
2666        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2667         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2668         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2669       IS_TRUE_SYMOP (IC_RESULT (ic)))
2670     {
2671       if (isOperandInFarSpace (IC_RESULT (ic))
2672           && getSize (operandType (IC_RESULT (ic))) <= 2)
2673         {
2674           int size = getSize (operandType (IC_RESULT (ic)));
2675
2676           /* Special case for 1 or 2 byte return in far space. */
2677           MOVA (fReturn[0]);
2678           if (size > 1)
2679             {
2680               emitcode ("mov", "b,%s", fReturn[1]);
2681               _G.bInUse++;
2682             }
2683
2684           _G.accInUse++;
2685           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2686           _G.accInUse--;
2687           
2688           if (size > 1)
2689             _G.bInUse--;
2690
2691           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2692
2693           if (size > 1)
2694             {
2695               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2696             }
2697           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2698         }
2699       else
2700         {
2701           _G.bInUse++;
2702           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2703           _G.bInUse--;
2704
2705           assignResultValue (IC_RESULT (ic));
2706
2707           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2708         }
2709     }
2710
2711   /* adjust the stack for parameters if
2712      required */
2713   if (ic->parmBytes) {
2714       int i;
2715       if (options.stack10bit) {
2716           if (ic->parmBytes <= 10) {
2717               emitcode(";","stack adjustment for parms");
2718               for (i=0; i < ic->parmBytes ; i++) {
2719                   emitcode("pop","acc");
2720               }
2721           } else {            
2722               PROTECT_SP;
2723               emitcode ("clr","c");
2724               emitcode ("mov","a,sp");
2725               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2726               emitcode ("mov","sp,a");
2727               emitcode ("mov","a,esp");
2728               adjustEsp("a");
2729               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2730               emitcode ("mov","esp,a");   
2731               UNPROTECT_SP;
2732           }
2733       } else {
2734           if (ic->parmBytes > 3) {
2735               emitcode ("mov", "a,%s", spname);
2736               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2737               emitcode ("mov", "%s,a", spname);
2738           } else
2739               for (i = 0; i < ic->parmBytes; i++)
2740                   emitcode ("dec", "%s", spname);
2741       }
2742   }
2743
2744   /* if we hade saved some registers then unsave them */
2745   if (ic->regsSaved)
2746     unsaveRegisters (ic);
2747
2748   /* if register bank was saved then pop them */
2749   if (restoreBank)
2750     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2751 }
2752
2753 /*-----------------------------------------------------------------*/
2754 /* genPcall - generates a call by pointer statement                */
2755 /*-----------------------------------------------------------------*/
2756 static void
2757 genPcall (iCode * ic)
2758 {
2759   sym_link *dtype;
2760   symbol *rlbl = newiTempLabel (NULL);
2761   bool restoreBank=FALSE;
2762
2763   D (emitcode (";", "genPcall ");
2764     );
2765
2766
2767   /* if caller saves & we have not saved then */
2768   if (!ic->regsSaved)
2769     saveRegisters (ic);
2770
2771   /* if we are calling a function that is not using
2772      the same register bank then we need to save the
2773      destination registers on the stack */
2774   dtype = operandType (IC_LEFT (ic));
2775   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2776       IFFUNC_ISISR (currFunc->type) &&
2777       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2778     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2779     restoreBank=TRUE;
2780   }
2781
2782   /* push the return address on to the stack */
2783   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2784   emitcode ("push", "acc");
2785   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2786   emitcode ("push", "acc");
2787
2788   if (options.model == MODEL_FLAT24)
2789     {
2790       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2791       emitcode ("push", "acc");
2792     }
2793
2794   /* now push the calling address */
2795   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2796
2797   pushSide (IC_LEFT (ic), FPTRSIZE);
2798
2799   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2800
2801   /* if send set is not empty the assign */
2802   if (_G.sendSet)
2803     {
2804         genSend(reverseSet(_G.sendSet));
2805         _G.sendSet = NULL;
2806     }
2807
2808   emitcode ("ret", "");
2809   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2810
2811
2812   /* if we need assign a result value */
2813   if ((IS_ITEMP (IC_RESULT (ic)) &&
2814        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2815         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2816       IS_TRUE_SYMOP (IC_RESULT (ic)))
2817     {
2818
2819       _G.accInUse++;
2820       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2821       _G.accInUse--;
2822
2823       assignResultValue (IC_RESULT (ic));
2824
2825       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2826     }
2827
2828   /* adjust the stack for parameters if
2829      required */
2830   if (ic->parmBytes)
2831     {
2832       int i;
2833       if (options.stack10bit) {
2834           if (ic->parmBytes <= 10) {
2835               emitcode(";","stack adjustment for parms");
2836               for (i=0; i < ic->parmBytes ; i++) {
2837                   emitcode("pop","acc");
2838               }
2839           } else {            
2840               PROTECT_SP;
2841               emitcode ("clr","c");
2842               emitcode ("mov","a,sp");
2843               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2844               emitcode ("mov","sp,a");
2845               emitcode ("mov","a,esp");
2846               adjustEsp("a");
2847               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2848               emitcode ("mov","esp,a");   
2849               UNPROTECT_SP;
2850           }
2851       } else {
2852           if (ic->parmBytes > 3) {
2853               emitcode ("mov", "a,%s", spname);
2854               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2855               emitcode ("mov", "%s,a", spname);
2856           }
2857           else
2858               for (i = 0; i < ic->parmBytes; i++)
2859                   emitcode ("dec", "%s", spname);
2860           
2861       }
2862     }
2863   /* if register bank was saved then unsave them */
2864   if (restoreBank)
2865     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2866   
2867   /* if we hade saved some registers then
2868      unsave them */
2869   if (ic->regsSaved)
2870     unsaveRegisters (ic);
2871
2872 }
2873
2874 /*-----------------------------------------------------------------*/
2875 /* resultRemat - result  is rematerializable                       */
2876 /*-----------------------------------------------------------------*/
2877 static int
2878 resultRemat (iCode * ic)
2879 {
2880   if (SKIP_IC (ic) || ic->op == IFX)
2881     return 0;
2882
2883   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2884     {
2885       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2886       if (sym->remat && !POINTER_SET (ic))
2887         return 1;
2888     }
2889
2890   return 0;
2891 }
2892
2893 #if defined(__BORLANDC__) || defined(_MSC_VER)
2894 #define STRCASECMP stricmp
2895 #else
2896 #define STRCASECMP strcasecmp
2897 #endif
2898
2899 /*-----------------------------------------------------------------*/
2900 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2901 /*-----------------------------------------------------------------*/
2902 static int
2903 regsCmp(void *p1, void *p2)
2904 {
2905   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2906 }
2907
2908 static bool
2909 inExcludeList (char *s)
2910 {
2911   const char *p = setFirstItem(options.excludeRegsSet);
2912
2913   if (p == NULL || STRCASECMP(p, "none") == 0)
2914     return FALSE;
2915
2916
2917   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2918 }
2919
2920 /*-----------------------------------------------------------------*/
2921 /* genFunction - generated code for function entry                 */
2922 /*-----------------------------------------------------------------*/
2923 static void
2924 genFunction (iCode * ic)
2925 {
2926   symbol *sym;
2927   sym_link *ftype;
2928   bool   switchedPSW = FALSE;
2929
2930   D (emitcode (";", "genFunction "););
2931
2932   _G.nRegsSaved = 0;
2933   /* create the function header */
2934   emitcode (";", "-----------------------------------------");
2935   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2936   emitcode (";", "-----------------------------------------");
2937
2938   emitcode ("", "%s:", sym->rname);
2939   ftype = operandType (IC_LEFT (ic));
2940
2941   if (IFFUNC_ISNAKED(ftype))
2942   {
2943       emitcode(";", "naked function: no prologue.");
2944       return;
2945   }
2946   
2947   if (options.stack_probe) 
2948       emitcode ("lcall","__stack_probe");
2949
2950   /* here we need to generate the equates for the
2951      register bank if required */
2952   if (FUNC_REGBANK (ftype) != rbank)
2953     {
2954       int i;
2955
2956       rbank = FUNC_REGBANK (ftype);
2957       for (i = 0; i < ds390_nRegs; i++)
2958         {
2959           if (regs390[i].print) {
2960               if (strcmp (regs390[i].base, "0") == 0)
2961                   emitcode ("", "%s !equ !constbyte",
2962                             regs390[i].dname,
2963                             8 * rbank + regs390[i].offset);
2964               else
2965                   emitcode ("", "%s !equ %s + !constbyte",
2966                             regs390[i].dname,
2967                             regs390[i].base,
2968                             8 * rbank + regs390[i].offset);
2969           }
2970         }
2971     }
2972
2973   /* if this is an interrupt service routine then
2974      save acc, b, dpl, dph  */
2975   if (IFFUNC_ISISR (sym->type))
2976       { /* is ISR */
2977       if (!inExcludeList ("acc"))
2978         emitcode ("push", "acc");
2979       if (!inExcludeList ("b"))
2980         emitcode ("push", "b");
2981       if (!inExcludeList ("dpl"))
2982         emitcode ("push", "dpl");
2983       if (!inExcludeList ("dph"))
2984         emitcode ("push", "dph");
2985       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2986         {
2987           emitcode ("push", "dpx");
2988           /* Make sure we're using standard DPTR */
2989           emitcode ("push", "dps");
2990           emitcode ("mov", "dps,#0");
2991           if (options.stack10bit)
2992             {
2993               /* This ISR could conceivably use DPTR2. Better save it. */
2994               emitcode ("push", "dpl1");
2995               emitcode ("push", "dph1");
2996               emitcode ("push", "dpx1");
2997               emitcode ("push",  DP2_RESULT_REG);
2998             }
2999         }
3000       /* if this isr has no bank i.e. is going to
3001          run with bank 0 , then we need to save more
3002          registers :-) */
3003       if (!FUNC_REGBANK (sym->type))
3004         {
3005             int i;
3006
3007           /* if this function does not call any other
3008              function then we can be economical and
3009              save only those registers that are used */
3010           if (!IFFUNC_HASFCALL(sym->type))
3011             {
3012
3013               /* if any registers used */
3014               if (sym->regsUsed)
3015                 {
3016                   /* save the registers used */
3017                   for (i = 0; i < sym->regsUsed->size; i++)
3018                     {
3019                       if (bitVectBitValue (sym->regsUsed, i) ||
3020                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3021                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3022                     }
3023                 }
3024               else if (ds390_ptrRegReq)
3025                 {
3026                   emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3027                   emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3028                 }
3029
3030             }
3031           else
3032             {
3033               /* this function has  a function call cannot
3034                  determines register usage so we will have to push the
3035                  entire bank */
3036               saveRBank (0, ic, FALSE);
3037               if (options.parms_in_bank1) {
3038                   for (i=0; i < 8 ; i++ ) {
3039                       emitcode ("push","%s",rb1regs[i]);
3040                   }
3041               }
3042             }
3043         }
3044         else
3045         {
3046             /* This ISR uses a non-zero bank.
3047              *
3048              * We assume that the bank is available for our
3049              * exclusive use.
3050              *
3051              * However, if this ISR calls a function which uses some
3052              * other bank, we must save that bank entirely.
3053              */
3054             unsigned long banksToSave = 0;
3055             
3056             if (IFFUNC_HASFCALL(sym->type))
3057             {
3058
3059 #define MAX_REGISTER_BANKS 4
3060
3061                 iCode *i;
3062                 int ix;
3063
3064                 for (i = ic; i; i = i->next)
3065                 {
3066                     if (i->op == ENDFUNCTION)
3067                     {
3068                         /* we got to the end OK. */
3069                         break;
3070                     }
3071                     
3072                     if (i->op == CALL)
3073                     {
3074                         sym_link *dtype;
3075                         
3076                         dtype = operandType (IC_LEFT(i));
3077                         if (dtype 
3078                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3079                         {
3080                              /* Mark this bank for saving. */
3081                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3082                              {
3083                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3084                              }
3085                              else
3086                              {
3087                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3088                              }
3089                              
3090                              /* And note that we don't need to do it in 
3091                               * genCall.
3092                               */
3093                              i->bankSaved = 1;
3094                         }
3095                     }
3096                     if (i->op == PCALL)
3097                     {
3098                         /* This is a mess; we have no idea what
3099                          * register bank the called function might
3100                          * use.
3101                          *
3102                          * The only thing I can think of to do is
3103                          * throw a warning and hope.
3104                          */
3105                         werror(W_FUNCPTR_IN_USING_ISR);   
3106                     }
3107                 }
3108
3109                 if (banksToSave && options.useXstack)
3110                 {
3111                     /* Since we aren't passing it an ic, 
3112                      * saveRBank will assume r0 is available to abuse.
3113                      *
3114                      * So switch to our (trashable) bank now, so
3115                      * the caller's R0 isn't trashed.
3116                      */
3117                     emitcode ("push", "psw");
3118                     emitcode ("mov", "psw,#!constbyte", 
3119                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3120                     switchedPSW = TRUE;
3121                 }
3122                 
3123                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3124                 {
3125                      if (banksToSave & (1 << ix))
3126                      {
3127                          saveRBank(ix, NULL, FALSE);
3128                      }
3129                 }
3130             }
3131             // TODO: this needs a closer look
3132             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3133         }
3134     }
3135   else
3136     {
3137       /* if callee-save to be used for this function
3138          then save the registers being used in this function */
3139       if (IFFUNC_CALLEESAVES(sym->type))
3140         {
3141           int i;
3142
3143           /* if any registers used */
3144           if (sym->regsUsed)
3145             {
3146               /* save the registers used */
3147               for (i = 0; i < sym->regsUsed->size; i++)
3148                 {
3149                   if (bitVectBitValue (sym->regsUsed, i) ||
3150                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3151                     {
3152                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3153                       _G.nRegsSaved++;
3154                     }
3155                 }
3156             }
3157           else if (ds390_ptrRegReq)
3158             {
3159               emitcode ("push", "%s", ds390_regWithIdx (R0_IDX)->dname);
3160               emitcode ("push", "%s", ds390_regWithIdx (R1_IDX)->dname);
3161               _G.nRegsSaved += 2;
3162             }
3163         }
3164     }
3165
3166   /* set the register bank to the desired value */
3167   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3168    && !switchedPSW)
3169     {
3170       emitcode ("push", "psw");
3171       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3172     }
3173
3174   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3175        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3176       if (options.stack10bit) {
3177           emitcode ("push","_bpx");
3178           emitcode ("push","_bpx+1");
3179           emitcode ("mov","_bpx,%s",spname);
3180           emitcode ("mov","_bpx+1,esp");
3181           adjustEsp("_bpx+1");
3182       } else {
3183           if (options.useXstack) {
3184               emitcode ("mov", "r0,%s", spname);
3185               emitcode ("mov", "a,_bp");
3186               emitcode ("movx", "@r0,a");
3187               emitcode ("inc", "%s", spname);
3188           } else {
3189               /* set up the stack */
3190               emitcode ("push", "_bp"); /* save the callers stack  */
3191           }
3192           emitcode ("mov", "_bp,%s", spname);
3193       }
3194   }
3195
3196   /* adjust the stack for the function */
3197   if (sym->stack) {
3198       int i = sym->stack;
3199       if (options.stack10bit) {
3200           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3201           assert (sym->recvSize <= 4);
3202           if (sym->stack <= 8) {
3203               while (i--) emitcode ("push","acc");
3204           } else {
3205               PROTECT_SP;
3206               emitcode ("mov","a,sp");
3207               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3208               emitcode ("mov","sp,a");
3209               emitcode ("mov","a,esp");
3210               adjustEsp("a");
3211               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3212               emitcode ("mov","esp,a");
3213               UNPROTECT_SP;
3214           }
3215       } else {
3216           if (i > 256)
3217               werror (W_STACK_OVERFLOW, sym->name);
3218           
3219           if (i > 3 && sym->recvSize < 4) {
3220               
3221               emitcode ("mov", "a,sp");
3222               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3223               emitcode ("mov", "sp,a");
3224               
3225           } else
3226               while (i--)
3227                   emitcode ("inc", "sp");
3228       }
3229   }
3230
3231   if (sym->xstack)
3232     {
3233
3234       emitcode ("mov", "a,_spx");
3235       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3236       emitcode ("mov", "_spx,a");
3237     }
3238   
3239   /* if critical function then turn interrupts off */
3240   if (IFFUNC_ISCRITICAL (ftype))
3241     {
3242       symbol *tlbl = newiTempLabel (NULL);
3243       emitcode ("setb", "c");
3244       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3245       emitcode ("clr", "c");
3246       emitcode ("", "%05d$:", (tlbl->key + 100));
3247       emitcode ("push", "psw"); /* save old ea via c in psw */
3248     }
3249
3250 }
3251
3252 /*-----------------------------------------------------------------*/
3253 /* genEndFunction - generates epilogue for functions               */
3254 /*-----------------------------------------------------------------*/
3255 static void
3256 genEndFunction (iCode * ic)
3257 {
3258   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3259   lineNode *lnp = lineCurr;
3260   bitVect *regsUsed;
3261   bitVect *regsUsedPrologue;
3262   bitVect *regsUnneeded;
3263   int idx;
3264
3265   D (emitcode (";", "genEndFunction "););
3266
3267   if (IFFUNC_ISNAKED(sym->type))
3268   {
3269       emitcode(";", "naked function: no epilogue.");
3270       return;
3271   }
3272
3273   if (IFFUNC_ISCRITICAL (sym->type))
3274     {
3275       emitcode ("pop", "psw"); /* restore ea via c in psw */
3276       emitcode ("mov", "ea,c");
3277     }
3278   
3279   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3280        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3281
3282       if (options.stack10bit) {
3283           PROTECT_SP;     
3284           emitcode ("mov", "sp,_bpx", spname);
3285           emitcode ("mov", "esp,_bpx+1", spname);
3286           UNPROTECT_SP;
3287       } else {
3288           emitcode ("mov", "%s,_bp", spname);
3289       }
3290   }
3291
3292   /* if use external stack but some variables were
3293      added to the local stack then decrement the
3294      local stack */
3295   if (options.useXstack && sym->stack) {
3296       emitcode ("mov", "a,sp");
3297       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3298       emitcode ("mov", "sp,a");
3299   }
3300
3301
3302   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3303        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3304
3305       if (options.useXstack) {
3306           emitcode ("mov", "r0,%s", spname);
3307           emitcode ("movx", "a,@r0");
3308           emitcode ("mov", "_bp,a");
3309           emitcode ("dec", "%s", spname);
3310       } else {
3311           if (options.stack10bit) {
3312               emitcode ("pop", "_bpx+1");
3313               emitcode ("pop", "_bpx");
3314           } else {
3315               emitcode ("pop", "_bp");
3316           }
3317       }
3318   }
3319
3320   /* restore the register bank  */
3321   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3322   {
3323     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3324      || !options.useXstack)
3325     {
3326         /* Special case of ISR using non-zero bank with useXstack
3327          * is handled below.
3328          */
3329         emitcode ("pop", "psw");
3330     }
3331   } 
3332
3333   if (IFFUNC_ISISR (sym->type))
3334       { /* is ISR */  
3335
3336       /* now we need to restore the registers */
3337       /* if this isr has no bank i.e. is going to
3338          run with bank 0 , then we need to save more
3339          registers :-) */
3340       if (!FUNC_REGBANK (sym->type))
3341         {
3342             int i;
3343           /* if this function does not call any other
3344              function then we can be economical and
3345              save only those registers that are used */
3346           if (!IFFUNC_HASFCALL(sym->type))
3347             {
3348
3349               /* if any registers used */
3350               if (sym->regsUsed)
3351                 {
3352                   /* save the registers used */
3353                   for (i = sym->regsUsed->size; i >= 0; i--)
3354                     {
3355                       if (bitVectBitValue (sym->regsUsed, i) ||
3356                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3357                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3358                     }
3359                 }
3360               else if (ds390_ptrRegReq)
3361                 {
3362                   emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3363                   emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3364                 }
3365
3366             }
3367           else
3368             {
3369               /* this function has  a function call cannot
3370                  determines register usage so we will have to pop the
3371                  entire bank */
3372               if (options.parms_in_bank1) {
3373                   for (i = 7 ; i >= 0 ; i-- ) {
3374                       emitcode ("pop","%s",rb1regs[i]);
3375                   }
3376               }
3377               unsaveRBank (0, ic, FALSE);
3378             }
3379         }
3380         else
3381         {
3382             /* This ISR uses a non-zero bank.
3383              *
3384              * Restore any register banks saved by genFunction
3385              * in reverse order.
3386              */
3387             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3388             int ix;
3389           
3390             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3391             {
3392                 if (savedBanks & (1 << ix))
3393                 {
3394                     unsaveRBank(ix, NULL, FALSE);
3395                 }
3396             }
3397             
3398             if (options.useXstack)
3399             {
3400                 /* Restore bank AFTER calling unsaveRBank,
3401                  * since it can trash r0.
3402                  */
3403                 emitcode ("pop", "psw");
3404             }
3405         }
3406
3407       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3408         {
3409           if (options.stack10bit)
3410             {
3411               emitcode ("pop", DP2_RESULT_REG);
3412               emitcode ("pop", "dpx1");
3413               emitcode ("pop", "dph1");
3414               emitcode ("pop", "dpl1");
3415             }
3416           emitcode ("pop", "dps");
3417           emitcode ("pop", "dpx");
3418         }
3419       if (!inExcludeList ("dph"))
3420         emitcode ("pop", "dph");
3421       if (!inExcludeList ("dpl"))
3422         emitcode ("pop", "dpl");
3423       if (!inExcludeList ("b"))
3424         emitcode ("pop", "b");
3425       if (!inExcludeList ("acc"))
3426         emitcode ("pop", "acc");
3427
3428       /* if debug then send end of function */
3429       if (options.debug && currFunc) {
3430           _G.debugLine = 1;
3431           emitcode ("", "C$%s$%d$%d$%d ==.",
3432                     FileBaseName (ic->filename), currFunc->lastLine,
3433                     ic->level, ic->block);
3434           if (IS_STATIC (currFunc->etype))
3435             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3436           else
3437             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3438           _G.debugLine = 0;
3439         }
3440
3441       emitcode ("reti", "");
3442     }
3443   else
3444     {
3445       if (IFFUNC_CALLEESAVES(sym->type))
3446         {
3447           int i;
3448
3449           /* if any registers used */
3450           if (sym->regsUsed)
3451             {
3452               /* save the registers used */
3453               for (i = sym->regsUsed->size; i >= 0; i--)
3454                 {
3455                   if (bitVectBitValue (sym->regsUsed, i) ||
3456                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3457                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3458                 }
3459             }
3460           else if (ds390_ptrRegReq)
3461             {
3462                emitcode ("pop", "%s", ds390_regWithIdx (R1_IDX)->dname);
3463                emitcode ("pop", "%s", ds390_regWithIdx (R0_IDX)->dname);
3464             }
3465
3466         }
3467
3468       /* if debug then send end of function */
3469       if (options.debug && currFunc)
3470         {
3471           _G.debugLine = 1;
3472           emitcode ("", "C$%s$%d$%d$%d ==.",
3473                     FileBaseName (ic->filename), currFunc->lastLine,
3474                     ic->level, ic->block);
3475           if (IS_STATIC (currFunc->etype))
3476             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3477           else
3478             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3479           _G.debugLine = 0;
3480         }
3481
3482       emitcode ("ret", "");
3483     }
3484
3485   if (!port->peep.getRegsRead || !port->peep.getRegsWritten)
3486     return;
3487   
3488   /* If this was an interrupt handler using bank 0 that called another */
3489   /* function, then all registers must be saved; nothing to optimized. */
3490   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3491       && !FUNC_REGBANK(sym->type))
3492     return;
3493     
3494   /* Compute the registers actually used */
3495   regsUsed = newBitVect (ds390_nRegs);
3496   regsUsedPrologue = newBitVect (ds390_nRegs);
3497   while (lnp)
3498     {
3499       if (lnp->ic && lnp->ic->op == FUNCTION)
3500         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3501       else
3502         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3503       
3504       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3505           && lnp->prev->ic && lnp->prev->ic->op != FUNCTION)
3506         break;
3507       if (!lnp->prev)
3508         break;
3509       lnp = lnp->prev;
3510     }
3511
3512   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3513       && !bitVectBitValue (regsUsed, DPS_IDX))
3514     {
3515       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3516     }
3517     
3518   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3519       && !bitVectBitValue (regsUsed, CND_IDX))
3520     {
3521       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3522       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type)
3523           && !sym->stack)
3524         bitVectUnSetBit (regsUsed, CND_IDX);
3525     }
3526   else
3527     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3528     
3529   /* If this was an interrupt handler that called another function */
3530   /* function, then assume working registers may be modified by it. */
3531   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3532     {
3533       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3534       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3535       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3536       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3537       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3538       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3539       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3540       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3541       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3542       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3543       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3544     }
3545
3546   /* Remove the unneeded push/pops */
3547   regsUnneeded = newBitVect (ds390_nRegs);
3548   while (lnp)
3549     {
3550       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3551         {
3552           if (!strncmp(lnp->line, "push", 4))
3553             {
3554               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3555               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3556                 {
3557                   connectLine (lnp->prev, lnp->next);
3558                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3559                 }
3560             }
3561           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3562             {
3563               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3564               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3565                 {
3566                   connectLine (lnp->prev, lnp->next);
3567                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3568                 }
3569             }
3570         }
3571       lnp = lnp->next;
3572     }  
3573   
3574   for (idx = 0; idx < regsUnneeded->size; idx++)
3575     if (bitVectBitValue (regsUnneeded, idx))
3576       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3577   
3578   freeBitVect (regsUnneeded);
3579   freeBitVect (regsUsed);
3580   freeBitVect (regsUsedPrologue);
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* genJavaNativeRet - generate code for return JavaNative          */
3585 /*-----------------------------------------------------------------*/
3586 static void genJavaNativeRet(iCode *ic)
3587 {
3588     int i, size;
3589
3590     aopOp (IC_LEFT (ic), ic, FALSE, 
3591            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3592     size = AOP_SIZE (IC_LEFT (ic));
3593
3594     assert (size <= 4);
3595
3596     /* it is assigned to GPR0-R3 then push them */
3597     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3598         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3599         for (i = 0 ; i < size ; i++ ) {
3600             emitcode ("push","%s",
3601                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3602         }
3603         for (i = (size-1) ; i >= 0 ; i--) {
3604             emitcode ("pop","a%s",javaRet[i]);
3605         }
3606     } else {
3607         for (i = 0 ; i < size ; i++) 
3608             emitcode ("mov","%s,%s",javaRet[i],
3609                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3610     }
3611     for (i = size ; i < 4 ; i++ )
3612             emitcode ("mov","%s,#0",javaRet[i]);
3613     return;
3614 }
3615
3616 /*-----------------------------------------------------------------*/
3617 /* genRet - generate code for return statement                     */
3618 /*-----------------------------------------------------------------*/
3619 static void
3620 genRet (iCode * ic)
3621 {
3622   int size, offset = 0, pushed = 0;
3623
3624   D (emitcode (";", "genRet "););
3625
3626   /* if we have no return value then
3627      just generate the "ret" */
3628   if (!IC_LEFT (ic))
3629     goto jumpret;
3630
3631   /* if this is a JavaNative function then return 
3632      value in different register */
3633   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3634       genJavaNativeRet(ic);
3635       goto jumpret;
3636   }
3637   /* we have something to return then
3638      move the return value into place */
3639   aopOp (IC_LEFT (ic), ic, FALSE, 
3640          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3641   size = AOP_SIZE (IC_LEFT (ic));
3642
3643   _startLazyDPSEvaluation ();
3644   while (size--)
3645     {
3646       char *l;
3647       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3648         {
3649           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3650                       FALSE, TRUE, NULL);
3651           emitcode ("push", "%s", l);
3652           pushed++;
3653         }
3654       else
3655         {
3656           /* Since A is the last element of fReturn,
3657            * is is OK to clobber it in the aopGet.
3658            */
3659           l = aopGet (AOP (IC_LEFT (ic)), offset,
3660                       FALSE, FALSE, NULL);
3661           if (strcmp (fReturn[offset], l))
3662             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3663         }
3664     }
3665   _endLazyDPSEvaluation ();
3666
3667   if (pushed)
3668     {
3669       while (pushed)
3670         {
3671           pushed--;
3672           if (strcmp (fReturn[pushed], "a"))
3673             emitcode ("pop", fReturn[pushed]);
3674           else
3675             emitcode ("pop", "acc");
3676         }
3677     }
3678   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3679
3680 jumpret:
3681   /* generate a jump to the return label
3682      if the next is not the return statement */
3683   if (!(ic->next && ic->next->op == LABEL &&
3684         IC_LABEL (ic->next) == returnLabel))
3685
3686     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3687
3688 }
3689
3690 /*-----------------------------------------------------------------*/
3691 /* genLabel - generates a label                                    */
3692 /*-----------------------------------------------------------------*/
3693 static void
3694 genLabel (iCode * ic)
3695 {
3696   /* special case never generate */
3697   if (IC_LABEL (ic) == entryLabel)
3698     return;
3699
3700   D (emitcode (";", "genLabel ");
3701     );
3702
3703   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3704 }
3705
3706 /*-----------------------------------------------------------------*/
3707 /* genGoto - generates a ljmp                                      */
3708 /*-----------------------------------------------------------------*/
3709 static void
3710 genGoto (iCode * ic)
3711 {
3712   D (emitcode (";", "genGoto ");
3713     );
3714   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3715 }
3716
3717 /*-----------------------------------------------------------------*/
3718 /* findLabelBackwards: walks back through the iCode chain looking  */
3719 /* for the given label. Returns number of iCode instructions     */
3720 /* between that label and given ic.          */
3721 /* Returns zero if label not found.          */
3722 /*-----------------------------------------------------------------*/
3723 static int
3724 findLabelBackwards (iCode * ic, int key)
3725 {
3726   int count = 0;
3727
3728   while (ic->prev)
3729     {
3730       ic = ic->prev;
3731       count++;
3732
3733       /* If we have any pushes or pops, we cannot predict the distance.
3734          I don't like this at all, this should be dealt with in the 
3735          back-end */
3736       if (ic->op == IPUSH || ic->op == IPOP) {
3737         return 0;
3738       }
3739
3740       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3741         {
3742           /* printf("findLabelBackwards = %d\n", count); */
3743           return count;
3744         }
3745     }
3746
3747   return 0;
3748 }
3749
3750 /*-----------------------------------------------------------------*/
3751 /* genPlusIncr :- does addition with increment if possible         */
3752 /*-----------------------------------------------------------------*/
3753 static bool
3754 genPlusIncr (iCode * ic)
3755 {
3756   unsigned int icount;
3757   unsigned int size = getDataSize (IC_RESULT (ic));
3758
3759   /* will try to generate an increment */
3760   /* if the right side is not a literal
3761      we cannot */
3762   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3763     return FALSE;
3764
3765   /* if the literal value of the right hand side
3766      is greater than 4 then it is not worth it */
3767   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3768     return FALSE;
3769
3770   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3771       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3772       while (icount--) {
3773           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3774       }
3775       return TRUE;
3776   }
3777   /* if increment 16 bits in register */
3778   if (
3779        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3780        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3781        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3782        (size > 1) &&
3783        (icount == 1))
3784     {
3785       symbol  *tlbl;
3786       int     emitTlbl;
3787       int     labelRange;
3788       char    *l;
3789
3790       /* If the next instruction is a goto and the goto target
3791        * is <= 5 instructions previous to this, we can generate
3792        * jumps straight to that target.
3793        */
3794       if (ic->next && ic->next->op == GOTO
3795           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3796           && labelRange <= 5)
3797         {
3798           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3799           tlbl = IC_LABEL (ic->next);
3800           emitTlbl = 0;
3801         }
3802       else
3803         {
3804           tlbl = newiTempLabel (NULL);
3805           emitTlbl = 1;
3806         }
3807         
3808       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3809       emitcode ("inc", "%s", l);
3810       
3811       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3812           IS_AOP_PREG (IC_RESULT (ic)))
3813       {   
3814         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3815       }
3816       else
3817       {
3818           emitcode ("clr", "a");
3819           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3820       }
3821
3822       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3823       emitcode ("inc", "%s", l);
3824       if (size > 2)
3825         {
3826             if (!strcmp(l, "acc"))
3827             {
3828                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3829             }
3830             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3831                      IS_AOP_PREG (IC_RESULT (ic)))
3832             {
3833                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3834             }
3835             else
3836             {
3837                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3838             }
3839
3840             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3841             emitcode ("inc", "%s", l);
3842         }
3843       if (size > 3)
3844         {
3845             if (!strcmp(l, "acc"))
3846             {
3847                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3848             }
3849             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3850                      IS_AOP_PREG (IC_RESULT (ic)))
3851             {
3852                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3853             }
3854             else
3855             {
3856                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3857             }
3858
3859             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3860             emitcode ("inc", "%s", l);  }
3861
3862       if (emitTlbl)
3863         {
3864           emitcode ("", "!tlabeldef", tlbl->key + 100);
3865         }
3866       return TRUE;
3867     }
3868
3869   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3870       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3871       options.model == MODEL_FLAT24 ) {
3872
3873       switch (size) {
3874       case 3:
3875           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3876       case 2:
3877           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3878       case 1:
3879           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3880           break;
3881       }
3882       while (icount--) emitcode ("inc","dptr");      
3883       return TRUE;
3884   }
3885
3886   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3887       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3888       icount <= 5 ) {
3889       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3890       while (icount--) emitcode ("inc","dptr");
3891       emitcode ("mov","dps,#0");
3892       return TRUE;
3893   }
3894
3895   /* if the sizes are greater than 1 then we cannot */
3896   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3897       AOP_SIZE (IC_LEFT (ic)) > 1)
3898     return FALSE;
3899
3900   /* we can if the aops of the left & result match or
3901      if they are in registers and the registers are the
3902      same */
3903   if (
3904        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3905        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3906        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3907     {
3908
3909       if (icount > 3)
3910         {
3911           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3912           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3913           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3914         }
3915       else
3916         {
3917
3918           _startLazyDPSEvaluation ();
3919           while (icount--)
3920             {
3921               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3922             }
3923           _endLazyDPSEvaluation ();
3924         }
3925
3926       return TRUE;
3927     }
3928
3929   return FALSE;
3930 }
3931
3932 /*-----------------------------------------------------------------*/
3933 /* outBitAcc - output a bit in acc                                 */
3934 /*-----------------------------------------------------------------*/
3935 static void
3936 outBitAcc (operand * result)
3937 {
3938   symbol *tlbl = newiTempLabel (NULL);
3939   /* if the result is a bit */
3940   if (AOP_TYPE (result) == AOP_CRY)
3941     {
3942       aopPut (AOP (result), "a", 0);
3943     }
3944   else
3945     {
3946       emitcode ("jz", "!tlabel", tlbl->key + 100);
3947       emitcode ("mov", "a,%s", one);
3948       emitcode ("", "!tlabeldef", tlbl->key + 100);
3949       outAcc (result);
3950     }
3951 }
3952
3953 /*-----------------------------------------------------------------*/
3954 /* genPlusBits - generates code for addition of two bits           */
3955 /*-----------------------------------------------------------------*/
3956 static void
3957 genPlusBits (iCode * ic)
3958 {
3959   D (emitcode (";", "genPlusBits "););
3960     
3961   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3962     {
3963       symbol *lbl = newiTempLabel (NULL);
3964       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3965       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3966       emitcode ("cpl", "c");
3967       emitcode ("", "!tlabeldef", (lbl->key + 100));
3968       outBitC (IC_RESULT (ic));
3969     }
3970   else
3971     {
3972       emitcode ("clr", "a");
3973       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3974       emitcode ("rlc", "a");
3975       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3976       emitcode ("addc", "a,#0");
3977       outAcc (IC_RESULT (ic));
3978     }
3979 }
3980
3981 static void
3982 adjustArithmeticResult (iCode * ic)
3983 {
3984   if (opIsGptr (IC_RESULT (ic)) &&
3985       opIsGptr (IC_LEFT (ic)) &&
3986       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3987     {
3988       aopPut (AOP (IC_RESULT (ic)),
3989               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3990               GPTRSIZE - 1);
3991     }
3992
3993   if (opIsGptr (IC_RESULT (ic)) &&
3994       opIsGptr (IC_RIGHT (ic)) &&
3995       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3996     {
3997       aopPut (AOP (IC_RESULT (ic)),
3998             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3999               GPTRSIZE - 1);
4000     }
4001
4002   if (opIsGptr (IC_RESULT (ic)) &&
4003       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4004       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4005       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4006       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4007     {
4008       char buff[5];
4009       SNPRINTF (buff, sizeof(buff), 
4010                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4011       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4012     }
4013 }
4014
4015 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4016 // generates the result if possible. If result is generated, returns TRUE; otherwise
4017 // returns false and caller must deal with fact that result isn't aopOp'd.
4018 bool aopOp3(iCode * ic)
4019 {
4020     bool dp1InUse, dp2InUse;
4021     bool useDp2;
4022
4023     // First, generate the right opcode. DPTR may be used if neither left nor result are
4024     // of type AOP_STR.
4025     
4026 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4027 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4028 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4029 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4030 //      );
4031 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4032 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4033 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4034 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4035 //      );
4036     
4037     // Right uses DPTR unless left or result is an AOP_STR; however,
4038     // if right is an AOP_STR, it must use DPTR regardless.
4039     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4040      && !AOP_IS_STR(IC_RIGHT(ic)))
4041     {
4042         useDp2 = TRUE;
4043     }
4044     else
4045     {
4046         useDp2 = FALSE;
4047     }
4048         
4049     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4050     
4051     // if the right used DPTR, left MUST use DPTR2.
4052     // if the right used DPTR2, left MUST use DPTR.
4053     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4054     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4055     // enabling us to assign DPTR to result.
4056      
4057     if (AOP_USESDPTR(IC_RIGHT(ic)))
4058     {
4059         useDp2 = TRUE;
4060     }
4061     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4062     {
4063         useDp2 = FALSE;
4064     }
4065     else
4066     {
4067         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4068         {
4069             useDp2 = TRUE;
4070         }
4071         else
4072         {
4073             useDp2 = FALSE;
4074         }
4075     }
4076
4077     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4078
4079         
4080     // We've op'd the left & right. So, if left or right are the same operand as result, 
4081     // we know aopOp will succeed, and we can just do it & bail.
4082     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4083       {
4084         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4085         return TRUE;
4086       }
4087     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4088       {
4089 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4090         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4091         return TRUE;
4092       }
4093     
4094     // Operands may be equivalent (but not equal) if they share a spill location. If
4095     // so, use the same DPTR or DPTR2.
4096     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4097       {
4098         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4099         return TRUE;
4100       }
4101     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4102       {
4103         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4104         return TRUE;
4105       }
4106     
4107     // Note which dptrs are currently in use.
4108     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4109     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4110     
4111     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
4112     // generate it.
4113     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4114     {
4115         return FALSE;
4116     }
4117     
4118     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4119     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4120     {
4121         return FALSE;
4122     }
4123     
4124     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4125     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4126     {
4127         return FALSE;
4128     }
4129
4130     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4131
4132     // Some sanity checking...
4133     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4134     {
4135         fprintf(stderr,
4136                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4137                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4138         emitcode(";", ">>> unexpected DPTR here.");
4139     }
4140     
4141     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4142     {
4143         fprintf(stderr,
4144                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4145                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4146         emitcode(";", ">>> unexpected DPTR2 here.");
4147     }    
4148     
4149     return TRUE;
4150 }
4151
4152 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4153 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4154 // will be set TRUE. The caller must then handle the case specially, noting
4155 // that the IC_RESULT operand is not aopOp'd.
4156 // 
4157 #define AOP_OP_3_NOFATAL(ic, rc) \
4158             do { rc = !aopOp3(ic); } while (0)
4159
4160 // aopOp the left & right operands of an ic.
4161 #define AOP_OP_2(ic) \
4162     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4163     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4164
4165 // convienience macro.
4166 #define AOP_SET_LOCALS(ic) \
4167     left = IC_LEFT(ic); \
4168     right = IC_RIGHT(ic); \
4169     result = IC_RESULT(ic);
4170
4171
4172 // Given an integer value of pushedSize bytes on the stack,
4173 // adjust it to be resultSize bytes, either by discarding
4174 // the most significant bytes or by zero-padding.
4175 //
4176 // On exit from this macro, pushedSize will have been adjusted to
4177 // equal resultSize, and ACC may be trashed.
4178 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4179       /* If the pushed data is bigger than the result,          \
4180        * simply discard unused bytes. Icky, but works.          \
4181        */                                                       \
4182       while (pushedSize > resultSize)                           \
4183       {                                                         \
4184           D (emitcode (";", "discarding unused result byte."););\
4185           emitcode ("pop", "acc");                              \
4186           pushedSize--;                                         \
4187       }                                                         \
4188       if (pushedSize < resultSize)                              \
4189       {                                                         \
4190           emitcode ("clr", "a");                                \
4191           /* Conversly, we haven't pushed enough here.          \
4192            * just zero-pad, and all is well.                    \
4193            */                                                   \
4194           while (pushedSize < resultSize)                       \
4195           {                                                     \
4196               emitcode("push", "acc");                          \
4197               pushedSize++;                                     \
4198           }                                                     \
4199       }                                                         \
4200       assert(pushedSize == resultSize);
4201
4202 /*-----------------------------------------------------------------*/
4203 /* genPlus - generates code for addition                           */
4204 /*-----------------------------------------------------------------*/
4205 static void
4206 genPlus (iCode * ic)
4207 {
4208   int size, offset = 0;
4209   bool pushResult;
4210   int rSize;
4211
4212   D (emitcode (";", "genPlus "););
4213
4214   /* special cases :- */
4215   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4216       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4217       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4218       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4219       if (size <= 9) {
4220           while (size--) emitcode ("inc","dptr");
4221       } else {
4222           emitcode ("mov","a,dpl");
4223           emitcode ("add","a,#!constbyte",size & 0xff);
4224           emitcode ("mov","dpl,a");
4225           emitcode ("mov","a,dph");
4226           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4227           emitcode ("mov","dph,a");
4228           emitcode ("mov","a,dpx");
4229           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4230           emitcode ("mov","dpx,a");
4231       }
4232       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4233       return ;
4234   }
4235   if ( IS_SYMOP(IC_LEFT(ic)) && 
4236        OP_SYMBOL(IC_LEFT(ic))->remat &&
4237        isOperandInFarSpace(IC_RIGHT(ic))) {
4238       operand *op = IC_RIGHT(ic);
4239       IC_RIGHT(ic) = IC_LEFT(ic);
4240       IC_LEFT(ic) = op;
4241   }
4242                 
4243   AOP_OP_3_NOFATAL (ic, pushResult);
4244     
4245   if (pushResult)
4246     {
4247       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4248     }
4249
4250   if (!pushResult)
4251     {
4252       /* if literal, literal on the right or
4253          if left requires ACC or right is already
4254          in ACC */
4255       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4256        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4257           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4258         {
4259           operand *t = IC_RIGHT (ic);
4260           IC_RIGHT (ic) = IC_LEFT (ic);
4261           IC_LEFT (ic) = t;
4262           emitcode (";", "Swapped plus args.");
4263         }
4264
4265       /* if both left & right are in bit
4266          space */
4267       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4269         {
4270           genPlusBits (ic);
4271           goto release;
4272         }
4273
4274       /* if left in bit space & right literal */
4275       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4277         {
4278           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279           /* if result in bit space */
4280           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4281             {
4282               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283                 emitcode ("cpl", "c");
4284               outBitC (IC_RESULT (ic));
4285             }
4286           else
4287             {
4288               size = getDataSize (IC_RESULT (ic));
4289               _startLazyDPSEvaluation ();
4290               while (size--)
4291                 {
4292                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4293                   emitcode ("addc", "a,#0");
4294                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4295                 }
4296               _endLazyDPSEvaluation ();
4297             }
4298           goto release;
4299         }
4300
4301       /* if I can do an increment instead
4302          of add then GOOD for ME */
4303       if (genPlusIncr (ic) == TRUE)
4304         {
4305           emitcode (";", "did genPlusIncr");
4306           goto release;
4307         }
4308
4309     }
4310   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4311
4312   _startLazyDPSEvaluation ();
4313   while (size--)
4314     {
4315       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4316         {
4317           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4318           if (offset == 0)
4319             emitcode ("add", "a,%s",
4320                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4321           else
4322             emitcode ("addc", "a,%s",
4323                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4324         }
4325       else
4326         {
4327           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4328           {
4329               /* right is going to use ACC or we would have taken the
4330                * above branch.
4331                */
4332               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4333        TR_AP("#3");
4334               D(emitcode(";", "+ AOP_ACC special case."););
4335               emitcode("xch", "a, %s", DP2_RESULT_REG);
4336           }
4337           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4338           if (offset == 0)
4339           {
4340             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4341             {
4342          TR_AP("#4");
4343                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4344             }
4345             else
4346             {
4347                 emitcode ("add", "a,%s",
4348                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4349                                   DP2_RESULT_REG));
4350             }
4351           }
4352           else
4353           {
4354             emitcode ("addc", "a,%s",
4355                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4356                           DP2_RESULT_REG));
4357           }
4358         }
4359       if (!pushResult)
4360         {
4361           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4362         }
4363       else
4364         {
4365           emitcode ("push", "acc");
4366         }
4367       offset++;
4368     }
4369   _endLazyDPSEvaluation ();
4370
4371   if (pushResult)
4372     {
4373       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4374
4375       size = getDataSize (IC_LEFT (ic));
4376       rSize = getDataSize (IC_RESULT (ic));
4377
4378       ADJUST_PUSHED_RESULT(size, rSize);
4379
4380       _startLazyDPSEvaluation ();
4381       while (size--)
4382         {
4383           emitcode ("pop", "acc");
4384           aopPut (AOP (IC_RESULT (ic)), "a", size);
4385         }
4386       _endLazyDPSEvaluation ();
4387     }
4388
4389   adjustArithmeticResult (ic);
4390
4391 release:
4392   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4395 }
4396
4397 /*-----------------------------------------------------------------*/
4398 /* genMinusDec :- does subtraction with deccrement if possible     */
4399 /*-----------------------------------------------------------------*/
4400 static bool
4401 genMinusDec (iCode * ic)
4402 {
4403   unsigned int icount;
4404   unsigned int size = getDataSize (IC_RESULT (ic));
4405
4406   /* will try to generate an increment */
4407   /* if the right side is not a literal
4408      we cannot */
4409   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4410     return FALSE;
4411
4412   /* if the literal value of the right hand side
4413      is greater than 4 then it is not worth it */
4414   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4415     return FALSE;
4416
4417   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4418       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4419       while (icount--) {
4420           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4421       }
4422       return TRUE;
4423   }
4424   /* if decrement 16 bits in register */
4425   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4426       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4427       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4428       (size > 1) &&
4429       (icount == 1))
4430     {
4431       symbol *tlbl;
4432       int    emitTlbl;
4433       int    labelRange;
4434       char   *l;
4435
4436       /* If the next instruction is a goto and the goto target
4437          * is <= 5 instructions previous to this, we can generate
4438          * jumps straight to that target.
4439        */
4440       if (ic->next && ic->next->op == GOTO
4441           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4442           && labelRange <= 5)
4443         {
4444           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4445           tlbl = IC_LABEL (ic->next);
4446           emitTlbl = 0;
4447         }
4448       else
4449         {
4450           tlbl = newiTempLabel (NULL);
4451           emitTlbl = 1;
4452         }
4453
4454       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4455       emitcode ("dec", "%s", l);
4456  
4457       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459           IS_AOP_PREG (IC_RESULT (ic)))
4460       {     
4461           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4462       }
4463       else
4464       {
4465           emitcode ("mov", "a,#!constbyte",0xff);
4466           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4467       }
4468       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4469       emitcode ("dec", "%s", l);
4470       if (size > 2)
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)), MSB24, FALSE, FALSE, NULL);
4488             emitcode ("dec", "%s", l);
4489         }
4490       if (size > 3)
4491         {
4492             if (!strcmp(l, "acc"))
4493             {
4494                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4495             }
4496             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4497                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4498                      IS_AOP_PREG (IC_RESULT (ic)))
4499             {       
4500                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4501             }
4502             else
4503             {
4504                 emitcode ("mov", "a,#!constbyte",0xff);
4505                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4506             }       
4507             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4508             emitcode ("dec", "%s", l);
4509         }
4510       if (emitTlbl)
4511         {
4512           emitcode ("", "!tlabeldef", tlbl->key + 100);
4513         }
4514       return TRUE;
4515     }
4516
4517   /* if the sizes are greater than 1 then we cannot */
4518   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4519       AOP_SIZE (IC_LEFT (ic)) > 1)
4520     return FALSE;
4521
4522   /* we can if the aops of the left & result match or
4523      if they are in registers and the registers are the
4524      same */
4525   if (
4526        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4527        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4528        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4529     {
4530
4531       _startLazyDPSEvaluation ();
4532       while (icount--)
4533         {
4534           emitcode ("dec", "%s",
4535                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4536         }
4537       _endLazyDPSEvaluation ();
4538
4539       return TRUE;
4540     }
4541
4542   return FALSE;
4543 }
4544
4545 /*-----------------------------------------------------------------*/
4546 /* addSign - complete with sign                                    */
4547 /*-----------------------------------------------------------------*/
4548 static void
4549 addSign (operand * result, int offset, int sign)
4550 {
4551   int size = (getDataSize (result) - offset);
4552   if (size > 0)
4553     {
4554       _startLazyDPSEvaluation();
4555       if (sign)
4556         {
4557           emitcode ("rlc", "a");
4558           emitcode ("subb", "a,acc");
4559           while (size--)
4560           {
4561             aopPut (AOP (result), "a", offset++);
4562           }
4563         }
4564       else
4565       {
4566         while (size--)
4567         {
4568           aopPut (AOP (result), zero, offset++);
4569         }
4570       }
4571       _endLazyDPSEvaluation();
4572     }
4573 }
4574
4575 /*-----------------------------------------------------------------*/
4576 /* genMinusBits - generates code for subtraction  of two bits      */
4577 /*-----------------------------------------------------------------*/
4578 static void
4579 genMinusBits (iCode * ic)
4580 {
4581   symbol *lbl = newiTempLabel (NULL);
4582
4583   D (emitcode (";", "genMinusBits "););
4584
4585   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4586     {
4587       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4588       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4589       emitcode ("cpl", "c");
4590       emitcode ("", "!tlabeldef", (lbl->key + 100));
4591       outBitC (IC_RESULT (ic));
4592     }
4593   else
4594     {
4595       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4596       emitcode ("subb", "a,acc");
4597       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4598       emitcode ("inc", "a");
4599       emitcode ("", "!tlabeldef", (lbl->key + 100));
4600       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4601       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4602     }
4603 }
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genMinus - generates code for subtraction                       */
4607 /*-----------------------------------------------------------------*/
4608 static void
4609 genMinus (iCode * ic)
4610 {
4611     int size, offset = 0;
4612     int rSize;
4613     long lit = 0L;
4614     bool pushResult;
4615
4616     D (emitcode (";", "genMinus "););
4617
4618     AOP_OP_3_NOFATAL(ic, pushResult);   
4619
4620     if (!pushResult)
4621     {
4622       /* special cases :- */
4623       /* if both left & right are in bit space */
4624       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4625           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4626         {
4627           genMinusBits (ic);
4628           goto release;
4629         }
4630
4631       /* if I can do an decrement instead
4632          of subtract then GOOD for ME */
4633       if (genMinusDec (ic) == TRUE)
4634         goto release;
4635
4636     }
4637
4638   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4639
4640   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4641     {
4642       CLRC;
4643     }
4644   else
4645     {
4646       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4647       lit = -lit;
4648     }
4649
4650
4651   /* if literal, add a,#-lit, else normal subb */
4652   _startLazyDPSEvaluation ();
4653   while (size--) {
4654       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4655           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4656               emitcode ("mov","b,%s",
4657                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4658               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4659               emitcode ("subb","a,b");
4660           } else {
4661               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4662               emitcode ("subb", "a,%s",
4663                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4664                                 DP2_RESULT_REG));
4665           }
4666       } else {
4667           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4668           /* first add without previous c */
4669           if (!offset) {
4670               if (!size && lit==-1) {
4671                   emitcode ("dec", "a");
4672               } else {
4673                   emitcode ("add", "a,#!constbyte",
4674                             (unsigned int) (lit & 0x0FFL));
4675               }
4676           } else {
4677               emitcode ("addc", "a,#!constbyte",
4678                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4679           }
4680       }
4681       
4682       if (pushResult) {
4683           emitcode ("push", "acc");
4684       } else {
4685           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4686       }
4687       offset++;
4688   }
4689   _endLazyDPSEvaluation ();
4690   
4691   if (pushResult)
4692     {
4693       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4694
4695       size = getDataSize (IC_LEFT (ic));
4696       rSize = getDataSize (IC_RESULT (ic));
4697
4698       ADJUST_PUSHED_RESULT(size, rSize);
4699
4700       _startLazyDPSEvaluation ();
4701       while (size--)
4702         {
4703           emitcode ("pop", "acc");
4704           aopPut (AOP (IC_RESULT (ic)), "a", size);
4705         }
4706       _endLazyDPSEvaluation ();
4707     }
4708
4709   adjustArithmeticResult (ic);
4710
4711 release:
4712   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4715 }
4716
4717
4718 /*-----------------------------------------------------------------*/
4719 /* genMultbits :- multiplication of bits                           */
4720 /*-----------------------------------------------------------------*/
4721 static void
4722 genMultbits (operand * left,
4723              operand * right,
4724              operand * result,
4725              iCode   * ic)
4726 {
4727   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4728   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729   aopOp(result, ic, TRUE, FALSE);
4730   outBitC (result);
4731 }
4732
4733
4734 /*-----------------------------------------------------------------*/
4735 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4736 /*-----------------------------------------------------------------*/
4737 static void
4738 genMultOneByte (operand * left,
4739                 operand * right,
4740                 operand * result,
4741                 iCode   * ic)
4742 {
4743   int size;
4744   symbol *lbl;
4745   bool runtimeSign, compiletimeSign;
4746   bool lUnsigned, rUnsigned;
4747   
4748
4749   /* (if two literals: the value is computed before) */
4750   /* if one literal, literal on the right */
4751   if (AOP_TYPE (left) == AOP_LIT)
4752     {
4753       operand *t = right;
4754       right = left;
4755       left = t;
4756       emitcode (";", "swapped left and right");
4757     }
4758
4759   /* (if two literals: the value is computed before) */
4760   /* if one literal, literal on the right */
4761   if (AOP_TYPE (left) == AOP_LIT)
4762     {
4763       operand *t = right;
4764       right = left;
4765       left = t;
4766       /* emitcode (";", "swapped left and right"); */
4767     }
4768   /* if no literal, unsigned on the right: shorter code */
4769   if (   AOP_TYPE (right) != AOP_LIT
4770       && SPEC_USIGN (getSpec (operandType (left))))
4771     {
4772       operand *t = right;
4773       right = left;
4774       left = t;
4775     }
4776
4777   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4778   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4779
4780   if ((lUnsigned && rUnsigned)
4781 /* sorry, I don't know how to get size
4782    without calling aopOp (result,...);
4783    see Feature Request  */
4784       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4785                    no need to take care about the signedness! */
4786     {
4787       /* just an unsigned 8 * 8 = 8 multiply
4788          or 8u * 8u = 16u */
4789       /* emitcode (";","unsigned"); */
4790       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4791       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4792       emitcode ("mul", "ab");
4793     
4794       _G.accInUse++; _G.bInUse++;
4795       aopOp (result, ic, TRUE, FALSE);
4796       size = AOP_SIZE (result);
4797   
4798       if (size < 1 || size > 2)
4799         {
4800           /* this should never happen */
4801           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4802                    size, __FILE__, lineno);
4803           exit (1);
4804         }
4805   
4806       aopPut (AOP (result), "a", 0);
4807       _G.accInUse--; _G.bInUse--;
4808       if (size == 2) 
4809         aopPut (AOP (result), "b", 1);
4810       return;
4811     }
4812
4813   /* we have to do a signed multiply */
4814   /* emitcode (";", "signed"); */
4815   
4816   /* now sign adjust for both left & right */
4817
4818   /* let's see what's needed: */
4819   /* apply negative sign during runtime */
4820   runtimeSign = FALSE;
4821   /* negative sign from literals */
4822   compiletimeSign = FALSE;
4823
4824   if (!lUnsigned)
4825     {
4826       if (AOP_TYPE(left) == AOP_LIT)
4827         {
4828           /* signed literal */
4829           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4830           if (val < 0)
4831             compiletimeSign = TRUE;
4832         }
4833       else
4834         /* signed but not literal */
4835         runtimeSign = TRUE;
4836     }
4837
4838   if (!rUnsigned)
4839     {
4840       if (AOP_TYPE(right) == AOP_LIT)
4841         {
4842           /* signed literal */
4843           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4844           if (val < 0)
4845             compiletimeSign ^= TRUE;
4846         }
4847       else
4848         /* signed but not literal */
4849         runtimeSign = TRUE;
4850     }
4851
4852   /* initialize F0, which stores the runtime sign */
4853   if (runtimeSign)
4854     {
4855       if (compiletimeSign)
4856         emitcode ("setb", "F0"); /* set sign flag */
4857       else
4858         emitcode ("clr", "F0"); /* reset sign flag */
4859     }
4860   
4861   /* save the signs of the operands */
4862   if (AOP_TYPE(right) == AOP_LIT)
4863     {
4864       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4865
4866       if (!rUnsigned && val < 0)
4867         emitcode ("mov", "b,#!constbyte", -val);
4868       else
4869         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4870     }
4871   else /* ! literal */
4872     {
4873       if (rUnsigned)  /* emitcode (";", "signed"); */
4874         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4875       else
4876         {
4877           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4878           lbl = newiTempLabel (NULL);
4879           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4880           emitcode ("cpl", "F0"); /* complement sign flag */
4881           emitcode ("cpl", "a");  /* 2's complement */
4882           emitcode ("inc", "a");
4883           emitcode ("", "!tlabeldef", lbl->key + 100);
4884           emitcode ("mov", "b,a");
4885         }
4886     }
4887
4888   if (AOP_TYPE(left) == AOP_LIT)
4889     {
4890       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4891
4892       if (!lUnsigned && val < 0)
4893         emitcode ("mov", "a,#!constbyte", -val);
4894       else
4895         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4896     }
4897   else /* ! literal */
4898     {
4899       if (lUnsigned)  /* emitcode (";", "signed"); */
4900
4901         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4902       else
4903         {
4904           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4905           lbl = newiTempLabel (NULL);
4906           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4907           emitcode ("cpl", "F0"); /* complement sign flag */
4908           emitcode ("cpl", "a");  /* 2's complement */
4909           emitcode ("inc", "a");
4910           emitcode ("", "!tlabeldef", lbl->key + 100);
4911         }
4912     }
4913
4914   /* now the multiplication */
4915   emitcode ("mul", "ab");
4916   _G.accInUse++;_G.bInUse++;
4917   aopOp(result, ic, TRUE, FALSE);
4918   size = AOP_SIZE (result);
4919
4920   if (size < 1 || size > 2) 
4921     {
4922       /* this should never happen */
4923       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4924                size, __FILE__, lineno);
4925       exit (1);
4926     }    
4927     
4928   if (runtimeSign || compiletimeSign)
4929     {
4930       lbl = newiTempLabel (NULL);
4931       if (runtimeSign)
4932         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4933       emitcode ("cpl", "a"); /* lsb 2's complement */
4934       if (size != 2)
4935         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4936       else
4937         {
4938           emitcode ("add", "a,#1"); /* this sets carry flag */
4939           emitcode ("xch", "a,b");
4940           emitcode ("cpl", "a"); /* msb 2's complement */
4941           emitcode ("addc", "a,#0");
4942           emitcode ("xch", "a,b");
4943         }
4944       emitcode ("", "!tlabeldef", lbl->key + 100);
4945     }
4946   aopPut (AOP (result), "a", 0);
4947   _G.accInUse--;_G.bInUse--;
4948   if (size == 2)
4949     aopPut (AOP (result), "b", 1);
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4954 /*-----------------------------------------------------------------*/
4955 static void genMultTwoByte (operand *left, operand *right, 
4956                             operand *result, iCode *ic)
4957 {
4958         sym_link *retype = getSpec(operandType(right));
4959         sym_link *letype = getSpec(operandType(left));
4960         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4961         symbol *lbl;
4962
4963         if (AOP_TYPE (left) == AOP_LIT) {
4964                 operand *t = right;
4965                 right = left;
4966                 left = t;
4967         }
4968         /* save EA bit in F1 */
4969         lbl = newiTempLabel(NULL);
4970         emitcode ("setb","F1");
4971         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4972         emitcode ("clr","F1");
4973         emitcode("","!tlabeldef",lbl->key+100);
4974
4975         /* load up MB with right */
4976         if (!umult) {
4977                 emitcode("clr","F0");
4978                 if (AOP_TYPE(right) == AOP_LIT) {
4979                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4980                         if (val < 0) {
4981                                 emitcode("setb","F0");
4982                                 val = -val;
4983                         }
4984                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4985                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4986                 } else {
4987                         lbl = newiTempLabel(NULL);
4988                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4989                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4990                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4991                         emitcode ("xch", "a,b");
4992                         emitcode ("cpl","a");
4993                         emitcode ("add", "a,#1");
4994                         emitcode ("xch", "a,b");
4995                         emitcode ("cpl", "a"); // msb
4996                         emitcode ("addc", "a,#0");
4997                         emitcode ("setb","F0");
4998                         emitcode ("","!tlabeldef",lbl->key+100);
4999                         emitcode ("mov","mb,b");
5000                         emitcode ("mov","mb,a");
5001                 }
5002         } else {
5003                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5004                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5005         }
5006         /* load up MA with left */
5007         if (!umult) {
5008                 lbl = newiTempLabel(NULL);
5009                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5010                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5011                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5012                 emitcode ("xch", "a,b");
5013                 emitcode ("cpl","a");
5014                 emitcode ("add", "a,#1");
5015                 emitcode ("xch", "a,b");
5016                 emitcode ("cpl", "a"); // msb
5017                 emitcode ("addc","a,#0");
5018                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5019                 emitcode ("setb","F0");
5020                 emitcode ("","!tlabeldef",lbl->key+100);
5021                 emitcode ("mov","ma,b");
5022                 emitcode ("mov","ma,a");
5023         } else {
5024                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5026         }
5027         /* wait for multiplication to finish */
5028         lbl = newiTempLabel(NULL);
5029         emitcode("","!tlabeldef", lbl->key+100);
5030         emitcode("mov","a,mcnt1");
5031         emitcode("anl","a,#!constbyte",0x80);
5032         emitcode("jnz","!tlabel",lbl->key+100);
5033         
5034         freeAsmop (left, NULL, ic, TRUE);
5035         freeAsmop (right, NULL, ic,TRUE);
5036         aopOp(result, ic, TRUE, FALSE);
5037
5038         /* if unsigned then simple */   
5039         if (umult) {
5040                 emitcode ("mov","a,ma");
5041                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5042                 emitcode ("mov","a,ma");
5043                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5044                 aopPut(AOP(result),"ma",1);
5045                 aopPut(AOP(result),"ma",0);
5046         } else {
5047                 emitcode("push","ma");
5048                 emitcode("push","ma");
5049                 emitcode("push","ma");
5050                 MOVA("ma");
5051                 /* negate result if needed */
5052                 lbl = newiTempLabel(NULL);      
5053                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054                 emitcode("cpl","a");
5055                 emitcode("add","a,#1");
5056                 emitcode("","!tlabeldef", lbl->key+100);
5057                 if (AOP_TYPE(result) == AOP_ACC)
5058                 {
5059                     D(emitcode(";", "ACC special case."););
5060                     /* We know result is the only live aop, and 
5061                      * it's obviously not a DPTR2, so AP is available.
5062                      */
5063                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5064                 }
5065                 else
5066                 {
5067                     aopPut(AOP(result),"a",0);
5068                 }
5069             
5070                 emitcode("pop","acc");
5071                 lbl = newiTempLabel(NULL);      
5072                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073                 emitcode("cpl","a");
5074                 emitcode("addc","a,#0");
5075                 emitcode("","!tlabeldef", lbl->key+100);
5076                 aopPut(AOP(result),"a",1);
5077                 emitcode("pop","acc");
5078                 if (AOP_SIZE(result) >= 3) {
5079                         lbl = newiTempLabel(NULL);      
5080                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5081                         emitcode("cpl","a");
5082                         emitcode("addc","a,#0");                        
5083                         emitcode("","!tlabeldef", lbl->key+100);
5084                         aopPut(AOP(result),"a",2);
5085                 }
5086                 emitcode("pop","acc");
5087                 if (AOP_SIZE(result) >= 4) {
5088                         lbl = newiTempLabel(NULL);      
5089                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5090                         emitcode("cpl","a");
5091                         emitcode("addc","a,#0");                        
5092                         emitcode("","!tlabeldef", lbl->key+100);
5093                         aopPut(AOP(result),"a",3);
5094                 }
5095                 if (AOP_TYPE(result) == AOP_ACC)
5096                 {
5097                     /* We stashed the result away above. */
5098                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5099                 }           
5100                 
5101         }
5102         freeAsmop (result, NULL, ic, TRUE);
5103
5104         /* restore EA bit in F1 */
5105         lbl = newiTempLabel(NULL);
5106         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5107         emitcode ("setb","EA");
5108         emitcode("","!tlabeldef",lbl->key+100);
5109         return ;
5110 }
5111
5112 /*-----------------------------------------------------------------*/
5113 /* genMult - generates code for multiplication                     */
5114 /*-----------------------------------------------------------------*/
5115 static void
5116 genMult (iCode * ic)
5117 {
5118   operand *left = IC_LEFT (ic);
5119   operand *right = IC_RIGHT (ic);
5120   operand *result = IC_RESULT (ic);
5121
5122   D (emitcode (";", "genMult "););
5123
5124   /* assign the amsops */
5125   AOP_OP_2 (ic);
5126
5127   /* special cases first */
5128   /* both are bits */
5129   if (AOP_TYPE (left) == AOP_CRY &&
5130       AOP_TYPE (right) == AOP_CRY)
5131     {
5132       genMultbits (left, right, result, ic);
5133       goto release;
5134     }
5135
5136   /* if both are of size == 1 */
5137   if (AOP_SIZE (left) == 1 &&
5138       AOP_SIZE (right) == 1)
5139     {
5140       genMultOneByte (left, right, result, ic);
5141       goto release;
5142     }
5143
5144   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5145           /* use the ds390 ARITHMETIC accel UNIT */
5146           genMultTwoByte (left, right, result, ic);
5147           return ;
5148   }
5149   /* should have been converted to function call */
5150   assert (0);
5151
5152 release:
5153   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5154   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155   freeAsmop (result, NULL, ic, TRUE);
5156 }
5157
5158 /*-----------------------------------------------------------------*/
5159 /* genDivbits :- division of bits                                  */
5160 /*-----------------------------------------------------------------*/
5161 static void
5162 genDivbits (operand * left,
5163             operand * right,
5164             operand * result,
5165             iCode   * ic)
5166 {
5167
5168   char *l;
5169
5170   /* the result must be bit */
5171   LOAD_AB_FOR_DIV (left, right, l);
5172   emitcode ("div", "ab");
5173   emitcode ("rrc", "a");
5174   aopOp(result, ic, TRUE, FALSE);
5175     
5176   aopPut (AOP (result), "c", 0);
5177 }
5178
5179 /*-----------------------------------------------------------------*/
5180 /* genDivOneByte : 8 bit division                                  */
5181 /*-----------------------------------------------------------------*/
5182 static void
5183 genDivOneByte (operand * left,
5184                operand * right,
5185                operand * result,
5186                iCode   * ic)
5187 {
5188   bool lUnsigned, rUnsigned;
5189   bool runtimeSign, compiletimeSign;
5190   char *l;
5191   symbol *lbl;
5192   int size, offset;
5193
5194   offset = 1;
5195   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5196   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5197   
5198   /* signed or unsigned */
5199   if (lUnsigned && rUnsigned)
5200     {
5201       /* unsigned is easy */
5202       LOAD_AB_FOR_DIV (left, right, l);
5203       emitcode ("div", "ab");
5204
5205       _G.accInUse++;
5206       aopOp (result, ic, TRUE, FALSE);
5207       aopPut (AOP (result), "a", 0);
5208       _G.accInUse--;
5209
5210       size = AOP_SIZE (result) - 1;
5211       
5212       while (size--)
5213         aopPut (AOP (result), zero, offset++);
5214       return;
5215     }
5216
5217   /* signed is a little bit more difficult */
5218
5219   /* now sign adjust for both left & right */
5220
5221   /* let's see what's needed: */
5222   /* apply negative sign during runtime */
5223   runtimeSign = FALSE;
5224   /* negative sign from literals */
5225   compiletimeSign = FALSE;
5226
5227   if (!lUnsigned)
5228     {
5229       if (AOP_TYPE(left) == AOP_LIT)
5230         {
5231           /* signed literal */
5232           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5233           if (val < 0)
5234             compiletimeSign = TRUE;
5235         }
5236       else
5237         /* signed but not literal */
5238         runtimeSign = TRUE;
5239     }
5240
5241   if (!rUnsigned)
5242     {
5243       if (AOP_TYPE(right) == AOP_LIT)
5244         {
5245           /* signed literal */
5246           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5247           if (val < 0)
5248             compiletimeSign ^= TRUE;
5249         }
5250       else
5251         /* signed but not literal */
5252         runtimeSign = TRUE;
5253     }
5254
5255   /* initialize F0, which stores the runtime sign */
5256   if (runtimeSign)
5257     {
5258       if (compiletimeSign)
5259         emitcode ("setb", "F0"); /* set sign flag */
5260       else
5261         emitcode ("clr", "F0"); /* reset sign flag */
5262     }
5263
5264   /* save the signs of the operands */
5265   if (AOP_TYPE(right) == AOP_LIT)
5266     {
5267       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5268
5269       if (!rUnsigned && val < 0)
5270         emitcode ("mov", "b,#0x%02x", -val);
5271       else
5272         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5273     }
5274   else /* ! literal */
5275     {
5276       if (rUnsigned)
5277         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5278       else
5279         {
5280           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5281           lbl = newiTempLabel (NULL);
5282           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5283           emitcode ("cpl", "F0"); /* complement sign flag */
5284           emitcode ("cpl", "a");  /* 2's complement */
5285           emitcode ("inc", "a");
5286           emitcode ("", "!tlabeldef", lbl->key + 100);
5287           emitcode ("mov", "b,a");
5288         }
5289     }
5290
5291   if (AOP_TYPE(left) == AOP_LIT)
5292     {
5293       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5294
5295       if (!lUnsigned && val < 0)
5296         emitcode ("mov", "a,#0x%02x", -val);
5297       else
5298         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5299     }
5300   else /* ! literal */
5301     {
5302       if (lUnsigned)
5303         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5304       else
5305         {
5306           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5307           lbl = newiTempLabel (NULL);
5308           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5309           emitcode ("cpl", "F0"); /* complement sign flag */
5310           emitcode ("cpl", "a");  /* 2's complement */
5311           emitcode ("inc", "a");
5312           emitcode ("", "!tlabeldef", lbl->key + 100);
5313         }
5314     }
5315   
5316   /* now the division */
5317   emitcode ("nop", "; workaround for DS80C390 div bug.");
5318   emitcode ("div", "ab");
5319   
5320   if (runtimeSign || compiletimeSign)
5321     {
5322       lbl = newiTempLabel (NULL);
5323       if (runtimeSign)
5324         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5325       emitcode ("cpl", "a"); /* lsb 2's complement */
5326       emitcode ("inc", "a");
5327       emitcode ("", "!tlabeldef", lbl->key + 100);
5328
5329       _G.accInUse++;     _G.bInUse++;
5330       aopOp (result, ic, TRUE, FALSE);
5331       size = AOP_SIZE (result) - 1;
5332
5333       if (size > 0)
5334         {
5335           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5336              then the result will be in b, a */
5337           emitcode ("mov", "b,a"); /* 1 */
5338           /* msb is 0x00 or 0xff depending on the sign */
5339           if (runtimeSign)
5340             {
5341               emitcode ("mov",  "c,F0");
5342               emitcode ("subb", "a,acc");
5343               emitcode ("xch",  "a,b"); /* 2 */
5344               while (size--)
5345                 aopPut (AOP (result), "b", offset++); /* write msb's */
5346             }
5347           else /* compiletimeSign */
5348             while (size--)
5349               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5350         }
5351       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5352     }
5353   else
5354     {
5355       _G.accInUse++;     _G.bInUse++;
5356       aopOp(result, ic, TRUE, FALSE);
5357       size = AOP_SIZE (result) - 1;
5358       
5359       aopPut (AOP (result), "a", 0);
5360       while (size--)
5361         aopPut (AOP (result), zero, offset++);
5362     }
5363   _G.accInUse--;     _G.bInUse--;
5364
5365 }
5366
5367 /*-----------------------------------------------------------------*/
5368 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5369 /*-----------------------------------------------------------------*/
5370 static void genDivTwoByte (operand *left, operand *right, 
5371                             operand *result, iCode *ic)
5372 {
5373         sym_link *retype = getSpec(operandType(right));
5374         sym_link *letype = getSpec(operandType(left));
5375         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5376         symbol *lbl;
5377
5378         /* save EA bit in F1 */
5379         lbl = newiTempLabel(NULL);
5380         emitcode ("setb","F1");
5381         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5382         emitcode ("clr","F1");
5383         emitcode("","!tlabeldef",lbl->key+100);
5384
5385         /* load up MA with left */
5386         if (!umult) {
5387                 emitcode("clr","F0");
5388                 lbl = newiTempLabel(NULL);
5389                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5390                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5391                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5392                 emitcode ("xch", "a,b");
5393                 emitcode ("cpl","a");
5394                 emitcode ("add", "a,#1");
5395                 emitcode ("xch", "a,b");
5396                 emitcode ("cpl", "a"); // msb
5397                 emitcode ("addc","a,#0");
5398                 emitcode ("setb","F0");
5399                 emitcode ("","!tlabeldef",lbl->key+100);
5400                 emitcode ("mov","ma,b");
5401                 emitcode ("mov","ma,a");
5402         } else {
5403                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5404                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5405         }
5406
5407         /* load up MB with right */
5408         if (!umult) {
5409                 if (AOP_TYPE(right) == AOP_LIT) {
5410                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5411                         if (val < 0) {
5412                                 lbl = newiTempLabel(NULL);
5413                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414                                 emitcode("setb","F0");
5415                                 emitcode ("","!tlabeldef",lbl->key+100);
5416                                 val = -val;
5417                         } 
5418                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5419                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5420                 } else {
5421                         lbl = newiTempLabel(NULL);
5422                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5423                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5425                         emitcode ("xch", "a,b");
5426                         emitcode ("cpl","a");
5427                         emitcode ("add", "a,#1");
5428                         emitcode ("xch", "a,b");
5429                         emitcode ("cpl", "a"); // msb
5430                         emitcode ("addc", "a,#0");
5431                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5432                         emitcode ("setb","F0");
5433                         emitcode ("","!tlabeldef",lbl->key+100);
5434                         emitcode ("mov","mb,b");
5435                         emitcode ("mov","mb,a");
5436                 }
5437         } else {
5438                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5439                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5440         }
5441
5442         /* wait for multiplication to finish */
5443         lbl = newiTempLabel(NULL);
5444         emitcode("","!tlabeldef", lbl->key+100);
5445         emitcode("mov","a,mcnt1");
5446         emitcode("anl","a,#!constbyte",0x80);
5447         emitcode("jnz","!tlabel",lbl->key+100);
5448         
5449         freeAsmop (left, NULL, ic, TRUE);
5450         freeAsmop (right, NULL, ic,TRUE);
5451         aopOp(result, ic, TRUE, FALSE);
5452
5453         /* if unsigned then simple */   
5454         if (umult) {
5455                 aopPut(AOP(result),"ma",1);
5456                 aopPut(AOP(result),"ma",0);
5457         } else {
5458                 emitcode("push","ma");
5459                 MOVA("ma");
5460                 /* negate result if needed */
5461                 lbl = newiTempLabel(NULL);      
5462                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5463                 emitcode("cpl","a");
5464                 emitcode("add","a,#1");
5465                 emitcode("","!tlabeldef", lbl->key+100);
5466                 aopPut(AOP(result),"a",0);
5467                 emitcode("pop","acc");
5468                 lbl = newiTempLabel(NULL);      
5469                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5470                 emitcode("cpl","a");
5471                 emitcode("addc","a,#0");
5472                 emitcode("","!tlabeldef", lbl->key+100);
5473                 aopPut(AOP(result),"a",1);
5474         }
5475         freeAsmop (result, NULL, ic, TRUE);
5476         /* restore EA bit in F1 */
5477         lbl = newiTempLabel(NULL);
5478         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5479         emitcode ("setb","EA");
5480         emitcode("","!tlabeldef",lbl->key+100);
5481         return ;
5482 }
5483
5484 /*-----------------------------------------------------------------*/
5485 /* genDiv - generates code for division                            */
5486 /*-----------------------------------------------------------------*/
5487 static void
5488 genDiv (iCode * ic)
5489 {
5490   operand *left = IC_LEFT (ic);
5491   operand *right = IC_RIGHT (ic);
5492   operand *result = IC_RESULT (ic);
5493
5494   D (emitcode (";", "genDiv "););
5495
5496   /* assign the amsops */
5497   AOP_OP_2 (ic);
5498
5499   /* special cases first */
5500   /* both are bits */
5501   if (AOP_TYPE (left) == AOP_CRY &&
5502       AOP_TYPE (right) == AOP_CRY)
5503     {
5504       genDivbits (left, right, result, ic);
5505       goto release;
5506     }
5507
5508   /* if both are of size == 1 */
5509   if (AOP_SIZE (left) == 1 &&
5510       AOP_SIZE (right) == 1)
5511     {
5512       genDivOneByte (left, right, result, ic);
5513       goto release;
5514     }
5515
5516   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5517           /* use the ds390 ARITHMETIC accel UNIT */
5518           genDivTwoByte (left, right, result, ic);
5519           return ;
5520   }
5521   /* should have been converted to function call */
5522   assert (0);
5523 release:
5524   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (result, NULL, ic, TRUE);
5527 }
5528
5529 /*-----------------------------------------------------------------*/
5530 /* genModbits :- modulus of bits                                   */
5531 /*-----------------------------------------------------------------*/
5532 static void
5533 genModbits (operand * left,
5534             operand * right,
5535             operand * result,
5536             iCode   * ic)
5537 {
5538
5539   char *l;
5540
5541   /* the result must be bit */
5542   LOAD_AB_FOR_DIV (left, right, l);
5543   emitcode ("div", "ab");
5544   emitcode ("mov", "a,b");
5545   emitcode ("rrc", "a");
5546   aopOp(result, ic, TRUE, FALSE);
5547   aopPut (AOP (result), "c", 0);
5548 }
5549
5550 /*-----------------------------------------------------------------*/
5551 /* genModOneByte : 8 bit modulus                                   */
5552 /*-----------------------------------------------------------------*/
5553 static void
5554 genModOneByte (operand * left,
5555                operand * right,
5556                operand * result,
5557                iCode   * ic)
5558 {
5559   bool lUnsigned, rUnsigned;
5560   bool runtimeSign, compiletimeSign;
5561   char *l;
5562   symbol *lbl;
5563   int size, offset;
5564
5565   offset = 1;
5566   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5567   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5568   
5569   /* signed or unsigned */
5570   if (lUnsigned && rUnsigned)
5571     {
5572       /* unsigned is easy */
5573       LOAD_AB_FOR_DIV (left, right, l);
5574       emitcode ("div", "ab");
5575       aopOp (result, ic, TRUE, FALSE);  
5576       aopPut (AOP (result), "b", 0);
5577
5578       for (size = AOP_SIZE (result) - 1; size--;)
5579         aopPut (AOP (result), zero, offset++);
5580       return;
5581     }
5582
5583   /* signed is a little bit more difficult */
5584
5585   /* now sign adjust for both left & right */
5586
5587   /* modulus: sign of the right operand has no influence on the result! */
5588   if (AOP_TYPE(right) == AOP_LIT)
5589     {
5590       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5591
5592       if (!rUnsigned && val < 0)
5593         emitcode ("mov", "b,#0x%02x", -val);
5594       else
5595         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5596     }
5597   else /* ! literal */
5598     {
5599       if (rUnsigned)
5600         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5601       else
5602         {
5603           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5604           lbl = newiTempLabel (NULL);
5605           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5606           emitcode ("cpl", "a");  /* 2's complement */
5607           emitcode ("inc", "a");
5608           emitcode ("", "!tlabeldef", lbl->key + 100);
5609           emitcode ("mov", "b,a");
5610         }
5611     }
5612   
5613   /* let's see what's needed: */
5614   /* apply negative sign during runtime */
5615   runtimeSign = FALSE;
5616   /* negative sign from literals */
5617   compiletimeSign = FALSE;
5618
5619   /* sign adjust left side */
5620   if (AOP_TYPE(left) == AOP_LIT)
5621     {
5622       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5623
5624       if (!lUnsigned && val < 0)
5625         {
5626           compiletimeSign = TRUE; /* set sign flag */
5627           emitcode ("mov", "a,#0x%02x", -val);
5628         }
5629       else
5630         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5631     }
5632   else /* ! literal */
5633     {
5634       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5635       
5636       if (!lUnsigned)
5637         {
5638           runtimeSign = TRUE;
5639           emitcode ("clr", "F0"); /* clear sign flag */
5640           
5641           lbl = newiTempLabel (NULL);
5642           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5643           emitcode ("setb", "F0"); /* set sign flag */
5644           emitcode ("cpl", "a");   /* 2's complement */
5645           emitcode ("inc", "a");
5646           emitcode ("", "!tlabeldef", lbl->key + 100);
5647         }
5648     }
5649   
5650   /* now the modulus */
5651   emitcode ("nop", "; workaround for DS80C390 div bug.");
5652   emitcode ("div", "ab");
5653   
5654   if (runtimeSign || compiletimeSign)
5655     {
5656       emitcode ("mov", "a,b");
5657       lbl = newiTempLabel (NULL);
5658       if (runtimeSign)
5659         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5660       emitcode ("cpl", "a"); /* lsb 2's complement */
5661       emitcode ("inc", "a");
5662       emitcode ("", "!tlabeldef", lbl->key + 100);
5663
5664       _G.accInUse++;     _G.bInUse++;
5665       aopOp (result, ic, TRUE, FALSE);
5666       size = AOP_SIZE (result) - 1;
5667       
5668       if (size > 0)
5669         {
5670           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5671              then the result will be in b, a */
5672           emitcode ("mov", "b,a"); /* 1 */
5673           /* msb is 0x00 or 0xff depending on the sign */
5674           if (runtimeSign)
5675             {
5676               emitcode ("mov",  "c,F0");
5677               emitcode ("subb", "a,acc");
5678               emitcode ("xch",  "a,b"); /* 2 */
5679               while (size--)
5680                 aopPut (AOP (result), "b", offset++); /* write msb's */
5681             }
5682           else /* compiletimeSign */
5683             while (size--)
5684               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5685         }
5686       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5687     }
5688   else
5689     {
5690       _G.accInUse++;     _G.bInUse++;
5691       aopOp(result, ic, TRUE, FALSE);
5692       size = AOP_SIZE (result) - 1;
5693       
5694       aopPut (AOP (result), "b", 0);
5695       while (size--)
5696         aopPut (AOP (result), zero, offset++);
5697     }
5698   _G.accInUse--;     _G.bInUse--;
5699
5700 }
5701
5702 /*-----------------------------------------------------------------*/
5703 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5704 /*-----------------------------------------------------------------*/
5705 static void genModTwoByte (operand *left, operand *right, 
5706                             operand *result, iCode *ic)
5707 {
5708         sym_link *retype = getSpec(operandType(right));
5709         sym_link *letype = getSpec(operandType(left));
5710         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5711         symbol *lbl;
5712
5713         /* load up MA with left */
5714         /* save EA bit in F1 */
5715         lbl = newiTempLabel(NULL);
5716         emitcode ("setb","F1");
5717         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5718         emitcode ("clr","F1");
5719         emitcode("","!tlabeldef",lbl->key+100);
5720
5721         if (!umult) {
5722                 lbl = newiTempLabel(NULL);
5723                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5724                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5725                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5726                 emitcode ("xch", "a,b");
5727                 emitcode ("cpl","a");
5728                 emitcode ("add", "a,#1");
5729                 emitcode ("xch", "a,b");
5730                 emitcode ("cpl", "a"); // msb
5731                 emitcode ("addc","a,#0");
5732                 emitcode ("","!tlabeldef",lbl->key+100);
5733                 emitcode ("mov","ma,b");
5734                 emitcode ("mov","ma,a");
5735         } else {
5736                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5737                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5738         }
5739
5740         /* load up MB with right */
5741         if (!umult) {
5742                 if (AOP_TYPE(right) == AOP_LIT) {
5743                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5744                         if (val < 0) {
5745                                 val = -val;
5746                         } 
5747                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5748                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5749                 } else {
5750                         lbl = newiTempLabel(NULL);
5751                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5752                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5753                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5754                         emitcode ("xch", "a,b");
5755                         emitcode ("cpl","a");
5756                         emitcode ("add", "a,#1");
5757                         emitcode ("xch", "a,b");
5758                         emitcode ("cpl", "a"); // msb
5759                         emitcode ("addc", "a,#0");
5760                         emitcode ("","!tlabeldef",lbl->key+100);
5761                         emitcode ("mov","mb,b");
5762                         emitcode ("mov","mb,a");
5763                 }
5764         } else {
5765                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5766                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5767         }
5768
5769         /* wait for multiplication to finish */
5770         lbl = newiTempLabel(NULL);
5771         emitcode("","!tlabeldef", lbl->key+100);
5772         emitcode("mov","a,mcnt1");
5773         emitcode("anl","a,#!constbyte",0x80);
5774         emitcode("jnz","!tlabel",lbl->key+100);
5775         
5776         freeAsmop (left, NULL, ic, TRUE);
5777         freeAsmop (right, NULL, ic,TRUE);
5778         aopOp(result, ic, TRUE, FALSE);
5779
5780         aopPut(AOP(result),"mb",1);
5781         aopPut(AOP(result),"mb",0);
5782         freeAsmop (result, NULL, ic, TRUE);
5783
5784         /* restore EA bit in F1 */
5785         lbl = newiTempLabel(NULL);
5786         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5787         emitcode ("setb","EA");
5788         emitcode("","!tlabeldef",lbl->key+100);
5789         return ;
5790 }
5791
5792 /*-----------------------------------------------------------------*/
5793 /* genMod - generates code for division                            */
5794 /*-----------------------------------------------------------------*/
5795 static void
5796 genMod (iCode * ic)
5797 {
5798   operand *left = IC_LEFT (ic);
5799   operand *right = IC_RIGHT (ic);
5800   operand *result = IC_RESULT (ic);
5801
5802   D (emitcode (";", "genMod "); );
5803
5804   /* assign the amsops */
5805   AOP_OP_2 (ic);
5806
5807   /* special cases first */
5808   /* both are bits */
5809   if (AOP_TYPE (left) == AOP_CRY &&
5810       AOP_TYPE (right) == AOP_CRY)
5811     {
5812       genModbits (left, right, result, ic);
5813       goto release;
5814     }
5815
5816   /* if both are of size == 1 */
5817   if (AOP_SIZE (left) == 1 &&
5818       AOP_SIZE (right) == 1)
5819     {
5820       genModOneByte (left, right, result, ic);
5821       goto release;
5822     }
5823
5824   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5825           /* use the ds390 ARITHMETIC accel UNIT */
5826           genModTwoByte (left, right, result, ic);
5827           return ;
5828   }
5829
5830   /* should have been converted to function call */
5831   assert (0);
5832
5833 release:
5834   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836   freeAsmop (result, NULL, ic, TRUE);
5837 }
5838
5839 /*-----------------------------------------------------------------*/
5840 /* genIfxJump :- will create a jump depending on the ifx           */
5841 /*-----------------------------------------------------------------*/
5842 static void
5843 genIfxJump (iCode * ic, char *jval)
5844 {
5845   symbol *jlbl;
5846   symbol *tlbl = newiTempLabel (NULL);
5847   char *inst;
5848
5849   D (emitcode (";", "genIfxJump"););
5850
5851   /* if true label then we jump if condition
5852      supplied is true */
5853   if (IC_TRUE (ic))
5854     {
5855       jlbl = IC_TRUE (ic);
5856       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5857                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5858     }
5859   else
5860     {
5861       /* false label is present */
5862       jlbl = IC_FALSE (ic);
5863       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5864                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5865     }
5866   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5867     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5868   else
5869     emitcode (inst, "!tlabel", tlbl->key + 100);
5870   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5871   emitcode ("", "!tlabeldef", tlbl->key + 100);
5872
5873   /* mark the icode as generated */
5874   ic->generated = 1;
5875 }
5876
5877 /*-----------------------------------------------------------------*/
5878 /* genCmp :- greater or less than comparison                       */
5879 /*-----------------------------------------------------------------*/
5880 static void
5881 genCmp (operand * left, operand * right,
5882         iCode * ic, iCode * ifx, int sign)
5883 {
5884   int size, offset = 0;
5885   unsigned long lit = 0L;
5886   operand *result;
5887
5888   D (emitcode (";", "genCmp"););
5889
5890   result = IC_RESULT (ic);
5891
5892   /* if left & right are bit variables */
5893   if (AOP_TYPE (left) == AOP_CRY &&
5894       AOP_TYPE (right) == AOP_CRY)
5895     {
5896       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5897       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5898     }
5899   else
5900     {
5901       /* subtract right from left if at the
5902          end the carry flag is set then we know that
5903          left is greater than right */
5904       size = max (AOP_SIZE (left), AOP_SIZE (right));
5905
5906       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5907       if ((size == 1) && !sign 
5908           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5909         {
5910           symbol *lbl = newiTempLabel (NULL);
5911           emitcode ("cjne", "%s,%s,!tlabel",
5912                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5913                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5914                     lbl->key + 100);
5915           emitcode ("", "!tlabeldef", lbl->key + 100);
5916         }
5917       else
5918         {
5919           if (AOP_TYPE (right) == AOP_LIT)
5920             {
5921               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5922               /* optimize if(x < 0) or if(x >= 0) */
5923               if (lit == 0L)
5924                 {
5925                   if (!sign)
5926                     {
5927                       CLRC;
5928                     }
5929                   else
5930                     {
5931                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5932
5933                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935
5936                       aopOp (result, ic, FALSE, FALSE);
5937
5938                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5939                         {
5940                           freeAsmop (result, NULL, ic, TRUE);
5941                           genIfxJump (ifx, "acc.7");
5942                           return;
5943                         }
5944                       else
5945                         {
5946                           emitcode ("rlc", "a");
5947                         }
5948                       goto release_freedLR;
5949                     }
5950                   goto release;
5951                 }
5952             }
5953           CLRC;
5954           while (size--)
5955             {
5956               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5957               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5958               // emitcode (";", "genCmp #2");
5959               if (sign && (size == 0))
5960                 {
5961                   // emitcode (";", "genCmp #3");
5962                   emitcode ("xrl", "a,#!constbyte",0x80);
5963                   if (AOP_TYPE (right) == AOP_LIT)
5964                     {
5965                       unsigned long lit = (unsigned long)
5966                       floatFromVal (AOP (right)->aopu.aop_lit);
5967                       // emitcode (";", "genCmp #3.1");
5968                       emitcode ("subb", "a,#!constbyte",
5969                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5970                     }
5971                   else
5972                     {
5973                       // emitcode (";", "genCmp #3.2");
5974                       saveAccWarn = 0;  
5975                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5976                       saveAccWarn = DEFAULT_ACC_WARNING;
5977                       emitcode ("xrl", "b,#!constbyte",0x80);
5978                       emitcode ("subb", "a,b");
5979                     }
5980                 }
5981               else
5982                 {
5983                   const char *s;
5984
5985                   // emitcode (";", "genCmp #4");
5986                   saveAccWarn = 0;
5987                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5988                   saveAccWarn = DEFAULT_ACC_WARNING;
5989
5990                   emitcode ("subb", "a,%s", s);
5991                 }
5992             }
5993         }
5994     }
5995
5996 release:
5997 /* Don't need the left & right operands any more; do need the result. */
5998   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000
6001   aopOp (result, ic, FALSE, FALSE);
6002
6003 release_freedLR:
6004
6005   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6006     {
6007       outBitC (result);
6008     }
6009   else
6010     {
6011       /* if the result is used in the next
6012          ifx conditional branch then generate
6013          code a little differently */
6014       if (ifx)
6015         {
6016           genIfxJump (ifx, "c");
6017         }
6018       else
6019         {
6020           outBitC (result);
6021         }
6022       /* leave the result in acc */
6023     }
6024   freeAsmop (result, NULL, ic, TRUE);
6025 }
6026
6027 /*-----------------------------------------------------------------*/
6028 /* genCmpGt :- greater than comparison                             */
6029 /*-----------------------------------------------------------------*/
6030 static void
6031 genCmpGt (iCode * ic, iCode * ifx)
6032 {
6033   operand *left, *right;
6034   sym_link *letype, *retype;
6035   int sign;
6036
6037   D (emitcode (";", "genCmpGt ");
6038     );
6039
6040   left = IC_LEFT (ic);
6041   right = IC_RIGHT (ic);
6042
6043   letype = getSpec (operandType (left));
6044   retype = getSpec (operandType (right));
6045   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6046
6047   /* assign the left & right amsops */
6048   AOP_OP_2 (ic);
6049
6050   genCmp (right, left, ic, ifx, sign);
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpLt - less than comparisons                                */
6055 /*-----------------------------------------------------------------*/
6056 static void
6057 genCmpLt (iCode * ic, iCode * ifx)
6058 {
6059   operand *left, *right;
6060   sym_link *letype, *retype;
6061   int sign;
6062
6063   D (emitcode (";", "genCmpLt "););
6064
6065   left = IC_LEFT (ic);
6066   right = IC_RIGHT (ic);
6067
6068   letype = getSpec (operandType (left));
6069   retype = getSpec (operandType (right));
6070   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6071
6072   /* assign the left & right amsops */
6073   AOP_OP_2 (ic);
6074
6075   genCmp (left, right, ic, ifx, sign);
6076 }
6077
6078 /*-----------------------------------------------------------------*/
6079 /* gencjneshort - compare and jump if not equal                    */
6080 /*-----------------------------------------------------------------*/
6081 static void
6082 gencjneshort (operand * left, operand * right, symbol * lbl)
6083 {
6084   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6085   int offset = 0;
6086   unsigned long lit = 0L;
6087
6088   D (emitcode (";", "gencjneshort");
6089     );
6090
6091   /* if the left side is a literal or
6092      if the right is in a pointer register and left
6093      is not */
6094   if ((AOP_TYPE (left) == AOP_LIT) ||
6095       (AOP_TYPE (left) == AOP_IMMD) ||
6096       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6097     {
6098       operand *t = right;
6099       right = left;
6100       left = t;
6101     }
6102
6103   if (AOP_TYPE (right) == AOP_LIT)
6104     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6105
6106   if (opIsGptr (left) || opIsGptr (right))
6107     {
6108       /* We are comparing a generic pointer to something.
6109        * Exclude the generic type byte from the comparison.
6110        */
6111       size--;
6112       D (emitcode (";", "cjneshort: generic ptr special case."););
6113     }
6114
6115
6116   /* if the right side is a literal then anything goes */
6117   if (AOP_TYPE (right) == AOP_LIT &&
6118       AOP_TYPE (left) != AOP_DIR)
6119     {
6120       while (size--)
6121         {
6122           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123           emitcode ("cjne", "a,%s,!tlabel",
6124                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6125                     lbl->key + 100);
6126           offset++;
6127         }
6128     }
6129
6130   /* if the right side is in a register or in direct space or
6131      if the left is a pointer register & right is not */
6132   else if (AOP_TYPE (right) == AOP_REG ||
6133            AOP_TYPE (right) == AOP_DIR ||
6134            AOP_TYPE (right) == AOP_LIT ||
6135            AOP_TYPE (right) == AOP_IMMD ||
6136            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6137            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6138     {
6139       while (size--)
6140         {
6141           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6142           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6143               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6144             emitcode ("jnz", "!tlabel", lbl->key + 100);
6145           else
6146             emitcode ("cjne", "a,%s,!tlabel",
6147                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6148                       lbl->key + 100);
6149           offset++;
6150         }
6151     }
6152   else
6153     {
6154       /* right is a pointer reg need both a & b */
6155       while (size--)
6156         {
6157           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6158           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6159           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6160           offset++;
6161         }
6162     }
6163 }
6164
6165 /*-----------------------------------------------------------------*/
6166 /* gencjne - compare and jump if not equal                         */
6167 /*-----------------------------------------------------------------*/
6168 static void
6169 gencjne (operand * left, operand * right, symbol * lbl)
6170 {
6171   symbol *tlbl = newiTempLabel (NULL);
6172
6173   D (emitcode (";", "gencjne");
6174     );
6175
6176   gencjneshort (left, right, lbl);
6177
6178   emitcode ("mov", "a,%s", one);
6179   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6180   emitcode ("", "!tlabeldef", lbl->key + 100);
6181   emitcode ("clr", "a");
6182   emitcode ("", "!tlabeldef", tlbl->key + 100);
6183 }
6184
6185 /*-----------------------------------------------------------------*/
6186 /* genCmpEq - generates code for equal to                          */
6187 /*-----------------------------------------------------------------*/
6188 static void
6189 genCmpEq (iCode * ic, iCode * ifx)
6190 {
6191   operand *left, *right, *result;
6192
6193   D (emitcode (";", "genCmpEq ");
6194     );
6195
6196   AOP_OP_2 (ic);
6197   AOP_SET_LOCALS (ic);
6198
6199   /* if literal, literal on the right or
6200      if the right is in a pointer register and left
6201      is not */
6202   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6203       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6204     {
6205       operand *t = IC_RIGHT (ic);
6206       IC_RIGHT (ic) = IC_LEFT (ic);
6207       IC_LEFT (ic) = t;
6208     }
6209
6210   if (ifx &&                    /* !AOP_SIZE(result) */
6211       OP_SYMBOL (result) &&
6212       OP_SYMBOL (result)->regType == REG_CND)
6213     {
6214       symbol *tlbl;
6215       /* if they are both bit variables */
6216       if (AOP_TYPE (left) == AOP_CRY &&
6217           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6218         {
6219           if (AOP_TYPE (right) == AOP_LIT)
6220             {
6221               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6222               if (lit == 0L)
6223                 {
6224                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6225                   emitcode ("cpl", "c");
6226                 }
6227               else if (lit == 1L)
6228                 {
6229                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6230                 }
6231               else
6232                 {
6233                   emitcode ("clr", "c");
6234                 }
6235               /* AOP_TYPE(right) == AOP_CRY */
6236             }
6237           else
6238             {
6239               symbol *lbl = newiTempLabel (NULL);
6240               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6241               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6242               emitcode ("cpl", "c");
6243               emitcode ("", "!tlabeldef", (lbl->key + 100));
6244             }
6245           /* if true label then we jump if condition
6246              supplied is true */
6247           tlbl = newiTempLabel (NULL);
6248           if (IC_TRUE (ifx))
6249             {
6250               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6251               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6252             }
6253           else
6254             {
6255               emitcode ("jc", "!tlabel", tlbl->key + 100);
6256               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6257             }
6258           emitcode ("", "!tlabeldef", tlbl->key + 100);
6259         }
6260       else
6261         {
6262           tlbl = newiTempLabel (NULL);
6263           gencjneshort (left, right, tlbl);
6264           if (IC_TRUE (ifx))
6265             {
6266               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6267               emitcode ("", "!tlabeldef", tlbl->key + 100);
6268             }
6269           else
6270             {
6271               symbol *lbl = newiTempLabel (NULL);
6272               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6273               emitcode ("", "!tlabeldef", tlbl->key + 100);
6274               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6275               emitcode ("", "!tlabeldef", lbl->key + 100);
6276             }
6277         }
6278       /* mark the icode as generated */
6279       ifx->generated = 1;
6280
6281       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6282       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6283       return;
6284     }
6285
6286   /* if they are both bit variables */
6287   if (AOP_TYPE (left) == AOP_CRY &&
6288       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6289     {
6290       if (AOP_TYPE (right) == AOP_LIT)
6291         {
6292           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6293           if (lit == 0L)
6294             {
6295               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296               emitcode ("cpl", "c");
6297             }
6298           else if (lit == 1L)
6299             {
6300               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6301             }
6302           else
6303             {
6304               emitcode ("clr", "c");
6305             }
6306           /* AOP_TYPE(right) == AOP_CRY */
6307         }
6308       else
6309         {
6310           symbol *lbl = newiTempLabel (NULL);
6311           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6312           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6313           emitcode ("cpl", "c");
6314           emitcode ("", "!tlabeldef", (lbl->key + 100));
6315         }
6316
6317       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319
6320       aopOp (result, ic, TRUE, FALSE);
6321
6322       /* c = 1 if egal */
6323       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6324         {
6325           outBitC (result);
6326           goto release;
6327         }
6328       if (ifx)
6329         {
6330           genIfxJump (ifx, "c");
6331           goto release;
6332         }
6333       /* if the result is used in an arithmetic operation
6334          then put the result in place */
6335       outBitC (result);
6336     }
6337   else
6338     {
6339       gencjne (left, right, newiTempLabel (NULL));
6340
6341       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6342       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343
6344       aopOp (result, ic, TRUE, FALSE);
6345
6346       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6347         {
6348           aopPut (AOP (result), "a", 0);
6349           goto release;
6350         }
6351       if (ifx)
6352         {
6353           genIfxJump (ifx, "a");
6354           goto release;
6355         }
6356       /* if the result is used in an arithmetic operation
6357          then put the result in place */
6358       if (AOP_TYPE (result) != AOP_CRY)
6359         outAcc (result);
6360       /* leave the result in acc */
6361     }
6362
6363 release:
6364   freeAsmop (result, NULL, ic, TRUE);
6365 }
6366
6367 /*-----------------------------------------------------------------*/
6368 /* ifxForOp - returns the icode containing the ifx for operand     */
6369 /*-----------------------------------------------------------------*/
6370 static iCode *
6371 ifxForOp (operand * op, iCode * ic)
6372 {
6373   /* if true symbol then needs to be assigned */
6374   if (IS_TRUE_SYMOP (op))
6375     return NULL;
6376
6377   /* if this has register type condition and
6378      the next instruction is ifx with the same operand
6379      and live to of the operand is upto the ifx only then */
6380   if (ic->next &&
6381       ic->next->op == IFX &&
6382       IC_COND (ic->next)->key == op->key &&
6383       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6384     return ic->next;
6385
6386   return NULL;
6387 }
6388 /*-----------------------------------------------------------------*/
6389 /* hasInc - operand is incremented before any other use            */
6390 /*-----------------------------------------------------------------*/
6391 static iCode *
6392 hasInc (operand *op, iCode *ic, int osize)
6393 {
6394   sym_link *type = operandType(op);
6395   sym_link *retype = getSpec (type);
6396   iCode *lic = ic->next;
6397   int isize ;
6398   
6399   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6400   if (!IS_SYMOP(op)) return NULL;
6401
6402   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6403   if (IS_AGGREGATE(type->next)) return NULL;
6404   if (osize != (isize = getSize(type->next))) return NULL;
6405
6406   while (lic) {
6407       /* if operand of the form op = op + <sizeof *op> */
6408       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6409           isOperandEqual(IC_RESULT(lic),op) && 
6410           isOperandLiteral(IC_RIGHT(lic)) &&
6411           operandLitValue(IC_RIGHT(lic)) == isize) {
6412           return lic;
6413       }
6414       /* if the operand used or deffed */
6415       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6416           return NULL;
6417       }
6418       /* if GOTO or IFX */
6419       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6420       lic = lic->next;
6421   }
6422   return NULL;
6423 }
6424
6425 /*-----------------------------------------------------------------*/
6426 /* genAndOp - for && operation                                     */
6427 /*-----------------------------------------------------------------*/
6428 static void
6429 genAndOp (iCode * ic)
6430 {
6431   operand *left, *right, *result;
6432   symbol *tlbl;
6433
6434   D (emitcode (";", "genAndOp "););
6435
6436   /* note here that && operations that are in an
6437      if statement are taken away by backPatchLabels
6438      only those used in arthmetic operations remain */
6439   AOP_OP_2 (ic);
6440   AOP_SET_LOCALS (ic);
6441
6442   /* if both are bit variables */
6443   if (AOP_TYPE (left) == AOP_CRY &&
6444       AOP_TYPE (right) == AOP_CRY)
6445     {
6446       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6447       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6448       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6449       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450   
6451       aopOp (result,ic,FALSE, FALSE);
6452       outBitC (result);
6453     }
6454   else
6455     {
6456       tlbl = newiTempLabel (NULL);
6457       toBoolean (left);
6458       emitcode ("jz", "!tlabel", tlbl->key + 100);
6459       toBoolean (right);
6460       emitcode ("", "!tlabeldef", tlbl->key + 100);
6461       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463   
6464       aopOp (result,ic,FALSE, FALSE);
6465       outBitAcc (result);
6466     }
6467     freeAsmop (result, NULL, ic, TRUE);
6468 }
6469
6470
6471 /*-----------------------------------------------------------------*/
6472 /* genOrOp - for || operation                                      */
6473 /*-----------------------------------------------------------------*/
6474 static void
6475 genOrOp (iCode * ic)
6476 {
6477   operand *left, *right, *result;
6478   symbol *tlbl;
6479
6480   D (emitcode (";", "genOrOp "););
6481
6482   /* note here that || operations that are in an
6483      if statement are taken away by backPatchLabels
6484      only those used in arthmetic operations remain */
6485   AOP_OP_2 (ic);
6486   AOP_SET_LOCALS (ic);
6487
6488   /* if both are bit variables */
6489   if (AOP_TYPE (left) == AOP_CRY &&
6490       AOP_TYPE (right) == AOP_CRY)
6491     {
6492       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6493       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6494       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6495       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6496   
6497       aopOp (result,ic,FALSE, FALSE);
6498       
6499       outBitC (result);
6500     }
6501   else
6502     {
6503       tlbl = newiTempLabel (NULL);
6504       toBoolean (left);
6505       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6506       toBoolean (right);
6507       emitcode ("", "!tlabeldef", tlbl->key + 100);
6508       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6509       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510   
6511       aopOp (result,ic,FALSE, FALSE);
6512       
6513       outBitAcc (result);
6514     }
6515
6516   freeAsmop (result, NULL, ic, TRUE);
6517 }
6518
6519 /*-----------------------------------------------------------------*/
6520 /* isLiteralBit - test if lit == 2^n                               */
6521 /*-----------------------------------------------------------------*/
6522 static int
6523 isLiteralBit (unsigned long lit)
6524 {
6525   unsigned long pw[32] =
6526   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6527    0x100L, 0x200L, 0x400L, 0x800L,
6528    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6529    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6530    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6531    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6532    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6533   int idx;
6534
6535   for (idx = 0; idx < 32; idx++)
6536     if (lit == pw[idx])
6537       return idx + 1;
6538   return 0;
6539 }
6540
6541 /*-----------------------------------------------------------------*/
6542 /* continueIfTrue -                                                */
6543 /*-----------------------------------------------------------------*/
6544 static void
6545 continueIfTrue (iCode * ic)
6546 {
6547   if (IC_TRUE (ic))
6548     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6549   ic->generated = 1;
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* jmpIfTrue -                                                     */
6554 /*-----------------------------------------------------------------*/
6555 static void
6556 jumpIfTrue (iCode * ic)
6557 {
6558   if (!IC_TRUE (ic))
6559     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6560   ic->generated = 1;
6561 }
6562
6563 /*-----------------------------------------------------------------*/
6564 /* jmpTrueOrFalse -                                                */
6565 /*-----------------------------------------------------------------*/
6566 static void
6567 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6568 {
6569   // ugly but optimized by peephole
6570   if (IC_TRUE (ic))
6571     {
6572       symbol *nlbl = newiTempLabel (NULL);
6573       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6574       emitcode ("", "!tlabeldef", tlbl->key + 100);
6575       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6576       emitcode ("", "!tlabeldef", nlbl->key + 100);
6577     }
6578   else
6579     {
6580       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6581       emitcode ("", "!tlabeldef", tlbl->key + 100);
6582     }
6583   ic->generated = 1;
6584 }
6585
6586 // Generate code to perform a bit-wise logic operation
6587 // on two operands in far space (assumed to already have been 
6588 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6589 // in far space. This requires pushing the result on the stack
6590 // then popping it into the result.
6591 static void
6592 genFarFarLogicOp(iCode *ic, char *logicOp)
6593 {
6594       int size, resultSize, compSize;
6595       int offset = 0;
6596       
6597       TR_AP("#5");
6598       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6599       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6600                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6601       
6602       _startLazyDPSEvaluation();
6603       for (size = compSize; (size--); offset++)
6604       {
6605           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6606           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6607           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6608           
6609           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6610           emitcode ("push", "acc");
6611       }
6612       _endLazyDPSEvaluation();
6613      
6614       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6615       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6617      
6618       resultSize = AOP_SIZE(IC_RESULT(ic));
6619
6620       ADJUST_PUSHED_RESULT(compSize, resultSize);
6621
6622       _startLazyDPSEvaluation();
6623       while (compSize--)
6624       {
6625           emitcode ("pop", "acc");
6626           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6627       }
6628       _endLazyDPSEvaluation();
6629       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6630 }
6631
6632
6633 /*-----------------------------------------------------------------*/
6634 /* genAnd  - code for and                                          */
6635 /*-----------------------------------------------------------------*/
6636 static void
6637 genAnd (iCode * ic, iCode * ifx)
6638 {
6639   operand *left, *right, *result;
6640   int size, offset = 0;
6641   unsigned long lit = 0L;
6642   int bytelit;
6643   char buff[10];
6644   bool pushResult;
6645
6646   D (emitcode (";", "genAnd "););
6647
6648   AOP_OP_3_NOFATAL (ic, pushResult);
6649   AOP_SET_LOCALS (ic);
6650
6651   if (pushResult)
6652   {
6653       genFarFarLogicOp(ic, "anl");
6654       return;
6655   }  
6656
6657 #ifdef DEBUG_TYPE
6658   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6659             AOP_TYPE (result),
6660             AOP_TYPE (left), AOP_TYPE (right));
6661   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6662             AOP_SIZE (result),
6663             AOP_SIZE (left), AOP_SIZE (right));
6664 #endif
6665
6666   /* if left is a literal & right is not then exchange them */
6667   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6668 #ifdef LOGIC_OPS_BROKEN      
6669     ||  AOP_NEEDSACC (left)
6670 #endif
6671     )
6672     {
6673       operand *tmp = right;
6674       right = left;
6675       left = tmp;
6676     }
6677
6678   /* if result = right then exchange them */
6679   if (sameRegs (AOP (result), AOP (right)))
6680     {
6681       operand *tmp = right;
6682       right = left;
6683       left = tmp;
6684     }
6685
6686   /* if right is bit then exchange them */
6687   if (AOP_TYPE (right) == AOP_CRY &&
6688       AOP_TYPE (left) != AOP_CRY)
6689     {
6690       operand *tmp = right;
6691       right = left;
6692       left = tmp;
6693     }
6694   if (AOP_TYPE (right) == AOP_LIT)
6695     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6696
6697   size = AOP_SIZE (result);
6698
6699   // if(bit & yy)
6700   // result = bit & yy;
6701   if (AOP_TYPE (left) == AOP_CRY)
6702     {
6703       // c = bit & literal;
6704       if (AOP_TYPE (right) == AOP_LIT)
6705         {
6706           if (lit & 1)
6707             {
6708               if (size && sameRegs (AOP (result), AOP (left)))
6709                 // no change
6710                 goto release;
6711               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6712             }
6713           else
6714             {
6715               // bit(result) = 0;
6716               if (size && (AOP_TYPE (result) == AOP_CRY))
6717                 {
6718                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6719                   goto release;
6720                 }
6721               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6722                 {
6723                   jumpIfTrue (ifx);
6724                   goto release;
6725                 }
6726               emitcode ("clr", "c");
6727             }
6728         }
6729       else
6730         {
6731           if (AOP_TYPE (right) == AOP_CRY)
6732             {
6733               // c = bit & bit;
6734               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6735               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6736             }
6737           else
6738             {
6739               // c = bit & val;
6740               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6741               // c = lsb
6742               emitcode ("rrc", "a");
6743               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6744             }
6745         }
6746       // bit = c
6747       // val = c
6748       if (size)
6749         outBitC (result);
6750       // if(bit & ...)
6751       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6752         genIfxJump (ifx, "c");
6753       goto release;
6754     }
6755
6756   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6757   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6758   if ((AOP_TYPE (right) == AOP_LIT) &&
6759       (AOP_TYPE (result) == AOP_CRY) &&
6760       (AOP_TYPE (left) != AOP_CRY))
6761     {
6762       int posbit = isLiteralBit (lit);
6763       /* left &  2^n */
6764       if (posbit)
6765         {
6766           posbit--;
6767           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6768           // bit = left & 2^n
6769           if (size)
6770             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6771           // if(left &  2^n)
6772           else
6773             {
6774               if (ifx)
6775                 {
6776                   SNPRINTF (buff, sizeof(buff), 
6777                             "acc.%d", posbit & 0x07);
6778                   genIfxJump (ifx, buff);
6779                 }
6780               else 
6781                   {
6782                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6783                   }
6784               goto release;
6785             }
6786         }
6787       else
6788         {
6789           symbol *tlbl = newiTempLabel (NULL);
6790           int sizel = AOP_SIZE (left);
6791           if (size)
6792             emitcode ("setb", "c");
6793           while (sizel--)
6794             {
6795               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6796                 {
6797                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6798                   // byte ==  2^n ?
6799                   if ((posbit = isLiteralBit (bytelit)) != 0)
6800                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6801                   else
6802                     {
6803                       if (bytelit != 0x0FFL)
6804                         emitcode ("anl", "a,%s",
6805                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6806                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6807                     }
6808                 }
6809               offset++;
6810             }
6811           // bit = left & literal
6812           if (size)
6813             {
6814               emitcode ("clr", "c");
6815               emitcode ("", "!tlabeldef", tlbl->key + 100);
6816             }
6817           // if(left & literal)
6818           else
6819             {
6820               if (ifx)
6821                 jmpTrueOrFalse (ifx, tlbl);
6822               else
6823                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6824               goto release;
6825             }
6826         }
6827       outBitC (result);
6828       goto release;
6829     }
6830
6831   /* if left is same as result */
6832   if (sameRegs (AOP (result), AOP (left)))
6833     {
6834       for (; size--; offset++)
6835         {
6836           if (AOP_TYPE (right) == AOP_LIT)
6837             {
6838               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6839                 continue;
6840               else if (bytelit == 0)
6841                 aopPut (AOP (result), zero, offset);
6842               else if (IS_AOP_PREG (result))
6843                 {
6844                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6845                   emitcode ("anl", "a,%s",
6846                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6847                   aopPut (AOP (result), "a", offset);
6848                 }
6849               else
6850                 emitcode ("anl", "%s,%s",
6851                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6852                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6853             }
6854           else
6855             {
6856               if (AOP_TYPE (left) == AOP_ACC)
6857                 emitcode ("anl", "a,%s",
6858                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6859               else
6860                 {
6861                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6862                   if (IS_AOP_PREG (result))
6863                     {
6864                       emitcode ("anl", "a,%s",
6865                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6866                       aopPut (AOP (result), "a", offset);
6867                     }
6868                   else
6869                     emitcode ("anl", "%s,a",
6870                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6871                 }
6872             }
6873         }
6874     }
6875   else
6876     {
6877       // left & result in different registers
6878       if (AOP_TYPE (result) == AOP_CRY)
6879         {
6880           // result = bit
6881           // if(size), result in bit
6882           // if(!size && ifx), conditional oper: if(left & right)
6883           symbol *tlbl = newiTempLabel (NULL);
6884           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6885           if (size)
6886             emitcode ("setb", "c");
6887           while (sizer--)
6888             {
6889               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6890                 emitcode ("anl", "a,%s",
6891                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6892               } else {
6893                 if (AOP_TYPE(left)==AOP_ACC) {
6894                   emitcode("mov", "b,a");
6895                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6896                   emitcode("anl", "a,b");
6897                 }else {
6898                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6899                   emitcode ("anl", "a,%s",
6900                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6901                 }
6902               }
6903               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6904               offset++;
6905             }
6906           if (size)
6907             {
6908               CLRC;
6909               emitcode ("", "!tlabeldef", tlbl->key + 100);
6910               outBitC (result);
6911             }
6912           else if (ifx)
6913             jmpTrueOrFalse (ifx, tlbl);
6914           else
6915             emitcode ("", "!tlabeldef", tlbl->key + 100);
6916         }
6917       else
6918         {
6919           for (; (size--); offset++)
6920             {
6921               // normal case
6922               // result = left & right
6923               if (AOP_TYPE (right) == AOP_LIT)
6924                 {
6925                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6926                     {
6927                       aopPut (AOP (result),
6928                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6929                               offset);
6930                       continue;
6931                     }
6932                   else if (bytelit == 0)
6933                     {
6934                       aopPut (AOP (result), zero, offset);
6935                       continue;
6936                     }
6937                   D (emitcode (";", "better literal AND."););
6938                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6939                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6940                                                     FALSE, FALSE, DP2_RESULT_REG));
6941
6942                 }
6943               else
6944                 {
6945                   // faster than result <- left, anl result,right
6946                   // and better if result is SFR
6947                   if (AOP_TYPE (left) == AOP_ACC)
6948                     {
6949                       emitcode ("anl", "a,%s", 
6950                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6951                     }
6952                   else
6953                     {
6954                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6955                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6956                       {
6957                           emitcode("mov", "b,a");
6958                           rOp = "b";
6959                       }
6960                         
6961                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6962                       emitcode ("anl", "a,%s", rOp);
6963                     }                   
6964                 }
6965               aopPut (AOP (result), "a", offset);
6966             }
6967         }
6968     }
6969
6970 release:
6971   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6972   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6973   freeAsmop (result, NULL, ic, TRUE);
6974 }
6975
6976
6977 /*-----------------------------------------------------------------*/
6978 /* genOr  - code for or                                            */
6979 /*-----------------------------------------------------------------*/
6980 static void
6981 genOr (iCode * ic, iCode * ifx)
6982 {
6983   operand *left, *right, *result;
6984   int size, offset = 0;
6985   unsigned long lit = 0L;
6986   bool     pushResult;
6987
6988   D (emitcode (";", "genOr "););
6989
6990   AOP_OP_3_NOFATAL (ic, pushResult);
6991   AOP_SET_LOCALS (ic);
6992
6993   if (pushResult)
6994   {
6995       genFarFarLogicOp(ic, "orl");
6996       return;
6997   }
6998
6999
7000 #ifdef DEBUG_TYPE
7001   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7002             AOP_TYPE (result),
7003             AOP_TYPE (left), AOP_TYPE (right));
7004   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7005             AOP_SIZE (result),
7006             AOP_SIZE (left), AOP_SIZE (right));
7007 #endif
7008
7009   /* if left is a literal & right is not then exchange them */
7010   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7011 #ifdef LOGIC_OPS_BROKEN
7012    || AOP_NEEDSACC (left) // I think this is a net loss now.
7013 #endif      
7014       )
7015     {
7016       operand *tmp = right;
7017       right = left;
7018       left = tmp;
7019     }
7020
7021   /* if result = right then exchange them */
7022   if (sameRegs (AOP (result), AOP (right)))
7023     {
7024       operand *tmp = right;
7025       right = left;
7026       left = tmp;
7027     }
7028
7029   /* if right is bit then exchange them */
7030   if (AOP_TYPE (right) == AOP_CRY &&
7031       AOP_TYPE (left) != AOP_CRY)
7032     {
7033       operand *tmp = right;
7034       right = left;
7035       left = tmp;
7036     }
7037   if (AOP_TYPE (right) == AOP_LIT)
7038     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7039
7040   size = AOP_SIZE (result);
7041
7042   // if(bit | yy)
7043   // xx = bit | yy;
7044   if (AOP_TYPE (left) == AOP_CRY)
7045     {
7046       if (AOP_TYPE (right) == AOP_LIT)
7047         {
7048           // c = bit & literal;
7049           if (lit)
7050             {
7051               // lit != 0 => result = 1
7052               if (AOP_TYPE (result) == AOP_CRY)
7053                 {
7054                   if (size)
7055                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7056                   else if (ifx)
7057                     continueIfTrue (ifx);
7058                   goto release;
7059                 }
7060               emitcode ("setb", "c");
7061             }
7062           else
7063             {
7064               // lit == 0 => result = left
7065               if (size && sameRegs (AOP (result), AOP (left)))
7066                 goto release;
7067               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7068             }
7069         }
7070       else
7071         {
7072           if (AOP_TYPE (right) == AOP_CRY)
7073             {
7074               // c = bit | bit;
7075               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7076               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7077             }
7078           else
7079             {
7080               // c = bit | val;
7081               symbol *tlbl = newiTempLabel (NULL);
7082               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7083                 emitcode ("setb", "c");
7084               emitcode ("jb", "%s,!tlabel",
7085                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7086               toBoolean (right);
7087               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7088               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7089                 {
7090                   jmpTrueOrFalse (ifx, tlbl);
7091                   goto release;
7092                 }
7093               else
7094                 {
7095                   CLRC;
7096                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7097                 }
7098             }
7099         }
7100       // bit = c
7101       // val = c
7102       if (size)
7103         outBitC (result);
7104       // if(bit | ...)
7105       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7106            genIfxJump (ifx, "c");
7107       goto release;
7108     }
7109
7110   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7111   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7112   if ((AOP_TYPE (right) == AOP_LIT) &&
7113       (AOP_TYPE (result) == AOP_CRY) &&
7114       (AOP_TYPE (left) != AOP_CRY))
7115     {
7116       if (lit)
7117         {
7118           // result = 1
7119           if (size)
7120             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7121           else
7122             continueIfTrue (ifx);
7123           goto release;
7124         }
7125       else
7126         {
7127           // lit = 0, result = boolean(left)
7128           if (size)
7129             emitcode ("setb", "c");
7130           toBoolean (right);
7131           if (size)
7132             {
7133               symbol *tlbl = newiTempLabel (NULL);
7134               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7135               CLRC;
7136               emitcode ("", "!tlabeldef", tlbl->key + 100);
7137             }
7138           else
7139             {
7140               genIfxJump (ifx, "a");
7141               goto release;
7142             }
7143         }
7144       outBitC (result);
7145       goto release;
7146     }
7147
7148   /* if left is same as result */
7149   if (sameRegs (AOP (result), AOP (left)))
7150     {
7151       for (; size--; offset++)
7152         {
7153           if (AOP_TYPE (right) == AOP_LIT)
7154             {
7155               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7156                 {
7157                   continue;
7158                 }
7159               else
7160                 {
7161                   if (IS_AOP_PREG (left))
7162                     {
7163                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7164                       emitcode ("orl", "a,%s",
7165                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7166                       aopPut (AOP (result), "a", offset);
7167                     }
7168                   else
7169                     {
7170                       emitcode ("orl", "%s,%s",
7171                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7172                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7173                     }
7174                 }
7175             }
7176           else
7177             {
7178               if (AOP_TYPE (left) == AOP_ACC)
7179                 {
7180                   emitcode ("orl", "a,%s",
7181                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7182                 }
7183               else
7184                 {
7185                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7186                   if (IS_AOP_PREG (left))
7187                     {
7188                       emitcode ("orl", "a,%s", 
7189                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7190                       aopPut (AOP (result), "a", offset);
7191                     }
7192                   else
7193                     {
7194                       emitcode ("orl", "%s,a",
7195                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7196                     }
7197                 }
7198             }
7199         }
7200     }
7201   else
7202     {
7203       // left & result in different registers
7204       if (AOP_TYPE (result) == AOP_CRY)
7205         {
7206           // result = bit
7207           // if(size), result in bit
7208           // if(!size && ifx), conditional oper: if(left | right)
7209           symbol *tlbl = newiTempLabel (NULL);
7210           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7211           if (size)
7212             emitcode ("setb", "c");
7213           while (sizer--)
7214             {
7215               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7216                 emitcode ("orl", "a,%s",
7217                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7218               } else {
7219                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7220                 emitcode ("orl", "a,%s",
7221                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7222               }
7223               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7224               offset++;
7225             }
7226           if (size)
7227             {
7228               CLRC;
7229               emitcode ("", "!tlabeldef", tlbl->key + 100);
7230               outBitC (result);
7231             }
7232           else if (ifx)
7233             jmpTrueOrFalse (ifx, tlbl);
7234           else
7235             emitcode ("", "!tlabeldef", tlbl->key + 100);
7236         }
7237       else
7238         {
7239             _startLazyDPSEvaluation();
7240           for (; (size--); offset++)
7241             {
7242               // normal case
7243               // result = left & right
7244               if (AOP_TYPE (right) == AOP_LIT)
7245                 {
7246                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7247                     {
7248                       aopPut (AOP (result),
7249                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7250                               offset);
7251                       continue;
7252                     }
7253                   D (emitcode (";", "better literal OR."););
7254                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7255                   emitcode ("orl", "a, %s",
7256                             aopGet (AOP (right), offset,
7257                                     FALSE, FALSE, DP2_RESULT_REG));
7258
7259                 }
7260               else
7261                 {
7262                   // faster than result <- left, anl result,right
7263                   // and better if result is SFR
7264                   if (AOP_TYPE (left) == AOP_ACC)
7265                     {
7266                       emitcode ("orl", "a,%s",
7267                                 aopGet (AOP (right), offset,
7268                                         FALSE, FALSE, DP2_RESULT_REG));
7269                     }
7270                   else
7271                     {
7272                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7273                         
7274                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7275                       {
7276                           emitcode("mov", "b,a");
7277                           rOp = "b";
7278                       }
7279                         
7280                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7281                       emitcode ("orl", "a,%s", rOp);
7282                     }
7283                 }
7284               aopPut (AOP (result), "a", offset);
7285             }
7286             _endLazyDPSEvaluation();
7287         }
7288     }
7289
7290 release:
7291   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7292   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7293   freeAsmop (result, NULL, ic, TRUE);
7294 }
7295
7296 /*-----------------------------------------------------------------*/
7297 /* genXor - code for xclusive or                                   */
7298 /*-----------------------------------------------------------------*/
7299 static void
7300 genXor (iCode * ic, iCode * ifx)
7301 {
7302   operand *left, *right, *result;
7303   int size, offset = 0;
7304   unsigned long lit = 0L;
7305   bool pushResult;
7306
7307   D (emitcode (";", "genXor "););
7308
7309   AOP_OP_3_NOFATAL (ic, pushResult);
7310   AOP_SET_LOCALS (ic);
7311
7312   if (pushResult)
7313   {
7314       genFarFarLogicOp(ic, "xrl");
7315       return;
7316   }  
7317
7318 #ifdef DEBUG_TYPE
7319   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7320             AOP_TYPE (result),
7321             AOP_TYPE (left), AOP_TYPE (right));
7322   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7323             AOP_SIZE (result),
7324             AOP_SIZE (left), AOP_SIZE (right));
7325 #endif
7326
7327   /* if left is a literal & right is not ||
7328      if left needs acc & right does not */
7329   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
7330 #ifdef LOGIC_OPS_BROKEN      
7331       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7332 #endif
7333      )
7334     {
7335       operand *tmp = right;
7336       right = left;
7337       left = tmp;
7338     }
7339
7340   /* if result = right then exchange them */
7341   if (sameRegs (AOP (result), AOP (right)))
7342     {
7343       operand *tmp = right;
7344       right = left;
7345       left = tmp;
7346     }
7347
7348   /* if right is bit then exchange them */
7349   if (AOP_TYPE (right) == AOP_CRY &&
7350       AOP_TYPE (left) != AOP_CRY)
7351     {
7352       operand *tmp = right;
7353       right = left;
7354       left = tmp;
7355     }
7356   if (AOP_TYPE (right) == AOP_LIT)
7357     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7358
7359   size = AOP_SIZE (result);
7360
7361   // if(bit ^ yy)
7362   // xx = bit ^ yy;
7363   if (AOP_TYPE (left) == AOP_CRY)
7364     {
7365       if (AOP_TYPE (right) == AOP_LIT)
7366         {
7367           // c = bit & literal;
7368           if (lit >> 1)
7369             {
7370               // lit>>1  != 0 => result = 1
7371               if (AOP_TYPE (result) == AOP_CRY)
7372                 {
7373                   if (size)
7374                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7375                   else if (ifx)
7376                     continueIfTrue (ifx);
7377                   goto release;
7378                 }
7379               emitcode ("setb", "c");
7380             }
7381           else
7382             {
7383               // lit == (0 or 1)
7384               if (lit == 0)
7385                 {
7386                   // lit == 0, result = left
7387                   if (size && sameRegs (AOP (result), AOP (left)))
7388                     goto release;
7389                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7390                 }
7391               else
7392                 {
7393                   // lit == 1, result = not(left)
7394                   if (size && sameRegs (AOP (result), AOP (left)))
7395                     {
7396                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7397                       goto release;
7398                     }
7399                   else
7400                     {
7401                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7402                       emitcode ("cpl", "c");
7403                     }
7404                 }
7405             }
7406
7407         }
7408       else
7409         {
7410           // right != literal
7411           symbol *tlbl = newiTempLabel (NULL);
7412           if (AOP_TYPE (right) == AOP_CRY)
7413             {
7414               // c = bit ^ bit;
7415               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7416             }
7417           else
7418             {
7419               int sizer = AOP_SIZE (right);
7420               // c = bit ^ val
7421               // if val>>1 != 0, result = 1
7422               emitcode ("setb", "c");
7423               while (sizer)
7424                 {
7425                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7426                   if (sizer == 1)
7427                     // test the msb of the lsb
7428                     emitcode ("anl", "a,#!constbyte",0xfe);
7429                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7430                   sizer--;
7431                 }
7432               // val = (0,1)
7433               emitcode ("rrc", "a");
7434             }
7435           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7436           emitcode ("cpl", "c");
7437           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7438         }
7439       // bit = c
7440       // val = c
7441       if (size)
7442         outBitC (result);
7443       // if(bit | ...)
7444       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7445         genIfxJump (ifx, "c");
7446       goto release;
7447     }
7448
7449   if (sameRegs (AOP (result), AOP (left)))
7450     {
7451       /* if left is same as result */
7452       for (; size--; offset++)
7453         {
7454           if (AOP_TYPE (right) == AOP_LIT)
7455             {
7456               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7457                 continue;
7458               else if (IS_AOP_PREG (left))
7459                 {
7460                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7461                   emitcode ("xrl", "a,%s",
7462                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7463                   aopPut (AOP (result), "a", offset);
7464                 }
7465               else
7466                 emitcode ("xrl", "%s,%s",
7467                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7468                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7469             }
7470           else
7471             {
7472               if (AOP_TYPE (left) == AOP_ACC)
7473                 emitcode ("xrl", "a,%s",
7474                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7475               else
7476                 {
7477                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7478                   if (IS_AOP_PREG (left))
7479                     {
7480                       emitcode ("xrl", "a,%s",
7481                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7482                       aopPut (AOP (result), "a", offset);
7483                     }
7484                   else
7485                     emitcode ("xrl", "%s,a",
7486                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7487                 }
7488             }
7489         }
7490     }
7491   else
7492     {
7493       // left & result in different registers
7494       if (AOP_TYPE (result) == AOP_CRY)
7495         {
7496           // result = bit
7497           // if(size), result in bit
7498           // if(!size && ifx), conditional oper: if(left ^ right)
7499           symbol *tlbl = newiTempLabel (NULL);
7500           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7501                   
7502           if (size)
7503             emitcode ("setb", "c");
7504           while (sizer--)
7505             {
7506               if ((AOP_TYPE (right) == AOP_LIT) &&
7507                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7508                 {
7509                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7510                 }
7511               else
7512                 {
7513                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7514                     emitcode ("xrl", "a,%s",
7515                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7516                   } else {
7517                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7518                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7519                       {
7520                           emitcode("mov", "b,a");
7521                           rOp = "b";
7522                       }
7523                         
7524                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7525                       emitcode ("xrl", "a,%s", rOp);                  
7526                   }
7527                 }
7528               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7529               offset++;
7530             }
7531           if (size)
7532             {
7533               CLRC;
7534               emitcode ("", "!tlabeldef", tlbl->key + 100);
7535               outBitC (result);
7536             }
7537           else if (ifx)
7538             jmpTrueOrFalse (ifx, tlbl);
7539         }
7540       else
7541         {
7542         for (; (size--); offset++)
7543           {
7544             // normal case
7545             // result = left & right
7546             if (AOP_TYPE (right) == AOP_LIT)
7547               {
7548                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7549                   {
7550                     aopPut (AOP (result),
7551                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7552                             offset);
7553                     continue;
7554                   }
7555                 D (emitcode (";", "better literal XOR."););
7556                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7557                 emitcode ("xrl", "a, %s",
7558                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7559               }
7560             else
7561               {
7562                 // faster than result <- left, anl result,right
7563                 // and better if result is SFR
7564                 if (AOP_TYPE (left) == AOP_ACC)
7565                   {
7566                     emitcode ("xrl", "a,%s",
7567                               aopGet (AOP (right), offset,
7568                                       FALSE, FALSE, DP2_RESULT_REG));
7569                   }
7570                 else
7571                   {
7572                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7573                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7574                       {
7575                           emitcode("mov", "b,a");
7576                           rOp = "b";
7577                       }
7578                         
7579                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7580                       emitcode ("xrl", "a,%s", rOp);
7581                   }
7582               }
7583             aopPut (AOP (result), "a", offset);
7584           }
7585         }
7586         
7587     }
7588
7589 release:
7590   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7591   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7592   freeAsmop (result, NULL, ic, TRUE);
7593 }
7594
7595 /*-----------------------------------------------------------------*/
7596 /* genInline - write the inline code out                           */
7597 /*-----------------------------------------------------------------*/
7598 static void
7599 genInline (iCode * ic)
7600 {
7601   char *buffer, *bp, *bp1;
7602
7603   D (emitcode (";", "genInline "); );
7604
7605   _G.inLine += (!options.asmpeep);
7606
7607   buffer = Safe_strdup(IC_INLINE(ic));
7608   bp = buffer;
7609   bp1 = buffer;
7610
7611   /* emit each line as a code */
7612   while (*bp)
7613     {
7614       if (*bp == '\n')
7615         {
7616           *bp++ = '\0';
7617           emitcode (bp1, "");
7618           bp1 = bp;
7619         }
7620       else
7621         {
7622           if (*bp == ':')
7623             {
7624               bp++;
7625               *bp = '\0';
7626               bp++;
7627               emitcode (bp1, "");
7628               bp1 = bp;
7629             }
7630           else
7631             bp++;
7632         }
7633     }
7634   if (bp1 != bp)
7635     emitcode (bp1, "");
7636   /*     emitcode("",buffer); */
7637   _G.inLine -= (!options.asmpeep);
7638 }
7639
7640 /*-----------------------------------------------------------------*/
7641 /* genRRC - rotate right with carry                                */
7642 /*-----------------------------------------------------------------*/
7643 static void
7644 genRRC (iCode * ic)
7645 {
7646   operand *left, *result;
7647   int     size, offset;
7648
7649   D (emitcode (";", "genRRC "););
7650
7651   /* rotate right with carry */
7652   left = IC_LEFT (ic);
7653   result = IC_RESULT (ic);
7654   aopOp (left, ic, FALSE, FALSE);
7655   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7656
7657   /* move it to the result */
7658   size = AOP_SIZE (result);
7659   offset = size - 1;
7660   CLRC;
7661
7662   _startLazyDPSEvaluation ();
7663   while (size--)
7664     {
7665       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7666       emitcode ("rrc", "a");
7667       if (AOP_SIZE (result) > 1)
7668         aopPut (AOP (result), "a", offset--);
7669     }
7670   _endLazyDPSEvaluation ();
7671
7672   /* now we need to put the carry into the
7673      highest order byte of the result */
7674   if (AOP_SIZE (result) > 1)
7675     {
7676       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7677     }
7678   emitcode ("mov", "acc.7,c");
7679   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7680   freeAsmop (left, NULL, ic, TRUE);
7681   freeAsmop (result, NULL, ic, TRUE);
7682 }
7683
7684 /*-----------------------------------------------------------------*/
7685 /* genRLC - generate code for rotate left with carry               */
7686 /*-----------------------------------------------------------------*/
7687 static void
7688 genRLC (iCode * ic)
7689 {
7690   operand *left, *result;
7691   int size, offset;
7692   char *l;
7693
7694   D (emitcode (";", "genRLC "););
7695
7696   /* rotate right with carry */
7697   left = IC_LEFT (ic);
7698   result = IC_RESULT (ic);
7699   aopOp (left, ic, FALSE, FALSE);
7700   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7701
7702   /* move it to the result */
7703   size = AOP_SIZE (result);
7704   offset = 0;
7705   if (size--)
7706     {
7707       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7708       MOVA (l);
7709       emitcode ("add", "a,acc");
7710       if (AOP_SIZE (result) > 1)
7711         {
7712           aopPut (AOP (result), "a", offset++);
7713         }
7714
7715       _startLazyDPSEvaluation ();
7716       while (size--)
7717         {
7718           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7719           MOVA (l);
7720           emitcode ("rlc", "a");
7721           if (AOP_SIZE (result) > 1)
7722             aopPut (AOP (result), "a", offset++);
7723         }
7724       _endLazyDPSEvaluation ();
7725     }
7726   /* now we need to put the carry into the
7727      highest order byte of the result */
7728   if (AOP_SIZE (result) > 1)
7729     {
7730       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7731       MOVA (l);
7732     }
7733   emitcode ("mov", "acc.0,c");
7734   aopPut (AOP (result), "a", 0);
7735   freeAsmop (left, NULL, ic, TRUE);
7736   freeAsmop (result, NULL, ic, TRUE);
7737 }
7738
7739 /*-----------------------------------------------------------------*/
7740 /* genGetHbit - generates code get highest order bit               */
7741 /*-----------------------------------------------------------------*/
7742 static void
7743 genGetHbit (iCode * ic)
7744 {
7745   operand *left, *result;
7746   left = IC_LEFT (ic);
7747   result = IC_RESULT (ic);
7748   aopOp (left, ic, FALSE, FALSE);
7749   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7750
7751   D (emitcode (";", "genGetHbit "););
7752
7753   /* get the highest order byte into a */
7754   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7755   if (AOP_TYPE (result) == AOP_CRY)
7756     {
7757       emitcode ("rlc", "a");
7758       outBitC (result);
7759     }
7760   else
7761     {
7762       emitcode ("rl", "a");
7763       emitcode ("anl", "a,#1");
7764       outAcc (result);
7765     }
7766
7767
7768   freeAsmop (left, NULL, ic, TRUE);
7769   freeAsmop (result, NULL, ic, TRUE);
7770 }
7771
7772 /*-----------------------------------------------------------------*/
7773 /* genSwap - generates code to swap nibbles or bytes               */
7774 /*-----------------------------------------------------------------*/
7775 static void
7776 genSwap (iCode * ic)
7777 {
7778   operand *left, *result;
7779
7780   D(emitcode (";     genSwap",""));
7781
7782   left = IC_LEFT (ic);
7783   result = IC_RESULT (ic);
7784   aopOp (left, ic, FALSE, FALSE);
7785   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7786   
7787   _startLazyDPSEvaluation ();
7788   switch (AOP_SIZE (left))
7789     {
7790     case 1: /* swap nibbles in byte */
7791       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7792       emitcode ("swap", "a");
7793       aopPut (AOP (result), "a", 0);
7794       break;
7795     case 2: /* swap bytes in word */
7796       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7797         {
7798           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7799           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7800           aopPut (AOP (result), "a", 1);
7801         }
7802       else if (operandsEqu (left, result))
7803         {
7804           char * reg = "a";
7805           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7806           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7807             {
7808               emitcode ("mov", "b,a");
7809               reg = "b";
7810               _G.bInUse=1;
7811             }
7812           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7813           aopPut (AOP (result), reg, 1);
7814           _G.bInUse=0;
7815         }
7816       else
7817         {
7818           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7819           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7820         }
7821       break;
7822     default:
7823       wassertl(FALSE, "unsupported SWAP operand size");
7824     }
7825   _endLazyDPSEvaluation ();
7826   
7827   freeAsmop (left, NULL, ic, TRUE);
7828   freeAsmop (result, NULL, ic, TRUE);
7829 }
7830
7831 /*-----------------------------------------------------------------*/
7832 /* AccRol - rotate left accumulator by known count                 */
7833 /*-----------------------------------------------------------------*/
7834 static void
7835 AccRol (int shCount)
7836 {
7837   shCount &= 0x0007;            // shCount : 0..7
7838
7839   switch (shCount)
7840     {
7841     case 0:
7842       break;
7843     case 1:
7844       emitcode ("rl", "a");
7845       break;
7846     case 2:
7847       emitcode ("rl", "a");
7848       emitcode ("rl", "a");
7849       break;
7850     case 3:
7851       emitcode ("swap", "a");
7852       emitcode ("rr", "a");
7853       break;
7854     case 4:
7855       emitcode ("swap", "a");
7856       break;
7857     case 5:
7858       emitcode ("swap", "a");
7859       emitcode ("rl", "a");
7860       break;
7861     case 6:
7862       emitcode ("rr", "a");
7863       emitcode ("rr", "a");
7864       break;
7865     case 7:
7866       emitcode ("rr", "a");
7867       break;
7868     }
7869 }
7870
7871 /*-----------------------------------------------------------------*/
7872 /* AccLsh - left shift accumulator by known count                  */
7873 /*-----------------------------------------------------------------*/
7874 static void
7875 AccLsh (int shCount)
7876 {
7877   if (shCount != 0)
7878     {
7879       if (shCount == 1)
7880         emitcode ("add", "a,acc");
7881       else if (shCount == 2)
7882         {
7883           emitcode ("add", "a,acc");
7884           emitcode ("add", "a,acc");
7885         }
7886       else
7887         {
7888           /* rotate left accumulator */
7889           AccRol (shCount);
7890           /* and kill the lower order bits */
7891           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7892         }
7893     }
7894 }
7895
7896 /*-----------------------------------------------------------------*/
7897 /* AccRsh - right shift accumulator by known count                 */
7898 /*-----------------------------------------------------------------*/
7899 static void
7900 AccRsh (int shCount)
7901 {
7902   if (shCount != 0)
7903     {
7904       if (shCount == 1)
7905         {
7906           CLRC;
7907           emitcode ("rrc", "a");
7908         }
7909       else
7910         {
7911           /* rotate right accumulator */
7912           AccRol (8 - shCount);
7913           /* and kill the higher order bits */
7914           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7915         }
7916     }
7917 }
7918
7919 #ifdef BETTER_LITERAL_SHIFT
7920 /*-----------------------------------------------------------------*/
7921 /* AccSRsh - signed right shift accumulator by known count                 */
7922 /*-----------------------------------------------------------------*/
7923 static void
7924 AccSRsh (int shCount)
7925 {
7926   symbol *tlbl;
7927   if (shCount != 0)
7928     {
7929       if (shCount == 1)
7930         {
7931           emitcode ("mov", "c,acc.7");
7932           emitcode ("rrc", "a");
7933         }
7934       else if (shCount == 2)
7935         {
7936           emitcode ("mov", "c,acc.7");
7937           emitcode ("rrc", "a");
7938           emitcode ("mov", "c,acc.7");
7939           emitcode ("rrc", "a");
7940         }
7941       else
7942         {
7943           tlbl = newiTempLabel (NULL);
7944           /* rotate right accumulator */
7945           AccRol (8 - shCount);
7946           /* and kill the higher order bits */
7947           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7948           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7949           emitcode ("orl", "a,#!constbyte",
7950                     (unsigned char) ~SRMask[shCount]);
7951           emitcode ("", "!tlabeldef", tlbl->key + 100);
7952         }
7953     }
7954 }
7955 #endif
7956
7957 #ifdef BETTER_LITERAL_SHIFT
7958 /*-----------------------------------------------------------------*/
7959 /* shiftR1Left2Result - shift right one byte from left to result   */
7960 /*-----------------------------------------------------------------*/
7961 static void
7962 shiftR1Left2Result (operand * left, int offl,
7963                     operand * result, int offr,
7964                     int shCount, int sign)
7965 {
7966   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7967   /* shift right accumulator */
7968   if (sign)
7969     AccSRsh (shCount);
7970   else
7971     AccRsh (shCount);
7972   aopPut (AOP (result), "a", offr);
7973 }
7974 #endif
7975
7976 #ifdef BETTER_LITERAL_SHIFT
7977 /*-----------------------------------------------------------------*/
7978 /* shiftL1Left2Result - shift left one byte from left to result    */
7979 /*-----------------------------------------------------------------*/
7980 static void
7981 shiftL1Left2Result (operand * left, int offl,
7982                     operand * result, int offr, int shCount)
7983 {
7984   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7985   /* shift left accumulator */
7986   AccLsh (shCount);
7987   aopPut (AOP (result), "a", offr);
7988 }
7989 #endif
7990
7991 #ifdef BETTER_LITERAL_SHIFT
7992 /*-----------------------------------------------------------------*/
7993 /* movLeft2Result - move byte from left to result                  */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 movLeft2Result (operand * left, int offl,
7997                 operand * result, int offr, int sign)
7998 {
7999   char *l;
8000   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8001   {
8002       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8003
8004       if (*l == '@' && (IS_AOP_PREG (result)))
8005       {
8006           emitcode ("mov", "a,%s", l);
8007           aopPut (AOP (result), "a", offr);
8008       }
8009       else
8010       {
8011           if (!sign)
8012           {
8013             aopPut (AOP (result), l, offr);
8014           }
8015           else
8016             {
8017               /* MSB sign in acc.7 ! */
8018               if (getDataSize (left) == offl + 1)
8019                 {
8020                   emitcode ("mov", "a,%s", l);
8021                   aopPut (AOP (result), "a", offr);
8022                 }
8023             }
8024       }
8025   }
8026 }
8027 #endif
8028
8029 #ifdef BETTER_LITERAL_SHIFT
8030 /*-----------------------------------------------------------------*/
8031 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8032 /*-----------------------------------------------------------------*/
8033 static void
8034 AccAXRrl1 (char *x)
8035 {
8036   emitcode ("rrc", "a");
8037   emitcode ("xch", "a,%s", x);
8038   emitcode ("rrc", "a");
8039   emitcode ("xch", "a,%s", x);
8040 }
8041 #endif
8042
8043 #ifdef BETTER_LITERAL_SHIFT
8044 //REMOVE ME!!!
8045 /*-----------------------------------------------------------------*/
8046 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8047 /*-----------------------------------------------------------------*/
8048 static void
8049 AccAXLrl1 (char *x)
8050 {
8051   emitcode ("xch", "a,%s", x);
8052   emitcode ("rlc", "a");
8053   emitcode ("xch", "a,%s", x);
8054   emitcode ("rlc", "a");
8055 }
8056 #endif
8057
8058 #ifdef BETTER_LITERAL_SHIFT
8059 /*-----------------------------------------------------------------*/
8060 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8061 /*-----------------------------------------------------------------*/
8062 static void
8063 AccAXLsh1 (char *x)
8064 {
8065   emitcode ("xch", "a,%s", x);
8066   emitcode ("add", "a,acc");
8067   emitcode ("xch", "a,%s", x);
8068   emitcode ("rlc", "a");
8069 }
8070 #endif
8071
8072 #ifdef BETTER_LITERAL_SHIFT
8073 /*-----------------------------------------------------------------*/
8074 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8075 /*-----------------------------------------------------------------*/
8076 static void
8077 AccAXLsh (char *x, int shCount)
8078 {
8079   switch (shCount)
8080     {
8081     case 0:
8082       break;
8083     case 1:
8084       AccAXLsh1 (x);
8085       break;
8086     case 2:
8087       AccAXLsh1 (x);
8088       AccAXLsh1 (x);
8089       break;
8090     case 3:
8091     case 4:
8092     case 5:                     // AAAAABBB:CCCCCDDD
8093
8094       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8095
8096       emitcode ("anl", "a,#!constbyte",
8097                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8098
8099       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8100
8101       AccRol (shCount);         // DDDCCCCC:BBB00000
8102
8103       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8104
8105       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8106
8107       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8108
8109       emitcode ("anl", "a,#!constbyte",
8110                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8111
8112       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8113
8114       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8115
8116       break;
8117     case 6:                     // AAAAAABB:CCCCCCDD
8118       emitcode ("anl", "a,#!constbyte",
8119                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8120       emitcode ("mov", "c,acc.0");      // c = B
8121       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8122 #if 0
8123       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8124       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8125 #else
8126       emitcode("rrc","a"); 
8127       emitcode("xch","a,%s", x); 
8128       emitcode("rrc","a"); 
8129       emitcode("mov","c,acc.0"); //<< get correct bit 
8130       emitcode("xch","a,%s", x); 
8131
8132       emitcode("rrc","a"); 
8133       emitcode("xch","a,%s", x); 
8134       emitcode("rrc","a"); 
8135       emitcode("xch","a,%s", x); 
8136 #endif
8137       break;
8138     case 7:                     // a:x <<= 7
8139
8140       emitcode ("anl", "a,#!constbyte",
8141                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8142
8143       emitcode ("mov", "c,acc.0");      // c = B
8144
8145       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8146
8147       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8148
8149       break;
8150     default:
8151       break;
8152     }
8153 }
8154 #endif
8155
8156 #ifdef BETTER_LITERAL_SHIFT
8157 //REMOVE ME!!!
8158 /*-----------------------------------------------------------------*/
8159 /* AccAXRsh - right shift a:x known count (0..7)                   */
8160 /*-----------------------------------------------------------------*/
8161 static void
8162 AccAXRsh (char *x, int shCount)
8163 {
8164   switch (shCount)
8165     {
8166     case 0:
8167       break;
8168     case 1:
8169       CLRC;
8170       AccAXRrl1 (x);            // 0->a:x
8171
8172       break;
8173     case 2:
8174       CLRC;
8175       AccAXRrl1 (x);            // 0->a:x
8176
8177       CLRC;
8178       AccAXRrl1 (x);            // 0->a:x
8179
8180       break;
8181     case 3:
8182     case 4:
8183     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8184
8185       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8186
8187       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8188
8189       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8190
8191       emitcode ("anl", "a,#!constbyte",
8192                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8193
8194       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8195
8196       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8197
8198       emitcode ("anl", "a,#!constbyte",
8199                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8200
8201       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8202
8203       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8204
8205       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8206
8207       break;
8208     case 6:                     // AABBBBBB:CCDDDDDD
8209
8210       emitcode ("mov", "c,acc.7");
8211       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8212
8213       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8214
8215       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8216
8217       emitcode ("anl", "a,#!constbyte",
8218                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8219
8220       break;
8221     case 7:                     // ABBBBBBB:CDDDDDDD
8222
8223       emitcode ("mov", "c,acc.7");      // c = A
8224
8225       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8226
8227       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8228
8229       emitcode ("anl", "a,#!constbyte",
8230                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8231
8232       break;
8233     default:
8234       break;
8235     }
8236 }
8237 #endif
8238
8239 #ifdef BETTER_LITERAL_SHIFT
8240 /*-----------------------------------------------------------------*/
8241 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8242 /*-----------------------------------------------------------------*/
8243 static void
8244 AccAXRshS (char *x, int shCount)
8245 {
8246   symbol *tlbl;
8247   switch (shCount)
8248     {
8249     case 0:
8250       break;
8251     case 1:
8252       emitcode ("mov", "c,acc.7");
8253       AccAXRrl1 (x);            // s->a:x
8254
8255       break;
8256     case 2:
8257       emitcode ("mov", "c,acc.7");
8258       AccAXRrl1 (x);            // s->a:x
8259
8260       emitcode ("mov", "c,acc.7");
8261       AccAXRrl1 (x);            // s->a:x
8262
8263       break;
8264     case 3:
8265     case 4:
8266     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8267
8268       tlbl = newiTempLabel (NULL);
8269       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8270
8271       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8272
8273       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8274
8275       emitcode ("anl", "a,#!constbyte",
8276                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8277
8278       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8279
8280       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8281
8282       emitcode ("anl", "a,#!constbyte",
8283                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8284
8285       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8286
8287       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8288
8289       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8290
8291       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8292       emitcode ("orl", "a,#!constbyte",
8293                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8294
8295       emitcode ("", "!tlabeldef", tlbl->key + 100);
8296       break;                    // SSSSAAAA:BBBCCCCC
8297
8298     case 6:                     // AABBBBBB:CCDDDDDD
8299
8300       tlbl = newiTempLabel (NULL);
8301       emitcode ("mov", "c,acc.7");
8302       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8303
8304       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8305
8306       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8307
8308       emitcode ("anl", "a,#!constbyte",
8309                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8310
8311       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8312       emitcode ("orl", "a,#!constbyte",
8313                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8314
8315       emitcode ("", "!tlabeldef", tlbl->key + 100);
8316       break;
8317     case 7:                     // ABBBBBBB:CDDDDDDD
8318
8319       tlbl = newiTempLabel (NULL);
8320       emitcode ("mov", "c,acc.7");      // c = A
8321
8322       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8323
8324       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8325
8326       emitcode ("anl", "a,#!constbyte",
8327                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8328
8329       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8330       emitcode ("orl", "a,#!constbyte",
8331                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8332
8333       emitcode ("", "!tlabeldef", tlbl->key + 100);
8334       break;
8335     default:
8336       break;
8337     }
8338 }
8339 #endif
8340
8341 #ifdef BETTER_LITERAL_SHIFT
8342 static void
8343 _loadLeftIntoAx(char    **lsb, 
8344                 operand *left, 
8345                 operand *result,
8346                 int     offl,
8347                 int     offr)
8348 {
8349   // Get the initial value from left into a pair of registers.
8350   // MSB must be in A, LSB can be any register.
8351   //
8352   // If the result is held in registers, it is an optimization
8353   // if the LSB can be held in the register which will hold the,
8354   // result LSB since this saves us from having to copy it into
8355   // the result following AccAXLsh.
8356   //
8357   // If the result is addressed indirectly, this is not a gain.
8358   if (AOP_NEEDSACC(result))
8359   {
8360        char *leftByte;
8361        
8362        _startLazyDPSEvaluation();
8363       if (AOP_TYPE(left) == AOP_DPTR2)
8364        {
8365            // Get MSB in A.
8366            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8367            // get LSB in DP2_RESULT_REG.
8368            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8369            assert(!strcmp(leftByte, DP2_RESULT_REG));
8370        }
8371        else
8372        {
8373            // get LSB into DP2_RESULT_REG
8374            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8375            if (strcmp(leftByte, DP2_RESULT_REG))
8376            {
8377                TR_AP("#7");
8378                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8379            }
8380            // And MSB in A.
8381            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8382            assert(strcmp(leftByte, DP2_RESULT_REG));
8383            MOVA(leftByte);
8384        }
8385        _endLazyDPSEvaluation();
8386        *lsb = DP2_RESULT_REG;
8387   }
8388   else
8389   {
8390       if (sameRegs (AOP (result), AOP (left)) &&
8391         ((offl + MSB16) == offr))
8392       {
8393           /* don't crash result[offr] */
8394           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8395           emitcode ("xch", "a,%s", 
8396                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8397       }
8398       else
8399       {
8400           movLeft2Result (left, offl, result, offr, 0);
8401           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8402       }
8403       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8404       assert(strcmp(*lsb,"a"));      
8405   }
8406 }
8407
8408 static void
8409 _storeAxResults(char    *lsb,
8410                 operand *result,
8411                 int     offr)
8412 {
8413   _startLazyDPSEvaluation();
8414   if (AOP_NEEDSACC(result))
8415   {
8416       /* We have to explicitly update the result LSB.
8417        */
8418       emitcode("xch","a,%s", lsb);
8419       aopPut(AOP(result), "a", offr);
8420       emitcode("mov","a,%s", lsb);
8421   }
8422   if (getDataSize (result) > 1)
8423   {
8424       aopPut (AOP (result), "a", offr + MSB16);
8425   }
8426   _endLazyDPSEvaluation();
8427 }
8428
8429 /*-----------------------------------------------------------------*/
8430 /* shiftL2Left2Result - shift left two bytes from left to result   */
8431 /*-----------------------------------------------------------------*/
8432 static void
8433 shiftL2Left2Result (operand * left, int offl,
8434                     operand * result, int offr, int shCount)
8435 {
8436   char *lsb;
8437
8438   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8439   
8440   AccAXLsh (lsb, shCount);
8441   
8442   _storeAxResults(lsb, result, offr);
8443 }
8444 #endif
8445
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* shiftR2Left2Result - shift right two bytes from left to result  */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 shiftR2Left2Result (operand * left, int offl,
8452                     operand * result, int offr,
8453                     int shCount, int sign)
8454 {
8455   char *lsb;
8456   
8457   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8458   
8459   /* a:x >> shCount (x = lsb(result)) */
8460   if (sign)
8461   {
8462      AccAXRshS(lsb, shCount);
8463   }
8464   else
8465   {
8466     AccAXRsh(lsb, shCount);
8467   }
8468   
8469   _storeAxResults(lsb, result, offr);
8470 }
8471 #endif
8472
8473 /*-----------------------------------------------------------------*/
8474 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8475 /*-----------------------------------------------------------------*/
8476 static void
8477 shiftLLeftOrResult (operand * left, int offl,
8478                     operand * result, int offr, int shCount)
8479 {
8480   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8481   /* shift left accumulator */
8482   AccLsh (shCount);
8483   /* or with result */
8484   emitcode ("orl", "a,%s",
8485             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8486   /* back to result */
8487   aopPut (AOP (result), "a", offr);
8488 }
8489
8490 #if 0
8491 //REMOVE ME!!!
8492 /*-----------------------------------------------------------------*/
8493 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8494 /*-----------------------------------------------------------------*/
8495 static void
8496 shiftRLeftOrResult (operand * left, int offl,
8497                     operand * result, int offr, int shCount)
8498 {
8499   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8500   /* shift right accumulator */
8501   AccRsh (shCount);
8502   /* or with result */
8503   emitcode ("orl", "a,%s",
8504             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8505   /* back to result */
8506   aopPut (AOP (result), "a", offr);
8507 }
8508 #endif
8509
8510 #ifdef BETTER_LITERAL_SHIFT
8511 /*-----------------------------------------------------------------*/
8512 /* genlshOne - left shift a one byte quantity by known count       */
8513 /*-----------------------------------------------------------------*/
8514 static void
8515 genlshOne (operand * result, operand * left, int shCount)
8516 {
8517   D (emitcode (";", "genlshOne "););
8518   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8519 }
8520 #endif
8521
8522 #ifdef BETTER_LITERAL_SHIFT
8523 /*-----------------------------------------------------------------*/
8524 /* genlshTwo - left shift two bytes by known amount != 0           */
8525 /*-----------------------------------------------------------------*/
8526 static void
8527 genlshTwo (operand * result, operand * left, int shCount)
8528 {
8529   int size;
8530
8531   D (emitcode (";", "genlshTwo "););
8532
8533   size = getDataSize (result);
8534
8535   /* if shCount >= 8 */
8536   if (shCount >= 8)
8537   {
8538       shCount -= 8;
8539
8540       _startLazyDPSEvaluation();
8541
8542       if (size > 1)
8543         {
8544           if (shCount)
8545           {
8546             _endLazyDPSEvaluation();
8547             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8548             aopPut (AOP (result), zero, LSB);       
8549           }
8550           else
8551           {
8552             movLeft2Result (left, LSB, result, MSB16, 0);
8553             aopPut (AOP (result), zero, LSB);
8554             _endLazyDPSEvaluation();
8555           }
8556         }
8557         else
8558         {
8559           aopPut (AOP (result), zero, LSB);
8560           _endLazyDPSEvaluation();
8561         }
8562   }
8563
8564   /*  1 <= shCount <= 7 */
8565   else
8566     {
8567       if (size == 1)
8568       {
8569         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8570       }
8571       else
8572       {
8573         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8574       }
8575     }
8576 }
8577 #endif
8578
8579 #if 0
8580 //REMOVE ME!!!
8581 /*-----------------------------------------------------------------*/
8582 /* shiftLLong - shift left one long from left to result            */
8583 /* offl = LSB or MSB16                                             */
8584 /*-----------------------------------------------------------------*/
8585 static void
8586 shiftLLong (operand * left, operand * result, int offr)
8587 {
8588   char *l;
8589   int size = AOP_SIZE (result);
8590
8591   if (size >= LSB + offr)
8592     {
8593       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8594       MOVA (l);
8595       emitcode ("add", "a,acc");
8596       if (sameRegs (AOP (left), AOP (result)) &&
8597           size >= MSB16 + offr && offr != LSB)
8598         emitcode ("xch", "a,%s",
8599                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8600       else
8601         aopPut (AOP (result), "a", LSB + offr);
8602     }
8603
8604   if (size >= MSB16 + offr)
8605     {
8606       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8607         {
8608           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8609         }
8610       emitcode ("rlc", "a");
8611       if (sameRegs (AOP (left), AOP (result)) &&
8612           size >= MSB24 + offr && offr != LSB)
8613         emitcode ("xch", "a,%s",
8614                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8615       else
8616         aopPut (AOP (result), "a", MSB16 + offr);
8617     }
8618
8619   if (size >= MSB24 + offr)
8620     {
8621       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8622         {
8623           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8624         }
8625       emitcode ("rlc", "a");
8626       if (sameRegs (AOP (left), AOP (result)) &&
8627           size >= MSB32 + offr && offr != LSB)
8628         emitcode ("xch", "a,%s",
8629                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8630       else
8631         aopPut (AOP (result), "a", MSB24 + offr);
8632     }
8633
8634   if (size > MSB32 + offr)
8635     {
8636       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8637         {
8638           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8639         }
8640       emitcode ("rlc", "a");
8641       aopPut (AOP (result), "a", MSB32 + offr);
8642     }
8643   if (offr != LSB)
8644     aopPut (AOP (result), zero, LSB);
8645 }
8646 #endif
8647
8648 #if 0
8649 //REMOVE ME!!!
8650 /*-----------------------------------------------------------------*/
8651 /* genlshFour - shift four byte by a known amount != 0             */
8652 /*-----------------------------------------------------------------*/
8653 static void
8654 genlshFour (operand * result, operand * left, int shCount)
8655 {
8656   int size;
8657
8658   D (emitcode (";", "genlshFour ");
8659     );
8660
8661   size = AOP_SIZE (result);
8662
8663   /* if shifting more that 3 bytes */
8664   if (shCount >= 24)
8665     {
8666       shCount -= 24;
8667       if (shCount)
8668         /* lowest order of left goes to the highest
8669            order of the destination */
8670         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8671       else
8672         movLeft2Result (left, LSB, result, MSB32, 0);
8673       aopPut (AOP (result), zero, LSB);
8674       aopPut (AOP (result), zero, MSB16);
8675       aopPut (AOP (result), zero, MSB24);
8676       return;
8677     }
8678
8679   /* more than two bytes */
8680   else if (shCount >= 16)
8681     {
8682       /* lower order two bytes goes to higher order two bytes */
8683       shCount -= 16;
8684       /* if some more remaining */
8685       if (shCount)
8686         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8687       else
8688         {
8689           movLeft2Result (left, MSB16, result, MSB32, 0);
8690           movLeft2Result (left, LSB, result, MSB24, 0);
8691         }
8692       aopPut (AOP (result), zero, MSB16);
8693       aopPut (AOP (result), zero, LSB);
8694       return;
8695     }
8696
8697   /* if more than 1 byte */
8698   else if (shCount >= 8)
8699     {
8700       /* lower order three bytes goes to higher order  three bytes */
8701       shCount -= 8;
8702       if (size == 2)
8703         {
8704           if (shCount)
8705             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8706           else
8707             movLeft2Result (left, LSB, result, MSB16, 0);
8708         }
8709       else
8710         {                       /* size = 4 */
8711           if (shCount == 0)
8712             {
8713               movLeft2Result (left, MSB24, result, MSB32, 0);
8714               movLeft2Result (left, MSB16, result, MSB24, 0);
8715               movLeft2Result (left, LSB, result, MSB16, 0);
8716               aopPut (AOP (result), zero, LSB);
8717             }
8718           else if (shCount == 1)
8719             shiftLLong (left, result, MSB16);
8720           else
8721             {
8722               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8723               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8724               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8725               aopPut (AOP (result), zero, LSB);
8726             }
8727         }
8728     }
8729
8730   /* 1 <= shCount <= 7 */
8731   else if (shCount <= 2)
8732     {
8733       shiftLLong (left, result, LSB);
8734       if (shCount == 2)
8735         shiftLLong (result, result, LSB);
8736     }
8737   /* 3 <= shCount <= 7, optimize */
8738   else
8739     {
8740       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8741       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8742       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8743     }
8744 }
8745 #endif
8746
8747 #ifdef BETTER_LITERAL_SHIFT
8748 /*-----------------------------------------------------------------*/
8749 /* genLeftShiftLiteral - left shifting by known count              */
8750 /*-----------------------------------------------------------------*/
8751 static bool
8752 genLeftShiftLiteral (operand * left,
8753                      operand * right,
8754                      operand * result,
8755                      iCode * ic)
8756 {
8757   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8758   int size;
8759
8760   size = getSize (operandType (result));
8761
8762   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8763
8764   /* We only handle certain easy cases so far. */
8765   if ((shCount != 0)
8766    && (shCount < (size * 8))
8767    && (size != 1)
8768    && (size != 2))
8769   {
8770       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8771       return FALSE;
8772   }
8773
8774   freeAsmop (right, NULL, ic, TRUE);
8775
8776   aopOp(left, ic, FALSE, FALSE);
8777   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8778
8779 #if 0 // debug spew
8780   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8781   {
8782         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8783         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8784         {
8785            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8786         }
8787   }
8788   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8789   {
8790         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8791         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8792         {
8793            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8794         }       
8795   }  
8796 #endif
8797   
8798 #if VIEW_SIZE
8799   emitcode ("; shift left ", "result %d, left %d", size,
8800             AOP_SIZE (left));
8801 #endif
8802
8803   /* I suppose that the left size >= result size */
8804   if (shCount == 0)
8805   {
8806         _startLazyDPSEvaluation();
8807         while (size--)
8808         {
8809           movLeft2Result (left, size, result, size, 0);
8810         }
8811         _endLazyDPSEvaluation();
8812   }
8813   else if (shCount >= (size * 8))
8814   {
8815     _startLazyDPSEvaluation();
8816     while (size--)
8817     {
8818       aopPut (AOP (result), zero, size);
8819     }
8820     _endLazyDPSEvaluation();
8821   }
8822   else
8823   {
8824       switch (size)
8825         {
8826         case 1:
8827           genlshOne (result, left, shCount);
8828           break;
8829
8830         case 2:
8831           genlshTwo (result, left, shCount);
8832           break;
8833 #if 0
8834         case 4:
8835           genlshFour (result, left, shCount);
8836           break;
8837 #endif
8838         default:
8839           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8840           break;
8841         }
8842     }
8843   freeAsmop (left, NULL, ic, TRUE);
8844   freeAsmop (result, NULL, ic, TRUE);
8845   return TRUE;
8846 }
8847 #endif
8848
8849 /*-----------------------------------------------------------------*/
8850 /* genLeftShift - generates code for left shifting                 */
8851 /*-----------------------------------------------------------------*/
8852 static void
8853 genLeftShift (iCode * ic)
8854 {
8855   operand *left, *right, *result;
8856   int size, offset;
8857   char *l;
8858   symbol *tlbl, *tlbl1;
8859
8860   D (emitcode (";", "genLeftShift "););
8861
8862   right = IC_RIGHT (ic);
8863   left = IC_LEFT (ic);
8864   result = IC_RESULT (ic);
8865
8866   aopOp (right, ic, FALSE, FALSE);
8867
8868
8869 #ifdef BETTER_LITERAL_SHIFT
8870   /* if the shift count is known then do it
8871      as efficiently as possible */
8872   if (AOP_TYPE (right) == AOP_LIT)
8873     {
8874       if (genLeftShiftLiteral (left, right, result, ic))
8875       {
8876         return;
8877       }
8878     }
8879 #endif
8880
8881   /* shift count is unknown then we have to form
8882      a loop get the loop count in B : Note: we take
8883      only the lower order byte since shifting
8884      more that 32 bits make no sense anyway, ( the
8885      largest size of an object can be only 32 bits ) */
8886
8887   if (AOP_TYPE (right) == AOP_LIT)
8888   {
8889       /* Really should be handled by genLeftShiftLiteral,
8890        * but since I'm too lazy to fix that today, at least we can make
8891        * some small improvement.
8892        */
8893        emitcode("mov", "b,#!constbyte",
8894                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8895   }
8896   else
8897   {
8898       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8899       emitcode ("inc", "b");
8900   }
8901   freeAsmop (right, NULL, ic, TRUE);
8902   aopOp (left, ic, FALSE, FALSE);
8903   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8904
8905   /* now move the left to the result if they are not the
8906      same */
8907   if (!sameRegs (AOP (left), AOP (result)) &&
8908       AOP_SIZE (result) > 1)
8909     {
8910
8911       size = AOP_SIZE (result);
8912       offset = 0;
8913       _startLazyDPSEvaluation ();
8914       while (size--)
8915         {
8916           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8917           if (*l == '@' && (IS_AOP_PREG (result)))
8918             {
8919
8920               emitcode ("mov", "a,%s", l);
8921               aopPut (AOP (result), "a", offset);
8922             }
8923           else
8924             aopPut (AOP (result), l, offset);
8925           offset++;
8926         }
8927       _endLazyDPSEvaluation ();
8928     }
8929
8930   tlbl = newiTempLabel (NULL);
8931   size = AOP_SIZE (result);
8932   offset = 0;
8933   tlbl1 = newiTempLabel (NULL);
8934
8935   /* if it is only one byte then */
8936   if (size == 1)
8937     {
8938       symbol *tlbl1 = newiTempLabel (NULL);
8939
8940       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8941       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8942       emitcode ("", "!tlabeldef", tlbl->key + 100);
8943       emitcode ("add", "a,acc");
8944       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8945       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8946       aopPut (AOP (result), "a", 0);
8947       goto release;
8948     }
8949
8950   reAdjustPreg (AOP (result));
8951
8952   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8953   emitcode ("", "!tlabeldef", tlbl->key + 100);
8954   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8955   emitcode ("add", "a,acc");
8956   aopPut (AOP (result), "a", offset++);
8957   _startLazyDPSEvaluation ();
8958   while (--size)
8959     {
8960       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961       emitcode ("rlc", "a");
8962       aopPut (AOP (result), "a", offset++);
8963     }
8964   _endLazyDPSEvaluation ();
8965   reAdjustPreg (AOP (result));
8966
8967   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969 release:
8970   freeAsmop (left, NULL, ic, TRUE);
8971   freeAsmop (result, NULL, ic, TRUE);
8972 }
8973
8974 #ifdef BETTER_LITERAL_SHIFT
8975 /*-----------------------------------------------------------------*/
8976 /* genrshOne - right shift a one byte quantity by known count      */
8977 /*-----------------------------------------------------------------*/
8978 static void
8979 genrshOne (operand * result, operand * left,
8980            int shCount, int sign)
8981 {
8982   D (emitcode (";", "genrshOne"););
8983   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8984 }
8985 #endif
8986
8987 #ifdef BETTER_LITERAL_SHIFT
8988 /*-----------------------------------------------------------------*/
8989 /* genrshTwo - right shift two bytes by known amount != 0          */
8990 /*-----------------------------------------------------------------*/
8991 static void
8992 genrshTwo (operand * result, operand * left,
8993            int shCount, int sign)
8994 {
8995   D (emitcode (";", "genrshTwo"););
8996
8997   /* if shCount >= 8 */
8998   if (shCount >= 8)
8999     {
9000       shCount -= 8;
9001       _startLazyDPSEvaluation();
9002       if (shCount)
9003       {
9004         shiftR1Left2Result (left, MSB16, result, LSB,
9005                             shCount, sign);
9006       }                     
9007       else
9008       {
9009         movLeft2Result (left, MSB16, result, LSB, sign);
9010       }
9011       addSign (result, MSB16, sign);
9012       _endLazyDPSEvaluation();
9013     }
9014
9015   /*  1 <= shCount <= 7 */
9016   else
9017   {
9018     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9019   }
9020 }
9021 #endif
9022
9023 /*-----------------------------------------------------------------*/
9024 /* shiftRLong - shift right one long from left to result           */
9025 /* offl = LSB or MSB16                                             */
9026 /*-----------------------------------------------------------------*/
9027 static void
9028 shiftRLong (operand * left, int offl,
9029             operand * result, int sign)
9030 {
9031   int isSameRegs=sameRegs(AOP(left),AOP(result));
9032
9033   if (isSameRegs && offl>1) {
9034     // we are in big trouble, but this shouldn't happen
9035     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9036   }
9037
9038   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9039   
9040   if (offl==MSB16) {
9041     // shift is > 8
9042     if (sign) {
9043       emitcode ("rlc", "a");
9044       emitcode ("subb", "a,acc");
9045       emitcode ("xch", "a,%s",
9046                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9047     } else {
9048       aopPut (AOP(result), zero, MSB32);
9049     }
9050   }
9051
9052   if (!sign) {
9053     emitcode ("clr", "c");
9054   } else {
9055     emitcode ("mov", "c,acc.7");
9056   }
9057
9058   emitcode ("rrc", "a");
9059
9060   if (isSameRegs && offl==MSB16) {
9061     emitcode ("xch",
9062               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9063   } else {
9064     aopPut (AOP (result), "a", MSB32);
9065     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9066   }
9067
9068   emitcode ("rrc", "a");
9069   if (isSameRegs && offl==1) {
9070     emitcode ("xch", "a,%s",
9071               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9072   } else {
9073     aopPut (AOP (result), "a", MSB24);
9074     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9075   }
9076   emitcode ("rrc", "a");
9077   aopPut (AOP (result), "a", MSB16 - offl);
9078
9079   if (offl == LSB)
9080     {
9081       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9082       emitcode ("rrc", "a");
9083       aopPut (AOP (result), "a", LSB);
9084     }
9085 }
9086
9087 /*-----------------------------------------------------------------*/
9088 /* genrshFour - shift four byte by a known amount != 0             */
9089 /*-----------------------------------------------------------------*/
9090 static void
9091 genrshFour (operand * result, operand * left,
9092             int shCount, int sign)
9093 {
9094   D (emitcode (";", "genrshFour"););
9095
9096   /* if shifting more that 3 bytes */
9097   if (shCount >= 24)
9098     {
9099       shCount -= 24;
9100       _startLazyDPSEvaluation();
9101       if (shCount)
9102         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9103       else
9104         movLeft2Result (left, MSB32, result, LSB, sign);
9105       addSign (result, MSB16, sign);
9106       _endLazyDPSEvaluation();
9107     }
9108   else if (shCount >= 16)
9109     {
9110       shCount -= 16;
9111       _startLazyDPSEvaluation();
9112       if (shCount)
9113         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9114       else
9115         {
9116           movLeft2Result (left, MSB24, result, LSB, 0);
9117           movLeft2Result (left, MSB32, result, MSB16, sign);
9118         }
9119       addSign (result, MSB24, sign);
9120       _endLazyDPSEvaluation();
9121     }
9122   else if (shCount >= 8)
9123     {
9124       shCount -= 8;
9125       _startLazyDPSEvaluation();
9126       if (shCount == 1)
9127         {
9128             shiftRLong (left, MSB16, result, sign);
9129         }
9130       else if (shCount == 0)
9131         {
9132           movLeft2Result (left, MSB16, result, LSB, 0);
9133           movLeft2Result (left, MSB24, result, MSB16, 0);
9134           movLeft2Result (left, MSB32, result, MSB24, sign);
9135           addSign (result, MSB32, sign);
9136         }
9137       else
9138         {
9139           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9140           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9141           /* the last shift is signed */
9142           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9143           addSign (result, MSB32, sign);
9144         }
9145         _endLazyDPSEvaluation();
9146     }
9147   else
9148     {   
9149         /* 1 <= shCount <= 7 */
9150       if (shCount <= 2)
9151         {
9152           shiftRLong (left, LSB, result, sign);
9153           if (shCount == 2)
9154             shiftRLong (result, LSB, result, sign);
9155         }
9156       else
9157         {
9158           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9159           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9160           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9161         }
9162     }
9163 }
9164
9165 #ifdef BETTER_LITERAL_SHIFT
9166 /*-----------------------------------------------------------------*/
9167 /* genRightShiftLiteral - right shifting by known count            */
9168 /*-----------------------------------------------------------------*/
9169 static bool
9170 genRightShiftLiteral (operand * left,
9171                       operand * right,
9172                       operand * result,
9173                       iCode * ic,
9174                       int sign)
9175 {
9176   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9177   int size;
9178
9179   size = getSize (operandType (result));
9180
9181   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9182
9183   /* We only handle certain easy cases so far. */
9184   if ((shCount != 0)
9185    && (shCount < (size * 8))
9186    && (size != 1)
9187    && (size != 2)
9188    && (size != 4))
9189   {
9190       D(emitcode (";", "genRightShiftLiteral wimping out"););
9191       return FALSE;
9192   }
9193
9194   freeAsmop (right, NULL, ic, TRUE);
9195
9196   aopOp (left, ic, FALSE, FALSE);
9197   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9198
9199 #if VIEW_SIZE
9200   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9201             AOP_SIZE (left));
9202 #endif
9203
9204   /* test the LEFT size !!! */
9205
9206   /* I suppose that the left size >= result size */
9207   if (shCount == 0)
9208   {
9209       size = getDataSize (result);
9210       _startLazyDPSEvaluation();
9211       while (size--)
9212       {
9213         movLeft2Result (left, size, result, size, 0);
9214       }
9215       _endLazyDPSEvaluation();
9216   }
9217   else if (shCount >= (size * 8))
9218     {
9219       if (sign)
9220       {
9221         /* get sign in acc.7 */
9222         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9223       }
9224       addSign (result, LSB, sign);
9225     }
9226   else
9227     {
9228       switch (size)
9229         {
9230         case 1:
9231           genrshOne (result, left, shCount, sign);
9232           break;
9233
9234         case 2:
9235           genrshTwo (result, left, shCount, sign);
9236           break;
9237 #if 1
9238         case 4:
9239           genrshFour (result, left, shCount, sign);
9240           break;
9241 #endif    
9242         default:
9243           break;
9244         }
9245     }
9246   freeAsmop (left, NULL, ic, TRUE);
9247   freeAsmop (result, NULL, ic, TRUE);
9248   
9249   return TRUE;
9250 }
9251 #endif
9252
9253 /*-----------------------------------------------------------------*/
9254 /* genSignedRightShift - right shift of signed number              */
9255 /*-----------------------------------------------------------------*/
9256 static void
9257 genSignedRightShift (iCode * ic)
9258 {
9259   operand *right, *left, *result;
9260   int size, offset;
9261   char *l;
9262   symbol *tlbl, *tlbl1;
9263
9264   D (emitcode (";", "genSignedRightShift "););
9265
9266   /* we do it the hard way put the shift count in b
9267      and loop thru preserving the sign */
9268
9269   right = IC_RIGHT (ic);
9270   left = IC_LEFT (ic);
9271   result = IC_RESULT (ic);
9272
9273   aopOp (right, ic, FALSE, FALSE);
9274
9275 #ifdef BETTER_LITERAL_SHIFT
9276   if (AOP_TYPE (right) == AOP_LIT)
9277     {
9278       if (genRightShiftLiteral (left, right, result, ic, 1))
9279       {
9280         return;
9281       }
9282     }
9283 #endif
9284   /* shift count is unknown then we have to form
9285      a loop get the loop count in B : Note: we take
9286      only the lower order byte since shifting
9287      more that 32 bits make no sense anyway, ( the
9288      largest size of an object can be only 32 bits ) */
9289
9290   if (AOP_TYPE (right) == AOP_LIT)
9291   {
9292       /* Really should be handled by genRightShiftLiteral,
9293        * but since I'm too lazy to fix that today, at least we can make
9294        * some small improvement.
9295        */
9296        emitcode("mov", "b,#!constbyte",
9297                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9298   }
9299   else
9300   {
9301         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9302         emitcode ("inc", "b");
9303   }
9304   freeAsmop (right, NULL, ic, TRUE);
9305   aopOp (left, ic, FALSE, FALSE);
9306   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
9307
9308   /* now move the left to the result if they are not the
9309      same */
9310   if (!sameRegs (AOP (left), AOP (result)) &&
9311       AOP_SIZE (result) > 1)
9312     {
9313
9314       size = AOP_SIZE (result);
9315       offset = 0;
9316       _startLazyDPSEvaluation ();
9317       while (size--)
9318         {
9319           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9320           if (*l == '@' && IS_AOP_PREG (result))
9321             {
9322
9323               emitcode ("mov", "a,%s", l);
9324               aopPut (AOP (result), "a", offset);
9325             }
9326           else
9327             aopPut (AOP (result), l, offset);
9328           offset++;
9329         }
9330       _endLazyDPSEvaluation ();
9331     }
9332
9333   /* mov the highest order bit to OVR */
9334   tlbl = newiTempLabel (NULL);
9335   tlbl1 = newiTempLabel (NULL);
9336
9337   size = AOP_SIZE (result);
9338   offset = size - 1;
9339   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9340   emitcode ("rlc", "a");
9341   emitcode ("mov", "ov,c");
9342   /* if it is only one byte then */
9343   if (size == 1)
9344     {
9345       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9346       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9347       emitcode ("", "!tlabeldef", tlbl->key + 100);
9348       emitcode ("mov", "c,ov");
9349       emitcode ("rrc", "a");
9350       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9351       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9352       aopPut (AOP (result), "a", 0);
9353       goto release;
9354     }
9355
9356   reAdjustPreg (AOP (result));
9357   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9358   emitcode ("", "!tlabeldef", tlbl->key + 100);
9359   emitcode ("mov", "c,ov");
9360   _startLazyDPSEvaluation ();
9361   while (size--)
9362     {
9363       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9364       emitcode ("rrc", "a");
9365       aopPut (AOP (result), "a", offset--);
9366     }
9367   _endLazyDPSEvaluation ();
9368   reAdjustPreg (AOP (result));
9369   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9370   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9371
9372 release:
9373   freeAsmop (left, NULL, ic, TRUE);
9374   freeAsmop (result, NULL, ic, TRUE);
9375 }
9376
9377 /*-----------------------------------------------------------------*/
9378 /* genRightShift - generate code for right shifting                */
9379 /*-----------------------------------------------------------------*/
9380 static void
9381 genRightShift (iCode * ic)
9382 {
9383   operand *right, *left, *result;
9384   sym_link *letype;
9385   int size, offset;
9386   char *l;
9387   symbol *tlbl, *tlbl1;
9388
9389   D (emitcode (";", "genRightShift "););
9390
9391   /* if signed then we do it the hard way preserve the
9392      sign bit moving it inwards */
9393   letype = getSpec (operandType (IC_LEFT (ic)));
9394
9395   if (!SPEC_USIGN (letype))
9396     {
9397       genSignedRightShift (ic);
9398       return;
9399     }
9400
9401   /* signed & unsigned types are treated the same : i.e. the
9402      signed is NOT propagated inwards : quoting from the
9403      ANSI - standard : "for E1 >> E2, is equivalent to division
9404      by 2**E2 if unsigned or if it has a non-negative value,
9405      otherwise the result is implementation defined ", MY definition
9406      is that the sign does not get propagated */
9407
9408   right = IC_RIGHT (ic);
9409   left = IC_LEFT (ic);
9410   result = IC_RESULT (ic);
9411
9412   aopOp (right, ic, FALSE, FALSE);
9413
9414 #ifdef BETTER_LITERAL_SHIFT
9415   /* if the shift count is known then do it
9416      as efficiently as possible */
9417   if (AOP_TYPE (right) == AOP_LIT)
9418     {
9419       if (genRightShiftLiteral (left, right, result, ic, 0))
9420       {
9421         return;
9422       }
9423     }
9424 #endif
9425
9426   /* shift count is unknown then we have to form
9427      a loop get the loop count in B : Note: we take
9428      only the lower order byte since shifting
9429      more that 32 bits make no sense anyway, ( the
9430      largest size of an object can be only 32 bits ) */
9431   
9432   if (AOP_TYPE (right) == AOP_LIT)
9433   {
9434       /* Really should be handled by genRightShiftLiteral,
9435        * but since I'm too lazy to fix that today, at least we can make
9436        * some small improvement.
9437        */
9438        emitcode("mov", "b,#!constbyte",
9439                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9440   }
9441   else
9442   {
9443       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9444       emitcode ("inc", "b");
9445   }
9446   freeAsmop (right, NULL, ic, TRUE);
9447   aopOp (left, ic, FALSE, FALSE);
9448   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9449
9450   /* now move the left to the result if they are not the
9451      same */
9452   if (!sameRegs (AOP (left), AOP (result)) &&
9453       AOP_SIZE (result) > 1)
9454     {
9455
9456       size = AOP_SIZE (result);
9457       offset = 0;
9458       _startLazyDPSEvaluation ();
9459       while (size--)
9460         {
9461           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9462           if (*l == '@' && IS_AOP_PREG (result))
9463             {
9464
9465               emitcode ("mov", "a,%s", l);
9466               aopPut (AOP (result), "a", offset);
9467             }
9468           else
9469             aopPut (AOP (result), l, offset);
9470           offset++;
9471         }
9472       _endLazyDPSEvaluation ();
9473     }
9474
9475   tlbl = newiTempLabel (NULL);
9476   tlbl1 = newiTempLabel (NULL);
9477   size = AOP_SIZE (result);
9478   offset = size - 1;
9479
9480   /* if it is only one byte then */
9481   if (size == 1)
9482     {
9483       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9484       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9485       emitcode ("", "!tlabeldef", tlbl->key + 100);
9486       CLRC;
9487       emitcode ("rrc", "a");
9488       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9489       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9490       aopPut (AOP (result), "a", 0);
9491       goto release;
9492     }
9493
9494   reAdjustPreg (AOP (result));
9495   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9496   emitcode ("", "!tlabeldef", tlbl->key + 100);
9497   CLRC;
9498   _startLazyDPSEvaluation ();
9499   while (size--)
9500     {
9501       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9502       emitcode ("rrc", "a");
9503       aopPut (AOP (result), "a", offset--);
9504     }
9505   _endLazyDPSEvaluation ();
9506   reAdjustPreg (AOP (result));
9507
9508   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9509   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9510
9511 release:
9512   freeAsmop (left, NULL, ic, TRUE);
9513   freeAsmop (result, NULL, ic, TRUE);
9514 }
9515
9516
9517 /*-----------------------------------------------------------------*/
9518 /* emitPtrByteGet - emits code to get a byte into A through a      */
9519 /*                  pointer register (R0, R1, or DPTR). The        */
9520 /*                  original value of A can be preserved in B.     */
9521 /*-----------------------------------------------------------------*/
9522 static void
9523 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9524 {
9525   switch (p_type)
9526     {
9527     case IPOINTER:
9528     case POINTER:
9529       if (preserveAinB)
9530         emitcode ("mov", "b,a");
9531       emitcode ("mov", "a,@%s", rname);
9532       break;
9533
9534     case PPOINTER:
9535       if (preserveAinB)
9536         emitcode ("mov", "b,a");
9537       emitcode ("movx", "a,@%s", rname);
9538       break;
9539       
9540     case FPOINTER:
9541       if (preserveAinB)
9542         emitcode ("mov", "b,a");
9543       emitcode ("movx", "a,@dptr");
9544       break;
9545
9546     case CPOINTER:
9547       if (preserveAinB)
9548         emitcode ("mov", "b,a");
9549       emitcode ("clr", "a");
9550       emitcode ("movc", "a,@a+dptr");
9551       break;
9552
9553     case GPOINTER:
9554       if (preserveAinB)
9555         {
9556           emitcode ("push", "b");
9557           emitcode ("push", "acc");
9558         }
9559       emitcode ("lcall", "__gptrget");
9560       if (preserveAinB)
9561         emitcode ("pop", "b");
9562       break;
9563     }
9564 }
9565
9566 /*-----------------------------------------------------------------*/
9567 /* emitPtrByteSet - emits code to set a byte from src through a    */
9568 /*                  pointer register (R0, R1, or DPTR).            */
9569 /*-----------------------------------------------------------------*/
9570 static void
9571 emitPtrByteSet (char *rname, int p_type, char *src)
9572 {
9573   switch (p_type)
9574     {
9575     case IPOINTER:
9576     case POINTER:
9577       if (*src=='@')
9578         {
9579           MOVA (src);
9580           emitcode ("mov", "@%s,a", rname);
9581         }
9582       else
9583         emitcode ("mov", "@%s,%s", rname, src);
9584       break;
9585
9586     case PPOINTER:
9587       MOVA (src);
9588       emitcode ("movx", "@%s,a", rname);
9589       break;
9590       
9591     case FPOINTER:
9592       MOVA (src);
9593       emitcode ("movx", "@dptr,a");
9594       break;
9595
9596     case GPOINTER:
9597       MOVA (src);
9598       emitcode ("lcall", "__gptrput");
9599       break;
9600     }
9601 }
9602
9603 /*-----------------------------------------------------------------*/
9604 /* genUnpackBits - generates code for unpacking bits               */
9605 /*-----------------------------------------------------------------*/
9606 static void
9607 genUnpackBits (operand * result, char *rname, int ptype)
9608 {
9609   int offset = 0;       /* result byte offset */
9610   int rsize;            /* result size */
9611   int rlen = 0;         /* remaining bitfield length */
9612   sym_link *etype;      /* bitfield type information */
9613   int blen;             /* bitfield length */
9614   int bstr;             /* bitfield starting bit within byte */
9615
9616   D(emitcode (";     genUnpackBits",""));
9617
9618   etype = getSpec (operandType (result));
9619   rsize = getSize (operandType (result));
9620   blen = SPEC_BLEN (etype);
9621   bstr = SPEC_BSTR (etype);
9622
9623   /* If the bitfield length is less than a byte */
9624   if (blen < 8)
9625     {
9626       emitPtrByteGet (rname, ptype, FALSE);
9627       AccRsh (bstr);
9628       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9629       aopPut (AOP (result), "a", offset++);
9630       goto finish;
9631     }
9632
9633   /* Bit field did not fit in a byte. Copy all
9634      but the partial byte at the end.  */
9635   for (rlen=blen;rlen>=8;rlen-=8)
9636     {
9637       emitPtrByteGet (rname, ptype, FALSE);
9638       aopPut (AOP (result), "a", offset++);
9639       if (rlen>8)
9640         emitcode ("inc", "%s", rname);
9641     }
9642
9643   /* Handle the partial byte at the end */
9644   if (rlen)
9645     {
9646       emitPtrByteGet (rname, ptype, FALSE);
9647       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9648       aopPut (AOP (result), "a", offset++);
9649     }
9650
9651 finish:
9652   if (offset < rsize)
9653     {
9654       rsize -= offset;
9655       while (rsize--)
9656         aopPut (AOP (result), zero, offset++);
9657     }
9658 }
9659
9660
9661 /*-----------------------------------------------------------------*/
9662 /* genDataPointerGet - generates code when ptr offset is known     */
9663 /*-----------------------------------------------------------------*/
9664 static void
9665 genDataPointerGet (operand * left,
9666                    operand * result,
9667                    iCode * ic)
9668 {
9669   char *l;
9670   char buff[256];
9671   int size, offset = 0;
9672   aopOp (result, ic, TRUE, FALSE);
9673
9674   /* get the string representation of the name */
9675   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9676   size = AOP_SIZE (result);
9677   _startLazyDPSEvaluation ();
9678   while (size--)
9679     {
9680         if (offset)
9681         {
9682             SNPRINTF (buff, sizeof(buff), 
9683                       "(%s + %d)", l + 1, offset);
9684         }
9685         else
9686         {
9687             SNPRINTF (buff, sizeof(buff), 
9688                       "%s", l + 1);
9689         }
9690       aopPut (AOP (result), buff, offset++);
9691     }
9692   _endLazyDPSEvaluation ();
9693
9694   freeAsmop (left, NULL, ic, TRUE);
9695   freeAsmop (result, NULL, ic, TRUE);
9696 }
9697
9698 /*-----------------------------------------------------------------*/
9699 /* genNearPointerGet - emitcode for near pointer fetch             */
9700 /*-----------------------------------------------------------------*/
9701 static void
9702 genNearPointerGet (operand * left,
9703                    operand * result,
9704                    iCode * ic,
9705                    iCode *pi)
9706 {
9707   asmop *aop = NULL;
9708   regs *preg;
9709   char *rname;
9710   sym_link *rtype, *retype, *letype;
9711   sym_link *ltype = operandType (left);
9712   char buff[80];
9713
9714   rtype = operandType (result);
9715   retype = getSpec (rtype);
9716   letype = getSpec (ltype);
9717
9718   aopOp (left, ic, FALSE, FALSE);
9719
9720   /* if left is rematerialisable and
9721      result is not bitfield variable type and
9722      the left is pointer to data space i.e
9723      lower 128 bytes of space */
9724   if (AOP_TYPE (left) == AOP_IMMD &&
9725       !IS_BITFIELD (retype) &&
9726       !IS_BITFIELD (letype) &&
9727       DCL_TYPE (ltype) == POINTER)
9728     {
9729       genDataPointerGet (left, result, ic);
9730       return;
9731     }
9732
9733   /* if the value is already in a pointer register
9734      then don't need anything more */
9735   if (!AOP_INPREG (AOP (left)))
9736     {
9737       /* otherwise get a free pointer register */
9738       aop = newAsmop (0);
9739       preg = getFreePtr (ic, &aop, FALSE);
9740       emitcode ("mov", "%s,%s",
9741                 preg->name,
9742                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9743       rname = preg->name;
9744     }
9745   else
9746     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9747
9748   freeAsmop (left, NULL, ic, TRUE);
9749   aopOp (result, ic, FALSE, FALSE);
9750
9751   /* if bitfield then unpack the bits */
9752   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9753     genUnpackBits (result, rname, POINTER);
9754   else
9755     {
9756       /* we have can just get the values */
9757       int size = AOP_SIZE (result);
9758       int offset = 0;
9759
9760       while (size--)
9761         {
9762           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9763             {
9764
9765               emitcode ("mov", "a,@%s", rname);
9766               aopPut (AOP (result), "a", offset);
9767             }
9768           else
9769             {
9770               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9771               aopPut (AOP (result), buff, offset);
9772             }
9773           offset++;
9774           if (size || pi)
9775             {
9776                 emitcode ("inc", "%s", rname);
9777             }
9778         }
9779     }
9780
9781   /* now some housekeeping stuff */
9782   if (aop)
9783     {
9784       /* we had to allocate for this iCode */
9785       if (pi) { /* post increment present */
9786         aopPut(AOP ( left ),rname,0);
9787       }
9788       freeAsmop (NULL, aop, ic, TRUE);
9789     }
9790   else
9791     {
9792       /* we did not allocate which means left
9793          already in a pointer register, then
9794          if size > 0 && this could be used again
9795          we have to point it back to where it
9796          belongs */
9797       if (AOP_SIZE (result) > 1 &&
9798           !OP_SYMBOL (left)->remat &&
9799           (OP_SYMBOL (left)->liveTo > ic->seq ||
9800            ic->depth) &&
9801           !pi)
9802         {
9803           int size = AOP_SIZE (result) - 1;
9804           while (size--)
9805             emitcode ("dec", "%s", rname);
9806         }
9807     }
9808
9809   /* done */
9810   freeAsmop (result, NULL, ic, TRUE);
9811   if (pi) pi->generated = 1;
9812 }
9813
9814 /*-----------------------------------------------------------------*/
9815 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9816 /*-----------------------------------------------------------------*/
9817 static void
9818 genPagedPointerGet (operand * left,
9819                     operand * result,
9820                     iCode * ic,
9821                     iCode * pi)
9822 {
9823   asmop *aop = NULL;
9824   regs *preg;
9825   char *rname;
9826   sym_link *rtype, *retype, *letype;
9827
9828   rtype = operandType (result);
9829   retype = getSpec (rtype);
9830   letype = getSpec (operandType (left));
9831   aopOp (left, ic, FALSE, FALSE);
9832
9833   /* if the value is already in a pointer register
9834      then don't need anything more */
9835   if (!AOP_INPREG (AOP (left)))
9836     {
9837       /* otherwise get a free pointer register */
9838       aop = newAsmop (0);
9839       preg = getFreePtr (ic, &aop, FALSE);
9840       emitcode ("mov", "%s,%s",
9841                 preg->name,
9842                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9843       rname = preg->name;
9844     }
9845   else
9846     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9847
9848   freeAsmop (left, NULL, ic, TRUE);
9849   aopOp (result, ic, FALSE, FALSE);
9850
9851   /* if bitfield then unpack the bits */
9852   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9853     genUnpackBits (result, rname, PPOINTER);
9854   else
9855     {
9856       /* we have can just get the values */
9857       int size = AOP_SIZE (result);
9858       int offset = 0;
9859
9860       while (size--)
9861         {
9862
9863           emitcode ("movx", "a,@%s", rname);
9864           aopPut (AOP (result), "a", offset);
9865
9866           offset++;
9867
9868           if (size || pi)
9869             emitcode ("inc", "%s", rname);
9870         }
9871     }
9872
9873   /* now some housekeeping stuff */
9874   if (aop)
9875     {
9876       /* we had to allocate for this iCode */
9877       if (pi) aopPut ( AOP (left), rname, 0);
9878       freeAsmop (NULL, aop, ic, TRUE);
9879     }
9880   else
9881     {
9882       /* we did not allocate which means left
9883          already in a pointer register, then
9884          if size > 0 && this could be used again
9885          we have to point it back to where it
9886          belongs */
9887       if (AOP_SIZE (result) > 1 &&
9888           !OP_SYMBOL (left)->remat &&
9889           (OP_SYMBOL (left)->liveTo > ic->seq ||
9890            ic->depth) &&
9891           !pi)
9892         {
9893           int size = AOP_SIZE (result) - 1;
9894           while (size--)
9895             emitcode ("dec", "%s", rname);
9896         }
9897     }
9898
9899   /* done */
9900   freeAsmop (result, NULL, ic, TRUE);
9901   if (pi) pi->generated = 1;
9902 }
9903
9904 /*-----------------------------------------------------------------*/
9905 /* genFarPointerGet - gget value from far space                    */
9906 /*-----------------------------------------------------------------*/
9907 static void
9908 genFarPointerGet (operand * left,
9909                   operand * result, iCode * ic, iCode *pi)
9910 {
9911     int size, offset, dopi=1;
9912   sym_link *retype = getSpec (operandType (result));
9913   sym_link *letype = getSpec (operandType (left));
9914   D (emitcode (";", "genFarPointerGet"););
9915
9916   aopOp (left, ic, FALSE, FALSE);
9917
9918   /* if the operand is already in dptr
9919      then we do nothing else we move the value to dptr */
9920   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9921     {
9922       /* if this is remateriazable */
9923       if (AOP_TYPE (left) == AOP_IMMD)
9924         {
9925           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9926         }
9927       else
9928         {
9929           /* we need to get it byte by byte */
9930           _startLazyDPSEvaluation ();
9931           if (AOP_TYPE (left) != AOP_DPTR)
9932             {
9933               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9934               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9935               if (options.model == MODEL_FLAT24)
9936                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9937             }
9938           else
9939             {
9940               /* We need to generate a load to DPTR indirect through DPTR. */
9941               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9942               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9943               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9944               if (options.model == MODEL_FLAT24)
9945                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9946               emitcode ("pop", "dph");
9947               emitcode ("pop", "dpl");
9948               dopi =0;
9949             }
9950           _endLazyDPSEvaluation ();
9951         }
9952     }
9953   /* so dptr know contains the address */
9954   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9955
9956   /* if bit then unpack */
9957   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9958       if (AOP_INDPTRn(left)) {
9959           genSetDPTR(AOP(left)->aopu.dptr);
9960       }
9961       genUnpackBits (result, "dptr", FPOINTER);
9962       if (AOP_INDPTRn(left)) {
9963           genSetDPTR(0);
9964       }
9965   } else
9966     {
9967       size = AOP_SIZE (result);
9968       offset = 0;
9969
9970       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9971           while (size--) {
9972               genSetDPTR(AOP(left)->aopu.dptr);
9973               emitcode ("movx", "a,@dptr");
9974               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9975                   emitcode ("inc", "dptr");
9976               genSetDPTR (0);
9977               aopPut (AOP (result), "a", offset++);
9978           }
9979       } else {
9980           _startLazyDPSEvaluation ();
9981           while (size--) {
9982               if (AOP_INDPTRn(left)) {
9983                   genSetDPTR(AOP(left)->aopu.dptr);
9984               } else {
9985                   genSetDPTR (0);
9986               }
9987               _flushLazyDPS ();
9988               
9989               emitcode ("movx", "a,@dptr");
9990               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9991                   emitcode ("inc", "dptr");
9992               
9993               aopPut (AOP (result), "a", offset++);
9994           }
9995           _endLazyDPSEvaluation ();
9996       }
9997     }
9998   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9999       if (!AOP_INDPTRn(left)) {
10000           _startLazyDPSEvaluation ();
10001           aopPut ( AOP (left), "dpl", 0);
10002           aopPut ( AOP (left), "dph", 1);
10003           if (options.model == MODEL_FLAT24)
10004               aopPut ( AOP (left), "dpx", 2);
10005           _endLazyDPSEvaluation ();
10006       }
10007     pi->generated = 1;
10008   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
10009              AOP_SIZE(result) > 1 &&
10010              IS_SYMOP(left) &&
10011              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10012       
10013       size = AOP_SIZE (result) - 1;
10014       if (AOP_INDPTRn(left)) {
10015           genSetDPTR(AOP(left)->aopu.dptr);
10016       }
10017       while (size--) emitcode ("lcall","__decdptr");
10018       if (AOP_INDPTRn(left)) {
10019           genSetDPTR(0);
10020       }
10021   }
10022
10023   freeAsmop (left, NULL, ic, TRUE);
10024   freeAsmop (result, NULL, ic, TRUE);
10025 }
10026
10027 /*-----------------------------------------------------------------*/
10028 /* genCodePointerGet - get value from code space                  */
10029 /*-----------------------------------------------------------------*/
10030 static void
10031 genCodePointerGet (operand * left,
10032                     operand * result, iCode * ic, iCode *pi)
10033 {
10034   int size, offset, dopi=1;
10035   sym_link *retype = getSpec (operandType (result));
10036
10037   aopOp (left, ic, FALSE, FALSE);
10038
10039   /* if the operand is already in dptr
10040      then we do nothing else we move the value to dptr */
10041   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10042     {
10043       /* if this is remateriazable */
10044       if (AOP_TYPE (left) == AOP_IMMD)
10045         {
10046           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10047         }
10048       else
10049         {                       /* we need to get it byte by byte */
10050           _startLazyDPSEvaluation ();
10051           if (AOP_TYPE (left) != AOP_DPTR)
10052             {
10053               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10054               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10055               if (options.model == MODEL_FLAT24)
10056                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10057             }
10058           else
10059             {
10060               /* We need to generate a load to DPTR indirect through DPTR. */
10061               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10062               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10063               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10064               if (options.model == MODEL_FLAT24)
10065                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10066               emitcode ("pop", "dph");
10067               emitcode ("pop", "dpl");
10068               dopi=0;
10069             }
10070           _endLazyDPSEvaluation ();
10071         }
10072     }
10073   /* so dptr know contains the address */
10074   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10075
10076   /* if bit then unpack */
10077   if (IS_BITFIELD (retype)) {
10078       if (AOP_INDPTRn(left)) {
10079           genSetDPTR(AOP(left)->aopu.dptr);
10080       }
10081       genUnpackBits (result, "dptr", CPOINTER);
10082       if (AOP_INDPTRn(left)) {
10083           genSetDPTR(0);
10084       }
10085   } else
10086     {
10087       size = AOP_SIZE (result);
10088       offset = 0;
10089       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10090           while (size--) {
10091               genSetDPTR(AOP(left)->aopu.dptr);
10092               emitcode ("clr", "a");
10093               emitcode ("movc", "a,@a+dptr");
10094               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10095                   emitcode ("inc", "dptr");
10096               genSetDPTR (0);
10097               aopPut (AOP (result), "a", offset++);
10098           }
10099       } else {
10100           _startLazyDPSEvaluation ();
10101           while (size--)
10102               {
10103                   if (AOP_INDPTRn(left)) {
10104                       genSetDPTR(AOP(left)->aopu.dptr);
10105                   } else {
10106                       genSetDPTR (0);
10107                   }
10108                   _flushLazyDPS ();
10109                   
10110                   emitcode ("clr", "a");
10111                   emitcode ("movc", "a,@a+dptr");
10112                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10113                       emitcode ("inc", "dptr");
10114                   aopPut (AOP (result), "a", offset++);
10115               }
10116           _endLazyDPSEvaluation ();
10117       }
10118     }
10119   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10120       if (!AOP_INDPTRn(left)) {
10121           _startLazyDPSEvaluation ();
10122           
10123           aopPut ( AOP (left), "dpl", 0);
10124           aopPut ( AOP (left), "dph", 1);
10125           if (options.model == MODEL_FLAT24)
10126               aopPut ( AOP (left), "dpx", 2);
10127
10128           _endLazyDPSEvaluation ();
10129       }
10130       pi->generated = 1;
10131   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
10132              AOP_SIZE(result) > 1 &&
10133              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10134       
10135       size = AOP_SIZE (result) - 1;
10136       if (AOP_INDPTRn(left)) {
10137           genSetDPTR(AOP(left)->aopu.dptr);
10138       }
10139       while (size--) emitcode ("lcall","__decdptr");
10140       if (AOP_INDPTRn(left)) {
10141           genSetDPTR(0);
10142       }
10143   }
10144   
10145   freeAsmop (left, NULL, ic, TRUE);
10146   freeAsmop (result, NULL, ic, TRUE);
10147 }
10148
10149 /*-----------------------------------------------------------------*/
10150 /* genGenPointerGet - gget value from generic pointer space        */
10151 /*-----------------------------------------------------------------*/
10152 static void
10153 genGenPointerGet (operand * left,
10154                   operand * result, iCode * ic, iCode * pi)
10155 {
10156   int size, offset;
10157   sym_link *retype = getSpec (operandType (result));
10158   sym_link *letype = getSpec (operandType (left));
10159
10160   D (emitcode (";", "genGenPointerGet "); );
10161
10162   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10163
10164   /* if the operand is already in dptr
10165      then we do nothing else we move the value to dptr */
10166   if (AOP_TYPE (left) != AOP_STR)
10167     {
10168       /* if this is remateriazable */
10169       if (AOP_TYPE (left) == AOP_IMMD)
10170         {
10171           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10172           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
10173             {
10174                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10175             }
10176             else
10177             {
10178                 emitcode ("mov", "b,#%d", pointerCode (retype));
10179             }
10180         }
10181       else
10182         {                       /* we need to get it byte by byte */
10183             _startLazyDPSEvaluation ();
10184             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10185             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10186             if (options.model == MODEL_FLAT24) {
10187                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10188                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10189             } else {
10190                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10191             }
10192             _endLazyDPSEvaluation ();
10193         }
10194     }
10195
10196   /* so dptr-b now contains the address */
10197   _G.bInUse++;
10198   aopOp (result, ic, FALSE, TRUE);
10199   _G.bInUse--;
10200
10201   /* if bit then unpack */
10202   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10203   {
10204     genUnpackBits (result, "dptr", GPOINTER);
10205   }
10206   else
10207     {
10208         size = AOP_SIZE (result);
10209         offset = 0;
10210
10211         while (size--)
10212         {
10213             if (size)
10214             {
10215                 // Get two bytes at a time, results in _AP & A.
10216                 // dptr will be incremented ONCE by __gptrgetWord.
10217                 //
10218                 // Note: any change here must be coordinated
10219                 // with the implementation of __gptrgetWord
10220                 // in device/lib/_gptrget.c
10221                 emitcode ("lcall", "__gptrgetWord");
10222                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10223                 aopPut (AOP (result), "a", offset++);
10224                 size--;
10225             }
10226             else
10227             {
10228                 // Only one byte to get.
10229                 emitcode ("lcall", "__gptrget");
10230                 aopPut (AOP (result), "a", offset++);
10231             }
10232             
10233             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10234             {
10235                 emitcode ("inc", "dptr");
10236             }
10237         }
10238     }
10239
10240   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10241     _startLazyDPSEvaluation ();
10242       
10243     aopPut ( AOP (left), "dpl", 0);
10244     aopPut ( AOP (left), "dph", 1);
10245     if (options.model == MODEL_FLAT24) {
10246         aopPut ( AOP (left), "dpx", 2);
10247         aopPut ( AOP (left), "b", 3);   
10248     } else  aopPut ( AOP (left), "b", 2);       
10249     
10250     _endLazyDPSEvaluation ();
10251       
10252     pi->generated = 1;
10253   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10254              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10255       
10256       size = AOP_SIZE (result) - 1;
10257       while (size--) emitcode ("lcall","__decdptr");
10258   }
10259
10260   freeAsmop (left, NULL, ic, TRUE);
10261   freeAsmop (result, NULL, ic, TRUE);
10262 }
10263
10264 /*-----------------------------------------------------------------*/
10265 /* genPointerGet - generate code for pointer get                   */
10266 /*-----------------------------------------------------------------*/
10267 static void
10268 genPointerGet (iCode * ic, iCode *pi)
10269 {
10270   operand *left, *result;
10271   sym_link *type, *etype;
10272   int p_type;
10273
10274   D (emitcode (";", "genPointerGet ");
10275     );
10276
10277   left = IC_LEFT (ic);
10278   result = IC_RESULT (ic);
10279
10280   /* depending on the type of pointer we need to
10281      move it to the correct pointer register */
10282   type = operandType (left);
10283   etype = getSpec (type);
10284   /* if left is of type of pointer then it is simple */
10285   if (IS_PTR (type) && !IS_FUNC (type->next))
10286     p_type = DCL_TYPE (type);
10287   else
10288     {
10289       /* we have to go by the storage class */
10290       p_type = PTR_TYPE (SPEC_OCLS (etype));
10291     }
10292   /* special case when cast remat */
10293   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10294       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
10295           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10296           type = operandType (left);
10297           p_type = DCL_TYPE (type);
10298   }
10299   /* now that we have the pointer type we assign
10300      the pointer values */
10301   switch (p_type)
10302     {
10303
10304     case POINTER:
10305     case IPOINTER:
10306       genNearPointerGet (left, result, ic, pi);
10307       break;
10308
10309     case PPOINTER:
10310       genPagedPointerGet (left, result, ic, pi);
10311       break;
10312
10313     case FPOINTER:
10314       genFarPointerGet (left, result, ic, pi);
10315       break;
10316
10317     case CPOINTER:
10318       genCodePointerGet (left, result, ic, pi);
10319       break;
10320
10321     case GPOINTER:
10322       genGenPointerGet (left, result, ic, pi);
10323       break;
10324     }
10325
10326 }
10327
10328 /*-----------------------------------------------------------------*/
10329 /* genPackBits - generates code for packed bit storage             */
10330 /*-----------------------------------------------------------------*/
10331 static void
10332 genPackBits (sym_link * etype,
10333              operand * right,
10334              char *rname, int p_type)
10335 {
10336   int offset = 0;       /* source byte offset */
10337   int rlen = 0;         /* remaining bitfield length */
10338   int blen;             /* bitfield length */
10339   int bstr;             /* bitfield starting bit within byte */
10340   int litval;           /* source literal value (if AOP_LIT) */
10341   unsigned char mask;   /* bitmask within current byte */
10342
10343   D(emitcode (";     genPackBits",""));
10344
10345   blen = SPEC_BLEN (etype);
10346   bstr = SPEC_BSTR (etype);
10347
10348   /* If the bitfield length is less than a byte */
10349   if (blen < 8)
10350     {
10351       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10352               (unsigned char) (0xFF >> (8 - bstr)));
10353
10354       if (AOP_TYPE (right) == AOP_LIT)
10355         {
10356           /* Case with a bitfield length <8 and literal source
10357           */
10358           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10359           litval <<= bstr;
10360           litval &= (~mask) & 0xff;
10361           emitPtrByteGet (rname, p_type, FALSE);
10362           if ((mask|litval)!=0xff)
10363             emitcode ("anl","a,#!constbyte", mask);
10364           if (litval)
10365             emitcode ("orl","a,#!constbyte", litval);
10366         }
10367       else
10368         {
10369           if ((blen==1) && (p_type!=GPOINTER))
10370             {
10371               /* Case with a bitfield length == 1 and no generic pointer
10372               */
10373               if (AOP_TYPE (right) == AOP_CRY)
10374                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10375               else
10376                 {
10377                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10378                   emitcode ("rrc","a");
10379                 }
10380               emitPtrByteGet (rname, p_type, FALSE);
10381               emitcode ("mov","acc.%d,c",bstr);
10382             }
10383           else
10384             {
10385               /* Case with a bitfield length < 8 and arbitrary source
10386               */
10387               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10388               /* shift and mask source value */
10389               AccLsh (bstr);
10390               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10391
10392               /* transfer A to B and get next byte */
10393               emitPtrByteGet (rname, p_type, TRUE);
10394
10395               emitcode ("anl", "a,#!constbyte", mask);
10396               emitcode ("orl", "a,b");
10397               if (p_type == GPOINTER)
10398                 emitcode ("pop", "b");
10399            }
10400         }
10401
10402       emitPtrByteSet (rname, p_type, "a");
10403       return;
10404     }
10405
10406   /* Bit length is greater than 7 bits. In this case, copy  */
10407   /* all except the partial byte at the end                 */
10408   for (rlen=blen;rlen>=8;rlen-=8)
10409     {
10410       emitPtrByteSet (rname, p_type, 
10411                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10412       if (rlen>8)
10413         emitcode ("inc", "%s", rname);
10414     }
10415
10416   /* If there was a partial byte at the end */
10417   if (rlen)
10418     {
10419       mask = (((unsigned char) -1 << rlen) & 0xff);
10420       
10421       if (AOP_TYPE (right) == AOP_LIT)
10422         {
10423           /* Case with partial byte and literal source
10424           */
10425           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10426           litval >>= (blen-rlen);
10427           litval &= (~mask) & 0xff;
10428           emitPtrByteGet (rname, p_type, FALSE);
10429           if ((mask|litval)!=0xff)
10430             emitcode ("anl","a,#!constbyte", mask);
10431           if (litval)
10432             emitcode ("orl","a,#!constbyte", litval);
10433         }
10434       else
10435         {
10436           /* Case with partial byte and arbitrary source
10437           */
10438           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10439           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10440
10441           /* transfer A to B and get next byte */
10442           emitPtrByteGet (rname, p_type, TRUE);
10443
10444           emitcode ("anl", "a,#!constbyte", mask);
10445           emitcode ("orl", "a,b");
10446           if (p_type == GPOINTER)
10447             emitcode ("pop", "b");
10448         }
10449       emitPtrByteSet (rname, p_type, "a");
10450     }
10451
10452 }
10453
10454
10455 /*-----------------------------------------------------------------*/
10456 /* genDataPointerSet - remat pointer to data space                 */
10457 /*-----------------------------------------------------------------*/
10458 static void
10459 genDataPointerSet (operand * right,
10460                    operand * result,
10461                    iCode * ic)
10462 {
10463   int size, offset = 0;
10464   char *l, buff[256];
10465
10466   aopOp (right, ic, FALSE, FALSE);
10467
10468   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10469   size = AOP_SIZE (right);
10470   while (size--)
10471     {
10472       if (offset)
10473         {
10474             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10475         }
10476       else
10477         {
10478             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10479         }
10480         
10481       emitcode ("mov", "%s,%s", buff,
10482                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10483     }
10484
10485   freeAsmop (right, NULL, ic, TRUE);
10486   freeAsmop (result, NULL, ic, TRUE);
10487 }
10488
10489 /*-----------------------------------------------------------------*/
10490 /* genNearPointerSet - emitcode for near pointer put                */
10491 /*-----------------------------------------------------------------*/
10492 static void
10493 genNearPointerSet (operand * right,
10494                    operand * result,
10495                    iCode * ic,
10496                    iCode * pi)
10497 {
10498   asmop *aop = NULL;
10499   char *rname, *l;
10500   sym_link *retype, *letype;
10501   sym_link *ptype = operandType (result);
10502
10503   retype = getSpec (operandType (right));
10504   letype = getSpec (ptype);
10505
10506   aopOp (result, ic, FALSE, FALSE);
10507
10508   /* if the result is rematerializable &
10509      in data space & not a bit variable */
10510   if (AOP_TYPE (result) == AOP_IMMD &&
10511       DCL_TYPE (ptype) == POINTER &&
10512       !IS_BITVAR (retype) &&
10513       !IS_BITVAR (letype))
10514     {
10515       genDataPointerSet (right, result, ic);
10516       return;
10517     }
10518
10519   /* if the value is already in a pointer register
10520      then don't need anything more */
10521   if (!AOP_INPREG (AOP (result)))
10522     {
10523       /* otherwise get a free pointer register */
10524       regs *preg;
10525         
10526       aop = newAsmop (0);
10527       preg = getFreePtr (ic, &aop, FALSE);
10528       emitcode ("mov", "%s,%s",
10529                 preg->name,
10530                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10531       rname = preg->name;
10532     }
10533   else
10534     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10535
10536   aopOp (right, ic, FALSE, FALSE);
10537
10538   /* if bitfield then unpack the bits */
10539   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10540     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10541   else
10542     {
10543       /* we have can just get the values */
10544       int size = AOP_SIZE (right);
10545       int offset = 0;
10546
10547       while (size--)
10548         {
10549           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10550           if (*l == '@')
10551             {
10552               MOVA (l);
10553               emitcode ("mov", "@%s,a", rname);
10554             }
10555           else
10556             emitcode ("mov", "@%s,%s", rname, l);
10557           if (size || pi)
10558             emitcode ("inc", "%s", rname);
10559           offset++;
10560         }
10561     }
10562
10563   /* now some housekeeping stuff */
10564   if (aop)
10565     {
10566       /* we had to allocate for this iCode */
10567       if (pi) aopPut (AOP (result),rname,0);
10568       freeAsmop (NULL, aop, ic, TRUE);
10569     }
10570   else
10571     {
10572       /* we did not allocate which means left
10573          already in a pointer register, then
10574          if size > 0 && this could be used again
10575          we have to point it back to where it
10576          belongs */
10577       if (AOP_SIZE (right) > 1 &&
10578           !OP_SYMBOL (result)->remat &&
10579           (OP_SYMBOL (result)->liveTo > ic->seq ||
10580            ic->depth) &&
10581           !pi)
10582         {
10583           int size = AOP_SIZE (right) - 1;
10584           while (size--)
10585             emitcode ("dec", "%s", rname);
10586         }
10587     }
10588
10589   /* done */
10590   if (pi) pi->generated = 1;
10591   freeAsmop (result, NULL, ic, TRUE);
10592   freeAsmop (right, NULL, ic, TRUE);
10593
10594
10595 }
10596
10597 /*-----------------------------------------------------------------*/
10598 /* genPagedPointerSet - emitcode for Paged pointer put             */
10599 /*-----------------------------------------------------------------*/
10600 static void
10601 genPagedPointerSet (operand * right,
10602                     operand * result,
10603                     iCode * ic,
10604                     iCode *pi)
10605 {
10606   asmop *aop = NULL;
10607   char *rname;
10608   sym_link *retype, *letype;
10609
10610   retype = getSpec (operandType (right));
10611   letype = getSpec (operandType (result));
10612
10613   aopOp (result, ic, FALSE, FALSE);
10614
10615   /* if the value is already in a pointer register
10616      then don't need anything more */
10617   if (!AOP_INPREG (AOP (result)))
10618     {
10619       /* otherwise get a free pointer register */
10620       regs *preg;
10621         
10622       aop = newAsmop (0);
10623       preg = getFreePtr (ic, &aop, FALSE);
10624       emitcode ("mov", "%s,%s",
10625                 preg->name,
10626                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10627       rname = preg->name;
10628     }
10629   else
10630     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10631
10632   aopOp (right, ic, FALSE, FALSE);
10633
10634   /* if bitfield then unpack the bits */
10635   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10636     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10637   else
10638     {
10639       /* we have can just get the values */
10640       int size = AOP_SIZE (right);
10641       int offset = 0;
10642
10643       while (size--)
10644         {
10645           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10646
10647           emitcode ("movx", "@%s,a", rname);
10648
10649           if (size || pi)
10650             emitcode ("inc", "%s", rname);
10651
10652           offset++;
10653         }
10654     }
10655
10656   /* now some housekeeping stuff */
10657   if (aop)
10658     {
10659       if (pi) aopPut (AOP (result),rname,0);
10660       /* we had to allocate for this iCode */
10661       freeAsmop (NULL, aop, ic, TRUE);
10662     }
10663   else
10664     {
10665       /* we did not allocate which means left
10666          already in a pointer register, then
10667          if size > 0 && this could be used again
10668          we have to point it back to where it
10669          belongs */
10670       if (AOP_SIZE (right) > 1 &&
10671           !OP_SYMBOL (result)->remat &&
10672           (OP_SYMBOL (result)->liveTo > ic->seq ||
10673            ic->depth) &&
10674           !pi)
10675         {
10676           int size = AOP_SIZE (right) - 1;
10677           while (size--)
10678             emitcode ("dec", "%s", rname);
10679         }
10680     }
10681
10682   /* done */
10683   if (pi) pi->generated = 1;
10684   freeAsmop (result, NULL, ic, TRUE);
10685   freeAsmop (right, NULL, ic, TRUE);
10686
10687
10688 }
10689
10690 /*-----------------------------------------------------------------*/
10691 /* genFarPointerSet - set value from far space                     */
10692 /*-----------------------------------------------------------------*/
10693 static void
10694 genFarPointerSet (operand * right,
10695                   operand * result, iCode * ic, iCode *pi)
10696 {
10697   int size, offset, dopi=1;
10698   sym_link *retype = getSpec (operandType (right));
10699   sym_link *letype = getSpec (operandType (result));
10700
10701   aopOp (result, ic, FALSE, FALSE);
10702
10703   /* if the operand is already in dptr
10704      then we do nothing else we move the value to dptr */
10705   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10706     {
10707       /* if this is remateriazable */
10708       if (AOP_TYPE (result) == AOP_IMMD)
10709         emitcode ("mov", "dptr,%s", 
10710                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10711       else
10712         {
10713           /* we need to get it byte by byte */
10714           _startLazyDPSEvaluation ();
10715           if (AOP_TYPE (result) != AOP_DPTR)
10716             {
10717               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10718               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10719               if (options.model == MODEL_FLAT24)
10720                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10721             }
10722           else
10723             {
10724               /* We need to generate a load to DPTR indirect through DPTR. */
10725               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10726                 
10727               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10728               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10729               if (options.model == MODEL_FLAT24)
10730                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10731               emitcode ("pop", "dph");
10732               emitcode ("pop", "dpl");
10733               dopi=0;
10734             }
10735           _endLazyDPSEvaluation ();
10736         }
10737     }
10738   /* so dptr know contains the address */
10739   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10740
10741   /* if bit then unpack */
10742   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10743       if (AOP_INDPTRn(result)) {
10744           genSetDPTR(AOP(result)->aopu.dptr);
10745       }
10746       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10747       if (AOP_INDPTRn(result)) {
10748           genSetDPTR(0);
10749       }
10750   } else {
10751       size = AOP_SIZE (right);
10752       offset = 0;
10753       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10754           while (size--) {
10755               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10756               
10757               genSetDPTR(AOP(result)->aopu.dptr);
10758               emitcode ("movx", "@dptr,a");
10759               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10760                   emitcode ("inc", "dptr");
10761               genSetDPTR (0);
10762           }
10763       } else {
10764           _startLazyDPSEvaluation ();
10765           while (size--) {
10766               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10767               
10768               if (AOP_INDPTRn(result)) {
10769                   genSetDPTR(AOP(result)->aopu.dptr);
10770               } else {
10771                   genSetDPTR (0);
10772               }
10773               _flushLazyDPS ();
10774               
10775               emitcode ("movx", "@dptr,a");
10776               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10777                   emitcode ("inc", "dptr");
10778           }
10779           _endLazyDPSEvaluation ();
10780       }
10781   }
10782   
10783   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10784       if (!AOP_INDPTRn(result)) {
10785           _startLazyDPSEvaluation ();
10786           
10787           aopPut (AOP(result),"dpl",0);
10788           aopPut (AOP(result),"dph",1);
10789           if (options.model == MODEL_FLAT24)
10790               aopPut (AOP(result),"dpx",2);
10791
10792           _endLazyDPSEvaluation ();
10793       }
10794       pi->generated=1;
10795   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10796              AOP_SIZE(right) > 1 &&
10797              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10798       
10799       size = AOP_SIZE (right) - 1;
10800       if (AOP_INDPTRn(result)) {
10801           genSetDPTR(AOP(result)->aopu.dptr);
10802       } 
10803       while (size--) emitcode ("lcall","__decdptr");
10804       if (AOP_INDPTRn(result)) {
10805           genSetDPTR(0);
10806       }
10807   }
10808   freeAsmop (result, NULL, ic, TRUE);
10809   freeAsmop (right, NULL, ic, TRUE);
10810 }
10811
10812 /*-----------------------------------------------------------------*/
10813 /* genGenPointerSet - set value from generic pointer space         */
10814 /*-----------------------------------------------------------------*/
10815 static void
10816 genGenPointerSet (operand * right,
10817                   operand * result, iCode * ic, iCode *pi)
10818 {
10819   int size, offset;
10820   sym_link *retype = getSpec (operandType (right));
10821   sym_link *letype = getSpec (operandType (result));
10822
10823   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10824
10825   /* if the operand is already in dptr
10826      then we do nothing else we move the value to dptr */
10827   if (AOP_TYPE (result) != AOP_STR)
10828     {
10829       _startLazyDPSEvaluation ();
10830       /* if this is remateriazable */
10831       if (AOP_TYPE (result) == AOP_IMMD)
10832         {
10833           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10834           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10835           {
10836               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10837           }
10838           else
10839           {
10840               emitcode ("mov", 
10841                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10842           }
10843         }
10844       else
10845         {                       /* we need to get it byte by byte */
10846           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10847           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10848           if (options.model == MODEL_FLAT24) {
10849             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10850             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10851           } else {
10852             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10853           }
10854         }
10855       _endLazyDPSEvaluation ();
10856     }
10857   /* so dptr + b now contains the address */
10858   _G.bInUse++;
10859   aopOp (right, ic, FALSE, TRUE);
10860   _G.bInUse--;
10861     
10862
10863   /* if bit then unpack */
10864   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10865     {
10866         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10867     }
10868   else
10869     {
10870         size = AOP_SIZE (right);
10871         offset = 0;
10872
10873         _startLazyDPSEvaluation ();
10874         while (size--)
10875         {
10876             if (size)
10877             {
10878                 // Set two bytes at a time, passed in _AP & A.
10879                 // dptr will be incremented ONCE by __gptrputWord.
10880                 //
10881                 // Note: any change here must be coordinated
10882                 // with the implementation of __gptrputWord
10883                 // in device/lib/_gptrput.c
10884                 emitcode("mov", "_ap, %s", 
10885                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10886                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10887                 
10888                 genSetDPTR (0);
10889                 _flushLazyDPS ();
10890                 emitcode ("lcall", "__gptrputWord");
10891                 size--;
10892             }
10893             else
10894             {
10895                 // Only one byte to put.
10896                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10897
10898                 genSetDPTR (0);
10899                 _flushLazyDPS ();               
10900                 emitcode ("lcall", "__gptrput");
10901             }
10902             
10903             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10904             {
10905                 emitcode ("inc", "dptr");
10906             }
10907         }
10908         _endLazyDPSEvaluation ();
10909     }
10910
10911   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10912       _startLazyDPSEvaluation ();
10913       
10914       aopPut (AOP(result),"dpl",0);
10915       aopPut (AOP(result),"dph",1);
10916       if (options.model == MODEL_FLAT24) {
10917           aopPut (AOP(result),"dpx",2);
10918           aopPut (AOP(result),"b",3);
10919       } else {
10920           aopPut (AOP(result),"b",2);
10921       }
10922       _endLazyDPSEvaluation ();
10923       
10924       pi->generated=1;
10925   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10926              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10927       
10928       size = AOP_SIZE (right) - 1;
10929       while (size--) emitcode ("lcall","__decdptr");
10930   }
10931   freeAsmop (result, NULL, ic, TRUE);
10932   freeAsmop (right, NULL, ic, TRUE);
10933 }
10934
10935 /*-----------------------------------------------------------------*/
10936 /* genPointerSet - stores the value into a pointer location        */
10937 /*-----------------------------------------------------------------*/
10938 static void
10939 genPointerSet (iCode * ic, iCode *pi)
10940 {
10941   operand *right, *result;
10942   sym_link *type, *etype;
10943   int p_type;
10944
10945   D (emitcode (";", "genPointerSet "););
10946
10947   right = IC_RIGHT (ic);
10948   result = IC_RESULT (ic);
10949
10950   /* depending on the type of pointer we need to
10951      move it to the correct pointer register */
10952   type = operandType (result);
10953   etype = getSpec (type);
10954   /* if left is of type of pointer then it is simple */
10955   if (IS_PTR (type) && !IS_FUNC (type->next))
10956     {
10957       p_type = DCL_TYPE (type);
10958     }
10959   else
10960     {
10961       /* we have to go by the storage class */
10962       p_type = PTR_TYPE (SPEC_OCLS (etype));
10963     }
10964   /* special case when cast remat */
10965   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10966       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10967           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10968           type = operandType (result);
10969           p_type = DCL_TYPE (type);
10970   }
10971
10972   /* now that we have the pointer type we assign
10973      the pointer values */
10974   switch (p_type)
10975     {
10976
10977     case POINTER:
10978     case IPOINTER:
10979       genNearPointerSet (right, result, ic, pi);
10980       break;
10981
10982     case PPOINTER:
10983       genPagedPointerSet (right, result, ic, pi);
10984       break;
10985
10986     case FPOINTER:
10987       genFarPointerSet (right, result, ic, pi);
10988       break;
10989
10990     case GPOINTER:
10991       genGenPointerSet (right, result, ic, pi);
10992       break;
10993
10994     default:
10995       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10996               "genPointerSet: illegal pointer type");
10997     }
10998
10999 }
11000
11001 /*-----------------------------------------------------------------*/
11002 /* genIfx - generate code for Ifx statement                        */
11003 /*-----------------------------------------------------------------*/
11004 static void
11005 genIfx (iCode * ic, iCode * popIc)
11006 {
11007   operand *cond = IC_COND (ic);
11008   int isbit = 0;
11009
11010   D (emitcode (";", "genIfx "););
11011
11012   aopOp (cond, ic, FALSE, FALSE);
11013
11014   /* get the value into acc */
11015   if (AOP_TYPE (cond) != AOP_CRY)
11016     {
11017         toBoolean (cond);
11018     }
11019   else
11020     {
11021         isbit = 1;
11022     }
11023     
11024   /* the result is now in the accumulator */
11025   freeAsmop (cond, NULL, ic, TRUE);
11026
11027   /* if there was something to be popped then do it */
11028   if (popIc)
11029     genIpop (popIc);
11030
11031   /* if the condition is  a bit variable */
11032   if (isbit && IS_ITEMP (cond) &&
11033       SPIL_LOC (cond))
11034     {
11035         genIfxJump (ic, SPIL_LOC (cond)->rname);
11036     }
11037   else if (isbit && !IS_ITEMP (cond))
11038     {
11039         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11040     }
11041   else
11042     {
11043         genIfxJump (ic, "a");
11044     }
11045
11046   ic->generated = 1;
11047 }
11048
11049 /*-----------------------------------------------------------------*/
11050 /* genAddrOf - generates code for address of                       */
11051 /*-----------------------------------------------------------------*/
11052 static void
11053 genAddrOf (iCode * ic)
11054 {
11055   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11056   int size, offset;
11057
11058   D (emitcode (";", "genAddrOf ");
11059     );
11060
11061   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11062
11063   /* if the operand is on the stack then we
11064      need to get the stack offset of this
11065      variable */
11066   if (sym->onStack) {
11067       
11068       /* if 10 bit stack */
11069       if (options.stack10bit) {
11070           char buff[10];
11071           int  offset;
11072           
11073           tsprintf(buff, sizeof(buff), 
11074                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11075           /* if it has an offset then we need to compute it */
11076 /*        emitcode ("subb", "a,#!constbyte", */
11077 /*                  -((sym->stack < 0) ? */
11078 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11079 /*                    ((short) sym->stack)) & 0xff); */
11080 /*        emitcode ("mov","b,a"); */
11081 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11082 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11083 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11084           if (sym->stack) {
11085               emitcode ("mov", "a,_bpx");
11086               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
11087                                              ((char) (sym->stack - _G.nRegsSaved)) :
11088                                              ((char) sym->stack )) & 0xff);
11089               emitcode ("mov", "b,a");
11090               emitcode ("mov", "a,_bpx+1");
11091               
11092               offset = (((sym->stack < 0) ? 
11093                          ((short) (sym->stack - _G.nRegsSaved)) :
11094                          ((short) sym->stack )) >> 8) & 0xff;
11095           
11096               emitcode ("addc","a,#!constbyte", offset);
11097
11098               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11099               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11100               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11101           } else {
11102               /* we can just move _bp */
11103               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11104               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11105               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11106           }       
11107       } else {
11108           /* if it has an offset then we need to compute it */
11109           if (sym->stack) {
11110               emitcode ("mov", "a,_bp");
11111               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11112               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11113           } else {
11114               /* we can just move _bp */
11115               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11116           }
11117           /* fill the result with zero */
11118           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11119           
11120           
11121           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11122               fprintf (stderr,
11123                        "*** warning: pointer to stack var truncated.\n");
11124           }
11125
11126           offset = 1;
11127           while (size--) {
11128               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11129           }      
11130       }
11131       goto release;
11132   }
11133
11134   /* object not on stack then we need the name */
11135   size = AOP_SIZE (IC_RESULT (ic));
11136   offset = 0;
11137
11138   while (size--)
11139     {
11140       char s[SDCC_NAME_MAX];
11141       if (offset) {
11142           switch (offset) {
11143           case 1:
11144               tsprintf(s, sizeof(s), "#!his",sym->rname);
11145               break;
11146           case 2:
11147               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11148               break;
11149           case 3:
11150               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11151               break;
11152           default: /* should not need this (just in case) */
11153               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11154                        sym->rname,
11155                        offset * 8);
11156           }
11157       } 
11158       else
11159       {
11160           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11161       }
11162         
11163       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11164     }
11165
11166 release:
11167   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11168
11169 }
11170
11171 #if 0 // obsolete, and buggy for != xdata
11172 /*-----------------------------------------------------------------*/
11173 /* genArrayInit - generates code for address of                       */
11174 /*-----------------------------------------------------------------*/
11175 static void
11176 genArrayInit (iCode * ic)
11177 {
11178     literalList *iLoop;
11179     int         ix, count;
11180     int         elementSize = 0, eIndex;
11181     unsigned    val, lastVal;
11182     sym_link    *type;
11183     operand     *left=IC_LEFT(ic);
11184     
11185     D (emitcode (";", "genArrayInit "););
11186
11187     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11188     
11189     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11190     {
11191         // Load immediate value into DPTR.
11192         emitcode("mov", "dptr, %s",
11193              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11194     }
11195     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11196     {
11197 #if 0
11198       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11199               "Unexpected operand to genArrayInit.\n");
11200       exit(1);
11201 #else
11202       // a regression because of SDCCcse.c:1.52
11203       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11204       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11205       if (options.model == MODEL_FLAT24)
11206         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11207 #endif
11208     }
11209     
11210     type = operandType(IC_LEFT(ic));
11211     
11212     if (type && type->next)
11213     {
11214         elementSize = getSize(type->next);
11215     }
11216     else
11217     {
11218         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11219                                 "can't determine element size in genArrayInit.\n");
11220         exit(1);
11221     }
11222     
11223     iLoop = IC_ARRAYILIST(ic);
11224     lastVal = 0xffff;
11225     
11226     while (iLoop)
11227     {
11228         bool firstpass = TRUE;
11229         
11230         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
11231                  iLoop->count, (int)iLoop->literalValue, elementSize);
11232         
11233         ix = iLoop->count;
11234         
11235         while (ix)
11236         {
11237             symbol *tlbl = NULL;
11238             
11239             count = ix > 256 ? 256 : ix;
11240             
11241             if (count > 1)
11242             {
11243                 tlbl = newiTempLabel (NULL);
11244                 if (firstpass || (count & 0xff))
11245                 {
11246                     emitcode("mov", "b, #!constbyte", count & 0xff);
11247                 }
11248                 
11249                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11250             }
11251             
11252             firstpass = FALSE;
11253                 
11254             for (eIndex = 0; eIndex < elementSize; eIndex++)
11255             {
11256                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11257                 if (val != lastVal)
11258                 {
11259                     emitcode("mov", "a, #!constbyte", val);
11260                     lastVal = val;
11261                 }
11262                 
11263                 emitcode("movx", "@dptr, a");
11264                 emitcode("inc", "dptr");
11265             }
11266             
11267             if (count > 1)
11268             {
11269                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11270             }
11271             
11272             ix -= count;
11273         }
11274         
11275         iLoop = iLoop->next;
11276     }
11277     
11278     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11279 }
11280 #endif
11281
11282 /*-----------------------------------------------------------------*/
11283 /* genFarFarAssign - assignment when both are in far space         */
11284 /*-----------------------------------------------------------------*/
11285 static void
11286 genFarFarAssign (operand * result, operand * right, iCode * ic)
11287 {
11288   int size = AOP_SIZE (right);
11289   int offset = 0;
11290   symbol *rSym = NULL;
11291
11292   if (size == 1)
11293   {
11294       /* quick & easy case. */
11295       D(emitcode(";","genFarFarAssign (1 byte case)"););      
11296       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11297       freeAsmop (right, NULL, ic, FALSE);
11298       /* now assign DPTR to result */
11299       _G.accInUse++;
11300       aopOp(result, ic, FALSE, FALSE);
11301       _G.accInUse--;
11302       aopPut(AOP(result), "a", 0);
11303       freeAsmop(result, NULL, ic, FALSE);
11304       return;
11305   }
11306   
11307   /* See if we've got an underlying symbol to abuse. */
11308   if (IS_SYMOP(result) && OP_SYMBOL(result))
11309   {
11310       if (IS_TRUE_SYMOP(result))
11311       {
11312           rSym = OP_SYMBOL(result);
11313       }
11314       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11315       {
11316           rSym = OP_SYMBOL(result)->usl.spillLoc;
11317       }
11318   }
11319              
11320   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11321   {
11322       /* We can use the '390 auto-toggle feature to good effect here. */
11323       
11324       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11325       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11326       emitcode ("mov", "dptr,#%s", rSym->rname); 
11327       /* DP2 = result, DP1 = right, DP1 is current. */
11328       while (size)
11329       {
11330           emitcode("movx", "a,@dptr");
11331           emitcode("movx", "@dptr,a");
11332           if (--size)
11333           {
11334                emitcode("inc", "dptr");
11335                emitcode("inc", "dptr");
11336           }
11337       }
11338       emitcode("mov", "dps,#0");
11339       freeAsmop (right, NULL, ic, FALSE);
11340 #if 0
11341 some alternative code for processors without auto-toggle
11342 no time to test now, so later well put in...kpb
11343         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11344         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11345         emitcode ("mov", "dptr,#%s", rSym->rname); 
11346         /* DP2 = result, DP1 = right, DP1 is current. */
11347         while (size)
11348         {
11349           --size;
11350           emitcode("movx", "a,@dptr");
11351           if (size)
11352             emitcode("inc", "dptr");
11353           emitcode("inc", "dps");
11354           emitcode("movx", "@dptr,a");
11355           if (size)
11356             emitcode("inc", "dptr");
11357           emitcode("inc", "dps");
11358         }
11359         emitcode("mov", "dps,#0");
11360         freeAsmop (right, NULL, ic, FALSE);
11361 #endif
11362   }
11363   else
11364   {
11365       D (emitcode (";", "genFarFarAssign"););
11366       aopOp (result, ic, TRUE, TRUE);
11367
11368       _startLazyDPSEvaluation ();
11369       
11370       while (size--)
11371         {
11372           aopPut (AOP (result),
11373                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11374           offset++;
11375         }
11376       _endLazyDPSEvaluation ();
11377       freeAsmop (result, NULL, ic, FALSE);
11378       freeAsmop (right, NULL, ic, FALSE);
11379   }
11380 }
11381
11382 /*-----------------------------------------------------------------*/
11383 /* genAssign - generate code for assignment                        */
11384 /*-----------------------------------------------------------------*/
11385 static void
11386 genAssign (iCode * ic)
11387 {
11388   operand *result, *right;
11389   int size, offset;
11390   unsigned long lit = 0L;
11391
11392   D (emitcode (";", "genAssign ");
11393     );
11394
11395   result = IC_RESULT (ic);
11396   right = IC_RIGHT (ic);
11397
11398   /* if they are the same */
11399   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11400     return;
11401
11402   aopOp (right, ic, FALSE, FALSE);
11403
11404   emitcode (";", "genAssign: resultIsFar = %s",
11405             isOperandInFarSpace (result) ?
11406             "TRUE" : "FALSE");
11407
11408   /* special case both in far space */
11409   if ((AOP_TYPE (right) == AOP_DPTR ||
11410        AOP_TYPE (right) == AOP_DPTR2) &&
11411   /* IS_TRUE_SYMOP(result)       && */
11412       isOperandInFarSpace (result))
11413     {
11414       genFarFarAssign (result, right, ic);
11415       return;
11416     }
11417
11418   aopOp (result, ic, TRUE, FALSE);
11419
11420   /* if they are the same registers */
11421   if (sameRegs (AOP (right), AOP (result)))
11422     goto release;
11423
11424   /* if the result is a bit */
11425   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11426     {
11427       /* if the right size is a literal then
11428          we know what the value is */
11429       if (AOP_TYPE (right) == AOP_LIT)
11430         {
11431           if (((int) operandLitValue (right)))
11432             aopPut (AOP (result), one, 0);
11433           else
11434             aopPut (AOP (result), zero, 0);
11435           goto release;
11436         }
11437
11438       /* the right is also a bit variable */
11439       if (AOP_TYPE (right) == AOP_CRY)
11440         {
11441           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11442           aopPut (AOP (result), "c", 0);
11443           goto release;
11444         }
11445
11446       /* we need to or */
11447       toBoolean (right);
11448       aopPut (AOP (result), "a", 0);
11449       goto release;
11450     }
11451
11452   /* bit variables done */
11453   /* general case */
11454   size = AOP_SIZE (result);
11455   offset = 0;
11456   if (AOP_TYPE (right) == AOP_LIT)
11457     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11458
11459   if ((size > 1) &&
11460       (AOP_TYPE (result) != AOP_REG) &&
11461       (AOP_TYPE (right) == AOP_LIT) &&
11462       !IS_FLOAT (operandType (right)))
11463     {
11464       _startLazyDPSEvaluation ();
11465       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11466         {
11467           aopPut (AOP (result),
11468                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11469                   offset);
11470           offset++;
11471           size--;
11472         }
11473       /* And now fill the rest with zeros. */
11474       if (size)
11475         {
11476           emitcode ("clr", "a");
11477         }
11478       while (size--)
11479         {
11480           aopPut (AOP (result), "a", offset++);
11481         }
11482       _endLazyDPSEvaluation ();
11483     }
11484   else
11485     {
11486       _startLazyDPSEvaluation ();
11487       while (size--)
11488         {
11489           aopPut (AOP (result),
11490                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11491                   offset);
11492           offset++;
11493         }
11494       _endLazyDPSEvaluation ();
11495     }
11496
11497 release:
11498   freeAsmop (right, NULL, ic, FALSE);
11499   freeAsmop (result, NULL, ic, TRUE);
11500 }
11501
11502 /*-----------------------------------------------------------------*/
11503 /* genJumpTab - generates code for jump table                      */
11504 /*-----------------------------------------------------------------*/
11505 static void
11506 genJumpTab (iCode * ic)
11507 {
11508   symbol *jtab;
11509   char *l;
11510
11511   D (emitcode (";", "genJumpTab ");
11512     );
11513
11514   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11515   /* get the condition into accumulator */
11516   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11517   MOVA (l);
11518   /* multiply by four! */
11519   emitcode ("add", "a,acc");
11520   emitcode ("add", "a,acc");
11521   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11522
11523   jtab = newiTempLabel (NULL);
11524   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11525   emitcode ("jmp", "@a+dptr");
11526   emitcode ("", "!tlabeldef", jtab->key + 100);
11527   /* now generate the jump labels */
11528   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11529        jtab = setNextItem (IC_JTLABELS (ic)))
11530     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11531
11532 }
11533
11534 /*-----------------------------------------------------------------*/
11535 /* genCast - gen code for casting                                  */
11536 /*-----------------------------------------------------------------*/
11537 static void
11538 genCast (iCode * ic)
11539 {
11540   operand *result = IC_RESULT (ic);
11541   sym_link *ctype = operandType (IC_LEFT (ic));
11542   sym_link *rtype = operandType (IC_RIGHT (ic));
11543   operand *right = IC_RIGHT (ic);
11544   int size, offset;
11545
11546   D (emitcode (";", "genCast "););
11547
11548   /* if they are equivalent then do nothing */
11549   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11550     return;
11551
11552   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11553   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11554
11555   /* if the result is a bit */
11556   if (IS_BITVAR (OP_SYMBOL (result)->type)
11557       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11558     {
11559       /* if the right size is a literal then
11560          we know what the value is */
11561       if (AOP_TYPE (right) == AOP_LIT)
11562         {
11563           if (((int) operandLitValue (right)))
11564             aopPut (AOP (result), one, 0);
11565           else
11566             aopPut (AOP (result), zero, 0);
11567
11568           goto release;
11569         }
11570
11571       /* the right is also a bit variable */
11572       if (AOP_TYPE (right) == AOP_CRY)
11573         {
11574           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11575           aopPut (AOP (result), "c", 0);
11576           goto release;
11577         }
11578
11579       /* we need to or */
11580       toBoolean (right);
11581       aopPut (AOP (result), "a", 0);
11582       goto release;
11583     }
11584
11585   /* if they are the same size : or less */
11586   if (AOP_SIZE (result) <= AOP_SIZE (right))
11587     {
11588
11589       /* if they are in the same place */
11590       if (sameRegs (AOP (right), AOP (result)))
11591         goto release;
11592
11593       /* if they in different places then copy */
11594       size = AOP_SIZE (result);
11595       offset = 0;
11596       _startLazyDPSEvaluation ();
11597       while (size--)
11598         {
11599           aopPut (AOP (result),
11600                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11601                   offset);
11602           offset++;
11603         }
11604       _endLazyDPSEvaluation ();
11605       goto release;
11606     }
11607
11608
11609   /* if the result is of type pointer */
11610   if (IS_PTR (ctype))
11611     {
11612
11613       int p_type;
11614       sym_link *type = operandType (right);
11615
11616       /* pointer to generic pointer */
11617       if (IS_GENPTR (ctype))
11618         {
11619           if (IS_PTR (type))
11620             {
11621               p_type = DCL_TYPE (type);
11622             }
11623           else
11624             {
11625 #if OLD_CAST_BEHAVIOR
11626               /* KV: we are converting a non-pointer type to
11627                * a generic pointer. This (ifdef'd out) code
11628                * says that the resulting generic pointer
11629                * should have the same class as the storage
11630                * location of the non-pointer variable.
11631                *
11632                * For example, converting an int (which happens
11633                * to be stored in DATA space) to a pointer results
11634                * in a DATA generic pointer; if the original int
11635                * in XDATA space, so will be the resulting pointer.
11636                *
11637                * I don't like that behavior, and thus this change:
11638                * all such conversions will be forced to XDATA and
11639                * throw a warning. If you want some non-XDATA
11640                * type, or you want to suppress the warning, you
11641                * must go through an intermediate cast, like so:
11642                *
11643                * char _generic *gp = (char _xdata *)(intVar);
11644                */
11645               sym_link *etype = getSpec (type);
11646
11647               /* we have to go by the storage class */
11648               if (SPEC_OCLS (etype) != generic)
11649                 {
11650                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11651                 }
11652               else
11653 #endif
11654                 {
11655                   /* Converting unknown class (i.e. register variable)
11656                    * to generic pointer. This is not good, but
11657                    * we'll make a guess (and throw a warning).
11658                    */
11659                   p_type = FPOINTER;
11660                   werror (W_INT_TO_GEN_PTR_CAST);
11661                 }
11662             }
11663
11664           /* the first two bytes are known */
11665           size = GPTRSIZE - 1;
11666           offset = 0;
11667           _startLazyDPSEvaluation ();
11668           while (size--)
11669             {
11670               aopPut (AOP (result),
11671                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11672                       offset);
11673               offset++;
11674             }
11675           _endLazyDPSEvaluation ();
11676
11677           /* the last byte depending on type */
11678             {
11679                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11680                 char gpValStr[10];
11681             
11682                 if (gpVal == -1)
11683                 {
11684                     // pointerTypeToGPByte will have bitched.
11685                     exit(1);
11686                 }
11687             
11688                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11689                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11690             }
11691           goto release;
11692         }
11693
11694       /* just copy the pointers */
11695       size = AOP_SIZE (result);
11696       offset = 0;
11697       _startLazyDPSEvaluation ();
11698       while (size--)
11699         {
11700           aopPut (AOP (result),
11701                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11702                   offset);
11703           offset++;
11704         }
11705       _endLazyDPSEvaluation ();
11706       goto release;
11707     }
11708
11709   /* so we now know that the size of destination is greater
11710      than the size of the source */
11711   /* we move to result for the size of source */
11712   size = AOP_SIZE (right);
11713   offset = 0;
11714   _startLazyDPSEvaluation ();
11715   while (size--)
11716     {
11717       aopPut (AOP (result),
11718               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11719               offset);
11720       offset++;
11721     }
11722   _endLazyDPSEvaluation ();
11723
11724   /* now depending on the sign of the source && destination */
11725   size = AOP_SIZE (result) - AOP_SIZE (right);
11726   /* if unsigned or not an integral type */
11727   /* also, if the source is a bit, we don't need to sign extend, because
11728    * it can't possibly have set the sign bit.
11729    */
11730   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11731     {
11732       while (size--)
11733         {
11734           aopPut (AOP (result), zero, offset++);
11735         }
11736     }
11737   else
11738     {
11739       /* we need to extend the sign :{ */
11740       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11741                         FALSE, FALSE, NULL));
11742       emitcode ("rlc", "a");
11743       emitcode ("subb", "a,acc");
11744       while (size--)
11745         aopPut (AOP (result), "a", offset++);
11746     }
11747
11748   /* we are done hurray !!!! */
11749
11750 release:
11751   freeAsmop (right, NULL, ic, TRUE);
11752   freeAsmop (result, NULL, ic, TRUE);
11753
11754 }
11755
11756 /*-----------------------------------------------------------------*/
11757 /* genDjnz - generate decrement & jump if not zero instrucion      */
11758 /*-----------------------------------------------------------------*/
11759 static int
11760 genDjnz (iCode * ic, iCode * ifx)
11761 {
11762   symbol *lbl, *lbl1;
11763   if (!ifx)
11764     return 0;
11765
11766   /* if the if condition has a false label
11767      then we cannot save */
11768   if (IC_FALSE (ifx))
11769     return 0;
11770
11771   /* if the minus is not of the form
11772      a = a - 1 */
11773   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11774       !IS_OP_LITERAL (IC_RIGHT (ic)))
11775     return 0;
11776
11777   if (operandLitValue (IC_RIGHT (ic)) != 1)
11778     return 0;
11779
11780   /* if the size of this greater than one then no
11781      saving */
11782   if (getSize (operandType (IC_RESULT (ic))) > 1)
11783     return 0;
11784
11785   /* otherwise we can save BIG */
11786   D(emitcode(";", "genDjnz"););
11787
11788   lbl = newiTempLabel (NULL);
11789   lbl1 = newiTempLabel (NULL);
11790
11791   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11792
11793   if (AOP_NEEDSACC(IC_RESULT(ic)))
11794   {
11795       /* If the result is accessed indirectly via
11796        * the accumulator, we must explicitly write
11797        * it back after the decrement.
11798        */
11799       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11800       
11801       if (strcmp(rByte, "a"))
11802       {
11803            /* Something is hopelessly wrong */
11804            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11805                    __FILE__, __LINE__);
11806            /* We can just give up; the generated code will be inefficient,
11807             * but what the hey.
11808             */
11809            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11810            return 0;
11811       }
11812       emitcode ("dec", "%s", rByte);
11813       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11814       emitcode ("jnz", "!tlabel", lbl->key + 100);
11815   }
11816   else if (IS_AOP_PREG (IC_RESULT (ic)))
11817     {
11818       emitcode ("dec", "%s",
11819                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11820       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11821       emitcode ("jnz", "!tlabel", lbl->key + 100);
11822     }
11823   else
11824     {
11825       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11826                 lbl->key + 100);
11827     }
11828   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11829   emitcode ("", "!tlabeldef", lbl->key + 100);
11830   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11831   emitcode ("", "!tlabeldef", lbl1->key + 100);
11832
11833   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11834   ifx->generated = 1;
11835   return 1;
11836 }
11837
11838 /*-----------------------------------------------------------------*/
11839 /* genReceive - generate code for a receive iCode                  */
11840 /*-----------------------------------------------------------------*/
11841 static void
11842 genReceive (iCode * ic)
11843 {
11844     int size = getSize (operandType (IC_RESULT (ic)));
11845     int offset = 0;
11846     int rb1off ;
11847     
11848     D (emitcode (";", "genReceive "););
11849
11850     if (ic->argreg == 1) 
11851     {
11852         /* first parameter */
11853         if (AOP_IS_STR(IC_RESULT(ic)))
11854         {
11855             /* Nothing to do: it's already in the proper place. */
11856             return;
11857         }
11858         else
11859         {
11860             bool useDp2;
11861             
11862             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11863                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11864                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11865             
11866             _G.accInUse++;
11867             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11868             _G.accInUse--; 
11869             
11870             /* Sanity checking... */
11871             if (AOP_USESDPTR(IC_RESULT(ic)))
11872             {
11873                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11874                         "genReceive got unexpected DPTR.");
11875             }
11876             assignResultValue (IC_RESULT (ic));
11877         }
11878     } 
11879     else 
11880     { 
11881         /* second receive onwards */
11882         /* this gets a little tricky since unused recevies will be
11883          eliminated, we have saved the reg in the type field . and
11884          we use that to figure out which register to use */
11885         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11886         rb1off = ic->argreg;
11887         while (size--) 
11888         {
11889             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11890         }
11891     }
11892     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11893 }
11894
11895 /*-----------------------------------------------------------------*/
11896 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11897 /*-----------------------------------------------------------------*/
11898 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11899 {
11900     operand *from , *to , *count;
11901     symbol *lbl;
11902     bitVect *rsave;
11903     int i;
11904
11905     /* we know it has to be 3 parameters */
11906     assert (nparms == 3);
11907     
11908     rsave = newBitVect(16);
11909     /* save DPTR if it needs to be saved */
11910     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11911             if (bitVectBitValue(ic->rMask,i))
11912                     rsave = bitVectSetBit(rsave,i);
11913     }
11914     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11915                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11916     savermask(rsave);
11917     
11918     to = parms[0];
11919     from = parms[1];
11920     count = parms[2];
11921
11922     aopOp (from, ic->next, FALSE, FALSE);
11923
11924     /* get from into DPTR1 */
11925     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11926     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11927     if (options.model == MODEL_FLAT24) {
11928         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11929     }
11930
11931     freeAsmop (from, NULL, ic, FALSE);
11932     aopOp (to, ic, FALSE, FALSE);
11933     /* get "to" into DPTR */
11934     /* if the operand is already in dptr
11935        then we do nothing else we move the value to dptr */
11936     if (AOP_TYPE (to) != AOP_STR) {
11937         /* if already in DPTR then we need to push */
11938         if (AOP_TYPE(to) == AOP_DPTR) {
11939             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11940             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11941             if (options.model == MODEL_FLAT24)
11942                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11943             emitcode ("pop", "dph");
11944             emitcode ("pop", "dpl");        
11945         } else {
11946             _startLazyDPSEvaluation ();
11947             /* if this is remateriazable */
11948             if (AOP_TYPE (to) == AOP_IMMD) {
11949                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11950             } else {                    /* we need to get it byte by byte */
11951                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11952                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11953                 if (options.model == MODEL_FLAT24) {
11954                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11955                 }
11956             }
11957             _endLazyDPSEvaluation ();
11958         }
11959     }
11960     freeAsmop (to, NULL, ic, FALSE);
11961     _G.dptrInUse = _G.dptr1InUse = 1;
11962     aopOp (count, ic->next->next, FALSE,FALSE);
11963     lbl =newiTempLabel(NULL);
11964
11965     /* now for the actual copy */
11966     if (AOP_TYPE(count) == AOP_LIT && 
11967         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11968         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11969         if (fromc) {
11970             emitcode ("lcall","__bi_memcpyc2x_s");
11971         } else {
11972             emitcode ("lcall","__bi_memcpyx2x_s");
11973         }
11974         freeAsmop (count, NULL, ic, FALSE);
11975     } else {
11976         symbol *lbl1 = newiTempLabel(NULL);
11977         
11978         emitcode (";"," Auto increment but no djnz");
11979         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11980         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11981         freeAsmop (count, NULL, ic, FALSE);
11982         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11983         emitcode ("","!tlabeldef",lbl->key+100);
11984         if (fromc) {
11985             emitcode ("clr","a");
11986             emitcode ("movc", "a,@a+dptr");
11987         } else 
11988             emitcode ("movx", "a,@dptr");
11989         emitcode ("movx", "@dptr,a");
11990         emitcode ("inc", "dptr");
11991         emitcode ("inc", "dptr");
11992         emitcode ("mov","a,b");
11993         emitcode ("orl","a,_ap");
11994         emitcode ("jz","!tlabel",lbl1->key+100);
11995         emitcode ("mov","a,_ap");
11996         emitcode ("add","a,#!constbyte",0xFF);
11997         emitcode ("mov","_ap,a");
11998         emitcode ("mov","a,b");
11999         emitcode ("addc","a,#!constbyte",0xFF);
12000         emitcode ("mov","b,a");
12001         emitcode ("sjmp","!tlabel",lbl->key+100);
12002         emitcode ("","!tlabeldef",lbl1->key+100);
12003     }
12004     emitcode ("mov", "dps,#0"); 
12005     _G.dptrInUse = _G.dptr1InUse = 0;
12006     unsavermask(rsave);
12007
12008 }
12009
12010 /*-----------------------------------------------------------------*/
12011 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12012 /*-----------------------------------------------------------------*/
12013 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12014 {
12015     operand *from , *to , *count;
12016     symbol *lbl,*lbl2;
12017     bitVect *rsave;
12018     int i;
12019
12020     /* we know it has to be 3 parameters */
12021     assert (nparms == 3);
12022     
12023     rsave = newBitVect(16);
12024     /* save DPTR if it needs to be saved */
12025     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12026             if (bitVectBitValue(ic->rMask,i))
12027                     rsave = bitVectSetBit(rsave,i);
12028     }
12029     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12030                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12031     savermask(rsave);
12032     
12033     to = parms[0];
12034     from = parms[1];
12035     count = parms[2];
12036
12037     aopOp (from, ic->next, FALSE, FALSE);
12038
12039     /* get from into DPTR1 */
12040     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12041     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12042     if (options.model == MODEL_FLAT24) {
12043         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12044     }
12045
12046     freeAsmop (from, NULL, ic, FALSE);
12047     aopOp (to, ic, FALSE, FALSE);
12048     /* get "to" into DPTR */
12049     /* if the operand is already in dptr
12050        then we do nothing else we move the value to dptr */
12051     if (AOP_TYPE (to) != AOP_STR) {
12052         /* if already in DPTR then we need to push */
12053         if (AOP_TYPE(to) == AOP_DPTR) {
12054             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12055             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12056             if (options.model == MODEL_FLAT24)
12057                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12058             emitcode ("pop", "dph");
12059             emitcode ("pop", "dpl");        
12060         } else {
12061             _startLazyDPSEvaluation ();
12062             /* if this is remateriazable */
12063             if (AOP_TYPE (to) == AOP_IMMD) {
12064                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12065             } else {                    /* we need to get it byte by byte */
12066                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12067                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12068                 if (options.model == MODEL_FLAT24) {
12069                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12070                 }
12071             }
12072             _endLazyDPSEvaluation ();
12073         }
12074     }
12075     freeAsmop (to, NULL, ic, FALSE);
12076     _G.dptrInUse = _G.dptr1InUse = 1;
12077     aopOp (count, ic->next->next, FALSE,FALSE);
12078     lbl =newiTempLabel(NULL);
12079     lbl2 =newiTempLabel(NULL);
12080
12081     /* now for the actual compare */
12082     if (AOP_TYPE(count) == AOP_LIT && 
12083         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12084         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12085         if (fromc)
12086             emitcode("lcall","__bi_memcmpc2x_s");
12087         else
12088             emitcode("lcall","__bi_memcmpx2x_s");
12089         freeAsmop (count, NULL, ic, FALSE);
12090         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12091         aopPut(AOP(IC_RESULT(ic)),"a",0);
12092         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12093     } else {
12094         symbol *lbl1 = newiTempLabel(NULL);
12095
12096         emitcode("push","ar0");         
12097         emitcode (";"," Auto increment but no djnz");
12098         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12099         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12100         freeAsmop (count, NULL, ic, FALSE);
12101         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12102         emitcode ("","!tlabeldef",lbl->key+100);
12103         if (fromc) {
12104             emitcode ("clr","a");
12105             emitcode ("movc", "a,@a+dptr");
12106         } else 
12107             emitcode ("movx", "a,@dptr");
12108         emitcode ("mov","r0,a");
12109         emitcode ("movx", "a,@dptr");
12110         emitcode ("clr","c");
12111         emitcode ("subb","a,r0");
12112         emitcode ("jnz","!tlabel",lbl2->key+100);
12113         emitcode ("inc", "dptr");
12114         emitcode ("inc", "dptr");
12115         emitcode ("mov","a,b");
12116         emitcode ("orl","a,_ap");
12117         emitcode ("jz","!tlabel",lbl1->key+100);
12118         emitcode ("mov","a,_ap");
12119         emitcode ("add","a,#!constbyte",0xFF);
12120         emitcode ("mov","_ap,a");
12121         emitcode ("mov","a,b");
12122         emitcode ("addc","a,#!constbyte",0xFF);
12123         emitcode ("mov","b,a");
12124         emitcode ("sjmp","!tlabel",lbl->key+100);
12125         emitcode ("","!tlabeldef",lbl1->key+100);
12126         emitcode ("clr","a");
12127         emitcode ("","!tlabeldef",lbl2->key+100);
12128         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12129         aopPut(AOP(IC_RESULT(ic)),"a",0);
12130         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12131         emitcode("pop","ar0");
12132         emitcode ("mov", "dps,#0");      
12133     }
12134     _G.dptrInUse = _G.dptr1InUse = 0;
12135     unsavermask(rsave);
12136
12137 }
12138
12139 /*-----------------------------------------------------------------*/
12140 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12141 /* port, first parameter output area second parameter pointer to   */
12142 /* port third parameter count                                      */
12143 /*-----------------------------------------------------------------*/
12144 static void genInp( iCode *ic, int nparms, operand **parms)
12145 {
12146     operand *from , *to , *count;
12147     symbol *lbl;
12148     bitVect *rsave;
12149     int i;
12150
12151     /* we know it has to be 3 parameters */
12152     assert (nparms == 3);
12153     
12154     rsave = newBitVect(16);
12155     /* save DPTR if it needs to be saved */
12156     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12157             if (bitVectBitValue(ic->rMask,i))
12158                     rsave = bitVectSetBit(rsave,i);
12159     }
12160     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12161                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12162     savermask(rsave);
12163     
12164     to = parms[0];
12165     from = parms[1];
12166     count = parms[2];
12167
12168     aopOp (from, ic->next, FALSE, FALSE);
12169
12170     /* get from into DPTR1 */
12171     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12172     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12173     if (options.model == MODEL_FLAT24) {
12174         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12175     }
12176
12177     freeAsmop (from, NULL, ic, FALSE);
12178     aopOp (to, ic, FALSE, FALSE);
12179     /* get "to" into DPTR */
12180     /* if the operand is already in dptr
12181        then we do nothing else we move the value to dptr */
12182     if (AOP_TYPE (to) != AOP_STR) {
12183         /* if already in DPTR then we need to push */
12184         if (AOP_TYPE(to) == AOP_DPTR) {
12185             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12186             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12187             if (options.model == MODEL_FLAT24)
12188                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12189             emitcode ("pop", "dph");
12190             emitcode ("pop", "dpl");        
12191         } else {
12192             _startLazyDPSEvaluation ();
12193             /* if this is remateriazable */
12194             if (AOP_TYPE (to) == AOP_IMMD) {
12195                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12196             } else {                    /* we need to get it byte by byte */
12197                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12198                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12199                 if (options.model == MODEL_FLAT24) {
12200                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12201                 }
12202             }
12203             _endLazyDPSEvaluation ();
12204         }
12205     }
12206     freeAsmop (to, NULL, ic, FALSE);
12207
12208     _G.dptrInUse = _G.dptr1InUse = 1;
12209     aopOp (count, ic->next->next, FALSE,FALSE);
12210     lbl =newiTempLabel(NULL);
12211
12212     /* now for the actual copy */
12213     if (AOP_TYPE(count) == AOP_LIT && 
12214         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12215         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12216         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12217         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12218         freeAsmop (count, NULL, ic, FALSE);
12219         emitcode ("","!tlabeldef",lbl->key+100);
12220         emitcode ("movx", "a,@dptr");   /* read data from port */
12221         emitcode ("dec","dps");         /* switch to DPTR */
12222         emitcode ("movx", "@dptr,a");   /* save into location */
12223         emitcode ("inc", "dptr");       /* point to next area */
12224         emitcode ("inc","dps");         /* switch to DPTR2 */
12225         emitcode ("djnz","b,!tlabel",lbl->key+100);
12226     } else {
12227         symbol *lbl1 = newiTempLabel(NULL);
12228         
12229         emitcode (";"," Auto increment but no djnz");
12230         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12231         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12232         freeAsmop (count, NULL, ic, FALSE);
12233         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12234         emitcode ("","!tlabeldef",lbl->key+100);
12235         emitcode ("movx", "a,@dptr");
12236         emitcode ("dec","dps");         /* switch to DPTR */
12237         emitcode ("movx", "@dptr,a");
12238         emitcode ("inc", "dptr");
12239         emitcode ("inc","dps");         /* switch to DPTR2 */
12240 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12241 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12242         emitcode ("mov","a,b");
12243         emitcode ("orl","a,_ap");
12244         emitcode ("jz","!tlabel",lbl1->key+100);
12245         emitcode ("mov","a,_ap");
12246         emitcode ("add","a,#!constbyte",0xFF);
12247         emitcode ("mov","_ap,a");
12248         emitcode ("mov","a,b");
12249         emitcode ("addc","a,#!constbyte",0xFF);
12250         emitcode ("mov","b,a");
12251         emitcode ("sjmp","!tlabel",lbl->key+100);
12252         emitcode ("","!tlabeldef",lbl1->key+100);
12253     }
12254     emitcode ("mov", "dps,#0"); 
12255     _G.dptrInUse = _G.dptr1InUse = 0;
12256     unsavermask(rsave);
12257
12258 }
12259
12260 /*-----------------------------------------------------------------*/
12261 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12262 /* port, first parameter output area second parameter pointer to   */
12263 /* port third parameter count                                      */
12264 /*-----------------------------------------------------------------*/
12265 static void genOutp( iCode *ic, int nparms, operand **parms)
12266 {
12267     operand *from , *to , *count;
12268     symbol *lbl;
12269     bitVect *rsave;
12270     int i;
12271
12272     /* we know it has to be 3 parameters */
12273     assert (nparms == 3);
12274     
12275     rsave = newBitVect(16);
12276     /* save DPTR if it needs to be saved */
12277     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12278             if (bitVectBitValue(ic->rMask,i))
12279                     rsave = bitVectSetBit(rsave,i);
12280     }
12281     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12282                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12283     savermask(rsave);
12284     
12285     to = parms[0];
12286     from = parms[1];
12287     count = parms[2];
12288
12289     aopOp (from, ic->next, FALSE, FALSE);
12290
12291     /* get from into DPTR1 */
12292     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12293     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12294     if (options.model == MODEL_FLAT24) {
12295         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12296     }
12297
12298     freeAsmop (from, NULL, ic, FALSE);
12299     aopOp (to, ic, FALSE, FALSE);
12300     /* get "to" into DPTR */
12301     /* if the operand is already in dptr
12302        then we do nothing else we move the value to dptr */
12303     if (AOP_TYPE (to) != AOP_STR) {
12304         /* if already in DPTR then we need to push */
12305         if (AOP_TYPE(to) == AOP_DPTR) {
12306             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12307             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12308             if (options.model == MODEL_FLAT24)
12309                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12310             emitcode ("pop", "dph");
12311             emitcode ("pop", "dpl");        
12312         } else {
12313             _startLazyDPSEvaluation ();
12314             /* if this is remateriazable */
12315             if (AOP_TYPE (to) == AOP_IMMD) {
12316                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12317             } else {                    /* we need to get it byte by byte */
12318                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12319                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12320                 if (options.model == MODEL_FLAT24) {
12321                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12322                 }
12323             }
12324             _endLazyDPSEvaluation ();
12325         }
12326     }
12327     freeAsmop (to, NULL, ic, FALSE);
12328
12329     _G.dptrInUse = _G.dptr1InUse = 1;
12330     aopOp (count, ic->next->next, FALSE,FALSE);
12331     lbl =newiTempLabel(NULL);
12332
12333     /* now for the actual copy */
12334     if (AOP_TYPE(count) == AOP_LIT && 
12335         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12336         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12337         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12338         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12339         emitcode ("","!tlabeldef",lbl->key+100);
12340         emitcode ("movx", "a,@dptr");   /* read data from port */
12341         emitcode ("inc","dps");         /* switch to DPTR2 */
12342         emitcode ("movx", "@dptr,a");   /* save into location */
12343         emitcode ("inc", "dptr");       /* point to next area */
12344         emitcode ("dec","dps");         /* switch to DPTR */
12345         emitcode ("djnz","b,!tlabel",lbl->key+100);
12346         freeAsmop (count, NULL, ic, FALSE);
12347     } else {
12348         symbol *lbl1 = newiTempLabel(NULL);
12349         
12350         emitcode (";"," Auto increment but no djnz");
12351         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12352         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12353         freeAsmop (count, NULL, ic, FALSE);
12354         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12355         emitcode ("","!tlabeldef",lbl->key+100);
12356         emitcode ("movx", "a,@dptr");
12357         emitcode ("inc", "dptr");
12358         emitcode ("inc","dps");         /* switch to DPTR2 */
12359         emitcode ("movx", "@dptr,a");
12360         emitcode ("dec","dps");         /* switch to DPTR */
12361         emitcode ("mov","a,b");
12362         emitcode ("orl","a,_ap");
12363         emitcode ("jz","!tlabel",lbl1->key+100);
12364         emitcode ("mov","a,_ap");
12365         emitcode ("add","a,#!constbyte",0xFF);
12366         emitcode ("mov","_ap,a");
12367         emitcode ("mov","a,b");
12368         emitcode ("addc","a,#!constbyte",0xFF);
12369         emitcode ("mov","b,a");
12370         emitcode ("sjmp","!tlabel",lbl->key+100);
12371         emitcode ("","!tlabeldef",lbl1->key+100);
12372     }
12373     emitcode ("mov", "dps,#0"); 
12374     _G.dptrInUse = _G.dptr1InUse = 0;
12375     unsavermask(rsave);
12376
12377 }
12378
12379 /*-----------------------------------------------------------------*/
12380 /* genSwapW - swap lower & high order bytes                        */
12381 /*-----------------------------------------------------------------*/
12382 static void genSwapW(iCode *ic, int nparms, operand **parms)
12383 {
12384     operand *dest;
12385     operand *src;
12386     assert (nparms==1);
12387
12388     src = parms[0];
12389     dest=IC_RESULT(ic);
12390
12391     assert(getSize(operandType(src))==2);
12392
12393     aopOp (src, ic, FALSE, FALSE);
12394     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12395     _G.accInUse++;
12396     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12397     _G.accInUse--;
12398     freeAsmop (src, NULL, ic, FALSE);
12399     
12400     aopOp (dest,ic, FALSE, FALSE);
12401     aopPut(AOP(dest),"b",0);
12402     aopPut(AOP(dest),"a",1);
12403     freeAsmop (dest, NULL, ic, FALSE);    
12404 }
12405
12406 /*-----------------------------------------------------------------*/
12407 /* genMemsetX - gencode for memSetX data                           */
12408 /*-----------------------------------------------------------------*/
12409 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12410 {
12411     operand *to , *val , *count;
12412     symbol *lbl;
12413     char *l;
12414     int i;
12415     bitVect *rsave;
12416
12417     /* we know it has to be 3 parameters */
12418     assert (nparms == 3);
12419     
12420     to = parms[0];
12421     val = parms[1];
12422     count = parms[2];
12423         
12424     /* save DPTR if it needs to be saved */
12425     rsave = newBitVect(16);
12426     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12427             if (bitVectBitValue(ic->rMask,i))
12428                     rsave = bitVectSetBit(rsave,i);
12429     }
12430     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12431                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12432     savermask(rsave);
12433
12434     aopOp (to, ic, FALSE, FALSE);
12435     /* get "to" into DPTR */
12436     /* if the operand is already in dptr
12437        then we do nothing else we move the value to dptr */
12438     if (AOP_TYPE (to) != AOP_STR) {
12439         /* if already in DPTR then we need to push */
12440         if (AOP_TYPE(to) == AOP_DPTR) {
12441             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12442             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12443             if (options.model == MODEL_FLAT24)
12444                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12445             emitcode ("pop", "dph");
12446             emitcode ("pop", "dpl");        
12447         } else {
12448             _startLazyDPSEvaluation ();
12449             /* if this is remateriazable */
12450             if (AOP_TYPE (to) == AOP_IMMD) {
12451                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12452             } else {                    /* we need to get it byte by byte */
12453                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12454                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12455                 if (options.model == MODEL_FLAT24) {
12456                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12457                 }
12458             }
12459             _endLazyDPSEvaluation ();
12460         }
12461     }
12462     freeAsmop (to, NULL, ic, FALSE);
12463
12464     aopOp (val, ic->next->next, FALSE,FALSE);
12465     aopOp (count, ic->next->next, FALSE,FALSE);    
12466     lbl =newiTempLabel(NULL);
12467     /* now for the actual copy */
12468     if (AOP_TYPE(count) == AOP_LIT && 
12469         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12470         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12471         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12472         MOVA(l);
12473         emitcode ("","!tlabeldef",lbl->key+100);
12474         emitcode ("movx", "@dptr,a");
12475         emitcode ("inc", "dptr");
12476         emitcode ("djnz","b,!tlabel",lbl->key+100);
12477     } else {
12478         symbol *lbl1 = newiTempLabel(NULL);
12479         
12480         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12481         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12482         emitcode ("","!tlabeldef",lbl->key+100);
12483         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12484         emitcode ("movx", "@dptr,a");
12485         emitcode ("inc", "dptr");
12486         emitcode ("mov","a,b");
12487         emitcode ("orl","a,_ap");
12488         emitcode ("jz","!tlabel",lbl1->key+100);
12489         emitcode ("mov","a,_ap");
12490         emitcode ("add","a,#!constbyte",0xFF);
12491         emitcode ("mov","_ap,a");
12492         emitcode ("mov","a,b");
12493         emitcode ("addc","a,#!constbyte",0xFF);
12494         emitcode ("mov","b,a");
12495         emitcode ("sjmp","!tlabel",lbl->key+100);
12496         emitcode ("","!tlabeldef",lbl1->key+100);
12497     }
12498     freeAsmop (count, NULL, ic, FALSE);
12499     unsavermask(rsave);
12500 }
12501
12502 /*-----------------------------------------------------------------*/
12503 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12504 /*-----------------------------------------------------------------*/
12505 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12506 {
12507         bitVect *rsave ;
12508         operand *pnum, *result;
12509         int i;
12510     
12511         assert (nparms==1);
12512         /* save registers that need to be saved */
12513         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12515     
12516         pnum = parms[0]; 
12517         aopOp (pnum, ic, FALSE, FALSE);
12518         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12519         freeAsmop (pnum, NULL, ic, FALSE);
12520         emitcode ("lcall","NatLib_LoadPrimitive");
12521         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12522         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12523             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12524                 for (i = (size-1) ; i >= 0 ; i-- ) {
12525                         emitcode ("push","a%s",javaRet[i]);
12526                 }
12527                 for (i=0; i < size ; i++ ) {
12528                         emitcode ("pop","a%s",
12529                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12530                 }
12531         } else {
12532                 for (i = 0 ; i < size ; i++ ) {
12533                         aopPut(AOP(result),javaRet[i],i);
12534                 }
12535         }    
12536         freeAsmop (result, NULL, ic, FALSE);
12537         unsavermask(rsave);
12538 }
12539
12540 /*-----------------------------------------------------------------*/
12541 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12542 /*-----------------------------------------------------------------*/
12543 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12544 {
12545         bitVect *rsave ;
12546         operand *pnum, *result;
12547         int size = 3;
12548         int i;
12549     
12550         assert (nparms==1);
12551         /* save registers that need to be saved */
12552         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12553                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12554     
12555         pnum = parms[0]; 
12556         aopOp (pnum, ic, FALSE, FALSE);
12557         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12558         freeAsmop (pnum, NULL, ic, FALSE);
12559         emitcode ("lcall","NatLib_LoadPointer");
12560         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12561         if (AOP_TYPE(result)!=AOP_STR) {
12562                 for (i = 0 ; i < size ; i++ ) {
12563                         aopPut(AOP(result),fReturn[i],i);
12564                 }
12565         }    
12566         freeAsmop (result, NULL, ic, FALSE);
12567         unsavermask(rsave);
12568 }
12569
12570 /*-----------------------------------------------------------------*/
12571 /* genNatLibInstallStateBlock -                                    */
12572 /*-----------------------------------------------------------------*/
12573 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12574                                        operand **parms, const char *name)
12575 {
12576         bitVect *rsave ;
12577         operand *psb, *handle;
12578         assert (nparms==2);
12579
12580         /* save registers that need to be saved */
12581         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12582                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12583         psb = parms[0];
12584         handle = parms[1];
12585
12586         /* put pointer to state block into DPTR1 */
12587         aopOp (psb, ic, FALSE, FALSE);
12588         if (AOP_TYPE (psb) == AOP_IMMD) {
12589                 emitcode ("mov","dps,#1");
12590                 emitcode ("mov", "dptr,%s",
12591                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12592                 emitcode ("mov","dps,#0");
12593         } else {
12594                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12595                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12596                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12597         }
12598         freeAsmop (psb, NULL, ic, FALSE);
12599
12600         /* put libraryID into DPTR */
12601         emitcode ("mov","dptr,#LibraryID");
12602
12603         /* put handle into r3:r2 */
12604         aopOp (handle, ic, FALSE, FALSE);
12605         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12606                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12607                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12608                 emitcode ("pop","ar3");
12609                 emitcode ("pop","ar2");
12610         } else {        
12611                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12612                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12613         }
12614         freeAsmop (psb, NULL, ic, FALSE);
12615
12616         /* make the call */
12617         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12618
12619         /* put return value into place*/
12620         _G.accInUse++;
12621         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12622         _G.accInUse--;
12623         aopPut(AOP(IC_RESULT(ic)),"a",0);
12624         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12625         unsavermask(rsave);
12626 }
12627
12628 /*-----------------------------------------------------------------*/
12629 /* genNatLibRemoveStateBlock -                                     */
12630 /*-----------------------------------------------------------------*/
12631 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12632 {
12633         bitVect *rsave ;
12634
12635         assert(nparms==0);
12636
12637         /* save registers that need to be saved */
12638         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12639                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12640
12641         /* put libraryID into DPTR */
12642         emitcode ("mov","dptr,#LibraryID");
12643         /* make the call */
12644         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12645         unsavermask(rsave);
12646 }
12647
12648 /*-----------------------------------------------------------------*/
12649 /* genNatLibGetStateBlock -                                        */
12650 /*-----------------------------------------------------------------*/
12651 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12652                                    operand **parms,const char *name)
12653 {
12654         bitVect *rsave ;
12655         symbol *lbl = newiTempLabel(NULL);
12656         
12657         assert(nparms==0);
12658         /* save registers that need to be saved */
12659         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12660                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12661
12662         /* put libraryID into DPTR */
12663         emitcode ("mov","dptr,#LibraryID");
12664         /* make the call */
12665         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12666         emitcode ("jnz","!tlabel",lbl->key+100);
12667
12668         /* put return value into place */
12669         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12670         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12671                 emitcode ("push","ar3");
12672                 emitcode ("push","ar2");
12673                 emitcode ("pop","%s",
12674                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12675                 emitcode ("pop","%s",
12676                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12677         } else {
12678                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12679                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12680         }
12681         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12682         emitcode ("","!tlabeldef",lbl->key+100);
12683         unsavermask(rsave);
12684 }
12685
12686 /*-----------------------------------------------------------------*/
12687 /* genMMMalloc -                                                   */
12688 /*-----------------------------------------------------------------*/
12689 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12690                          int size, const char *name)
12691 {
12692         bitVect *rsave ;
12693         operand *bsize;
12694         symbol *rsym;
12695         symbol *lbl = newiTempLabel(NULL);
12696
12697         assert (nparms == 1);
12698         /* save registers that need to be saved */
12699         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12700                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12701         
12702         bsize=parms[0];
12703         aopOp (bsize,ic,FALSE,FALSE);
12704
12705         /* put the size in R4-R2 */
12706         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12707                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12708                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12709                 if (size==3) {
12710                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12711                         emitcode("pop","ar4");
12712                 }
12713                 emitcode("pop","ar3");
12714                 emitcode("pop","ar2");          
12715         } else {
12716                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12717                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12718                 if (size==3) {
12719                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12720                 }
12721         }
12722         freeAsmop (bsize, NULL, ic, FALSE);
12723
12724         /* make the call */
12725         emitcode ("lcall","MM_%s",name);
12726         emitcode ("jz","!tlabel",lbl->key+100);
12727         emitcode ("mov","r2,#!constbyte",0xff);
12728         emitcode ("mov","r3,#!constbyte",0xff);
12729         emitcode ("","!tlabeldef",lbl->key+100);
12730         /* we don't care about the pointer : we just save the handle */
12731         rsym = OP_SYMBOL(IC_RESULT(ic));
12732         if (rsym->liveFrom != rsym->liveTo) {
12733                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12734                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12735                         emitcode ("push","ar3");
12736                         emitcode ("push","ar2");
12737                         emitcode ("pop","%s",
12738                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12739                         emitcode ("pop","%s",
12740                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12741                 } else {
12742                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12743                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12744                 }
12745                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12746         }
12747         unsavermask(rsave);
12748 }
12749
12750 /*-----------------------------------------------------------------*/
12751 /* genMMDeref -                                                    */
12752 /*-----------------------------------------------------------------*/
12753 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12754 {
12755         bitVect *rsave ;
12756         operand *handle;
12757
12758         assert (nparms == 1);
12759         /* save registers that need to be saved */
12760         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12761                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12762         
12763         handle=parms[0];
12764         aopOp (handle,ic,FALSE,FALSE);
12765
12766         /* put the size in R4-R2 */
12767         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12768                 emitcode("push","%s",
12769                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12770                 emitcode("push","%s",
12771                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12772                 emitcode("pop","ar3");
12773                 emitcode("pop","ar2");          
12774         } else {
12775                 emitcode ("mov","r2,%s",
12776                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12777                 emitcode ("mov","r3,%s",
12778                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12779         }
12780         freeAsmop (handle, NULL, ic, FALSE);
12781
12782         /* make the call */
12783         emitcode ("lcall","MM_Deref");
12784         
12785         {
12786                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12787                 if (rsym->liveFrom != rsym->liveTo) {                   
12788                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12789                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12790                             _startLazyDPSEvaluation ();
12791                             
12792                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12793                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12794                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12795
12796                             _endLazyDPSEvaluation ();
12797                             
12798                         }
12799                 }
12800         }
12801         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12802         unsavermask(rsave);
12803 }
12804
12805 /*-----------------------------------------------------------------*/
12806 /* genMMUnrestrictedPersist -                                      */
12807 /*-----------------------------------------------------------------*/
12808 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12809 {
12810         bitVect *rsave ;
12811         operand *handle;
12812
12813         assert (nparms == 1);
12814         /* save registers that need to be saved */
12815         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12816                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12817         
12818         handle=parms[0];
12819         aopOp (handle,ic,FALSE,FALSE);
12820
12821         /* put the size in R3-R2 */
12822         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12823                 emitcode("push","%s",
12824                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12825                 emitcode("push","%s",
12826                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12827                 emitcode("pop","ar3");
12828                 emitcode("pop","ar2");          
12829         } else {
12830                 emitcode ("mov","r2,%s",
12831                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12832                 emitcode ("mov","r3,%s",
12833                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12834         }
12835         freeAsmop (handle, NULL, ic, FALSE);
12836
12837         /* make the call */
12838         emitcode ("lcall","MM_UnrestrictedPersist");
12839
12840         {
12841                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12842                 if (rsym->liveFrom != rsym->liveTo) {   
12843                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12844                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12845                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12846                 }
12847         }
12848         unsavermask(rsave);
12849 }
12850
12851 /*-----------------------------------------------------------------*/
12852 /* genSystemExecJavaProcess -                                      */
12853 /*-----------------------------------------------------------------*/
12854 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12855 {
12856         bitVect *rsave ;
12857         operand *handle, *pp;
12858
12859         assert (nparms==2);
12860         /* save registers that need to be saved */
12861         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12862                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12863         
12864         pp = parms[0];
12865         handle = parms[1];
12866         
12867         /* put the handle in R3-R2 */
12868         aopOp (handle,ic,FALSE,FALSE);
12869         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12870                 emitcode("push","%s",
12871                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12872                 emitcode("push","%s",
12873                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12874                 emitcode("pop","ar3");
12875                 emitcode("pop","ar2");          
12876         } else {
12877                 emitcode ("mov","r2,%s",
12878                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12879                 emitcode ("mov","r3,%s",
12880                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12881         }
12882         freeAsmop (handle, NULL, ic, FALSE);
12883         
12884         /* put pointer in DPTR */
12885         aopOp (pp,ic,FALSE,FALSE);
12886         if (AOP_TYPE(pp) == AOP_IMMD) {
12887                 emitcode ("mov", "dptr,%s",
12888                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12889         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12890                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12891                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12892                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12893         }
12894         freeAsmop (handle, NULL, ic, FALSE);
12895
12896         /* make the call */
12897         emitcode ("lcall","System_ExecJavaProcess");
12898         
12899         /* put result in place */
12900         {
12901                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12902                 if (rsym->liveFrom != rsym->liveTo) {   
12903                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12904                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12905                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12906                 }
12907         }
12908         
12909         unsavermask(rsave);
12910 }
12911
12912 /*-----------------------------------------------------------------*/
12913 /* genSystemRTCRegisters -                                         */
12914 /*-----------------------------------------------------------------*/
12915 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12916                                   char *name)
12917 {
12918         bitVect *rsave ;
12919         operand *pp;
12920
12921         assert (nparms==1);
12922         /* save registers that need to be saved */
12923         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12924                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12925         
12926         pp=parms[0];
12927         /* put pointer in DPTR */
12928         aopOp (pp,ic,FALSE,FALSE);
12929         if (AOP_TYPE (pp) == AOP_IMMD) {
12930                 emitcode ("mov","dps,#1");
12931                 emitcode ("mov", "dptr,%s", 
12932                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12933                 emitcode ("mov","dps,#0");
12934         } else {
12935                 emitcode ("mov","dpl1,%s",
12936                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12937                 emitcode ("mov","dph1,%s",
12938                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12939                 emitcode ("mov","dpx1,%s",
12940                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12941         }
12942         freeAsmop (pp, NULL, ic, FALSE);
12943
12944         /* make the call */
12945         emitcode ("lcall","System_%sRTCRegisters",name);
12946
12947         unsavermask(rsave);
12948 }
12949
12950 /*-----------------------------------------------------------------*/
12951 /* genSystemThreadSleep -                                          */
12952 /*-----------------------------------------------------------------*/
12953 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12954 {
12955         bitVect *rsave ;
12956         operand *to, *s;
12957
12958         assert (nparms==1);
12959         /* save registers that need to be saved */
12960         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12961                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12962
12963         to = parms[0];
12964         aopOp(to,ic,FALSE,FALSE);
12965         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12966             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12967                 emitcode ("push","%s",
12968                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12969                 emitcode ("push","%s",
12970                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12971                 emitcode ("push","%s",
12972                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12973                 emitcode ("push","%s",
12974                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12975                 emitcode ("pop","ar3");
12976                 emitcode ("pop","ar2");
12977                 emitcode ("pop","ar1");
12978                 emitcode ("pop","ar0");
12979         } else {
12980                 emitcode ("mov","r0,%s",
12981                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12982                 emitcode ("mov","r1,%s",
12983                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12984                 emitcode ("mov","r2,%s",
12985                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12986                 emitcode ("mov","r3,%s",
12987                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12988         }
12989         freeAsmop (to, NULL, ic, FALSE);
12990
12991         /* suspend in acc */
12992         s = parms[1];
12993         aopOp(s,ic,FALSE,FALSE);
12994         emitcode ("mov","a,%s",
12995                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12996         freeAsmop (s, NULL, ic, FALSE);
12997
12998         /* make the call */
12999         emitcode ("lcall","System_%s",name);
13000
13001         unsavermask(rsave);
13002 }
13003
13004 /*-----------------------------------------------------------------*/
13005 /* genSystemThreadResume -                                         */
13006 /*-----------------------------------------------------------------*/
13007 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13008 {
13009         bitVect *rsave ;
13010         operand *tid,*pid;
13011
13012         assert (nparms==2);
13013         /* save registers that need to be saved */
13014         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13015                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13016         
13017         tid = parms[0];
13018         pid = parms[1];
13019         
13020         /* PID in R0 */
13021         aopOp(pid,ic,FALSE,FALSE);
13022         emitcode ("mov","r0,%s",
13023                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13024         freeAsmop (pid, NULL, ic, FALSE);
13025         
13026         /* tid into ACC */
13027         aopOp(tid,ic,FALSE,FALSE);
13028         emitcode ("mov","a,%s",
13029                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13030         freeAsmop (tid, NULL, ic, FALSE);
13031         
13032         emitcode ("lcall","System_ThreadResume");
13033
13034         /* put result into place */
13035         {
13036                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13037                 if (rsym->liveFrom != rsym->liveTo) {   
13038                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13039                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13040                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13041                 }
13042         }
13043         unsavermask(rsave);
13044 }
13045
13046 /*-----------------------------------------------------------------*/
13047 /* genSystemProcessResume -                                        */
13048 /*-----------------------------------------------------------------*/
13049 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13050 {
13051         bitVect *rsave ;
13052         operand *pid;
13053
13054         assert (nparms==1);
13055         /* save registers that need to be saved */
13056         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13057                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13058         
13059         pid = parms[0];
13060         
13061         /* pid into ACC */
13062         aopOp(pid,ic,FALSE,FALSE);
13063         emitcode ("mov","a,%s",
13064                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13065         freeAsmop (pid, NULL, ic, FALSE);
13066         
13067         emitcode ("lcall","System_ProcessResume");
13068
13069         unsavermask(rsave);
13070 }
13071
13072 /*-----------------------------------------------------------------*/
13073 /* genSystem -                                                     */
13074 /*-----------------------------------------------------------------*/
13075 static void genSystem (iCode *ic,int nparms,char *name)
13076 {
13077         assert(nparms == 0);
13078
13079         emitcode ("lcall","System_%s",name);
13080 }
13081
13082 /*-----------------------------------------------------------------*/
13083 /* genSystemPoll -                                                  */
13084 /*-----------------------------------------------------------------*/
13085 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13086 {
13087         bitVect *rsave ;
13088         operand *fp;
13089
13090         assert (nparms==1);
13091         /* save registers that need to be saved */
13092         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13093                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13094
13095         fp = parms[0];
13096         aopOp (fp,ic,FALSE,FALSE);
13097         if (AOP_TYPE (fp) == AOP_IMMD) {
13098                 emitcode ("mov", "dptr,%s", 
13099                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13100         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13101                 emitcode ("mov","dpl,%s",
13102                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13103                 emitcode ("mov","dph,%s",
13104                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13105                 emitcode ("mov","dpx,%s",
13106                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13107         }
13108         freeAsmop (fp, NULL, ic, FALSE);
13109
13110         emitcode ("lcall","System_%sPoll",name);
13111
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         unsavermask(rsave);
13122 }
13123
13124 /*-----------------------------------------------------------------*/
13125 /* genSystemGetCurrentID -                                         */
13126 /*-----------------------------------------------------------------*/
13127 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13128 {
13129         assert (nparms==0);
13130
13131         emitcode ("lcall","System_GetCurrent%sId",name);
13132         /* put result into place */
13133         {
13134                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13135                 if (rsym->liveFrom != rsym->liveTo) {   
13136                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13137                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13138                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13139                 }
13140         }
13141 }
13142
13143 /*-----------------------------------------------------------------*/
13144 /* genDummyRead - generate code for dummy read of volatiles        */
13145 /*-----------------------------------------------------------------*/
13146 static void
13147 genDummyRead (iCode * ic)
13148 {
13149   operand *op;
13150   int size, offset;
13151
13152   D(emitcode(";     genDummyRead",""));
13153
13154   op = IC_RIGHT (ic);
13155   if (op && IS_SYMOP (op))
13156     {
13157       aopOp (op, ic, FALSE, FALSE);
13158
13159       /* if the result is a bit */
13160       if (AOP_TYPE (op) == AOP_CRY)
13161         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13162       else
13163         {
13164           /* bit variables done */
13165           /* general case */
13166           size = AOP_SIZE (op);
13167           offset = 0;
13168           while (size--)
13169           {
13170             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13171             offset++;
13172           }
13173         }
13174
13175       freeAsmop (op, NULL, ic, TRUE);
13176     }
13177
13178   op = IC_LEFT (ic);
13179   if (op && IS_SYMOP (op))
13180     {
13181       aopOp (op, ic, FALSE, FALSE);
13182
13183       /* if the result is a bit */
13184       if (AOP_TYPE (op) == AOP_CRY)
13185         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13186       else
13187         {
13188           /* bit variables done */
13189           /* general case */
13190           size = AOP_SIZE (op);
13191           offset = 0;
13192           while (size--)
13193           {
13194             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13195             offset++;
13196           }
13197         }
13198
13199       freeAsmop (op, NULL, ic, TRUE);
13200     }
13201     
13202 }
13203
13204 /*-----------------------------------------------------------------*/
13205 /* genCritical - generate code for start of a critical sequence    */
13206 /*-----------------------------------------------------------------*/
13207 static void
13208 genCritical (iCode *ic)
13209 {
13210   symbol *tlbl = newiTempLabel (NULL);
13211
13212   D(emitcode(";     genCritical",""));
13213   
13214   if (IC_RESULT (ic))
13215     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13216
13217   emitcode ("setb", "c");
13218   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13219   emitcode ("clr", "c");
13220   emitcode ("", "%05d$:", (tlbl->key + 100));
13221
13222   if (IC_RESULT (ic))
13223     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13224   else
13225     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13226
13227   if (IC_RESULT (ic))
13228     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13229 }
13230
13231 /*-----------------------------------------------------------------*/
13232 /* genEndCritical - generate code for end of a critical sequence   */
13233 /*-----------------------------------------------------------------*/
13234 static void
13235 genEndCritical (iCode *ic)
13236 {
13237   D(emitcode(";     genEndCritical",""));
13238   
13239   if (IC_RIGHT (ic))
13240     {
13241       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13242       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13243         {
13244           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13245           emitcode ("mov", "ea,c");
13246         }
13247       else
13248         {
13249           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13250           emitcode ("rrc", "a");
13251           emitcode ("mov", "ea,c");
13252         }
13253       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13254     }
13255   else
13256     {
13257       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13258       emitcode ("mov", "ea,c");
13259     }
13260 }
13261
13262
13263
13264 /*-----------------------------------------------------------------*/
13265 /* genBuiltIn - calls the appropriate function to  generating code */
13266 /* for a built in function                                         */
13267 /*-----------------------------------------------------------------*/
13268 static void genBuiltIn (iCode *ic)
13269 {
13270         operand *bi_parms[MAX_BUILTIN_ARGS];
13271         int nbi_parms;
13272         iCode *bi_iCode;
13273         symbol *bif;
13274
13275         /* get all the arguments for a built in function */
13276         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13277
13278         /* which function is it */
13279         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13280         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13281                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13282         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13283                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13284         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13285                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13286         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13287                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13288         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13289                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13290         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13291                 genInp(bi_iCode,nbi_parms,bi_parms);
13292         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13293                 genOutp(bi_iCode,nbi_parms,bi_parms);
13294         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13295                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13296                 /* JavaNative builtIns */               
13297         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13298                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13299         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13300                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13301         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13302                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13303         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13304                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13305         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13306                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13307         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13308                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13309         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13310                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13311         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13312                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13313         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13314                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13315         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13316                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13317         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13318                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13319         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13320                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13321         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13322                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13323         } else if (strcmp(bif->name,"MM_Free")==0) {
13324                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13325         } else if (strcmp(bif->name,"MM_Deref")==0) {
13326                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13327         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13328                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13329         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13330                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13331         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13332                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13333         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13334                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13335         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13336                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13337         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13338                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13339         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13340                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13341         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13342                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13343         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13344                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13345         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13346                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13347         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13348                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13349         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13350                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13351         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13352                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13353         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13354                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13355         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13356                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13357         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13358                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13359         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13360                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13361         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13362                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13363         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13364                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13365         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13366                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13367         } else {
13368                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13369                 return ;
13370         }
13371         return ;    
13372 }
13373
13374 /*-----------------------------------------------------------------*/
13375 /* gen390Code - generate code for Dallas 390 based controllers     */
13376 /*-----------------------------------------------------------------*/
13377 void
13378 gen390Code (iCode * lic)
13379 {
13380   iCode *ic;
13381   int cln = 0;
13382
13383   lineHead = lineCurr = NULL;
13384   dptrn[1][0] = "dpl1";
13385   dptrn[1][1] = "dph1";
13386   dptrn[1][2] = "dpx1";
13387   
13388   if (options.model == MODEL_FLAT24) {
13389     fReturnSizeDS390 = 5;
13390     fReturn = fReturn24;
13391   } else {
13392     fReturnSizeDS390 = 4;
13393     fReturn = fReturn16;
13394     options.stack10bit=0;
13395   }
13396 #if 1
13397   /* print the allocation information */
13398   if (allocInfo && currFunc)
13399     printAllocInfo (currFunc, codeOutFile);
13400 #endif
13401   /* if debug information required */
13402   if (options.debug && currFunc)
13403     {
13404       debugFile->writeFunction(currFunc);
13405       _G.debugLine = 1;
13406       if (IS_STATIC (currFunc->etype))
13407         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13408       else
13409         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13410       _G.debugLine = 0;
13411     }
13412   /* stack pointer name */
13413   if (options.useXstack)
13414     spname = "_spx";
13415   else
13416     spname = "sp";
13417
13418
13419   for (ic = lic; ic; ic = ic->next)
13420     {
13421
13422       _G.current_iCode = ic;
13423       
13424       if (ic->lineno && cln != ic->lineno)
13425         {
13426           if (options.debug)
13427             {
13428               _G.debugLine = 1;
13429               emitcode ("", "C$%s$%d$%d$%d ==.",
13430                         FileBaseName (ic->filename), ic->lineno,
13431                         ic->level, ic->block);
13432               _G.debugLine = 0;
13433             }
13434           if (!options.noCcodeInAsm) {
13435             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13436                       printCLine(ic->filename, ic->lineno));
13437           }
13438           cln = ic->lineno;
13439         }
13440       if (options.iCodeInAsm) {
13441         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13442       }
13443       /* if the result is marked as
13444          spilt and rematerializable or code for
13445          this has already been generated then
13446          do nothing */
13447       if (resultRemat (ic) || ic->generated)
13448         continue;
13449
13450       /* depending on the operation */
13451       switch (ic->op)
13452         {
13453         case '!':
13454           genNot (ic);
13455           break;
13456
13457         case '~':
13458           genCpl (ic);
13459           break;
13460
13461         case UNARYMINUS:
13462           genUminus (ic);
13463           break;
13464
13465         case IPUSH:
13466           genIpush (ic);
13467           break;
13468
13469         case IPOP:
13470           /* IPOP happens only when trying to restore a
13471              spilt live range, if there is an ifx statement
13472              following this pop then the if statement might
13473              be using some of the registers being popped which
13474              would destory the contents of the register so
13475              we need to check for this condition and handle it */
13476           if (ic->next &&
13477               ic->next->op == IFX &&
13478               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13479             genIfx (ic->next, ic);
13480           else
13481             genIpop (ic);
13482           break;
13483
13484         case CALL:
13485           genCall (ic);
13486           break;
13487
13488         case PCALL:
13489           genPcall (ic);
13490           break;
13491
13492         case FUNCTION:
13493           genFunction (ic);
13494           break;
13495
13496         case ENDFUNCTION:
13497           genEndFunction (ic);
13498           break;
13499
13500         case RETURN:
13501           genRet (ic);
13502           break;
13503
13504         case LABEL:
13505           genLabel (ic);
13506           break;
13507
13508         case GOTO:
13509           genGoto (ic);
13510           break;
13511
13512         case '+':
13513           genPlus (ic);
13514           break;
13515
13516         case '-':
13517           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13518             genMinus (ic);
13519           break;
13520
13521         case '*':
13522           genMult (ic);
13523           break;
13524
13525         case '/':
13526           genDiv (ic);
13527           break;
13528
13529         case '%':
13530           genMod (ic);
13531           break;
13532
13533         case '>':
13534           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13535           break;
13536
13537         case '<':
13538           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13539           break;
13540
13541         case LE_OP:
13542         case GE_OP:
13543         case NE_OP:
13544
13545           /* note these two are xlated by algebraic equivalence
13546              during parsing SDCC.y */
13547           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13548                   "got '>=' or '<=' shouldn't have come here");
13549           break;
13550
13551         case EQ_OP:
13552           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13553           break;
13554
13555         case AND_OP:
13556           genAndOp (ic);
13557           break;
13558
13559         case OR_OP:
13560           genOrOp (ic);
13561           break;
13562
13563         case '^':
13564           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13565           break;
13566
13567         case '|':
13568           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13569           break;
13570
13571         case BITWISEAND:
13572           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13573           break;
13574
13575         case INLINEASM:
13576           genInline (ic);
13577           break;
13578
13579         case RRC:
13580           genRRC (ic);
13581           break;
13582
13583         case RLC:
13584           genRLC (ic);
13585           break;
13586
13587         case GETHBIT:
13588           genGetHbit (ic);
13589           break;
13590
13591         case LEFT_OP:
13592           genLeftShift (ic);
13593           break;
13594
13595         case RIGHT_OP:
13596           genRightShift (ic);
13597           break;
13598
13599         case GET_VALUE_AT_ADDRESS:
13600           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13601           break;
13602
13603         case '=':
13604           if (POINTER_SET (ic))
13605             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13606           else
13607             genAssign (ic);
13608           break;
13609
13610         case IFX:
13611           genIfx (ic, NULL);
13612           break;
13613
13614         case ADDRESS_OF:
13615           genAddrOf (ic);
13616           break;
13617
13618         case JUMPTABLE:
13619           genJumpTab (ic);
13620           break;
13621
13622         case CAST:
13623           genCast (ic);
13624           break;
13625
13626         case RECEIVE:
13627           genReceive (ic);
13628           break;
13629
13630         case SEND:
13631           if (ic->builtinSEND) genBuiltIn(ic);
13632           else addSet (&_G.sendSet, ic);
13633           break;
13634
13635         case DUMMY_READ_VOLATILE:
13636           genDummyRead (ic);
13637           break;
13638
13639         case CRITICAL:
13640           genCritical (ic);
13641           break;
13642
13643         case ENDCRITICAL:
13644           genEndCritical (ic);
13645           break;
13646         
13647         case SWAP:
13648           genSwap (ic);
13649           break;
13650           
13651 #if 0 // obsolete, and buggy for != xdata
13652         case ARRAYINIT:
13653             genArrayInit(ic);
13654             break;
13655 #endif
13656             
13657         default:
13658           ic = ic;
13659         }
13660     }
13661
13662
13663   /* now we are ready to call the
13664      peep hole optimizer */
13665   if (!options.nopeep)
13666     peepHole (&lineHead);
13667
13668   /* now do the actual printing */
13669   printLine (lineHead, codeOutFile);
13670   return;
13671 }