Feature request 799831: added code to allow nesting of critical functions
[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   }
83 _G;
84
85 static char *rb1regs[] = {
86     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 };
88
89 static void saveRBank (int, iCode *, bool);
90
91 #define RESULTONSTACK(x) \
92                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
93                          IC_RESULT(x)->aop->type == AOP_STK )
94
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
97                 
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "_ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
120                                 symbol *lbl = newiTempLabel(NULL);              \
121                                 emitcode ("setb","F1");                         \
122                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
123                                 emitcode ("clr","F1");                          \
124                                 emitcode ("","!tlabeldef",lbl->key+100);        \
125                         }}
126 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
127                                 symbol *lbl = newiTempLabel(NULL);              \
128                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
129                                 emitcode ("setb","EA");                         \
130                                 emitcode ("","!tlabeldef",lbl->key+100);        \
131                         }}
132
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140     va_list ap;
141     char lb[INITIAL_INLINEASM];
142     char *lbp = lb;
143     
144     va_start (ap, fmt);
145     
146     if (inst && *inst)
147     {
148         if (fmt && *fmt)
149         {
150             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
151         }
152         else
153         {
154             SNPRINTF (lb, sizeof(lb), "%s", inst);
155         }
156         
157         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
158                    fmt, ap);
159     }
160     else
161     {
162         tvsprintf (lb, sizeof(lb), fmt, ap);
163     }
164     
165
166     while (isspace (*lbp))
167     {
168         lbp++;
169     }
170
171     if (lbp && *lbp)
172     {
173         lineCurr = (lineCurr ?
174                     connectLine (lineCurr, newLineNode (lb)) :
175                     (lineHead = newLineNode (lb)));
176     }
177     
178     lineCurr->isInline = _G.inLine;
179     lineCurr->isDebug = _G.debugLine;
180     va_end (ap);
181 }
182
183 //
184 // Move the passed value into A unless it is already there.
185 // 
186 static void
187 _movA(const char *s)
188 {
189     if (strcmp(s,"a") && strcmp(s,"acc"))
190     { 
191         emitcode("mov","a,%s",s);
192     } 
193 }
194
195 //
196 // Move the passed value into B unless it is already there.
197 // 
198 static void
199 _movB(const char *s)
200 {
201     if (strcmp(s,"b"))
202     { 
203         emitcode("mov","b,%s",s);
204     } 
205 }
206
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
210 static regs *
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
212 {
213   bool r0iu, r1iu;
214   bool r0ou, r1ou;
215
216   /* the logic: if r0 & r1 used in the instruction
217      then we are in trouble otherwise */
218
219   /* first check if r0 & r1 are used by this
220      instruction, in which case we are in trouble */
221   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
223   if (r0iu && r1iu) {
224       goto endOfWorld;
225     }
226
227   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
229
230   /* if no usage of r0 then return it */
231   if (!r0iu && !r0ou)
232     {
233       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234       (*aopp)->type = AOP_R0;
235
236       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
237     }
238
239   /* if no usage of r1 then return it */
240   if (!r1iu && !r1ou)
241     {
242       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243       (*aopp)->type = AOP_R1;
244
245       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
246     }
247
248   /* now we know they both have usage */
249   /* if r0 not used in this instruction */
250   if (!r0iu)
251     {
252       /* push it if not already pushed */
253       if (!_G.r0Pushed)
254         {
255           emitcode ("push", "%s",
256                     ds390_regWithIdx (R0_IDX)->dname);
257           _G.r0Pushed++;
258         }
259
260       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261       (*aopp)->type = AOP_R0;
262
263       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
264     }
265
266   /* if r1 not used then */
267
268   if (!r1iu)
269     {
270       /* push it if not already pushed */
271       if (!_G.r1Pushed)
272         {
273           emitcode ("push", "%s",
274                     ds390_regWithIdx (R1_IDX)->dname);
275           _G.r1Pushed++;
276         }
277
278       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279       (*aopp)->type = AOP_R1;
280       return ds390_regWithIdx (R1_IDX);
281     }
282
283 endOfWorld:
284   /* I said end of world but not quite end of world yet */
285   /* if this is a result then we can push it on the stack */
286   if (result)
287     {
288       (*aopp)->type = AOP_STK;
289       return NULL;
290     }
291
292   /* other wise this is true end of the world */
293   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294           "getFreePtr should never reach here");
295   exit (1);
296     
297   return NULL; // notreached, but makes compiler happy.
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp                                  */
302 /*-----------------------------------------------------------------*/
303 static asmop *
304 newAsmop (short type)
305 {
306   asmop *aop;
307
308   aop = Safe_calloc (1, sizeof (asmop));
309   aop->type = type;
310   return aop;
311 }
312
313 static int _currentDPS;         /* Current processor DPS. */
314 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
316
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
320 /* alternate DPTR (DPL1/DPH1/DPX1).          */
321 /*-----------------------------------------------------------------*/
322 static void
323 genSetDPTR (int n)
324 {
325
326   /* If we are doing lazy evaluation, simply note the desired
327    * change, but don't emit any code yet.
328    */
329   if (_lazyDPS)
330     {
331       _desiredDPS = n;
332       return;
333     }
334
335   if (!n)
336     {
337       emitcode ("mov", "dps,#0");
338     }
339   else
340     {
341       TR_DPTR("#1");
342       emitcode ("mov", "dps,#1");
343     }
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
348 /*                   */
349 /* Any code that operates on DPTR (NB: not on the individual     */
350 /* components, like DPH) *must* call _flushLazyDPS() before using  */
351 /* DPTR within a lazy DPS evaluation block.        */
352 /*                   */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
355 /* DPS evaluation block.             */
356 /*                   */
357 /* Also, _flushLazyDPS must be called before any flow control      */
358 /* operations that could potentially branch out of the block.    */
359 /*                         */
360 /* Lazy DPS evaluation is simply an optimization (though an      */
361 /* important one), so if in doubt, leave it out.       */
362 /*-----------------------------------------------------------------*/
363 static void
364 _startLazyDPSEvaluation (void)
365 {
366   _currentDPS = 0;
367   _desiredDPS = 0;
368 #ifdef BETTER_LITERAL_SHIFT  
369   _lazyDPS++;
370 #else
371   _lazyDPS = 1;
372 #endif  
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
378 /* block.                */
379 /*-----------------------------------------------------------------*/
380 static void
381 _flushLazyDPS (void)
382 {
383   if (!_lazyDPS)
384     {
385       /* nothing to do. */
386       return;
387     }
388
389   if (_desiredDPS != _currentDPS)
390     {
391       if (_desiredDPS)
392         {
393           emitcode ("inc", "dps");
394         }
395       else
396         {
397           emitcode ("dec", "dps");
398         }
399       _currentDPS = _desiredDPS;
400     }
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
405 /*                   */
406 /* Forces us back to the safe state (standard DPTR selected).    */
407 /*-----------------------------------------------------------------*/
408 static void
409 _endLazyDPSEvaluation (void)
410 {
411 #ifdef BETTER_LITERAL_SHIFT  
412   _lazyDPS--;
413 #else
414   _lazyDPS = 0;
415 #endif    
416   if (!_lazyDPS)
417   {
418     if (_currentDPS)
419     {
420       genSetDPTR (0);
421       _flushLazyDPS ();
422     }
423     _currentDPS = 0;
424     _desiredDPS = 0;
425   }
426 }
427
428
429
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type               */
432 /*-----------------------------------------------------------------*/
433 static int
434 pointerCode (sym_link * etype)
435 {
436
437   return PTR_TYPE (SPEC_OCLS (etype));
438
439 }
440
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands   */
443 /*-----------------------------------------------------------------*/
444 static int
445 leftRightUseAcc(iCode *ic)
446 {
447   operand *op;
448   int size;
449   int accuseSize = 0;
450   int accuse = 0;
451   
452   if (!ic)
453     {
454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455               "null iCode pointer");
456       return 0;
457     }
458
459   if (ic->op == IFX)
460     {
461       op = IC_COND (ic);
462       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
463         {
464           accuse = 1;
465           size = getSize (OP_SYMBOL (op)->type);
466           if (size>accuseSize)
467             accuseSize = size;
468         }
469     }
470   else if (ic->op == JUMPTABLE)
471     {
472       op = IC_JTCOND (ic);
473       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
474         {
475           accuse = 1;
476           size = getSize (OP_SYMBOL (op)->type);
477           if (size>accuseSize)
478             accuseSize = size;
479         }
480     }
481   else
482     {
483       op = IC_LEFT (ic);
484       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
485         {
486           accuse = 1;
487           size = getSize (OP_SYMBOL (op)->type);
488           if (size>accuseSize)
489             accuseSize = size;
490         }
491       op = IC_RIGHT (ic);
492       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
493         {
494           accuse = 1;
495           size = getSize (OP_SYMBOL (op)->type);
496           if (size>accuseSize)
497             accuseSize = size;
498         }
499     }
500   
501   if (accuseSize)
502     return accuseSize;
503   else
504     return accuse;
505 }
506
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol                                   */
509 /*-----------------------------------------------------------------*/
510 static asmop *
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
512 {
513   asmop *aop;
514   memmap *space = SPEC_OCLS (sym->etype);
515   int accuse = leftRightUseAcc (ic);
516
517   /* if already has one */
518   if (sym->aop)
519     return sym->aop;
520
521   /* assign depending on the storage class */
522   /* if it is on the stack or indirectly addressable */
523   /* space we need to assign either r0 or r1 to it   */
524   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
525     {
526       sym->aop = aop = newAsmop (0);
527       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528       aop->size = getSize (sym->type);
529
530       /* now assign the address of the variable to
531          the pointer register */
532       if (aop->type != AOP_STK)
533         {
534
535           if (sym->onStack)
536             {
537               if (_G.accInUse || accuse)
538                 emitcode ("push", "acc");
539
540               if (_G.bInUse || (accuse>1))
541                 emitcode ("push", "b");
542
543               emitcode ("mov", "a,_bp");
544               emitcode ("add", "a,#!constbyte",
545                         ((sym->stack < 0) ?
546                          ((char) (sym->stack - _G.nRegsSaved)) :
547                          ((char) sym->stack)) & 0xff);
548               emitcode ("mov", "%s,a",
549                         aop->aopu.aop_ptr->name);
550
551               if (_G.bInUse || (accuse>1))
552                 emitcode ("pop", "b");
553
554               if (_G.accInUse || accuse)
555                 emitcode ("pop", "acc");
556             }
557           else
558             emitcode ("mov", "%s,#%s",
559                       aop->aopu.aop_ptr->name,
560                       sym->rname);
561           aop->paged = space->paged;
562         }
563       else
564         aop->aopu.aop_stk = sym->stack;
565       return aop;
566     }
567
568   if (sym->onStack && options.stack10bit)
569     {
570         short stack_val = -((sym->stack < 0) ?
571                             ((short) (sym->stack - _G.nRegsSaved)) :
572                             ((short) sym->stack)) ;
573         if (useDP2 && _G.dptr1InUse) {
574             emitcode ("push","dpl1");
575             emitcode ("push","dph1");
576             emitcode ("push","dpx1");
577         } else if (_G.dptrInUse ) {
578             emitcode ("push","dpl");
579             emitcode ("push","dph");
580             emitcode ("push","dpx");
581         }
582       /* It's on the 10 bit stack, which is located in
583        * far data space.
584        */           
585         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
586             if (useDP2) {
587                 if (options.model == MODEL_FLAT24)
588                 {
589                     emitcode ("mov", "dpx1,#!constbyte",
590                               (options.stack_loc >> 16) & 0xff);
591                 }
592                 emitcode ("mov", "dph1,_bpx+1");
593                 
594                 emitcode ("mov", "dpl1,_bpx");
595                 emitcode ("mov","dps,#1");
596             } else {
597                 if (options.model == MODEL_FLAT24)
598                 {
599                     emitcode ("mov", "dpx,#!constbyte",
600                               (options.stack_loc >> 16) & 0xff);
601                 }
602                 emitcode ("mov", "dph,_bpx+1");
603                 emitcode ("mov", "dpl,_bpx");
604             }
605             stack_val = -stack_val;
606             while (stack_val--) {
607                 emitcode ("inc","dptr");
608             }
609             if (useDP2) {
610                 emitcode("mov","dps,#0");
611             }
612         }  else {
613             if (_G.accInUse || accuse)
614                 emitcode ("push", "acc");
615             
616             if (_G.bInUse || (accuse>1))
617                 emitcode ("push", "b");
618         
619             emitcode ("mov", "a,_bpx");
620             emitcode ("clr","c");
621             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622             emitcode ("mov","b,a");
623             emitcode ("mov","a,_bpx+1");
624             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
625             if (useDP2) {
626                 if (options.model == MODEL_FLAT24)
627                 {
628                     emitcode ("mov", "dpx1,#!constbyte",
629                               (options.stack_loc >> 16) & 0xff);
630                 }
631                 emitcode ("mov", "dph1,a");
632                 emitcode ("mov", "dpl1,b");
633             } else {
634                 if (options.model == MODEL_FLAT24)
635                 {
636                     emitcode ("mov", "dpx,#!constbyte",
637                               (options.stack_loc >> 16) & 0xff);
638                 }
639                 emitcode ("mov", "dph,a");
640                 emitcode ("mov", "dpl,b");
641             }
642             
643             if (_G.bInUse || (accuse>1))
644                 emitcode ("pop", "b");
645             
646             if (_G.accInUse || accuse)
647                 emitcode ("pop", "acc");
648         }
649         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650         aop->size = getSize (sym->type);
651         return aop;
652     }
653
654   /* if in bit space */
655   if (IN_BITSPACE (space))
656     {
657       sym->aop = aop = newAsmop (AOP_CRY);
658       aop->aopu.aop_dir = sym->rname;
659       aop->size = getSize (sym->type);
660       return aop;
661     }
662   /* if it is in direct space */
663   if (IN_DIRSPACE (space))
664     {
665       sym->aop = aop = newAsmop (AOP_DIR);
666       aop->aopu.aop_dir = sym->rname;
667       aop->size = getSize (sym->type);
668       return aop;
669     }
670
671   /* special case for a function */
672   if (IS_FUNC (sym->type) && !(sym->isitmp))
673     {
674       sym->aop = aop = newAsmop (AOP_IMMD);
675       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676       aop->size = FPTRSIZE;
677       return aop;
678     }
679
680   /* only remaining is far space */
681   /* in which case DPTR gets the address */
682   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
683   if (useDP2)
684     {
685       genSetDPTR (1);
686       _flushLazyDPS ();
687       emitcode ("mov", "dptr,#%s", sym->rname);
688       genSetDPTR (0);
689     }
690   else
691     {
692       emitcode ("mov", "dptr,#%s", sym->rname);
693     }
694   aop->size = getSize (sym->type);
695
696   /* if it is in code space */
697   if (IN_CODESPACE (space))
698     aop->code = 1;
699
700   return aop;
701 }
702
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object                           */
705 /*-----------------------------------------------------------------*/
706 static asmop *
707 aopForRemat (symbol * sym)
708 {
709   iCode *ic = sym->rematiCode;
710   asmop *aop = newAsmop (AOP_IMMD);
711   int ptr_type =0;
712   int val = 0;
713
714   for (;;)
715     {
716       if (ic->op == '+')
717         val += (int) operandLitValue (IC_RIGHT (ic));
718       else if (ic->op == '-')
719         val -= (int) operandLitValue (IC_RIGHT (ic));
720       else if (IS_CAST_ICODE(ic)) {
721               sym_link *from_type = operandType(IC_RIGHT(ic));
722               aop->aopu.aop_immd.from_cast_remat = 1;
723               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724               ptr_type = DCL_TYPE(from_type);
725               if (ptr_type == IPOINTER) {
726                 // bug #481053
727                 ptr_type = POINTER;
728               }
729               continue ;
730       } else break;
731       
732       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
733     }
734
735   if (val)
736   {
737       SNPRINTF (buffer, sizeof(buffer),
738                 "(%s %c 0x%04x)",
739                 OP_SYMBOL (IC_LEFT (ic))->rname,
740                 val >= 0 ? '+' : '-',
741                 abs (val) & 0xffffff);
742   }
743   else 
744   {
745       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
746       {
747           SNPRINTF(buffer, sizeof(buffer), 
748                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
749       }
750       else
751       {
752           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
753       }
754   }
755
756   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
757   /* set immd2 field if required */
758   if (aop->aopu.aop_immd.from_cast_remat) 
759   {
760       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
762   }
763
764   return aop;
765 }
766
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to       */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
771 {
772     int size =0;
773
774     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
775
776     for (; size < aop->size ; size++) {
777         int reg;
778         for (reg = from ; reg <= to ; reg++)
779             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
780     }
781     return 0;
782 }
783
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common       */
786 /*-----------------------------------------------------------------*/
787 static bool
788 regsInCommon (operand * op1, operand * op2)
789 {
790   symbol *sym1, *sym2;
791   int i;
792
793   /* if they have registers in common */
794   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
795     return FALSE;
796
797   sym1 = OP_SYMBOL (op1);
798   sym2 = OP_SYMBOL (op2);
799
800   if (sym1->nRegs == 0 || sym2->nRegs == 0)
801     return FALSE;
802
803   for (i = 0; i < sym1->nRegs; i++)
804     {
805       int j;
806       if (!sym1->regs[i])
807         continue;
808
809       for (j = 0; j < sym2->nRegs; j++)
810         {
811           if (!sym2->regs[j])
812             continue;
813
814           if (sym2->regs[j] == sym1->regs[i])
815             return TRUE;
816         }
817     }
818
819   return FALSE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent                                        */
824 /*-----------------------------------------------------------------*/
825 static bool
826 operandsEqu (operand * op1, operand * op2)
827 {
828   symbol *sym1, *sym2;
829
830   /* if they not symbols */
831   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
832     return FALSE;
833
834   sym1 = OP_SYMBOL (op1);
835   sym2 = OP_SYMBOL (op2);
836
837   /* if both are itemps & one is spilt
838      and the other is not then false */
839   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840       sym1->isspilt != sym2->isspilt)
841     return FALSE;
842
843   /* if they are the same */
844   if (sym1 == sym2)
845     return TRUE;
846
847   if (strcmp (sym1->rname, sym2->rname) == 0)
848     return TRUE;
849
850
851   /* if left is a tmp & right is not */
852   if (IS_ITEMP (op1) &&
853       !IS_ITEMP (op2) &&
854       sym1->isspilt &&
855       (sym1->usl.spillLoc == sym2))
856     return TRUE;
857
858   if (IS_ITEMP (op2) &&
859       !IS_ITEMP (op1) &&
860       sym2->isspilt &&
861       sym1->level > 0 &&
862       (sym2->usl.spillLoc == sym1))
863     return TRUE;
864
865   return FALSE;
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers                   */
870 /*-----------------------------------------------------------------*/
871 static bool
872 sameRegs (asmop * aop1, asmop * aop2)
873 {
874   int i;
875
876   if (aop1 == aop2)
877     {
878       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
879         {
880           return FALSE;
881         }
882       return TRUE;
883     }
884
885   if (aop1->type != AOP_REG ||
886       aop2->type != AOP_REG)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] !=
894         aop2->aopu.aop_reg[i])
895       return FALSE;
896
897   return TRUE;
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand  :                    */
902 /*-----------------------------------------------------------------*/
903 static void
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
905 {
906   asmop *aop;
907   symbol *sym;
908   int i;
909
910   if (!op)
911     return;
912
913   /* if this a literal */
914   if (IS_OP_LITERAL (op))
915     {
916       op->aop = aop = newAsmop (AOP_LIT);
917       aop->aopu.aop_lit = op->operand.valOperand;
918       aop->size = getSize (operandType (op));
919       return;
920     }
921
922   /* if already has a asmop then continue */
923   if (op->aop)
924     return;
925
926   /* if the underlying symbol has a aop */
927   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
928     {
929       op->aop = OP_SYMBOL (op)->aop;
930       return;
931     }
932
933   /* if this is a true symbol */
934   if (IS_TRUE_SYMOP (op))
935     {
936       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
937       return;
938     }
939
940   /* this is a temporary : this has
941      only four choices :
942      a) register
943      b) spillocation
944      c) rematerialize
945      d) conditional
946      e) can be a return use only */
947
948   sym = OP_SYMBOL (op);
949
950
951   /* if the type is a conditional */
952   if (sym->regType == REG_CND)
953     {
954       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
955       aop->size = 0;
956       return;
957     }
958
959   /* if it is spilt then two situations
960      a) is rematerialize
961      b) has a spill location */
962   if (sym->isspilt || sym->nRegs == 0)
963     {
964
965       /* rematerialize it NOW */
966       if (sym->remat)
967         {
968           sym->aop = op->aop = aop =
969             aopForRemat (sym);
970           aop->size = getSize (sym->type);
971           return;
972         }
973
974       if (sym->accuse)
975         {
976           int i;
977           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978           aop->size = getSize (sym->type);
979           for (i = 0; i < 2; i++)
980             aop->aopu.aop_str[i] = accUse[i];
981           return;
982         }
983
984       if (sym->ruonly)
985         {
986           int i;
987
988           if (useDP2)
989             {
990               /* a AOP_STR uses DPTR, but DPTR is already in use;
991                * we're just hosed.
992                */
993                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
994             }
995
996           aop = op->aop = sym->aop = newAsmop (AOP_STR);
997           aop->size = getSize (sym->type);
998           for (i = 0; i < (int) fReturnSizeDS390; i++)
999             aop->aopu.aop_str[i] = fReturn[i];
1000           return;
1001         }
1002       
1003       if (sym->dptr) { /* has been allocated to a DPTRn */
1004           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005           aop->size = getSize (sym->type);
1006           aop->aopu.dptr = sym->dptr;
1007           return ;
1008       }
1009       /* else spill location  */
1010       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1011           /* force a new aop if sizes differ */
1012           sym->usl.spillLoc->aop = NULL;
1013       }
1014       sym->aop = op->aop = aop =
1015         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1016       aop->size = getSize (sym->type);
1017       return;
1018     }
1019
1020   /* must be in a register */
1021   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1022   aop->size = sym->nRegs;
1023   for (i = 0; i < sym->nRegs; i++)
1024     aop->aopu.aop_reg[i] = sym->regs[i];
1025 }
1026
1027 /*-----------------------------------------------------------------*/
1028 /* freeAsmop - free up the asmop given to an operand               */
1029 /*----------------------------------------------------------------*/
1030 static void
1031 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1032 {
1033   asmop *aop;
1034
1035   if (!op)
1036     aop = aaop;
1037   else
1038     aop = op->aop;
1039
1040   if (!aop)
1041     return;
1042
1043   if (aop->freed)
1044     goto dealloc;
1045
1046   aop->freed = 1;
1047
1048   /* depending on the asmop type only three cases need work AOP_RO
1049      , AOP_R1 && AOP_STK */
1050   switch (aop->type)
1051     {
1052     case AOP_R0:
1053       if (_G.r0Pushed)
1054         {
1055           if (pop)
1056             {
1057               emitcode ("pop", "ar0");
1058               _G.r0Pushed--;
1059             }
1060         }
1061       bitVectUnSetBit (ic->rUsed, R0_IDX);
1062       break;
1063
1064     case AOP_R1:
1065       if (_G.r1Pushed)
1066         {
1067           if (pop)
1068             {
1069               emitcode ("pop", "ar1");
1070               _G.r1Pushed--;
1071             }
1072         }
1073       bitVectUnSetBit (ic->rUsed, R1_IDX);
1074       break;
1075
1076     case AOP_STK:
1077       {
1078         int sz = aop->size;
1079         int stk = aop->aopu.aop_stk + aop->size;
1080         bitVectUnSetBit (ic->rUsed, R0_IDX);
1081         bitVectUnSetBit (ic->rUsed, R1_IDX);
1082
1083         getFreePtr (ic, &aop, FALSE);
1084
1085         if (options.stack10bit)
1086           {
1087             /* I'm not sure what to do here yet... */
1088             /* #STUB */
1089             fprintf (stderr,
1090                      "*** Warning: probably generating bad code for "
1091                      "10 bit stack mode.\n");
1092           }
1093
1094         if (stk)
1095           {
1096             emitcode ("mov", "a,_bp");
1097             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1098             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1099           }
1100         else
1101           {
1102             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1103           }
1104
1105         while (sz--)
1106           {
1107             emitcode ("pop", "acc");
1108             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1109             if (!sz)
1110               break;
1111             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1112           }
1113         op->aop = aop;
1114         freeAsmop (op, NULL, ic, TRUE);
1115         if (_G.r0Pushed)
1116           {
1117             emitcode ("pop", "ar0");
1118             _G.r0Pushed--;
1119           }
1120
1121         if (_G.r1Pushed)
1122           {
1123             emitcode ("pop", "ar1");
1124             _G.r1Pushed--;
1125           }
1126       }
1127     case AOP_DPTR2:
1128         if (_G.dptr1InUse) {
1129             emitcode ("pop","dpx1");
1130             emitcode ("pop","dph1");
1131             emitcode ("pop","dpl1");
1132         }
1133         break;
1134     case AOP_DPTR:
1135         if (_G.dptrInUse) {
1136             emitcode ("pop","dpx");
1137             emitcode ("pop","dph");
1138             emitcode ("pop","dpl");
1139         }
1140         break;
1141     }
1142 dealloc:
1143   /* all other cases just dealloc */
1144   if (op)
1145     {
1146       op->aop = NULL;
1147       if (IS_SYMOP (op))
1148         {
1149           OP_SYMBOL (op)->aop = NULL;
1150           /* if the symbol has a spill */
1151           if (SPIL_LOC (op))
1152             SPIL_LOC (op)->aop = NULL;
1153         }
1154     }
1155 }
1156
1157 #define DEFAULT_ACC_WARNING 0
1158 static int saveAccWarn = DEFAULT_ACC_WARNING;
1159
1160 /*-------------------------------------------------------------------*/
1161 /* aopGet - for fetching value of the aop                            */
1162 /*                                                                   */
1163 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1164 /* in the accumulator. Set it to the name of a free register         */
1165 /* if acc must be preserved; the register will be used to preserve   */
1166 /* acc temporarily and to return the result byte.                    */
1167 /*-------------------------------------------------------------------*/
1168
1169 static char *
1170 aopGet (asmop *aop,
1171         int   offset,
1172         bool  bit16,
1173         bool  dname,
1174         char  *saveAcc)
1175 {
1176   /* offset is greater than
1177      size then zero */
1178   if (offset > (aop->size - 1) &&
1179       aop->type != AOP_LIT)
1180     return zero;
1181
1182   /* depending on type */
1183   switch (aop->type)
1184     {
1185
1186     case AOP_R0:
1187     case AOP_R1:
1188       /* if we need to increment it */
1189       while (offset > aop->coff)
1190         {
1191           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1192           aop->coff++;
1193         }
1194
1195       while (offset < aop->coff)
1196         {
1197           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1198           aop->coff--;
1199         }
1200
1201       aop->coff = offset;
1202       if (aop->paged)
1203         {
1204           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1205           return (dname ? "acc" : "a");
1206         }
1207       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1208       return Safe_strdup(buffer);       
1209
1210     case AOP_DPTRn:
1211         assert(offset <= 3);
1212         return dptrn[aop->aopu.dptr][offset];
1213
1214     case AOP_DPTR:
1215     case AOP_DPTR2:
1216
1217       if (aop->type == AOP_DPTR2)
1218         {
1219           genSetDPTR (1);
1220         }
1221         
1222       if (saveAcc)
1223         {
1224             TR_AP("#1");
1225 //          if (aop->type != AOP_DPTR2)
1226 //          {
1227 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1228 //              emitcode(";", "spanky: saveAcc for DPTR");
1229 //          }
1230             
1231             emitcode ("xch", "a, %s", saveAcc);
1232         }
1233
1234       _flushLazyDPS ();
1235
1236       while (offset > aop->coff)
1237         {
1238           emitcode ("inc", "dptr");
1239           aop->coff++;
1240         }
1241
1242       while (offset < aop->coff)
1243         {
1244           emitcode ("lcall", "__decdptr");
1245           aop->coff--;
1246         }
1247
1248       aop->coff = offset;
1249       if (aop->code)
1250         {
1251           emitcode ("clr", "a");
1252           emitcode ("movc", "a,@a+dptr");
1253         }
1254       else
1255         {
1256           emitcode ("movx", "a,@dptr");
1257         }
1258
1259       if (aop->type == AOP_DPTR2)
1260         {
1261           genSetDPTR (0);
1262         }
1263         
1264         if (saveAcc)
1265         {
1266        TR_AP("#2");
1267               emitcode ("xch", "a, %s", saveAcc);
1268 //            if (strcmp(saveAcc, "_ap"))
1269 //            {
1270 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1271 //            }
1272                   
1273               return saveAcc;
1274         }
1275       return (dname ? "acc" : "a");
1276
1277     case AOP_IMMD:
1278       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1279       {
1280           SNPRINTF(buffer, sizeof(buffer), 
1281                    "%s",aop->aopu.aop_immd.aop_immd2);
1282       } 
1283       else if (bit16)
1284       {
1285          SNPRINTF(buffer, sizeof(buffer), 
1286                   "#%s", aop->aopu.aop_immd.aop_immd1);
1287       }
1288       else if (offset) 
1289       {
1290           switch (offset) {
1291           case 1:
1292               tsprintf(buffer, sizeof(buffer),
1293                        "#!his",aop->aopu.aop_immd.aop_immd1);
1294               break;
1295           case 2:
1296               tsprintf(buffer, sizeof(buffer), 
1297                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1298               break;
1299           case 3:
1300               tsprintf(buffer, sizeof(buffer),
1301                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1302               break;
1303           default: /* should not need this (just in case) */
1304               SNPRINTF (buffer, sizeof(buffer), 
1305                         "#(%s >> %d)",
1306                        aop->aopu.aop_immd.aop_immd1,
1307                        offset * 8);
1308           }
1309       }
1310       else
1311       {
1312         SNPRINTF (buffer, sizeof(buffer), 
1313                   "#%s", aop->aopu.aop_immd.aop_immd1);
1314       }
1315       return Safe_strdup(buffer);       
1316
1317     case AOP_DIR:
1318       if (offset)
1319       {
1320         SNPRINTF (buffer, sizeof(buffer),
1321                   "(%s + %d)",
1322                  aop->aopu.aop_dir,
1323                  offset);
1324       }
1325       else
1326       {
1327         SNPRINTF(buffer, sizeof(buffer), 
1328                  "%s", aop->aopu.aop_dir);
1329       }
1330
1331       return Safe_strdup(buffer);
1332
1333     case AOP_REG:
1334       if (dname)
1335         return aop->aopu.aop_reg[offset]->dname;
1336       else
1337         return aop->aopu.aop_reg[offset]->name;
1338
1339     case AOP_CRY:
1340       emitcode ("clr", "a");
1341       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1342       emitcode ("rlc", "a");
1343       return (dname ? "acc" : "a");
1344
1345     case AOP_ACC:
1346       if (!offset && dname)
1347         return "acc";
1348       return aop->aopu.aop_str[offset];
1349
1350     case AOP_LIT:
1351       return aopLiteral (aop->aopu.aop_lit, offset);
1352
1353     case AOP_STR:
1354       aop->coff = offset;
1355       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1356           dname)
1357         return "acc";
1358
1359       return aop->aopu.aop_str[offset];
1360
1361     }
1362
1363   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1364           "aopget got unsupported aop->type");
1365   exit (1);
1366     
1367   return NULL;  // not reached, but makes compiler happy.
1368 }
1369 /*-----------------------------------------------------------------*/
1370 /* aopPut - puts a string for a aop                                */
1371 /*-----------------------------------------------------------------*/
1372 static void
1373 aopPut (asmop * aop, char *s, int offset)
1374 {
1375   if (aop->size && offset > (aop->size - 1))
1376     {
1377       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378               "aopPut got offset > aop->size");
1379       exit (1);
1380     }
1381
1382   /* will assign value to value */
1383   /* depending on where it is ofcourse */
1384   switch (aop->type)
1385     {
1386     case AOP_DIR:
1387         if (offset)
1388         {
1389             SNPRINTF (buffer, sizeof(buffer),
1390                       "(%s + %d)",
1391                       aop->aopu.aop_dir, offset);
1392         }
1393         else
1394         {
1395             SNPRINTF (buffer, sizeof(buffer), 
1396                      "%s", aop->aopu.aop_dir);
1397         }
1398         
1399
1400         if (strcmp (buffer, s))
1401         {
1402             emitcode ("mov", "%s,%s", buffer, s);
1403         }
1404       break;
1405
1406     case AOP_REG:
1407       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1408           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1409         {
1410           if (*s == '@' ||
1411               strcmp (s, "r0") == 0 ||
1412               strcmp (s, "r1") == 0 ||
1413               strcmp (s, "r2") == 0 ||
1414               strcmp (s, "r3") == 0 ||
1415               strcmp (s, "r4") == 0 ||
1416               strcmp (s, "r5") == 0 ||
1417               strcmp (s, "r6") == 0 ||
1418               strcmp (s, "r7") == 0)
1419             {
1420                 emitcode ("mov", "%s,%s",
1421                           aop->aopu.aop_reg[offset]->dname, s);
1422             }
1423             else
1424             {
1425                 emitcode ("mov", "%s,%s",
1426                           aop->aopu.aop_reg[offset]->name, s);
1427             }
1428         }
1429       break;
1430
1431     case AOP_DPTRn:
1432         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1433         break;
1434
1435     case AOP_DPTR:
1436     case AOP_DPTR2:
1437
1438       if (aop->type == AOP_DPTR2)
1439         {
1440           genSetDPTR (1);
1441         }
1442       _flushLazyDPS ();
1443
1444       if (aop->code)
1445         {
1446           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1447                   "aopPut writting to code space");
1448           exit (1);
1449         }
1450
1451       while (offset > aop->coff)
1452         {
1453           aop->coff++;
1454           emitcode ("inc", "dptr");
1455         }
1456
1457       while (offset < aop->coff)
1458         {
1459           aop->coff--;
1460           emitcode ("lcall", "__decdptr");
1461         }
1462
1463       aop->coff = offset;
1464
1465       /* if not in accumulater */
1466       MOVA (s);
1467
1468       emitcode ("movx", "@dptr,a");
1469
1470       if (aop->type == AOP_DPTR2)
1471         {
1472           genSetDPTR (0);
1473         }
1474       break;
1475
1476     case AOP_R0:
1477     case AOP_R1:
1478       while (offset > aop->coff)
1479         {
1480           aop->coff++;
1481           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1482         }
1483       while (offset < aop->coff)
1484         {
1485           aop->coff--;
1486           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1487         }
1488       aop->coff = offset;
1489
1490       if (aop->paged)
1491         {
1492           MOVA (s);
1493           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1494
1495         }
1496       else if (*s == '@')
1497         {
1498           MOVA (s);
1499           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1500         }
1501       else if (strcmp (s, "r0") == 0 ||
1502                strcmp (s, "r1") == 0 ||
1503                strcmp (s, "r2") == 0 ||
1504                strcmp (s, "r3") == 0 ||
1505                strcmp (s, "r4") == 0 ||
1506                strcmp (s, "r5") == 0 ||
1507                strcmp (s, "r6") == 0 ||
1508                strcmp (s, "r7") == 0)
1509         {
1510           char buff[10];
1511           SNPRINTF(buff, sizeof(buff), 
1512                    "a%s", s);
1513           emitcode ("mov", "@%s,%s",
1514                     aop->aopu.aop_ptr->name, buff);
1515         }
1516         else
1517         {
1518             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1519         }
1520       break;
1521
1522     case AOP_STK:
1523       if (strcmp (s, "a") == 0)
1524         emitcode ("push", "acc");
1525       else
1526         if (*s=='@') {
1527           MOVA(s);
1528           emitcode ("push", "acc");
1529         } else {
1530           emitcode ("push", s);
1531         }
1532
1533       break;
1534
1535     case AOP_CRY:
1536       /* if bit variable */
1537       if (!aop->aopu.aop_dir)
1538         {
1539           emitcode ("clr", "a");
1540           emitcode ("rlc", "a");
1541         }
1542       else
1543         {
1544           if (s == zero)
1545             emitcode ("clr", "%s", aop->aopu.aop_dir);
1546           else if (s == one)
1547             emitcode ("setb", "%s", aop->aopu.aop_dir);
1548           else if (!strcmp (s, "c"))
1549             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1550           else
1551             {
1552               if (strcmp (s, "a"))
1553                 {
1554                   MOVA (s);
1555                 }
1556               {
1557                 /* set C, if a >= 1 */
1558                 emitcode ("add", "a,#!constbyte",0xff);
1559                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1560               }
1561             }
1562         }
1563       break;
1564
1565     case AOP_STR:
1566       aop->coff = offset;
1567       if (strcmp (aop->aopu.aop_str[offset], s))
1568         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1569       break;
1570
1571     case AOP_ACC:
1572       aop->coff = offset;
1573       if (!offset && (strcmp (s, "acc") == 0))
1574         break;
1575
1576       if (strcmp (aop->aopu.aop_str[offset], s))
1577         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1578       break;
1579
1580     default:
1581       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1582               "aopPut got unsupported aop->type");
1583       exit (1);
1584     }
1585
1586 }
1587
1588
1589 /*--------------------------------------------------------------------*/
1590 /* reAdjustPreg - points a register back to where it should (coff==0) */
1591 /*--------------------------------------------------------------------*/
1592 static void
1593 reAdjustPreg (asmop * aop)
1594 {
1595   if ((aop->coff==0) || (aop->size <= 1)) {
1596     return;
1597   }
1598
1599   switch (aop->type)
1600     {
1601     case AOP_R0:
1602     case AOP_R1:
1603       while (aop->coff--)
1604         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1605       break;
1606     case AOP_DPTR:
1607     case AOP_DPTR2:
1608       if (aop->type == AOP_DPTR2)
1609         {
1610           genSetDPTR (1);
1611           _flushLazyDPS ();
1612         }
1613       while (aop->coff--)
1614         {
1615           emitcode ("lcall", "__decdptr");
1616         }
1617
1618       if (aop->type == AOP_DPTR2)
1619         {
1620           genSetDPTR (0);
1621         }
1622       break;
1623
1624     }
1625   aop->coff=0;
1626 }
1627
1628 #define AOP(op) op->aop
1629 #define AOP_TYPE(op) AOP(op)->type
1630 #define AOP_SIZE(op) AOP(op)->size
1631 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1632                        AOP_TYPE(x) == AOP_R0))
1633
1634 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1635                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1636                          AOP(x)->paged))
1637
1638 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1639                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1640                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1641 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1642 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1643 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1644
1645 // The following two macros can be used even if the aop has not yet been aopOp'd.
1646 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1647 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1648
1649 /* Workaround for DS80C390 bug: div ab may return bogus results
1650  * if A is accessed in instruction immediately before the div.
1651  *
1652  * Will be fixed in B4 rev of processor, Dallas claims.
1653  */
1654
1655 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1656     if (!AOP_NEEDSACC(RIGHT))         \
1657     {               \
1658       /* We can load A first, then B, since     \
1659        * B (the RIGHT operand) won't clobber A,   \
1660        * thus avoiding touching A right before the div. \
1661        */             \
1662       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1663       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1664       MOVA(L);            \
1665       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1666       MOVB(L); \
1667     }               \
1668     else              \
1669     {               \
1670       /* Just stuff in a nop after loading A. */    \
1671       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1672       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1673       MOVA(L);            \
1674       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1675     }
1676
1677
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is       */
1680 /* a generic pointer type.             */
1681 /*-----------------------------------------------------------------*/
1682 static int
1683 opIsGptr (operand * op)
1684 {
1685   sym_link *type = operandType (op);
1686
1687   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1688     {
1689       return 1;
1690     }
1691   return 0;
1692 }
1693
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size                         */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 getDataSize (operand * op)
1699 {
1700   int size;
1701   size = AOP_SIZE (op);
1702   if (size == GPTRSIZE)
1703     {
1704       sym_link *type = operandType (op);
1705       if (IS_GENPTR (type))
1706         {
1707           /* generic pointer; arithmetic operations
1708            * should ignore the high byte (pointer type).
1709            */
1710           size--;
1711         }
1712     }
1713   return size;
1714 }
1715
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc                                             */
1718 /*-----------------------------------------------------------------*/
1719 static void
1720 outAcc (operand * result)
1721 {
1722   int size, offset;
1723   size = getDataSize (result);
1724   if (size)
1725     {
1726       aopPut (AOP (result), "a", 0);
1727       size--;
1728       offset = 1;
1729       /* unsigned or positive */
1730       while (size--)
1731         {
1732           aopPut (AOP (result), zero, offset++);
1733         }
1734     }
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C                                        */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 outBitC (operand * result)
1742 {
1743   /* if the result is bit */
1744   if (AOP_TYPE (result) == AOP_CRY)
1745     {
1746       aopPut (AOP (result), "c", 0);
1747     }
1748   else
1749     {
1750       emitcode ("clr", "a");
1751       emitcode ("rlc", "a");
1752       outAcc (result);
1753     }
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* toBoolean - emit code for orl a,operator(sizeop)                */
1758 /*-----------------------------------------------------------------*/
1759 static void
1760 toBoolean (operand * oper)
1761 {
1762   int   size = AOP_SIZE (oper) - 1;
1763   int   offset = 1;
1764   bool usedB = FALSE;
1765
1766   /* The generic part of a generic pointer should
1767    * not participate in it's truth value.
1768    *
1769    * i.e. 0x10000000 is zero.
1770    */
1771   if (opIsGptr (oper))
1772     {
1773       D (emitcode (";", "toBoolean: generic ptr special case."););
1774       size--;
1775     }
1776
1777   _startLazyDPSEvaluation ();
1778   if (AOP_NEEDSACC (oper) && size)
1779     {
1780       usedB = TRUE;
1781       if (_G.bInUse)
1782       {
1783           emitcode ("push", "b");
1784       }
1785       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1786     }
1787   else
1788     {
1789       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1790     }
1791     
1792   while (size--)
1793     {
1794       if (usedB)
1795         {
1796           emitcode ("orl", "b,%s",
1797                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1798         }
1799       else
1800         {
1801           emitcode ("orl", "a,%s",
1802                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1803         }
1804     }
1805   _endLazyDPSEvaluation ();
1806
1807   if (usedB)
1808     {
1809       emitcode ("mov", "a,b");
1810       if (_G.bInUse)
1811       {
1812           emitcode ("pop", "b");
1813       }
1814         
1815     }
1816 }
1817
1818
1819 /*-----------------------------------------------------------------*/
1820 /* genNot - generate code for ! operation                          */
1821 /*-----------------------------------------------------------------*/
1822 static void
1823 genNot (iCode * ic)
1824 {
1825   symbol *tlbl;
1826
1827   D (emitcode (";", "genNot "););
1828
1829   /* assign asmOps to operand & result */
1830   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1831   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1832
1833   /* if in bit space then a special case */
1834   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1835     {
1836       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1837       emitcode ("cpl", "c");
1838       outBitC (IC_RESULT (ic));
1839       goto release;
1840     }
1841
1842   toBoolean (IC_LEFT (ic));
1843
1844   tlbl = newiTempLabel (NULL);
1845   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1846   emitcode ("", "!tlabeldef", tlbl->key + 100);
1847   outBitC (IC_RESULT (ic));
1848
1849 release:
1850   /* release the aops */
1851   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1852   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1853 }
1854
1855
1856 /*-----------------------------------------------------------------*/
1857 /* genCpl - generate code for complement                           */
1858 /*-----------------------------------------------------------------*/
1859 static void
1860 genCpl (iCode * ic)
1861 {
1862   int offset = 0;
1863   int size;
1864   symbol *tlbl;
1865
1866   D (emitcode (";", "genCpl "););
1867
1868
1869   /* assign asmOps to operand & result */
1870   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1871   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1872
1873   /* special case if in bit space */
1874   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1875     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1876       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1877       emitcode ("cpl", "c");
1878       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1879       goto release;
1880     }
1881     tlbl=newiTempLabel(NULL);
1882     emitcode ("cjne", "%s,#0x01,%05d$", 
1883               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1884     emitcode ("", "%05d$:", tlbl->key+100);
1885     outBitC (IC_RESULT(ic));
1886     goto release;
1887   }
1888
1889   size = AOP_SIZE (IC_RESULT (ic));
1890   _startLazyDPSEvaluation ();
1891   while (size--)
1892     {
1893       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1894       emitcode ("cpl", "a");
1895       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1896     }
1897   _endLazyDPSEvaluation ();
1898
1899
1900 release:
1901   /* release the aops */
1902   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1903   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1904 }
1905
1906 /*-----------------------------------------------------------------*/
1907 /* genUminusFloat - unary minus for floating points                */
1908 /*-----------------------------------------------------------------*/
1909 static void
1910 genUminusFloat (operand * op, operand * result)
1911 {
1912   int size, offset = 0;
1913     
1914   D(emitcode (";", "genUminusFloat"););
1915   
1916   /* for this we just copy and then flip the bit */
1917     
1918   _startLazyDPSEvaluation ();
1919   size = AOP_SIZE (op) - 1;
1920
1921   while (size--)
1922   {
1923       aopPut (AOP (result),
1924               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1925               offset);
1926       offset++;
1927     }
1928   
1929   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1930
1931   emitcode ("cpl", "acc.7");
1932   aopPut (AOP (result), "a", offset);    
1933   _endLazyDPSEvaluation ();
1934 }
1935
1936 /*-----------------------------------------------------------------*/
1937 /* genUminus - unary minus code generation                         */
1938 /*-----------------------------------------------------------------*/
1939 static void
1940 genUminus (iCode * ic)
1941 {
1942   int offset, size;
1943   sym_link *optype;
1944
1945   D (emitcode (";", "genUminus "););
1946
1947   /* assign asmops */
1948   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1949   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1950
1951   /* if both in bit space then special
1952      case */
1953   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1954       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1955     {
1956
1957       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1958       emitcode ("cpl", "c");
1959       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1960       goto release;
1961     }
1962
1963   optype = operandType (IC_LEFT (ic));
1964
1965   /* if float then do float stuff */
1966   if (IS_FLOAT (optype))
1967     {
1968       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1969       goto release;
1970     }
1971
1972   /* otherwise subtract from zero */
1973   size = AOP_SIZE (IC_LEFT (ic));
1974   offset = 0;
1975   _startLazyDPSEvaluation ();
1976   while (size--)
1977     {
1978       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1979       if (!strcmp (l, "a"))
1980         {
1981           if (offset == 0)
1982             SETC;
1983           emitcode ("cpl", "a");
1984           emitcode ("addc", "a,#0");
1985         }
1986       else
1987         {
1988           if (offset == 0)
1989             CLRC;
1990           emitcode ("clr", "a");
1991           emitcode ("subb", "a,%s", l);
1992         }
1993       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1994     }
1995   _endLazyDPSEvaluation ();
1996
1997   /* if any remaining bytes in the result */
1998   /* we just need to propagate the sign   */
1999   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2000     {
2001       emitcode ("rlc", "a");
2002       emitcode ("subb", "a,acc");
2003       while (size--)
2004         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2005     }
2006
2007 release:
2008   /* release the aops */
2009   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2010   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2011 }
2012
2013 /*-----------------------------------------------------------------*/
2014 /* savermask - saves registers in the mask                         */
2015 /*-----------------------------------------------------------------*/
2016 static void savermask(bitVect *rs_mask)
2017 {
2018     int i;
2019     if (options.useXstack) {
2020         if (bitVectBitValue (rs_mask, R0_IDX))
2021             emitcode ("mov", "b,r0");
2022         emitcode ("mov", "r0,%s", spname);
2023         for (i = 0; i < ds390_nRegs; i++) {
2024             if (bitVectBitValue (rs_mask, i)) {
2025                 if (i == R0_IDX)
2026                     emitcode ("mov", "a,b");
2027                 else
2028                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2029                 emitcode ("movx", "@r0,a");
2030                 emitcode ("inc", "r0");
2031             }
2032         }
2033         emitcode ("mov", "%s,r0", spname);
2034         if (bitVectBitValue (rs_mask, R0_IDX))
2035             emitcode ("mov", "r0,b");
2036     } else {
2037         for (i = 0; i < ds390_nRegs; i++) {
2038             if (bitVectBitValue (rs_mask, i))
2039                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2040         }
2041     }
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* saveRegisters - will look for a call and save the registers     */
2046 /*-----------------------------------------------------------------*/
2047 static void
2048 saveRegisters (iCode * lic)
2049 {
2050   iCode *ic;
2051   bitVect *rsave;
2052
2053   /* look for call */
2054   for (ic = lic; ic; ic = ic->next)
2055     if (ic->op == CALL || ic->op == PCALL)
2056       break;
2057
2058   if (!ic)
2059     {
2060       fprintf (stderr, "found parameter push with no function call\n");
2061       return;
2062     }
2063
2064   /* if the registers have been saved already then
2065      do nothing */
2066   if (ic->regsSaved 
2067       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2068     return ;
2069
2070   /* special case if DPTR alive across a function call then must save it 
2071      even though callee saves */
2072   if (IS_SYMOP(IC_LEFT(ic)) &&
2073       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2074       int i;
2075       rsave = newBitVect(ic->rMask->size);
2076       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2077           if (bitVectBitValue(ic->rMask,i))
2078               rsave = bitVectSetBit(rsave,i);
2079       }
2080       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2081   } else {
2082     /* safe the registers in use at this time but skip the
2083        ones for the result */
2084     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2085                            ds390_rUmaskForOp (IC_RESULT(ic)));
2086   }
2087   ic->regsSaved = 1;
2088   savermask(rsave);
2089 }
2090
2091 /*-----------------------------------------------------------------*/
2092 /* usavermask - restore registers with mask                        */
2093 /*-----------------------------------------------------------------*/
2094 static void unsavermask(bitVect *rs_mask)
2095 {
2096     int i;
2097     if (options.useXstack) {
2098         emitcode ("mov", "r0,%s", spname);
2099         for (i = ds390_nRegs; i >= 0; i--) {
2100             if (bitVectBitValue (rs_mask, i)) {
2101                 emitcode ("dec", "r0");
2102                 emitcode ("movx", "a,@r0");
2103                 if (i == R0_IDX)
2104                     emitcode ("mov", "b,a");
2105                 else
2106                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2107             }       
2108         }
2109         emitcode ("mov", "%s,r0", spname);
2110         if (bitVectBitValue (rs_mask, R0_IDX))
2111             emitcode ("mov", "r0,b");
2112     } else {
2113         for (i = ds390_nRegs; i >= 0; i--) {
2114             if (bitVectBitValue (rs_mask, i))
2115                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2116         }
2117     }
2118 }
2119
2120 /*-----------------------------------------------------------------*/
2121 /* unsaveRegisters - pop the pushed registers                      */
2122 /*-----------------------------------------------------------------*/
2123 static void
2124 unsaveRegisters (iCode * ic)
2125 {
2126   bitVect *rsave;
2127
2128   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2129       int i;
2130       rsave = newBitVect(ic->rMask->size);
2131       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2132           if (bitVectBitValue(ic->rMask,i))
2133               rsave = bitVectSetBit(rsave,i);
2134       }
2135       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2136   } else {
2137     /* restore the registers in use at this time but skip the
2138        ones for the result */
2139     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2140                            ds390_rUmaskForOp (IC_RESULT(ic)));
2141   }
2142   unsavermask(rsave);
2143 }
2144
2145
2146 /*-----------------------------------------------------------------*/
2147 /* pushSide -                */
2148 /*-----------------------------------------------------------------*/
2149 static void
2150 pushSide (operand * oper, int size)
2151 {
2152   int offset = 0;
2153   _startLazyDPSEvaluation ();
2154   while (size--)
2155     {
2156       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2157       if (AOP_TYPE (oper) != AOP_REG &&
2158           AOP_TYPE (oper) != AOP_DIR &&
2159           strcmp (l, "a"))
2160         {
2161           emitcode ("mov", "a,%s", l);
2162           emitcode ("push", "acc");
2163         }
2164       else
2165         emitcode ("push", "%s", l);
2166     }
2167   _endLazyDPSEvaluation ();
2168 }
2169
2170 /*-----------------------------------------------------------------*/
2171 /* assignResultValue -               */
2172 /*-----------------------------------------------------------------*/
2173 static void
2174 assignResultValue (operand * oper)
2175 {
2176   int offset = 0;
2177   int size = AOP_SIZE (oper);
2178   bool pushedAcc = FALSE;
2179
2180   if (size == fReturnSizeDS390)
2181   {
2182       /* I don't think this case can ever happen... */
2183       /* ACC is the last part of this. If writing the result
2184        * uses AC, we must preserve it.
2185        */
2186       if (AOP_NEEDSACC(oper))
2187       {
2188           emitcode(";", "assignResultValue special case for ACC.");
2189           emitcode("push", "acc");
2190           pushedAcc = TRUE;
2191           size--;
2192       }
2193   }
2194     
2195     
2196   _startLazyDPSEvaluation ();
2197   while (size--)
2198     {
2199       aopPut (AOP (oper), fReturn[offset], offset);
2200       offset++;
2201     }
2202   _endLazyDPSEvaluation ();
2203     
2204   if (pushedAcc)
2205     {
2206         emitcode("pop", "acc");
2207         aopPut(AOP(oper), "a", offset);
2208     }
2209 }
2210
2211
2212 /*-----------------------------------------------------------------*/
2213 /* genXpush - pushes onto the external stack                       */
2214 /*-----------------------------------------------------------------*/
2215 static void
2216 genXpush (iCode * ic)
2217 {
2218   asmop *aop = newAsmop (0);
2219   regs *r;
2220   int size, offset = 0;
2221
2222   D (emitcode (";", "genXpush ");
2223     );
2224
2225   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226   r = getFreePtr (ic, &aop, FALSE);
2227
2228
2229   emitcode ("mov", "%s,_spx", r->name);
2230
2231   size = AOP_SIZE (IC_LEFT (ic));
2232   _startLazyDPSEvaluation ();
2233   while (size--)
2234     {
2235
2236       MOVA (aopGet (AOP (IC_LEFT (ic)),
2237                         offset++, FALSE, FALSE, NULL));
2238       emitcode ("movx", "@%s,a", r->name);
2239       emitcode ("inc", "%s", r->name);
2240
2241     }
2242   _endLazyDPSEvaluation ();
2243
2244
2245   emitcode ("mov", "_spx,%s", r->name);
2246
2247   freeAsmop (NULL, aop, ic, TRUE);
2248   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2249 }
2250
2251 /*-----------------------------------------------------------------*/
2252 /* genIpush - generate code for pushing this gets a little complex  */
2253 /*-----------------------------------------------------------------*/
2254 static void
2255 genIpush (iCode * ic)
2256 {
2257   int size, offset = 0;
2258   char *l;
2259
2260   D (emitcode (";", "genIpush ");
2261     );
2262
2263   /* if this is not a parm push : ie. it is spill push
2264      and spill push is always done on the local stack */
2265   if (!ic->parmPush)
2266     {
2267
2268       /* and the item is spilt then do nothing */
2269       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2270         return;
2271
2272       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2273       size = AOP_SIZE (IC_LEFT (ic));
2274       /* push it on the stack */
2275       _startLazyDPSEvaluation ();
2276       while (size--)
2277         {
2278           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2279           if (*l == '#')
2280             {
2281               MOVA (l);
2282               l = "acc";
2283             }
2284           emitcode ("push", "%s", l);
2285         }
2286       _endLazyDPSEvaluation ();
2287       return;
2288     }
2289
2290   /* this is a paramter push: in this case we call
2291      the routine to find the call and save those
2292      registers that need to be saved */
2293   saveRegisters (ic);
2294
2295   /* if use external stack then call the external
2296      stack pushing routine */
2297   if (options.useXstack)
2298     {
2299       genXpush (ic);
2300       return;
2301     }
2302
2303   /* then do the push */
2304   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2305
2306   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2307   size = AOP_SIZE (IC_LEFT (ic));
2308
2309   _startLazyDPSEvaluation ();
2310   while (size--)
2311     {
2312       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2313       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2314           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2315           strcmp (l, "acc"))
2316         {
2317           emitcode ("mov", "a,%s", l);
2318           emitcode ("push", "acc");
2319         }
2320       else
2321         {
2322             emitcode ("push", "%s", l);
2323         }
2324     }
2325   _endLazyDPSEvaluation ();
2326
2327   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2328 }
2329
2330 /*-----------------------------------------------------------------*/
2331 /* genIpop - recover the registers: can happen only for spilling   */
2332 /*-----------------------------------------------------------------*/
2333 static void
2334 genIpop (iCode * ic)
2335 {
2336   int size, offset;
2337
2338   D (emitcode (";", "genIpop ");
2339     );
2340
2341
2342   /* if the temp was not pushed then */
2343   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2344     return;
2345
2346   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2347   size = AOP_SIZE (IC_LEFT (ic));
2348   offset = (size - 1);
2349   _startLazyDPSEvaluation ();
2350   while (size--)
2351     {
2352       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2353                                      FALSE, TRUE, NULL));
2354     }
2355   _endLazyDPSEvaluation ();
2356
2357   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2358 }
2359
2360 /*-----------------------------------------------------------------*/
2361 /* unsaveRBank - restores the resgister bank from stack            */
2362 /*-----------------------------------------------------------------*/
2363 static void
2364 unsaveRBank (int bank, iCode * ic, bool popPsw)
2365 {
2366   int i;
2367   asmop *aop = NULL;
2368   regs *r = NULL;
2369
2370   if (options.useXstack)
2371   {
2372       if (!ic)
2373       {
2374           /* Assume r0 is available for use. */
2375           r = ds390_regWithIdx (R0_IDX);;          
2376       } 
2377       else
2378       {
2379           aop = newAsmop (0);
2380           r = getFreePtr (ic, &aop, FALSE);
2381       }
2382       emitcode ("mov", "%s,_spx", r->name);      
2383   }
2384   
2385   if (popPsw)
2386     {
2387       if (options.useXstack)
2388       {
2389           emitcode ("movx", "a,@%s", r->name);
2390           emitcode ("mov", "psw,a");
2391           emitcode ("dec", "%s", r->name);
2392         }
2393       else
2394       {
2395         emitcode ("pop", "psw");
2396       }
2397     }
2398
2399   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2400     {
2401       if (options.useXstack)
2402         {
2403           emitcode ("movx", "a,@%s", r->name);
2404           emitcode ("mov", "(%s+%d),a",
2405                     regs390[i].base, 8 * bank + regs390[i].offset);
2406           emitcode ("dec", "%s", r->name);
2407
2408         }
2409       else
2410         emitcode ("pop", "(%s+%d)",
2411                   regs390[i].base, 8 * bank + regs390[i].offset);
2412     }
2413
2414   if (options.useXstack)
2415     {
2416       emitcode ("mov", "_spx,%s", r->name);
2417     }
2418     
2419   if (aop)
2420   {
2421       freeAsmop (NULL, aop, ic, TRUE);  
2422   }    
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* saveRBank - saves an entire register bank on the stack          */
2427 /*-----------------------------------------------------------------*/
2428 static void
2429 saveRBank (int bank, iCode * ic, bool pushPsw)
2430 {
2431   int i;
2432   asmop *aop = NULL;
2433   regs *r = NULL;
2434
2435   if (options.useXstack)
2436     {
2437         if (!ic)
2438         {
2439           /* Assume r0 is available for use. */
2440                   r = ds390_regWithIdx (R0_IDX);;
2441         }
2442         else
2443         {
2444           aop = newAsmop (0);
2445           r = getFreePtr (ic, &aop, FALSE);
2446         }
2447         emitcode ("mov", "%s,_spx", r->name);    
2448     }
2449
2450   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2451     {
2452       if (options.useXstack)
2453         {
2454           emitcode ("inc", "%s", r->name);
2455           emitcode ("mov", "a,(%s+%d)",
2456                     regs390[i].base, 8 * bank + regs390[i].offset);
2457           emitcode ("movx", "@%s,a", r->name);
2458         }
2459       else
2460         emitcode ("push", "(%s+%d)",
2461                   regs390[i].base, 8 * bank + regs390[i].offset);
2462     }
2463
2464   if (pushPsw)
2465     {
2466       if (options.useXstack)
2467         {
2468           emitcode ("mov", "a,psw");
2469           emitcode ("movx", "@%s,a", r->name);
2470           emitcode ("inc", "%s", r->name);
2471           emitcode ("mov", "_spx,%s", r->name);
2472         }
2473       else
2474       {
2475         emitcode ("push", "psw");
2476       }
2477
2478       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2479     }
2480   
2481   if (aop)
2482   {
2483        freeAsmop (NULL, aop, ic, TRUE);
2484   }    
2485     
2486   if (ic)
2487   {  
2488       ic->bankSaved = 1;
2489   }
2490 }
2491
2492 /*-----------------------------------------------------------------*/
2493 /* genSend - gen code for SEND                                     */
2494 /*-----------------------------------------------------------------*/
2495 static void genSend(set *sendSet)
2496 {
2497     iCode *sic;
2498     int sendCount = 0 ;
2499     static int rb1_count = 0;
2500
2501     for (sic = setFirstItem (sendSet); sic;
2502          sic = setNextItem (sendSet)) {     
2503         int size, offset = 0;
2504         
2505         size=getSize(operandType(IC_LEFT(sic)));
2506         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2507         if (sendCount == 0) { /* first parameter */
2508             // we know that dpl(hxb) is the result, so
2509             rb1_count = 0 ;
2510             _startLazyDPSEvaluation ();
2511             if (size>1) {
2512                 aopOp (IC_LEFT (sic), sic, FALSE, 
2513                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2514             } else {
2515                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2516             }
2517             while (size--) {
2518                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2519                                   FALSE, FALSE, NULL);
2520                 if (strcmp (l, fReturn[offset])) {
2521                     emitcode ("mov", "%s,%s",
2522                               fReturn[offset],
2523                               l);
2524                 }
2525                 offset++;
2526             }
2527             _endLazyDPSEvaluation ();
2528             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2529             rb1_count =0;
2530         } else { /* if more parameter in registers */
2531             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2532             while (size--) {
2533                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2534                                                                 FALSE, FALSE, NULL));
2535             }
2536             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2537         }
2538         sendCount++;
2539     }
2540 }
2541
2542 static void
2543 adjustEsp(const char *reg)
2544 {
2545     emitcode ("anl","%s,#3", reg);
2546     if (TARGET_IS_DS400)
2547     {
2548         emitcode ("orl","%s,#!constbyte",
2549                   reg,
2550                   (options.stack_loc >> 8) & 0xff);
2551     }
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* genCall - generates a call statement                            */
2556 /*-----------------------------------------------------------------*/
2557 static void
2558 genCall (iCode * ic)
2559 {
2560   sym_link *dtype;
2561   bool restoreBank = FALSE;
2562   bool swapBanks = FALSE;
2563
2564   D (emitcode (";", "genCall "););
2565
2566   /* if we are calling a not _naked function that is not using
2567      the same register bank then we need to save the
2568      destination registers on the stack */
2569   dtype = operandType (IC_LEFT (ic));
2570   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2571       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2572       IFFUNC_ISISR (currFunc->type))
2573   {
2574       if (!ic->bankSaved) 
2575       {
2576            /* This is unexpected; the bank should have been saved in
2577             * genFunction.
2578             */
2579            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2580            restoreBank = TRUE;
2581       }
2582       swapBanks = TRUE;
2583   }
2584   
2585     /* if caller saves & we have not saved then */
2586     if (!ic->regsSaved)
2587       saveRegisters (ic);
2588   
2589   /* if send set is not empty the assign */
2590   /* We've saved all the registers we care about;
2591   * therefore, we may clobber any register not used
2592   * in the calling convention (i.e. anything not in
2593   * fReturn.
2594   */
2595   if (_G.sendSet)
2596     {
2597         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2598             genSend(reverseSet(_G.sendSet));
2599         } else {
2600             genSend(_G.sendSet);
2601         }
2602       _G.sendSet = NULL;
2603     }  
2604     
2605   if (swapBanks)
2606   {
2607         emitcode ("mov", "psw,#!constbyte", 
2608            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2609   }
2610
2611   /* make the call */
2612   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2613                             OP_SYMBOL (IC_LEFT (ic))->rname :
2614                             OP_SYMBOL (IC_LEFT (ic))->name));
2615
2616   if (swapBanks)
2617   {
2618        emitcode ("mov", "psw,#!constbyte", 
2619           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2620   }
2621
2622   /* if we need assign a result value */
2623   if ((IS_ITEMP (IC_RESULT (ic)) &&
2624        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2625         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2626         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2627       IS_TRUE_SYMOP (IC_RESULT (ic)))
2628     {
2629       if (isOperandInFarSpace (IC_RESULT (ic))
2630           && getSize (operandType (IC_RESULT (ic))) <= 2)
2631         {
2632           int size = getSize (operandType (IC_RESULT (ic)));
2633
2634           /* Special case for 1 or 2 byte return in far space. */
2635           MOVA (fReturn[0]);
2636           if (size > 1)
2637             {
2638               emitcode ("mov", "b,%s", fReturn[1]);
2639             }
2640
2641           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2642           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2643
2644           if (size > 1)
2645             {
2646               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2647             }
2648           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2649         }
2650       else
2651         {
2652           _G.accInUse++;
2653           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2654           _G.accInUse--;
2655
2656           assignResultValue (IC_RESULT (ic));
2657
2658           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2659         }
2660     }
2661
2662   /* adjust the stack for parameters if
2663      required */
2664   if (ic->parmBytes) {
2665       int i;
2666       if (options.stack10bit) {
2667           if (ic->parmBytes <= 10) {
2668               emitcode(";","stack adjustment for parms");
2669               for (i=0; i < ic->parmBytes ; i++) {
2670                   emitcode("pop","acc");
2671               }
2672           } else {            
2673               PROTECT_SP;
2674               emitcode ("clr","c");
2675               emitcode ("mov","a,sp");
2676               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2677               emitcode ("mov","sp,a");
2678               emitcode ("mov","a,esp");
2679               adjustEsp("a");
2680               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2681               emitcode ("mov","esp,a");   
2682               UNPROTECT_SP;
2683           }
2684       } else {
2685           if (ic->parmBytes > 3) {
2686               emitcode ("mov", "a,%s", spname);
2687               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2688               emitcode ("mov", "%s,a", spname);
2689           } else
2690               for (i = 0; i < ic->parmBytes; i++)
2691                   emitcode ("dec", "%s", spname);
2692       }
2693   }
2694
2695   /* if we hade saved some registers then unsave them */
2696   if (ic->regsSaved)
2697     unsaveRegisters (ic);
2698
2699   /* if register bank was saved then pop them */
2700   if (restoreBank)
2701     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genPcall - generates a call by pointer statement                */
2706 /*-----------------------------------------------------------------*/
2707 static void
2708 genPcall (iCode * ic)
2709 {
2710   sym_link *dtype;
2711   symbol *rlbl = newiTempLabel (NULL);
2712   bool restoreBank=FALSE;
2713
2714   D (emitcode (";", "genPcall ");
2715     );
2716
2717
2718   /* if caller saves & we have not saved then */
2719   if (!ic->regsSaved)
2720     saveRegisters (ic);
2721
2722   /* if we are calling a function that is not using
2723      the same register bank then we need to save the
2724      destination registers on the stack */
2725   dtype = operandType (IC_LEFT (ic));
2726   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2727       IFFUNC_ISISR (currFunc->type) &&
2728       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2729     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2730     restoreBank=TRUE;
2731   }
2732
2733   /* push the return address on to the stack */
2734   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2735   emitcode ("push", "acc");
2736   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2737   emitcode ("push", "acc");
2738
2739   if (options.model == MODEL_FLAT24)
2740     {
2741       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2742       emitcode ("push", "acc");
2743     }
2744
2745   /* now push the calling address */
2746   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2747
2748   pushSide (IC_LEFT (ic), FPTRSIZE);
2749
2750   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2751
2752   /* if send set is not empty the assign */
2753   if (_G.sendSet)
2754     {
2755         genSend(reverseSet(_G.sendSet));
2756         _G.sendSet = NULL;
2757     }
2758
2759   emitcode ("ret", "");
2760   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2761
2762
2763   /* if we need assign a result value */
2764   if ((IS_ITEMP (IC_RESULT (ic)) &&
2765        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2766         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2767       IS_TRUE_SYMOP (IC_RESULT (ic)))
2768     {
2769
2770       _G.accInUse++;
2771       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2772       _G.accInUse--;
2773
2774       assignResultValue (IC_RESULT (ic));
2775
2776       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2777     }
2778
2779   /* adjust the stack for parameters if
2780      required */
2781   if (ic->parmBytes)
2782     {
2783       int i;
2784       if (options.stack10bit) {
2785           if (ic->parmBytes <= 10) {
2786               emitcode(";","stack adjustment for parms");
2787               for (i=0; i < ic->parmBytes ; i++) {
2788                   emitcode("pop","acc");
2789               }
2790           } else {            
2791               PROTECT_SP;
2792               emitcode ("clr","c");
2793               emitcode ("mov","a,sp");
2794               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2795               emitcode ("mov","sp,a");
2796               emitcode ("mov","a,esp");
2797               adjustEsp("a");
2798               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2799               emitcode ("mov","esp,a");   
2800               UNPROTECT_SP;
2801           }
2802       } else {
2803           if (ic->parmBytes > 3) {
2804               emitcode ("mov", "a,%s", spname);
2805               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2806               emitcode ("mov", "%s,a", spname);
2807           }
2808           else
2809               for (i = 0; i < ic->parmBytes; i++)
2810                   emitcode ("dec", "%s", spname);
2811           
2812       }
2813     }
2814   /* if register bank was saved then unsave them */
2815   if (restoreBank)
2816     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2817   
2818   /* if we hade saved some registers then
2819      unsave them */
2820   if (ic->regsSaved)
2821     unsaveRegisters (ic);
2822
2823 }
2824
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result  is rematerializable                       */
2827 /*-----------------------------------------------------------------*/
2828 static int
2829 resultRemat (iCode * ic)
2830 {
2831   if (SKIP_IC (ic) || ic->op == IFX)
2832     return 0;
2833
2834   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2835     {
2836       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2837       if (sym->remat && !POINTER_SET (ic))
2838         return 1;
2839     }
2840
2841   return 0;
2842 }
2843
2844 #if defined(__BORLANDC__) || defined(_MSC_VER)
2845 #define STRCASECMP stricmp
2846 #else
2847 #define STRCASECMP strcasecmp
2848 #endif
2849
2850 /*-----------------------------------------------------------------*/
2851 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2852 /*-----------------------------------------------------------------*/
2853 static int
2854 regsCmp(void *p1, void *p2)
2855 {
2856   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2857 }
2858
2859 static bool
2860 inExcludeList (char *s)
2861 {
2862   const char *p = setFirstItem(options.excludeRegsSet);
2863
2864   if (p == NULL || STRCASECMP(p, "none") == 0)
2865     return FALSE;
2866
2867
2868   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2869 }
2870
2871 /*-----------------------------------------------------------------*/
2872 /* genFunction - generated code for function entry                 */
2873 /*-----------------------------------------------------------------*/
2874 static void
2875 genFunction (iCode * ic)
2876 {
2877   symbol *sym;
2878   sym_link *ftype;
2879   bool   switchedPSW = FALSE;
2880
2881   D (emitcode (";", "genFunction "););
2882
2883   _G.nRegsSaved = 0;
2884   /* create the function header */
2885   emitcode (";", "-----------------------------------------");
2886   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2887   emitcode (";", "-----------------------------------------");
2888
2889   emitcode ("", "%s:", sym->rname);
2890   ftype = operandType (IC_LEFT (ic));
2891
2892   if (IFFUNC_ISNAKED(ftype))
2893   {
2894       emitcode(";", "naked function: no prologue.");
2895       return;
2896   }
2897   
2898   if (options.stack_probe) 
2899       emitcode ("lcall","__stack_probe");
2900   /* if critical function then turn interrupts off */
2901   if (IFFUNC_ISCRITICAL (ftype))
2902     {
2903       emitcode ("mov", "c,ea");
2904       emitcode ("push", "psw"); /* save old ea via c in psw */
2905       emitcode ("clr", "ea");
2906     }
2907
2908   /* here we need to generate the equates for the
2909      register bank if required */
2910   if (FUNC_REGBANK (ftype) != rbank)
2911     {
2912       int i;
2913
2914       rbank = FUNC_REGBANK (ftype);
2915       for (i = 0; i < ds390_nRegs; i++)
2916         {
2917           if (regs390[i].print) {
2918               if (strcmp (regs390[i].base, "0") == 0)
2919                   emitcode ("", "%s !equ !constbyte",
2920                             regs390[i].dname,
2921                             8 * rbank + regs390[i].offset);
2922               else
2923                   emitcode ("", "%s !equ %s + !constbyte",
2924                             regs390[i].dname,
2925                             regs390[i].base,
2926                             8 * rbank + regs390[i].offset);
2927           }
2928         }
2929     }
2930
2931   /* if this is an interrupt service routine then
2932      save acc, b, dpl, dph  */
2933   if (IFFUNC_ISISR (sym->type))
2934       { /* is ISR */
2935       if (!inExcludeList ("acc"))
2936         emitcode ("push", "acc");
2937       if (!inExcludeList ("b"))
2938         emitcode ("push", "b");
2939       if (!inExcludeList ("dpl"))
2940         emitcode ("push", "dpl");
2941       if (!inExcludeList ("dph"))
2942         emitcode ("push", "dph");
2943       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2944         {
2945           emitcode ("push", "dpx");
2946           /* Make sure we're using standard DPTR */
2947           emitcode ("push", "dps");
2948           emitcode ("mov", "dps,#0");
2949           if (options.stack10bit)
2950             {
2951               /* This ISR could conceivably use DPTR2. Better save it. */
2952               emitcode ("push", "dpl1");
2953               emitcode ("push", "dph1");
2954               emitcode ("push", "dpx1");
2955               emitcode ("push",  DP2_RESULT_REG);
2956             }
2957         }
2958       /* if this isr has no bank i.e. is going to
2959          run with bank 0 , then we need to save more
2960          registers :-) */
2961       if (!FUNC_REGBANK (sym->type))
2962         {
2963             int i;
2964
2965           /* if this function does not call any other
2966              function then we can be economical and
2967              save only those registers that are used */
2968           if (!IFFUNC_HASFCALL(sym->type))
2969             {
2970
2971               /* if any registers used */
2972               if (sym->regsUsed)
2973                 {
2974                   /* save the registers used */
2975                   for (i = 0; i < sym->regsUsed->size; i++)
2976                     {
2977                       if (bitVectBitValue (sym->regsUsed, i) ||
2978                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2979                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2980                     }
2981                 }
2982
2983             }
2984           else
2985             {
2986               /* this function has  a function call cannot
2987                  determines register usage so we will have to push the
2988                  entire bank */
2989               saveRBank (0, ic, FALSE);
2990               if (options.parms_in_bank1) {
2991                   for (i=0; i < 8 ; i++ ) {
2992                       emitcode ("push","%s",rb1regs[i]);
2993                   }
2994               }
2995             }
2996         }
2997         else
2998         {
2999             /* This ISR uses a non-zero bank.
3000              *
3001              * We assume that the bank is available for our
3002              * exclusive use.
3003              *
3004              * However, if this ISR calls a function which uses some
3005              * other bank, we must save that bank entirely.
3006              */
3007             unsigned long banksToSave = 0;
3008             
3009             if (IFFUNC_HASFCALL(sym->type))
3010             {
3011
3012 #define MAX_REGISTER_BANKS 4
3013
3014                 iCode *i;
3015                 int ix;
3016
3017                 for (i = ic; i; i = i->next)
3018                 {
3019                     if (i->op == ENDFUNCTION)
3020                     {
3021                         /* we got to the end OK. */
3022                         break;
3023                     }
3024                     
3025                     if (i->op == CALL)
3026                     {
3027                         sym_link *dtype;
3028                         
3029                         dtype = operandType (IC_LEFT(i));
3030                         if (dtype 
3031                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3032                         {
3033                              /* Mark this bank for saving. */
3034                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3035                              {
3036                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3037                              }
3038                              else
3039                              {
3040                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3041                              }
3042                              
3043                              /* And note that we don't need to do it in 
3044                               * genCall.
3045                               */
3046                              i->bankSaved = 1;
3047                         }
3048                     }
3049                     if (i->op == PCALL)
3050                     {
3051                         /* This is a mess; we have no idea what
3052                          * register bank the called function might
3053                          * use.
3054                          *
3055                          * The only thing I can think of to do is
3056                          * throw a warning and hope.
3057                          */
3058                         werror(W_FUNCPTR_IN_USING_ISR);   
3059                     }
3060                 }
3061
3062                 if (banksToSave && options.useXstack)
3063                 {
3064                     /* Since we aren't passing it an ic, 
3065                      * saveRBank will assume r0 is available to abuse.
3066                      *
3067                      * So switch to our (trashable) bank now, so
3068                      * the caller's R0 isn't trashed.
3069                      */
3070                     emitcode ("push", "psw");
3071                     emitcode ("mov", "psw,#!constbyte", 
3072                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3073                     switchedPSW = TRUE;
3074                 }
3075                 
3076                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3077                 {
3078                      if (banksToSave & (1 << ix))
3079                      {
3080                          saveRBank(ix, NULL, FALSE);
3081                      }
3082                 }
3083             }
3084             // TODO: this needs a closer look
3085             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3086         }
3087     }
3088   else
3089     {
3090       /* if callee-save to be used for this function
3091          then save the registers being used in this function */
3092       if (IFFUNC_CALLEESAVES(sym->type))
3093         {
3094           int i;
3095
3096           /* if any registers used */
3097           if (sym->regsUsed)
3098             {
3099               /* save the registers used */
3100               for (i = 0; i < sym->regsUsed->size; i++)
3101                 {
3102                   if (bitVectBitValue (sym->regsUsed, i) ||
3103                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3104                     {
3105                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3106                       _G.nRegsSaved++;
3107                     }
3108                 }
3109             }
3110         }
3111     }
3112
3113   /* set the register bank to the desired value */
3114   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3115    && !switchedPSW)
3116     {
3117       emitcode ("push", "psw");
3118       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3119     }
3120
3121   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3122        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3123       if (options.stack10bit) {
3124           emitcode ("push","_bpx");
3125           emitcode ("push","_bpx+1");
3126           emitcode ("mov","_bpx,%s",spname);
3127           emitcode ("mov","_bpx+1,esp");
3128           adjustEsp("_bpx+1");
3129       } else {
3130           if (options.useXstack) {
3131               emitcode ("mov", "r0,%s", spname);
3132               emitcode ("mov", "a,_bp");
3133               emitcode ("movx", "@r0,a");
3134               emitcode ("inc", "%s", spname);
3135           } else {
3136               /* set up the stack */
3137               emitcode ("push", "_bp"); /* save the callers stack  */
3138           }
3139           emitcode ("mov", "_bp,%s", spname);
3140       }
3141   }
3142
3143   /* adjust the stack for the function */
3144   if (sym->stack) {
3145       int i = sym->stack;
3146       if (options.stack10bit) {
3147           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3148           assert (sym->recvSize <= 4);
3149           if (sym->stack <= 8) {
3150               while (i--) emitcode ("push","acc");
3151           } else {
3152               PROTECT_SP;
3153               emitcode ("mov","a,sp");
3154               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3155               emitcode ("mov","sp,a");
3156               emitcode ("mov","a,esp");
3157               adjustEsp("a");
3158               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3159               emitcode ("mov","esp,a");
3160               UNPROTECT_SP;
3161           }
3162       } else {
3163           if (i > 256)
3164               werror (W_STACK_OVERFLOW, sym->name);
3165           
3166           if (i > 3 && sym->recvSize < 4) {
3167               
3168               emitcode ("mov", "a,sp");
3169               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3170               emitcode ("mov", "sp,a");
3171               
3172           } else
3173               while (i--)
3174                   emitcode ("inc", "sp");
3175       }
3176   }
3177
3178   if (sym->xstack)
3179     {
3180
3181       emitcode ("mov", "a,_spx");
3182       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3183       emitcode ("mov", "_spx,a");
3184     }
3185
3186 }
3187
3188 /*-----------------------------------------------------------------*/
3189 /* genEndFunction - generates epilogue for functions               */
3190 /*-----------------------------------------------------------------*/
3191 static void
3192 genEndFunction (iCode * ic)
3193 {
3194   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3195
3196   D (emitcode (";", "genEndFunction "););
3197
3198   if (IFFUNC_ISNAKED(sym->type))
3199   {
3200       emitcode(";", "naked function: no epilogue.");
3201       return;
3202   }
3203
3204   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3205        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3206
3207       if (options.stack10bit) {
3208           PROTECT_SP;     
3209           emitcode ("mov", "sp,_bpx", spname);
3210           emitcode ("mov", "esp,_bpx+1", spname);
3211           UNPROTECT_SP;
3212       } else {
3213           emitcode ("mov", "%s,_bp", spname);
3214       }
3215   }
3216
3217   /* if use external stack but some variables were
3218      added to the local stack then decrement the
3219      local stack */
3220   if (options.useXstack && sym->stack) {
3221       emitcode ("mov", "a,sp");
3222       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3223       emitcode ("mov", "sp,a");
3224   }
3225
3226
3227   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3228        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3229
3230       if (options.useXstack) {
3231           emitcode ("mov", "r0,%s", spname);
3232           emitcode ("movx", "a,@r0");
3233           emitcode ("mov", "_bp,a");
3234           emitcode ("dec", "%s", spname);
3235       } else {
3236           if (options.stack10bit) {
3237               emitcode ("pop", "_bpx+1");
3238               emitcode ("pop", "_bpx");
3239           } else {
3240               emitcode ("pop", "_bp");
3241           }
3242       }
3243   }
3244
3245   /* restore the register bank  */
3246   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3247   {
3248     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3249      || !options.useXstack)
3250     {
3251         /* Special case of ISR using non-zero bank with useXstack
3252          * is handled below.
3253          */
3254         emitcode ("pop", "psw");
3255     }
3256   } 
3257
3258   if (IFFUNC_ISISR (sym->type))
3259       { /* is ISR */  
3260
3261       /* now we need to restore the registers */
3262       /* if this isr has no bank i.e. is going to
3263          run with bank 0 , then we need to save more
3264          registers :-) */
3265       if (!FUNC_REGBANK (sym->type))
3266         {
3267             int i;
3268           /* if this function does not call any other
3269              function then we can be economical and
3270              save only those registers that are used */
3271           if (!IFFUNC_HASFCALL(sym->type))
3272             {
3273
3274               /* if any registers used */
3275               if (sym->regsUsed)
3276                 {
3277                   /* save the registers used */
3278                   for (i = sym->regsUsed->size; i >= 0; i--)
3279                     {
3280                       if (bitVectBitValue (sym->regsUsed, i) ||
3281                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3282                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3283                     }
3284                 }
3285
3286             }
3287           else
3288             {
3289               /* this function has  a function call cannot
3290                  determines register usage so we will have to pop the
3291                  entire bank */
3292               if (options.parms_in_bank1) {
3293                   for (i = 7 ; i >= 0 ; i-- ) {
3294                       emitcode ("pop","%s",rb1regs[i]);
3295                   }
3296               }
3297               unsaveRBank (0, ic, FALSE);
3298             }
3299         }
3300         else
3301         {
3302             /* This ISR uses a non-zero bank.
3303              *
3304              * Restore any register banks saved by genFunction
3305              * in reverse order.
3306              */
3307             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3308             int ix;
3309           
3310             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3311             {
3312                 if (savedBanks & (1 << ix))
3313                 {
3314                     unsaveRBank(ix, NULL, FALSE);
3315                 }
3316             }
3317             
3318             if (options.useXstack)
3319             {
3320                 /* Restore bank AFTER calling unsaveRBank,
3321                  * since it can trash r0.
3322                  */
3323                 emitcode ("pop", "psw");
3324             }
3325         }
3326
3327       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3328         {
3329           if (options.stack10bit)
3330             {
3331               emitcode ("pop", DP2_RESULT_REG);
3332               emitcode ("pop", "dpx1");
3333               emitcode ("pop", "dph1");
3334               emitcode ("pop", "dpl1");
3335             }
3336           emitcode ("pop", "dps");
3337           emitcode ("pop", "dpx");
3338         }
3339       if (!inExcludeList ("dph"))
3340         emitcode ("pop", "dph");
3341       if (!inExcludeList ("dpl"))
3342         emitcode ("pop", "dpl");
3343       if (!inExcludeList ("b"))
3344         emitcode ("pop", "b");
3345       if (!inExcludeList ("acc"))
3346         emitcode ("pop", "acc");
3347
3348       if (IFFUNC_ISCRITICAL (sym->type))
3349         {
3350           emitcode ("pop", "psw"); /* restore ea via c in psw */
3351           emitcode ("mov", "ea,c");
3352         }
3353
3354       /* if debug then send end of function */
3355       if (options.debug && currFunc) {
3356           _G.debugLine = 1;
3357           emitcode ("", "C$%s$%d$%d$%d ==.",
3358                     FileBaseName (ic->filename), currFunc->lastLine,
3359                     ic->level, ic->block);
3360           if (IS_STATIC (currFunc->etype))
3361             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3362           else
3363             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3364           _G.debugLine = 0;
3365         }
3366
3367       emitcode ("reti", "");
3368     }
3369   else
3370     {
3371       if (IFFUNC_ISCRITICAL (sym->type))
3372         {
3373           emitcode ("pop", "psw"); /* restore ea via c in psw */
3374           emitcode ("mov", "ea,c");
3375         }
3376
3377       if (IFFUNC_CALLEESAVES(sym->type))
3378         {
3379           int i;
3380
3381           /* if any registers used */
3382           if (sym->regsUsed)
3383             {
3384               /* save the registers used */
3385               for (i = sym->regsUsed->size; i >= 0; i--)
3386                 {
3387                   if (bitVectBitValue (sym->regsUsed, i) ||
3388                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3389                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3390                 }
3391             }
3392
3393         }
3394
3395       /* if debug then send end of function */
3396       if (options.debug && currFunc)
3397         {
3398           _G.debugLine = 1;
3399           emitcode ("", "C$%s$%d$%d$%d ==.",
3400                     FileBaseName (ic->filename), currFunc->lastLine,
3401                     ic->level, ic->block);
3402           if (IS_STATIC (currFunc->etype))
3403             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3404           else
3405             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3406           _G.debugLine = 0;
3407         }
3408
3409       emitcode ("ret", "");
3410     }
3411
3412 }
3413
3414 /*-----------------------------------------------------------------*/
3415 /* genJavaNativeRet - generate code for return JavaNative          */
3416 /*-----------------------------------------------------------------*/
3417 static void genJavaNativeRet(iCode *ic)
3418 {
3419     int i, size;
3420
3421     aopOp (IC_LEFT (ic), ic, FALSE, 
3422            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3423     size = AOP_SIZE (IC_LEFT (ic));
3424
3425     assert (size <= 4);
3426
3427     /* it is assigned to GPR0-R3 then push them */
3428     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3429         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3430         for (i = 0 ; i < size ; i++ ) {
3431             emitcode ("push","%s",
3432                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3433         }
3434         for (i = (size-1) ; i >= 0 ; i--) {
3435             emitcode ("pop","a%s",javaRet[i]);
3436         }
3437     } else {
3438         for (i = 0 ; i < size ; i++) 
3439             emitcode ("mov","%s,%s",javaRet[i],
3440                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3441     }
3442     for (i = size ; i < 4 ; i++ )
3443             emitcode ("mov","%s,#0",javaRet[i]);
3444     return;
3445 }
3446
3447 /*-----------------------------------------------------------------*/
3448 /* genRet - generate code for return statement                     */
3449 /*-----------------------------------------------------------------*/
3450 static void
3451 genRet (iCode * ic)
3452 {
3453   int size, offset = 0, pushed = 0;
3454
3455   D (emitcode (";", "genRet "););
3456
3457   /* if we have no return value then
3458      just generate the "ret" */
3459   if (!IC_LEFT (ic))
3460     goto jumpret;
3461
3462   /* if this is a JavaNative function then return 
3463      value in different register */
3464   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3465       genJavaNativeRet(ic);
3466       goto jumpret;
3467   }
3468   /* we have something to return then
3469      move the return value into place */
3470   aopOp (IC_LEFT (ic), ic, FALSE, 
3471          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3472   size = AOP_SIZE (IC_LEFT (ic));
3473
3474   _startLazyDPSEvaluation ();
3475   while (size--)
3476     {
3477       char *l;
3478       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3479         {
3480           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3481                       FALSE, TRUE, NULL);
3482           emitcode ("push", "%s", l);
3483           pushed++;
3484         }
3485       else
3486         {
3487           /* Since A is the last element of fReturn,
3488            * is is OK to clobber it in the aopGet.
3489            */
3490           l = aopGet (AOP (IC_LEFT (ic)), offset,
3491                       FALSE, FALSE, NULL);
3492           if (strcmp (fReturn[offset], l))
3493             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3494         }
3495     }
3496   _endLazyDPSEvaluation ();
3497
3498   if (pushed)
3499     {
3500       while (pushed)
3501         {
3502           pushed--;
3503           if (strcmp (fReturn[pushed], "a"))
3504             emitcode ("pop", fReturn[pushed]);
3505           else
3506             emitcode ("pop", "acc");
3507         }
3508     }
3509   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3510
3511 jumpret:
3512   /* generate a jump to the return label
3513      if the next is not the return statement */
3514   if (!(ic->next && ic->next->op == LABEL &&
3515         IC_LABEL (ic->next) == returnLabel))
3516
3517     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3518
3519 }
3520
3521 /*-----------------------------------------------------------------*/
3522 /* genLabel - generates a label                                    */
3523 /*-----------------------------------------------------------------*/
3524 static void
3525 genLabel (iCode * ic)
3526 {
3527   /* special case never generate */
3528   if (IC_LABEL (ic) == entryLabel)
3529     return;
3530
3531   D (emitcode (";", "genLabel ");
3532     );
3533
3534   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3535 }
3536
3537 /*-----------------------------------------------------------------*/
3538 /* genGoto - generates a ljmp                                      */
3539 /*-----------------------------------------------------------------*/
3540 static void
3541 genGoto (iCode * ic)
3542 {
3543   D (emitcode (";", "genGoto ");
3544     );
3545   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3546 }
3547
3548 /*-----------------------------------------------------------------*/
3549 /* findLabelBackwards: walks back through the iCode chain looking  */
3550 /* for the given label. Returns number of iCode instructions     */
3551 /* between that label and given ic.          */
3552 /* Returns zero if label not found.          */
3553 /*-----------------------------------------------------------------*/
3554 static int
3555 findLabelBackwards (iCode * ic, int key)
3556 {
3557   int count = 0;
3558
3559   while (ic->prev)
3560     {
3561       ic = ic->prev;
3562       count++;
3563
3564       /* If we have any pushes or pops, we cannot predict the distance.
3565          I don't like this at all, this should be dealt with in the 
3566          back-end */
3567       if (ic->op == IPUSH || ic->op == IPOP) {
3568         return 0;
3569       }
3570
3571       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3572         {
3573           /* printf("findLabelBackwards = %d\n", count); */
3574           return count;
3575         }
3576     }
3577
3578   return 0;
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* genPlusIncr :- does addition with increment if possible         */
3583 /*-----------------------------------------------------------------*/
3584 static bool
3585 genPlusIncr (iCode * ic)
3586 {
3587   unsigned int icount;
3588   unsigned int size = getDataSize (IC_RESULT (ic));
3589
3590   /* will try to generate an increment */
3591   /* if the right side is not a literal
3592      we cannot */
3593   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3594     return FALSE;
3595
3596   /* if the literal value of the right hand side
3597      is greater than 4 then it is not worth it */
3598   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3599     return FALSE;
3600
3601   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3602       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3603       while (icount--) {
3604           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3605       }
3606       return TRUE;
3607   }
3608   /* if increment 16 bits in register */
3609   if (
3610        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3611        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3612        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3613        (size > 1) &&
3614        (icount == 1))
3615     {
3616       symbol  *tlbl;
3617       int     emitTlbl;
3618       int     labelRange;
3619       char    *l;
3620
3621       /* If the next instruction is a goto and the goto target
3622        * is <= 5 instructions previous to this, we can generate
3623        * jumps straight to that target.
3624        */
3625       if (ic->next && ic->next->op == GOTO
3626           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3627           && labelRange <= 5)
3628         {
3629           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3630           tlbl = IC_LABEL (ic->next);
3631           emitTlbl = 0;
3632         }
3633       else
3634         {
3635           tlbl = newiTempLabel (NULL);
3636           emitTlbl = 1;
3637         }
3638         
3639       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3640       emitcode ("inc", "%s", l);
3641       
3642       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3643           IS_AOP_PREG (IC_RESULT (ic)))
3644       {   
3645         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3646       }
3647       else
3648       {
3649           emitcode ("clr", "a");
3650           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3651       }
3652
3653       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3654       emitcode ("inc", "%s", l);
3655       if (size > 2)
3656         {
3657             if (!strcmp(l, "acc"))
3658             {
3659                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3660             }
3661             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3662                      IS_AOP_PREG (IC_RESULT (ic)))
3663             {
3664                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3665             }
3666             else
3667             {
3668                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3669             }
3670
3671             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3672             emitcode ("inc", "%s", l);
3673         }
3674       if (size > 3)
3675         {
3676             if (!strcmp(l, "acc"))
3677             {
3678                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3679             }
3680             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3681                      IS_AOP_PREG (IC_RESULT (ic)))
3682             {
3683                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3684             }
3685             else
3686             {
3687                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3688             }
3689
3690             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3691             emitcode ("inc", "%s", l);  }
3692
3693       if (emitTlbl)
3694         {
3695           emitcode ("", "!tlabeldef", tlbl->key + 100);
3696         }
3697       return TRUE;
3698     }
3699
3700   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3701       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3702       options.model == MODEL_FLAT24 ) {
3703
3704       switch (size) {
3705       case 3:
3706           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3707       case 2:
3708           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3709       case 1:
3710           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3711           break;
3712       }
3713       while (icount--) emitcode ("inc","dptr");      
3714       return TRUE;
3715   }
3716
3717   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3718       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3719       icount <= 5 ) {
3720       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3721       while (icount--) emitcode ("inc","dptr");
3722       emitcode ("mov","dps,#0");
3723       return TRUE;
3724   }
3725
3726   /* if the sizes are greater than 1 then we cannot */
3727   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3728       AOP_SIZE (IC_LEFT (ic)) > 1)
3729     return FALSE;
3730
3731   /* we can if the aops of the left & result match or
3732      if they are in registers and the registers are the
3733      same */
3734   if (
3735        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3736        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3737        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3738     {
3739
3740       if (icount > 3)
3741         {
3742           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3743           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3744           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3745         }
3746       else
3747         {
3748
3749           _startLazyDPSEvaluation ();
3750           while (icount--)
3751             {
3752               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3753             }
3754           _endLazyDPSEvaluation ();
3755         }
3756
3757       return TRUE;
3758     }
3759
3760   return FALSE;
3761 }
3762
3763 /*-----------------------------------------------------------------*/
3764 /* outBitAcc - output a bit in acc                                 */
3765 /*-----------------------------------------------------------------*/
3766 static void
3767 outBitAcc (operand * result)
3768 {
3769   symbol *tlbl = newiTempLabel (NULL);
3770   /* if the result is a bit */
3771   if (AOP_TYPE (result) == AOP_CRY)
3772     {
3773       aopPut (AOP (result), "a", 0);
3774     }
3775   else
3776     {
3777       emitcode ("jz", "!tlabel", tlbl->key + 100);
3778       emitcode ("mov", "a,%s", one);
3779       emitcode ("", "!tlabeldef", tlbl->key + 100);
3780       outAcc (result);
3781     }
3782 }
3783
3784 /*-----------------------------------------------------------------*/
3785 /* genPlusBits - generates code for addition of two bits           */
3786 /*-----------------------------------------------------------------*/
3787 static void
3788 genPlusBits (iCode * ic)
3789 {
3790   D (emitcode (";", "genPlusBits "););
3791     
3792   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3793     {
3794       symbol *lbl = newiTempLabel (NULL);
3795       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3796       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3797       emitcode ("cpl", "c");
3798       emitcode ("", "!tlabeldef", (lbl->key + 100));
3799       outBitC (IC_RESULT (ic));
3800     }
3801   else
3802     {
3803       emitcode ("clr", "a");
3804       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3805       emitcode ("rlc", "a");
3806       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3807       emitcode ("addc", "a,#0");
3808       outAcc (IC_RESULT (ic));
3809     }
3810 }
3811
3812 static void
3813 adjustArithmeticResult (iCode * ic)
3814 {
3815   if (opIsGptr (IC_RESULT (ic)) &&
3816       opIsGptr (IC_LEFT (ic)) &&
3817       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3818     {
3819       aopPut (AOP (IC_RESULT (ic)),
3820               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3821               GPTRSIZE - 1);
3822     }
3823
3824   if (opIsGptr (IC_RESULT (ic)) &&
3825       opIsGptr (IC_RIGHT (ic)) &&
3826       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3827     {
3828       aopPut (AOP (IC_RESULT (ic)),
3829             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3830               GPTRSIZE - 1);
3831     }
3832
3833   if (opIsGptr (IC_RESULT (ic)) &&
3834       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3835       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3836       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3837       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3838     {
3839       char buff[5];
3840       SNPRINTF (buff, sizeof(buff), 
3841                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3842       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3843     }
3844 }
3845
3846 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3847 // generates the result if possible. If result is generated, returns TRUE; otherwise
3848 // returns false and caller must deal with fact that result isn't aopOp'd.
3849 bool aopOp3(iCode * ic)
3850 {
3851     bool dp1InUse, dp2InUse;
3852     bool useDp2;
3853     
3854     // First, generate the right opcode. DPTR may be used if neither left nor result are
3855     // of type AOP_STR.
3856     
3857 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3858 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3859 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3860 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3861 //      );
3862 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3863 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3864 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3865 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3866 //      );
3867     
3868     // Right uses DPTR unless left or result is an AOP_STR; however,
3869     // if right is an AOP_STR, it must use DPTR regardless.
3870     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3871      && !AOP_IS_STR(IC_RIGHT(ic)))
3872     {
3873         useDp2 = TRUE;
3874     }
3875     else
3876     {
3877         useDp2 = FALSE;
3878     }
3879         
3880     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3881     
3882     // if the right used DPTR, left MUST use DPTR2.
3883     // if the right used DPTR2, left MUST use DPTR.
3884     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3885     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3886     // enabling us to assign DPTR to result.
3887      
3888     if (AOP_USESDPTR(IC_RIGHT(ic)))
3889     {
3890         useDp2 = TRUE;
3891     }
3892     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3893     {
3894         useDp2 = FALSE;
3895     }
3896     else
3897     {
3898         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3899         {
3900             useDp2 = TRUE;
3901         }
3902         else
3903         {
3904             useDp2 = FALSE;
3905         }
3906     }
3907
3908     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3909     
3910     // We've op'd the left & right. So, if left or right are the same operand as result, 
3911     // we know aopOp will succeed, and we can just do it & bail.
3912     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3913         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3914     {
3915 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3916         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3917         return TRUE;
3918     }
3919     
3920     // Note which dptrs are currently in use.
3921     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3922     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3923     
3924     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3925     // generate it.
3926     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3927     {
3928         return FALSE;
3929     }
3930     
3931     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3932     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3933     {
3934         return FALSE;
3935     }
3936     
3937     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3938     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3939     {
3940         return FALSE;
3941     }
3942
3943     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3944
3945     // Some sanity checking...
3946     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3947     {
3948         fprintf(stderr,
3949                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3950                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3951         emitcode(";", ">>> unexpected DPTR here.");
3952     }
3953     
3954     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3955     {
3956         fprintf(stderr,
3957                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3958                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3959         emitcode(";", ">>> unexpected DPTR2 here.");
3960     }    
3961     
3962     return TRUE;
3963 }
3964
3965 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3966 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3967 // will be set TRUE. The caller must then handle the case specially, noting
3968 // that the IC_RESULT operand is not aopOp'd.
3969 // 
3970 #define AOP_OP_3_NOFATAL(ic, rc) \
3971             do { rc = !aopOp3(ic); } while (0)
3972
3973 // aopOp the left & right operands of an ic.
3974 #define AOP_OP_2(ic) \
3975     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3976     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3977
3978 // convienience macro.
3979 #define AOP_SET_LOCALS(ic) \
3980     left = IC_LEFT(ic); \
3981     right = IC_RIGHT(ic); \
3982     result = IC_RESULT(ic);
3983
3984
3985 // Given an integer value of pushedSize bytes on the stack,
3986 // adjust it to be resultSize bytes, either by discarding
3987 // the most significant bytes or by zero-padding.
3988 //
3989 // On exit from this macro, pushedSize will have been adjusted to
3990 // equal resultSize, and ACC may be trashed.
3991 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3992       /* If the pushed data is bigger than the result,          \
3993        * simply discard unused bytes. Icky, but works.          \
3994        */                                                       \
3995       while (pushedSize > resultSize)                           \
3996       {                                                         \
3997           D (emitcode (";", "discarding unused result byte."););\
3998           emitcode ("pop", "acc");                              \
3999           pushedSize--;                                         \
4000       }                                                         \
4001       if (pushedSize < resultSize)                              \
4002       {                                                         \
4003           emitcode ("clr", "a");                                \
4004           /* Conversly, we haven't pushed enough here.          \
4005            * just zero-pad, and all is well.                    \
4006            */                                                   \
4007           while (pushedSize < resultSize)                       \
4008           {                                                     \
4009               emitcode("push", "acc");                          \
4010               pushedSize++;                                     \
4011           }                                                     \
4012       }                                                         \
4013       assert(pushedSize == resultSize);
4014
4015 /*-----------------------------------------------------------------*/
4016 /* genPlus - generates code for addition                           */
4017 /*-----------------------------------------------------------------*/
4018 static void
4019 genPlus (iCode * ic)
4020 {
4021   int size, offset = 0;
4022   bool pushResult;
4023   int rSize;
4024
4025   D (emitcode (";", "genPlus "););
4026
4027   /* special cases :- */
4028   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4029       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4030       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4031       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4032       if (size <= 9) {
4033           while (size--) emitcode ("inc","dptr");
4034       } else {
4035           emitcode ("mov","a,dpl");
4036           emitcode ("add","a,#!constbyte",size & 0xff);
4037           emitcode ("mov","dpl,a");
4038           emitcode ("mov","a,dph");
4039           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4040           emitcode ("mov","dph,a");
4041           emitcode ("mov","a,dpx");
4042           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4043           emitcode ("mov","dpx,a");
4044       }
4045       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4046       return ;
4047   }
4048   if ( IS_SYMOP(IC_LEFT(ic)) && 
4049        OP_SYMBOL(IC_LEFT(ic))->remat &&
4050        isOperandInFarSpace(IC_RIGHT(ic))) {
4051       operand *op = IC_RIGHT(ic);
4052       IC_RIGHT(ic) = IC_LEFT(ic);
4053       IC_LEFT(ic) = op;
4054   }
4055                 
4056   AOP_OP_3_NOFATAL (ic, pushResult);
4057     
4058   if (pushResult)
4059     {
4060       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4061     }
4062
4063   if (!pushResult)
4064     {
4065       /* if literal, literal on the right or
4066          if left requires ACC or right is already
4067          in ACC */
4068       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4069        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4070           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4071         {
4072           operand *t = IC_RIGHT (ic);
4073           IC_RIGHT (ic) = IC_LEFT (ic);
4074           IC_LEFT (ic) = t;
4075           emitcode (";", "Swapped plus args.");
4076         }
4077
4078       /* if both left & right are in bit
4079          space */
4080       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4081           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4082         {
4083           genPlusBits (ic);
4084           goto release;
4085         }
4086
4087       /* if left in bit space & right literal */
4088       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4089           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4090         {
4091           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4092           /* if result in bit space */
4093           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4094             {
4095               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4096                 emitcode ("cpl", "c");
4097               outBitC (IC_RESULT (ic));
4098             }
4099           else
4100             {
4101               size = getDataSize (IC_RESULT (ic));
4102               _startLazyDPSEvaluation ();
4103               while (size--)
4104                 {
4105                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4106                   emitcode ("addc", "a,#0");
4107                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4108                 }
4109               _endLazyDPSEvaluation ();
4110             }
4111           goto release;
4112         }
4113
4114       /* if I can do an increment instead
4115          of add then GOOD for ME */
4116       if (genPlusIncr (ic) == TRUE)
4117         {
4118           emitcode (";", "did genPlusIncr");
4119           goto release;
4120         }
4121
4122     }
4123   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4124
4125   _startLazyDPSEvaluation ();
4126   while (size--)
4127     {
4128       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4129         {
4130           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4131           if (offset == 0)
4132             emitcode ("add", "a,%s",
4133                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4134           else
4135             emitcode ("addc", "a,%s",
4136                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4137         }
4138       else
4139         {
4140           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4141           {
4142               /* right is going to use ACC or we would have taken the
4143                * above branch.
4144                */
4145               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4146        TR_AP("#3");
4147               D(emitcode(";", "+ AOP_ACC special case."););
4148               emitcode("xch", "a, %s", DP2_RESULT_REG);
4149           }
4150           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4151           if (offset == 0)
4152           {
4153             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4154             {
4155          TR_AP("#4");
4156                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4157             }
4158             else
4159             {
4160                 emitcode ("add", "a,%s",
4161                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4162                                   DP2_RESULT_REG));
4163             }
4164           }
4165           else
4166           {
4167             emitcode ("addc", "a,%s",
4168                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4169                           DP2_RESULT_REG));
4170           }
4171         }
4172       if (!pushResult)
4173         {
4174           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4175         }
4176       else
4177         {
4178           emitcode ("push", "acc");
4179         }
4180       offset++;
4181     }
4182   _endLazyDPSEvaluation ();
4183
4184   if (pushResult)
4185     {
4186       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4187
4188       size = getDataSize (IC_LEFT (ic));
4189       rSize = getDataSize (IC_RESULT (ic));
4190
4191       ADJUST_PUSHED_RESULT(size, rSize);
4192
4193       _startLazyDPSEvaluation ();
4194       while (size--)
4195         {
4196           emitcode ("pop", "acc");
4197           aopPut (AOP (IC_RESULT (ic)), "a", size);
4198         }
4199       _endLazyDPSEvaluation ();
4200     }
4201
4202   adjustArithmeticResult (ic);
4203
4204 release:
4205   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4206   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4207   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4208 }
4209
4210 /*-----------------------------------------------------------------*/
4211 /* genMinusDec :- does subtraction with deccrement if possible     */
4212 /*-----------------------------------------------------------------*/
4213 static bool
4214 genMinusDec (iCode * ic)
4215 {
4216   unsigned int icount;
4217   unsigned int size = getDataSize (IC_RESULT (ic));
4218
4219   /* will try to generate an increment */
4220   /* if the right side is not a literal
4221      we cannot */
4222   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4223     return FALSE;
4224
4225   /* if the literal value of the right hand side
4226      is greater than 4 then it is not worth it */
4227   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4228     return FALSE;
4229
4230   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4231       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4232       while (icount--) {
4233           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4234       }
4235       return TRUE;
4236   }
4237   /* if decrement 16 bits in register */
4238   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4239       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4240       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4241       (size > 1) &&
4242       (icount == 1))
4243     {
4244       symbol *tlbl;
4245       int    emitTlbl;
4246       int    labelRange;
4247       char   *l;
4248
4249       /* If the next instruction is a goto and the goto target
4250          * is <= 5 instructions previous to this, we can generate
4251          * jumps straight to that target.
4252        */
4253       if (ic->next && ic->next->op == GOTO
4254           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4255           && labelRange <= 5)
4256         {
4257           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4258           tlbl = IC_LABEL (ic->next);
4259           emitTlbl = 0;
4260         }
4261       else
4262         {
4263           tlbl = newiTempLabel (NULL);
4264           emitTlbl = 1;
4265         }
4266
4267       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4268       emitcode ("dec", "%s", l);
4269  
4270       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4271           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4272           IS_AOP_PREG (IC_RESULT (ic)))
4273       {     
4274           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4275       }
4276       else
4277       {
4278           emitcode ("mov", "a,#!constbyte",0xff);
4279           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4280       }
4281       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4282       emitcode ("dec", "%s", l);
4283       if (size > 2)
4284         {
4285             if (!strcmp(l, "acc"))
4286             {
4287                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4288             }
4289             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4290                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4291                      IS_AOP_PREG (IC_RESULT (ic)))
4292             {       
4293                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4294             }
4295             else
4296             {
4297                 emitcode ("mov", "a,#!constbyte",0xff);
4298                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4299             }
4300             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4301             emitcode ("dec", "%s", l);
4302         }
4303       if (size > 3)
4304         {
4305             if (!strcmp(l, "acc"))
4306             {
4307                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4308             }
4309             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4310                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4311                      IS_AOP_PREG (IC_RESULT (ic)))
4312             {       
4313                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4314             }
4315             else
4316             {
4317                 emitcode ("mov", "a,#!constbyte",0xff);
4318                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4319             }       
4320             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4321             emitcode ("dec", "%s", l);
4322         }
4323       if (emitTlbl)
4324         {
4325           emitcode ("", "!tlabeldef", tlbl->key + 100);
4326         }
4327       return TRUE;
4328     }
4329
4330   /* if the sizes are greater than 1 then we cannot */
4331   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4332       AOP_SIZE (IC_LEFT (ic)) > 1)
4333     return FALSE;
4334
4335   /* we can if the aops of the left & result match or
4336      if they are in registers and the registers are the
4337      same */
4338   if (
4339        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4340        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4341        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4342     {
4343
4344       _startLazyDPSEvaluation ();
4345       while (icount--)
4346         {
4347           emitcode ("dec", "%s",
4348                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4349         }
4350       _endLazyDPSEvaluation ();
4351
4352       return TRUE;
4353     }
4354
4355   return FALSE;
4356 }
4357
4358 /*-----------------------------------------------------------------*/
4359 /* addSign - complete with sign                                    */
4360 /*-----------------------------------------------------------------*/
4361 static void
4362 addSign (operand * result, int offset, int sign)
4363 {
4364   int size = (getDataSize (result) - offset);
4365   if (size > 0)
4366     {
4367       _startLazyDPSEvaluation();
4368       if (sign)
4369         {
4370           emitcode ("rlc", "a");
4371           emitcode ("subb", "a,acc");
4372           while (size--)
4373           {
4374             aopPut (AOP (result), "a", offset++);
4375           }
4376         }
4377       else
4378       {
4379         while (size--)
4380         {
4381           aopPut (AOP (result), zero, offset++);
4382         }
4383       }
4384       _endLazyDPSEvaluation();
4385     }
4386 }
4387
4388 /*-----------------------------------------------------------------*/
4389 /* genMinusBits - generates code for subtraction  of two bits      */
4390 /*-----------------------------------------------------------------*/
4391 static void
4392 genMinusBits (iCode * ic)
4393 {
4394   symbol *lbl = newiTempLabel (NULL);
4395
4396   D (emitcode (";", "genMinusBits "););
4397
4398   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4399     {
4400       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4401       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4402       emitcode ("cpl", "c");
4403       emitcode ("", "!tlabeldef", (lbl->key + 100));
4404       outBitC (IC_RESULT (ic));
4405     }
4406   else
4407     {
4408       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4409       emitcode ("subb", "a,acc");
4410       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4411       emitcode ("inc", "a");
4412       emitcode ("", "!tlabeldef", (lbl->key + 100));
4413       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4414       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4415     }
4416 }
4417
4418 /*-----------------------------------------------------------------*/
4419 /* genMinus - generates code for subtraction                       */
4420 /*-----------------------------------------------------------------*/
4421 static void
4422 genMinus (iCode * ic)
4423 {
4424     int size, offset = 0;
4425     int rSize;
4426     long lit = 0L;
4427     bool pushResult;
4428
4429     D (emitcode (";", "genMinus "););
4430
4431     AOP_OP_3_NOFATAL(ic, pushResult);   
4432
4433     if (!pushResult)
4434     {
4435       /* special cases :- */
4436       /* if both left & right are in bit space */
4437       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4438           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4439         {
4440           genMinusBits (ic);
4441           goto release;
4442         }
4443
4444       /* if I can do an decrement instead
4445          of subtract then GOOD for ME */
4446       if (genMinusDec (ic) == TRUE)
4447         goto release;
4448
4449     }
4450
4451   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4452
4453   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4454     {
4455       CLRC;
4456     }
4457   else
4458     {
4459       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4460       lit = -lit;
4461     }
4462
4463
4464   /* if literal, add a,#-lit, else normal subb */
4465   _startLazyDPSEvaluation ();
4466   while (size--) {
4467       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4468           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4469               emitcode ("mov","b,%s",
4470                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4471               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4472               emitcode ("subb","a,b");
4473           } else {
4474               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4475               emitcode ("subb", "a,%s",
4476                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4477                                 DP2_RESULT_REG));
4478           }
4479       } else {
4480           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4481           /* first add without previous c */
4482           if (!offset) {
4483               if (!size && lit==-1) {
4484                   emitcode ("dec", "a");
4485               } else {
4486                   emitcode ("add", "a,#!constbyte",
4487                             (unsigned int) (lit & 0x0FFL));
4488               }
4489           } else {
4490               emitcode ("addc", "a,#!constbyte",
4491                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4492           }
4493       }
4494       
4495       if (pushResult) {
4496           emitcode ("push", "acc");
4497       } else {
4498           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4499       }
4500       offset++;
4501   }
4502   _endLazyDPSEvaluation ();
4503   
4504   if (pushResult)
4505     {
4506       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4507
4508       size = getDataSize (IC_LEFT (ic));
4509       rSize = getDataSize (IC_RESULT (ic));
4510
4511       ADJUST_PUSHED_RESULT(size, rSize);
4512
4513       _startLazyDPSEvaluation ();
4514       while (size--)
4515         {
4516           emitcode ("pop", "acc");
4517           aopPut (AOP (IC_RESULT (ic)), "a", size);
4518         }
4519       _endLazyDPSEvaluation ();
4520     }
4521
4522   adjustArithmeticResult (ic);
4523
4524 release:
4525   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4527   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4528 }
4529
4530
4531 /*-----------------------------------------------------------------*/
4532 /* genMultbits :- multiplication of bits                           */
4533 /*-----------------------------------------------------------------*/
4534 static void
4535 genMultbits (operand * left,
4536              operand * right,
4537              operand * result,
4538              iCode   * ic)
4539 {
4540   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4541   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4542   aopOp(result, ic, TRUE, FALSE);
4543   outBitC (result);
4544 }
4545
4546
4547 /*-----------------------------------------------------------------*/
4548 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4549 /*-----------------------------------------------------------------*/
4550 static void
4551 genMultOneByte (operand * left,
4552                 operand * right,
4553                 operand * result,
4554                 iCode   * ic)
4555 {
4556   sym_link *opetype = operandType (result);
4557   symbol *lbl;
4558
4559
4560   /* (if two literals: the value is computed before) */
4561   /* if one literal, literal on the right */
4562   if (AOP_TYPE (left) == AOP_LIT)
4563     {
4564       operand *t = right;
4565       right = left;
4566       left = t;
4567       emitcode (";", "swapped left and right");
4568     }
4569
4570   if (SPEC_USIGN(opetype)
4571       // ignore the sign of left and right, what else can we do?
4572       || (SPEC_USIGN(operandType(left)) && 
4573           SPEC_USIGN(operandType(right)))) {
4574     // just an unsigned 8*8=8/16 multiply
4575     //emitcode (";","unsigned");
4576     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4577     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4578     emitcode ("mul", "ab");
4579    
4580     _G.accInUse++; _G.bInUse++;
4581     aopOp(result, ic, TRUE, FALSE);
4582       
4583       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4584       {
4585           // this should never happen
4586           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4587                    AOP_SIZE(result), __FILE__, lineno);
4588           exit (1);
4589       }      
4590       
4591     aopPut (AOP (result), "a", 0);
4592     _G.accInUse--; _G.bInUse--;
4593     if (AOP_SIZE(result)==2) 
4594     {
4595       aopPut (AOP (result), "b", 1);
4596     }
4597     return;
4598   }
4599
4600   // we have to do a signed multiply
4601
4602   emitcode (";", "signed");
4603   emitcode ("clr", "F0"); // reset sign flag
4604   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4605
4606   lbl=newiTempLabel(NULL);
4607   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4608   // left side is negative, 8-bit two's complement, this fails for -128
4609   emitcode ("setb", "F0"); // set sign flag
4610   emitcode ("cpl", "a");
4611   emitcode ("inc", "a");
4612
4613   emitcode ("", "!tlabeldef", lbl->key+100);
4614
4615   /* if literal */
4616   if (AOP_TYPE(right)==AOP_LIT) {
4617     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4618     /* AND literal negative */
4619     if ((int) val < 0) {
4620       emitcode ("cpl", "F0"); // complement sign flag
4621       emitcode ("mov", "b,#!constbyte", -val);
4622     } else {
4623       emitcode ("mov", "b,#!constbyte", val);
4624     }
4625   } else {
4626     lbl=newiTempLabel(NULL);
4627     emitcode ("mov", "b,a");
4628     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4629     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4630     // right side is negative, 8-bit two's complement
4631     emitcode ("cpl", "F0"); // complement sign flag
4632     emitcode ("cpl", "a");
4633     emitcode ("inc", "a");
4634     emitcode ("", "!tlabeldef", lbl->key+100);
4635   }
4636   emitcode ("mul", "ab");
4637     
4638   _G.accInUse++;_G.bInUse++;
4639   aopOp(result, ic, TRUE, FALSE);
4640     
4641   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4642   {
4643     // this should never happen
4644       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4645                AOP_SIZE(result), __FILE__, lineno);
4646       exit (1);
4647   }    
4648     
4649   lbl=newiTempLabel(NULL);
4650   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4651   // only ONE op was negative, we have to do a 8/16-bit two's complement
4652   emitcode ("cpl", "a"); // lsb
4653   if (AOP_SIZE(result)==1) {
4654     emitcode ("inc", "a");
4655   } else {
4656     emitcode ("add", "a,#1");
4657     emitcode ("xch", "a,b");
4658     emitcode ("cpl", "a"); // msb
4659     emitcode ("addc", "a,#0");
4660     emitcode ("xch", "a,b");
4661   }
4662
4663   emitcode ("", "!tlabeldef", lbl->key+100);
4664   aopPut (AOP (result), "a", 0);
4665   _G.accInUse--;_G.bInUse--;
4666   if (AOP_SIZE(result)==2) {
4667     aopPut (AOP (result), "b", 1);
4668   }
4669 }
4670
4671 /*-----------------------------------------------------------------*/
4672 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4673 /*-----------------------------------------------------------------*/
4674 static void genMultTwoByte (operand *left, operand *right, 
4675                             operand *result, iCode *ic)
4676 {
4677         sym_link *retype = getSpec(operandType(right));
4678         sym_link *letype = getSpec(operandType(left));
4679         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4680         symbol *lbl;
4681
4682         if (AOP_TYPE (left) == AOP_LIT) {
4683                 operand *t = right;
4684                 right = left;
4685                 left = t;
4686         }
4687         /* save EA bit in F1 */
4688         lbl = newiTempLabel(NULL);
4689         emitcode ("setb","F1");
4690         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4691         emitcode ("clr","F1");
4692         emitcode("","!tlabeldef",lbl->key+100);
4693
4694         /* load up MB with right */
4695         if (!umult) {
4696                 emitcode("clr","F0");
4697                 if (AOP_TYPE(right) == AOP_LIT) {
4698                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4699                         if (val < 0) {
4700                                 emitcode("setb","F0");
4701                                 val = -val;
4702                         }
4703                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4704                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4705                 } else {
4706                         lbl = newiTempLabel(NULL);
4707                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4708                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4709                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4710                         emitcode ("xch", "a,b");
4711                         emitcode ("cpl","a");
4712                         emitcode ("add", "a,#1");
4713                         emitcode ("xch", "a,b");
4714                         emitcode ("cpl", "a"); // msb
4715                         emitcode ("addc", "a,#0");
4716                         emitcode ("setb","F0");
4717                         emitcode ("","!tlabeldef",lbl->key+100);
4718                         emitcode ("mov","mb,b");
4719                         emitcode ("mov","mb,a");
4720                 }
4721         } else {
4722                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4723                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4724         }
4725         /* load up MA with left */
4726         if (!umult) {
4727                 lbl = newiTempLabel(NULL);
4728                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4729                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4730                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4731                 emitcode ("xch", "a,b");
4732                 emitcode ("cpl","a");
4733                 emitcode ("add", "a,#1");
4734                 emitcode ("xch", "a,b");
4735                 emitcode ("cpl", "a"); // msb
4736                 emitcode ("addc","a,#0");
4737                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4738                 emitcode ("setb","F0");
4739                 emitcode ("","!tlabeldef",lbl->key+100);
4740                 emitcode ("mov","ma,b");
4741                 emitcode ("mov","ma,a");
4742         } else {
4743                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4744                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4745         }
4746         /* wait for multiplication to finish */
4747         lbl = newiTempLabel(NULL);
4748         emitcode("","!tlabeldef", lbl->key+100);
4749         emitcode("mov","a,mcnt1");
4750         emitcode("anl","a,#!constbyte",0x80);
4751         emitcode("jnz","!tlabel",lbl->key+100);
4752         
4753         freeAsmop (left, NULL, ic, TRUE);
4754         freeAsmop (right, NULL, ic,TRUE);
4755         aopOp(result, ic, TRUE, FALSE);
4756
4757         /* if unsigned then simple */   
4758         if (umult) {
4759                 emitcode ("mov","a,ma");
4760                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4761                 emitcode ("mov","a,ma");
4762                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4763                 aopPut(AOP(result),"ma",1);
4764                 aopPut(AOP(result),"ma",0);
4765         } else {
4766                 emitcode("push","ma");
4767                 emitcode("push","ma");
4768                 emitcode("push","ma");
4769                 MOVA("ma");
4770                 /* negate result if needed */
4771                 lbl = newiTempLabel(NULL);      
4772                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4773                 emitcode("cpl","a");
4774                 emitcode("add","a,#1");
4775                 emitcode("","!tlabeldef", lbl->key+100);
4776                 if (AOP_TYPE(result) == AOP_ACC)
4777                 {
4778                     D(emitcode(";", "ACC special case."););
4779                     /* We know result is the only live aop, and 
4780                      * it's obviously not a DPTR2, so AP is available.
4781                      */
4782                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4783                 }
4784                 else
4785                 {
4786                     aopPut(AOP(result),"a",0);
4787                 }
4788             
4789                 emitcode("pop","acc");
4790                 lbl = newiTempLabel(NULL);      
4791                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4792                 emitcode("cpl","a");
4793                 emitcode("addc","a,#0");
4794                 emitcode("","!tlabeldef", lbl->key+100);
4795                 aopPut(AOP(result),"a",1);
4796                 emitcode("pop","acc");
4797                 if (AOP_SIZE(result) >= 3) {
4798                         lbl = newiTempLabel(NULL);      
4799                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4800                         emitcode("cpl","a");
4801                         emitcode("addc","a,#0");                        
4802                         emitcode("","!tlabeldef", lbl->key+100);
4803                         aopPut(AOP(result),"a",2);
4804                 }
4805                 emitcode("pop","acc");
4806                 if (AOP_SIZE(result) >= 4) {
4807                         lbl = newiTempLabel(NULL);      
4808                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4809                         emitcode("cpl","a");
4810                         emitcode("addc","a,#0");                        
4811                         emitcode("","!tlabeldef", lbl->key+100);
4812                         aopPut(AOP(result),"a",3);
4813                 }
4814                 if (AOP_TYPE(result) == AOP_ACC)
4815                 {
4816                     /* We stashed the result away above. */
4817                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4818                 }           
4819                 
4820         }
4821         freeAsmop (result, NULL, ic, TRUE);
4822
4823         /* restore EA bit in F1 */
4824         lbl = newiTempLabel(NULL);
4825         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4826         emitcode ("setb","EA");
4827         emitcode("","!tlabeldef",lbl->key+100);
4828         return ;
4829 }
4830
4831 /*-----------------------------------------------------------------*/
4832 /* genMult - generates code for multiplication                     */
4833 /*-----------------------------------------------------------------*/
4834 static void
4835 genMult (iCode * ic)
4836 {
4837   operand *left = IC_LEFT (ic);
4838   operand *right = IC_RIGHT (ic);
4839   operand *result = IC_RESULT (ic);
4840
4841   D (emitcode (";", "genMult "););
4842
4843   /* assign the amsops */
4844   AOP_OP_2 (ic);
4845
4846   /* special cases first */
4847   /* both are bits */
4848   if (AOP_TYPE (left) == AOP_CRY &&
4849       AOP_TYPE (right) == AOP_CRY)
4850     {
4851       genMultbits (left, right, result, ic);
4852       goto release;
4853     }
4854
4855   /* if both are of size == 1 */
4856   if (AOP_SIZE (left) == 1 &&
4857       AOP_SIZE (right) == 1)
4858     {
4859       genMultOneByte (left, right, result, ic);
4860       goto release;
4861     }
4862
4863   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4864           /* use the ds390 ARITHMETIC accel UNIT */
4865           genMultTwoByte (left, right, result, ic);
4866           return ;
4867   }
4868   /* should have been converted to function call */
4869   assert (0);
4870
4871 release:
4872   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4873   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874   freeAsmop (result, NULL, ic, TRUE);
4875 }
4876
4877 /*-----------------------------------------------------------------*/
4878 /* genDivbits :- division of bits                                  */
4879 /*-----------------------------------------------------------------*/
4880 static void
4881 genDivbits (operand * left,
4882             operand * right,
4883             operand * result,
4884             iCode   * ic)
4885 {
4886
4887   char *l;
4888
4889   /* the result must be bit */
4890   LOAD_AB_FOR_DIV (left, right, l);
4891   emitcode ("div", "ab");
4892   emitcode ("rrc", "a");
4893   aopOp(result, ic, TRUE, FALSE);
4894     
4895   aopPut (AOP (result), "c", 0);
4896 }
4897
4898 /*-----------------------------------------------------------------*/
4899 /* genDivOneByte : 8 bit division                                  */
4900 /*-----------------------------------------------------------------*/
4901 static void
4902 genDivOneByte (operand * left,
4903                operand * right,
4904                operand * result,
4905                iCode   * ic)
4906 {
4907   sym_link *opetype = operandType (result);
4908   char *l;
4909   symbol *lbl;
4910   int size, offset;
4911
4912   offset = 1;
4913   /* signed or unsigned */
4914   if (SPEC_USIGN (opetype))
4915     {
4916         /* unsigned is easy */
4917         LOAD_AB_FOR_DIV (left, right, l);
4918         emitcode ("div", "ab");
4919
4920         _G.accInUse++;
4921         aopOp(result, ic, TRUE, FALSE);
4922         aopPut (AOP (result), "a", 0);
4923         _G.accInUse--;
4924
4925         size = AOP_SIZE (result) - 1;
4926         
4927         while (size--)
4928         {
4929             aopPut (AOP (result), zero, offset++);
4930         }
4931       return;
4932     }
4933
4934   /* signed is a little bit more difficult */
4935
4936   /* save the signs of the operands */
4937   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4938   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4939   emitcode ("push", "acc");     /* save it on the stack */
4940
4941   /* now sign adjust for both left & right */
4942   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4943   lbl = newiTempLabel (NULL);
4944   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4945   emitcode ("cpl", "a");
4946   emitcode ("inc", "a");
4947   emitcode ("", "!tlabeldef", (lbl->key + 100));
4948   emitcode ("mov", "b,a");
4949
4950   /* sign adjust left side */
4951   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4952
4953   lbl = newiTempLabel (NULL);
4954   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4955   emitcode ("cpl", "a");
4956   emitcode ("inc", "a");
4957   emitcode ("", "!tlabeldef", (lbl->key + 100));
4958
4959   /* now the division */
4960   emitcode ("nop", "; workaround for DS80C390 div bug.");
4961   emitcode ("div", "ab");
4962   /* we are interested in the lower order
4963      only */
4964   emitcode ("mov", "b,a");
4965   lbl = newiTempLabel (NULL);
4966   emitcode ("pop", "acc");
4967   /* if there was an over flow we don't
4968      adjust the sign of the result */
4969   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4970   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4971   CLRC;
4972   emitcode ("clr", "a");
4973   emitcode ("subb", "a,b");
4974   emitcode ("mov", "b,a");
4975   emitcode ("", "!tlabeldef", (lbl->key + 100));
4976
4977   /* now we are done */
4978   _G.accInUse++;     _G.bInUse++;
4979     aopOp(result, ic, TRUE, FALSE);
4980     
4981     aopPut (AOP (result), "b", 0);
4982     
4983     size = AOP_SIZE (result) - 1;
4984     
4985     if (size > 0)
4986     {
4987       emitcode ("mov", "c,b.7");
4988       emitcode ("subb", "a,acc");
4989     }
4990     while (size--)
4991     {
4992         aopPut (AOP (result), "a", offset++);
4993     }
4994     _G.accInUse--;     _G.bInUse--;
4995
4996 }
4997
4998 /*-----------------------------------------------------------------*/
4999 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5000 /*-----------------------------------------------------------------*/
5001 static void genDivTwoByte (operand *left, operand *right, 
5002                             operand *result, iCode *ic)
5003 {
5004         sym_link *retype = getSpec(operandType(right));
5005         sym_link *letype = getSpec(operandType(left));
5006         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5007         symbol *lbl;
5008
5009         /* save EA bit in F1 */
5010         lbl = newiTempLabel(NULL);
5011         emitcode ("setb","F1");
5012         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5013         emitcode ("clr","F1");
5014         emitcode("","!tlabeldef",lbl->key+100);
5015
5016         /* load up MA with left */
5017         if (!umult) {
5018                 emitcode("clr","F0");
5019                 lbl = newiTempLabel(NULL);
5020                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5021                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5022                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5023                 emitcode ("xch", "a,b");
5024                 emitcode ("cpl","a");
5025                 emitcode ("add", "a,#1");
5026                 emitcode ("xch", "a,b");
5027                 emitcode ("cpl", "a"); // msb
5028                 emitcode ("addc","a,#0");
5029                 emitcode ("setb","F0");
5030                 emitcode ("","!tlabeldef",lbl->key+100);
5031                 emitcode ("mov","ma,b");
5032                 emitcode ("mov","ma,a");
5033         } else {
5034                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5035                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5036         }
5037
5038         /* load up MB with right */
5039         if (!umult) {
5040                 if (AOP_TYPE(right) == AOP_LIT) {
5041                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5042                         if (val < 0) {
5043                                 lbl = newiTempLabel(NULL);
5044                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5045                                 emitcode("setb","F0");
5046                                 emitcode ("","!tlabeldef",lbl->key+100);
5047                                 val = -val;
5048                         } 
5049                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5050                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5051                 } else {
5052                         lbl = newiTempLabel(NULL);
5053                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5054                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5055                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5056                         emitcode ("xch", "a,b");
5057                         emitcode ("cpl","a");
5058                         emitcode ("add", "a,#1");
5059                         emitcode ("xch", "a,b");
5060                         emitcode ("cpl", "a"); // msb
5061                         emitcode ("addc", "a,#0");
5062                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5063                         emitcode ("setb","F0");
5064                         emitcode ("","!tlabeldef",lbl->key+100);
5065                         emitcode ("mov","mb,b");
5066                         emitcode ("mov","mb,a");
5067                 }
5068         } else {
5069                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5070                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5071         }
5072
5073         /* wait for multiplication to finish */
5074         lbl = newiTempLabel(NULL);
5075         emitcode("","!tlabeldef", lbl->key+100);
5076         emitcode("mov","a,mcnt1");
5077         emitcode("anl","a,#!constbyte",0x80);
5078         emitcode("jnz","!tlabel",lbl->key+100);
5079         
5080         freeAsmop (left, NULL, ic, TRUE);
5081         freeAsmop (right, NULL, ic,TRUE);
5082         aopOp(result, ic, TRUE, FALSE);
5083
5084         /* if unsigned then simple */   
5085         if (umult) {
5086                 aopPut(AOP(result),"ma",1);
5087                 aopPut(AOP(result),"ma",0);
5088         } else {
5089                 emitcode("push","ma");
5090                 MOVA("ma");
5091                 /* negate result if needed */
5092                 lbl = newiTempLabel(NULL);      
5093                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5094                 emitcode("cpl","a");
5095                 emitcode("add","a,#1");
5096                 emitcode("","!tlabeldef", lbl->key+100);
5097                 aopPut(AOP(result),"a",0);
5098                 emitcode("pop","acc");
5099                 lbl = newiTempLabel(NULL);      
5100                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5101                 emitcode("cpl","a");
5102                 emitcode("addc","a,#0");
5103                 emitcode("","!tlabeldef", lbl->key+100);
5104                 aopPut(AOP(result),"a",1);
5105         }
5106         freeAsmop (result, NULL, ic, TRUE);
5107         /* restore EA bit in F1 */
5108         lbl = newiTempLabel(NULL);
5109         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5110         emitcode ("setb","EA");
5111         emitcode("","!tlabeldef",lbl->key+100);
5112         return ;
5113 }
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genDiv - generates code for division                            */
5117 /*-----------------------------------------------------------------*/
5118 static void
5119 genDiv (iCode * ic)
5120 {
5121   operand *left = IC_LEFT (ic);
5122   operand *right = IC_RIGHT (ic);
5123   operand *result = IC_RESULT (ic);
5124
5125   D (emitcode (";", "genDiv "););
5126
5127   /* assign the amsops */
5128   AOP_OP_2 (ic);
5129
5130   /* special cases first */
5131   /* both are bits */
5132   if (AOP_TYPE (left) == AOP_CRY &&
5133       AOP_TYPE (right) == AOP_CRY)
5134     {
5135       genDivbits (left, right, result, ic);
5136       goto release;
5137     }
5138
5139   /* if both are of size == 1 */
5140   if (AOP_SIZE (left) == 1 &&
5141       AOP_SIZE (right) == 1)
5142     {
5143       genDivOneByte (left, right, result, ic);
5144       goto release;
5145     }
5146
5147   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5148           /* use the ds390 ARITHMETIC accel UNIT */
5149           genDivTwoByte (left, right, result, ic);
5150           return ;
5151   }
5152   /* should have been converted to function call */
5153   assert (0);
5154 release:
5155   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5156   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5157   freeAsmop (result, NULL, ic, TRUE);
5158 }
5159
5160 /*-----------------------------------------------------------------*/
5161 /* genModbits :- modulus of bits                                   */
5162 /*-----------------------------------------------------------------*/
5163 static void
5164 genModbits (operand * left,
5165             operand * right,
5166             operand * result,
5167             iCode   * ic)
5168 {
5169
5170   char *l;
5171
5172   /* the result must be bit */
5173   LOAD_AB_FOR_DIV (left, right, l);
5174   emitcode ("div", "ab");
5175   emitcode ("mov", "a,b");
5176   emitcode ("rrc", "a");
5177   aopOp(result, ic, TRUE, FALSE);
5178   aopPut (AOP (result), "c", 0);
5179 }
5180
5181 /*-----------------------------------------------------------------*/
5182 /* genModOneByte : 8 bit modulus                                   */
5183 /*-----------------------------------------------------------------*/
5184 static void
5185 genModOneByte (operand * left,
5186                operand * right,
5187                operand * result,
5188                iCode   * ic)
5189 {
5190   sym_link *opetype = operandType (result);
5191   char *l;
5192   symbol *lbl;
5193
5194   /* signed or unsigned */
5195   if (SPEC_USIGN (opetype))
5196     {
5197       /* unsigned is easy */
5198       LOAD_AB_FOR_DIV (left, right, l);
5199       emitcode ("div", "ab");
5200       aopOp(result, ic, TRUE, FALSE);   
5201       aopPut (AOP (result), "b", 0);
5202       return;
5203     }
5204
5205   /* signed is a little bit more difficult */
5206
5207   /* save the signs of the operands */
5208   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5209
5210   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5211   emitcode ("push", "acc");     /* save it on the stack */
5212
5213   /* now sign adjust for both left & right */
5214   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5215
5216   lbl = newiTempLabel (NULL);
5217   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5218   emitcode ("cpl", "a");
5219   emitcode ("inc", "a");
5220   emitcode ("", "!tlabeldef", (lbl->key + 100));
5221   emitcode ("mov", "b,a");
5222
5223   /* sign adjust left side */
5224   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5225
5226   lbl = newiTempLabel (NULL);
5227   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5228   emitcode ("cpl", "a");
5229   emitcode ("inc", "a");
5230   emitcode ("", "!tlabeldef", (lbl->key + 100));
5231
5232   /* now the multiplication */
5233   emitcode ("nop", "; workaround for DS80C390 div bug.");
5234   emitcode ("div", "ab");
5235   /* we are interested in the lower order
5236      only */
5237   lbl = newiTempLabel (NULL);
5238   emitcode ("pop", "acc");
5239   /* if there was an over flow we don't
5240      adjust the sign of the result */
5241   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5242   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5243   CLRC;
5244   emitcode ("clr", "a");
5245   emitcode ("subb", "a,b");
5246   emitcode ("mov", "b,a");
5247   emitcode ("", "!tlabeldef", (lbl->key + 100));
5248   
5249   _G.bInUse++;
5250   /* now we are done */
5251   aopOp(result, ic, TRUE, FALSE);    
5252   aopPut (AOP (result), "b", 0);
5253   _G.bInUse--;
5254
5255 }
5256
5257 /*-----------------------------------------------------------------*/
5258 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5259 /*-----------------------------------------------------------------*/
5260 static void genModTwoByte (operand *left, operand *right, 
5261                             operand *result, iCode *ic)
5262 {
5263         sym_link *retype = getSpec(operandType(right));
5264         sym_link *letype = getSpec(operandType(left));
5265         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5266         symbol *lbl;
5267
5268         /* load up MA with left */
5269         /* save EA bit in F1 */
5270         lbl = newiTempLabel(NULL);
5271         emitcode ("setb","F1");
5272         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5273         emitcode ("clr","F1");
5274         emitcode("","!tlabeldef",lbl->key+100);
5275
5276         if (!umult) {
5277                 lbl = newiTempLabel(NULL);
5278                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5279                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5280                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5281                 emitcode ("xch", "a,b");
5282                 emitcode ("cpl","a");
5283                 emitcode ("add", "a,#1");
5284                 emitcode ("xch", "a,b");
5285                 emitcode ("cpl", "a"); // msb
5286                 emitcode ("addc","a,#0");
5287                 emitcode ("","!tlabeldef",lbl->key+100);
5288                 emitcode ("mov","ma,b");
5289                 emitcode ("mov","ma,a");
5290         } else {
5291                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293         }
5294
5295         /* load up MB with right */
5296         if (!umult) {
5297                 if (AOP_TYPE(right) == AOP_LIT) {
5298                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5299                         if (val < 0) {
5300                                 val = -val;
5301                         } 
5302                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5303                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5304                 } else {
5305                         lbl = newiTempLabel(NULL);
5306                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5307                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5308                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5309                         emitcode ("xch", "a,b");
5310                         emitcode ("cpl","a");
5311                         emitcode ("add", "a,#1");
5312                         emitcode ("xch", "a,b");
5313                         emitcode ("cpl", "a"); // msb
5314                         emitcode ("addc", "a,#0");
5315                         emitcode ("","!tlabeldef",lbl->key+100);
5316                         emitcode ("mov","mb,b");
5317                         emitcode ("mov","mb,a");
5318                 }
5319         } else {
5320                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5321                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5322         }
5323
5324         /* wait for multiplication to finish */
5325         lbl = newiTempLabel(NULL);
5326         emitcode("","!tlabeldef", lbl->key+100);
5327         emitcode("mov","a,mcnt1");
5328         emitcode("anl","a,#!constbyte",0x80);
5329         emitcode("jnz","!tlabel",lbl->key+100);
5330         
5331         freeAsmop (left, NULL, ic, TRUE);
5332         freeAsmop (right, NULL, ic,TRUE);
5333         aopOp(result, ic, TRUE, FALSE);
5334
5335         aopPut(AOP(result),"mb",1);
5336         aopPut(AOP(result),"mb",0);
5337         freeAsmop (result, NULL, ic, TRUE);
5338
5339         /* restore EA bit in F1 */
5340         lbl = newiTempLabel(NULL);
5341         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5342         emitcode ("setb","EA");
5343         emitcode("","!tlabeldef",lbl->key+100);
5344         return ;
5345 }
5346
5347 /*-----------------------------------------------------------------*/
5348 /* genMod - generates code for division                            */
5349 /*-----------------------------------------------------------------*/
5350 static void
5351 genMod (iCode * ic)
5352 {
5353   operand *left = IC_LEFT (ic);
5354   operand *right = IC_RIGHT (ic);
5355   operand *result = IC_RESULT (ic);
5356
5357   D (emitcode (";", "genMod "); );
5358
5359   /* assign the amsops */
5360   AOP_OP_2 (ic);
5361
5362   /* special cases first */
5363   /* both are bits */
5364   if (AOP_TYPE (left) == AOP_CRY &&
5365       AOP_TYPE (right) == AOP_CRY)
5366     {
5367       genModbits (left, right, result, ic);
5368       goto release;
5369     }
5370
5371   /* if both are of size == 1 */
5372   if (AOP_SIZE (left) == 1 &&
5373       AOP_SIZE (right) == 1)
5374     {
5375       genModOneByte (left, right, result, ic);
5376       goto release;
5377     }
5378
5379   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5380           /* use the ds390 ARITHMETIC accel UNIT */
5381           genModTwoByte (left, right, result, ic);
5382           return ;
5383   }
5384
5385   /* should have been converted to function call */
5386   assert (0);
5387
5388 release:
5389   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5390   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5391   freeAsmop (result, NULL, ic, TRUE);
5392 }
5393
5394 /*-----------------------------------------------------------------*/
5395 /* genIfxJump :- will create a jump depending on the ifx           */
5396 /*-----------------------------------------------------------------*/
5397 static void
5398 genIfxJump (iCode * ic, char *jval)
5399 {
5400   symbol *jlbl;
5401   symbol *tlbl = newiTempLabel (NULL);
5402   char *inst;
5403
5404   D (emitcode (";", "genIfxJump"););
5405
5406   /* if true label then we jump if condition
5407      supplied is true */
5408   if (IC_TRUE (ic))
5409     {
5410       jlbl = IC_TRUE (ic);
5411       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5412                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5413     }
5414   else
5415     {
5416       /* false label is present */
5417       jlbl = IC_FALSE (ic);
5418       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5419                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5420     }
5421   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5422     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5423   else
5424     emitcode (inst, "!tlabel", tlbl->key + 100);
5425   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5426   emitcode ("", "!tlabeldef", tlbl->key + 100);
5427
5428   /* mark the icode as generated */
5429   ic->generated = 1;
5430 }
5431
5432 /*-----------------------------------------------------------------*/
5433 /* genCmp :- greater or less than comparison                       */
5434 /*-----------------------------------------------------------------*/
5435 static void
5436 genCmp (operand * left, operand * right,
5437         iCode * ic, iCode * ifx, int sign)
5438 {
5439   int size, offset = 0;
5440   unsigned long lit = 0L;
5441   operand *result;
5442
5443   D (emitcode (";", "genCmp"););
5444
5445   result = IC_RESULT (ic);
5446
5447   /* if left & right are bit variables */
5448   if (AOP_TYPE (left) == AOP_CRY &&
5449       AOP_TYPE (right) == AOP_CRY)
5450     {
5451       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5452       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5453     }
5454   else
5455     {
5456       /* subtract right from left if at the
5457          end the carry flag is set then we know that
5458          left is greater than right */
5459       size = max (AOP_SIZE (left), AOP_SIZE (right));
5460
5461       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5462       if ((size == 1) && !sign 
5463           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5464         {
5465           symbol *lbl = newiTempLabel (NULL);
5466           emitcode ("cjne", "%s,%s,!tlabel",
5467                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5468                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5469                     lbl->key + 100);
5470           emitcode ("", "!tlabeldef", lbl->key + 100);
5471         }
5472       else
5473         {
5474           if (AOP_TYPE (right) == AOP_LIT)
5475             {
5476               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5477               /* optimize if(x < 0) or if(x >= 0) */
5478               if (lit == 0L)
5479                 {
5480                   if (!sign)
5481                     {
5482                       CLRC;
5483                     }
5484                   else
5485                     {
5486                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5487
5488                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490
5491                       aopOp (result, ic, FALSE, FALSE);
5492
5493                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5494                         {
5495                           freeAsmop (result, NULL, ic, TRUE);
5496                           genIfxJump (ifx, "acc.7");
5497                           return;
5498                         }
5499                       else
5500                         {
5501                           emitcode ("rlc", "a");
5502                         }
5503                       goto release_freedLR;
5504                     }
5505                   goto release;
5506                 }
5507             }
5508           CLRC;
5509           while (size--)
5510             {
5511               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5512               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5513               // emitcode (";", "genCmp #2");
5514               if (sign && (size == 0))
5515                 {
5516                   // emitcode (";", "genCmp #3");
5517                   emitcode ("xrl", "a,#!constbyte",0x80);
5518                   if (AOP_TYPE (right) == AOP_LIT)
5519                     {
5520                       unsigned long lit = (unsigned long)
5521                       floatFromVal (AOP (right)->aopu.aop_lit);
5522                       // emitcode (";", "genCmp #3.1");
5523                       emitcode ("subb", "a,#!constbyte",
5524                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5525                     }
5526                   else
5527                     {
5528                       // emitcode (";", "genCmp #3.2");
5529                       saveAccWarn = 0;  
5530                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5531                       saveAccWarn = DEFAULT_ACC_WARNING;
5532                       emitcode ("xrl", "b,#!constbyte",0x80);
5533                       emitcode ("subb", "a,b");
5534                     }
5535                 }
5536               else
5537                 {
5538                   const char *s;
5539
5540                   // emitcode (";", "genCmp #4");
5541                   saveAccWarn = 0;
5542                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5543                   saveAccWarn = DEFAULT_ACC_WARNING;
5544
5545                   emitcode ("subb", "a,%s", s);
5546                 }
5547             }
5548         }
5549     }
5550
5551 release:
5552 /* Don't need the left & right operands any more; do need the result. */
5553   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5554   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5555
5556   aopOp (result, ic, FALSE, FALSE);
5557
5558 release_freedLR:
5559
5560   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5561     {
5562       outBitC (result);
5563     }
5564   else
5565     {
5566       /* if the result is used in the next
5567          ifx conditional branch then generate
5568          code a little differently */
5569       if (ifx)
5570         {
5571           genIfxJump (ifx, "c");
5572         }
5573       else
5574         {
5575           outBitC (result);
5576         }
5577       /* leave the result in acc */
5578     }
5579   freeAsmop (result, NULL, ic, TRUE);
5580 }
5581
5582 /*-----------------------------------------------------------------*/
5583 /* genCmpGt :- greater than comparison                             */
5584 /*-----------------------------------------------------------------*/
5585 static void
5586 genCmpGt (iCode * ic, iCode * ifx)
5587 {
5588   operand *left, *right;
5589   sym_link *letype, *retype;
5590   int sign;
5591
5592   D (emitcode (";", "genCmpGt ");
5593     );
5594
5595   left = IC_LEFT (ic);
5596   right = IC_RIGHT (ic);
5597
5598   letype = getSpec (operandType (left));
5599   retype = getSpec (operandType (right));
5600   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5601
5602   /* assign the left & right amsops */
5603   AOP_OP_2 (ic);
5604
5605   genCmp (right, left, ic, ifx, sign);
5606 }
5607
5608 /*-----------------------------------------------------------------*/
5609 /* genCmpLt - less than comparisons                                */
5610 /*-----------------------------------------------------------------*/
5611 static void
5612 genCmpLt (iCode * ic, iCode * ifx)
5613 {
5614   operand *left, *right;
5615   sym_link *letype, *retype;
5616   int sign;
5617
5618   D (emitcode (";", "genCmpLt "););
5619
5620   left = IC_LEFT (ic);
5621   right = IC_RIGHT (ic);
5622
5623   letype = getSpec (operandType (left));
5624   retype = getSpec (operandType (right));
5625   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5626
5627   /* assign the left & right amsops */
5628   AOP_OP_2 (ic);
5629
5630   genCmp (left, right, ic, ifx, sign);
5631 }
5632
5633 /*-----------------------------------------------------------------*/
5634 /* gencjneshort - compare and jump if not equal                    */
5635 /*-----------------------------------------------------------------*/
5636 static void
5637 gencjneshort (operand * left, operand * right, symbol * lbl)
5638 {
5639   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5640   int offset = 0;
5641   unsigned long lit = 0L;
5642
5643   D (emitcode (";", "gencjneshort");
5644     );
5645
5646   /* if the left side is a literal or
5647      if the right is in a pointer register and left
5648      is not */
5649   if ((AOP_TYPE (left) == AOP_LIT) ||
5650       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5651     {
5652       operand *t = right;
5653       right = left;
5654       left = t;
5655     }
5656
5657   if (AOP_TYPE (right) == AOP_LIT)
5658     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5659
5660   if (opIsGptr (left) || opIsGptr (right))
5661     {
5662       /* We are comparing a generic pointer to something.
5663        * Exclude the generic type byte from the comparison.
5664        */
5665       size--;
5666       D (emitcode (";", "cjneshort: generic ptr special case."););
5667     }
5668
5669
5670   /* if the right side is a literal then anything goes */
5671   if (AOP_TYPE (right) == AOP_LIT &&
5672       AOP_TYPE (left) != AOP_DIR)
5673     {
5674       while (size--)
5675         {
5676           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5677           emitcode ("cjne", "a,%s,!tlabel",
5678                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5679                     lbl->key + 100);
5680           offset++;
5681         }
5682     }
5683
5684   /* if the right side is in a register or in direct space or
5685      if the left is a pointer register & right is not */
5686   else if (AOP_TYPE (right) == AOP_REG ||
5687            AOP_TYPE (right) == AOP_DIR ||
5688            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5689            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5690     {
5691       while (size--)
5692         {
5693           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5694           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5695               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5696             emitcode ("jnz", "!tlabel", lbl->key + 100);
5697           else
5698             emitcode ("cjne", "a,%s,!tlabel",
5699                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5700                       lbl->key + 100);
5701           offset++;
5702         }
5703     }
5704   else
5705     {
5706       /* right is a pointer reg need both a & b */
5707       while (size--)
5708         {
5709           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5711           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5712           offset++;
5713         }
5714     }
5715 }
5716
5717 /*-----------------------------------------------------------------*/
5718 /* gencjne - compare and jump if not equal                         */
5719 /*-----------------------------------------------------------------*/
5720 static void
5721 gencjne (operand * left, operand * right, symbol * lbl)
5722 {
5723   symbol *tlbl = newiTempLabel (NULL);
5724
5725   D (emitcode (";", "gencjne");
5726     );
5727
5728   gencjneshort (left, right, lbl);
5729
5730   emitcode ("mov", "a,%s", one);
5731   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5732   emitcode ("", "!tlabeldef", lbl->key + 100);
5733   emitcode ("clr", "a");
5734   emitcode ("", "!tlabeldef", tlbl->key + 100);
5735 }
5736
5737 /*-----------------------------------------------------------------*/
5738 /* genCmpEq - generates code for equal to                          */
5739 /*-----------------------------------------------------------------*/
5740 static void
5741 genCmpEq (iCode * ic, iCode * ifx)
5742 {
5743   operand *left, *right, *result;
5744
5745   D (emitcode (";", "genCmpEq ");
5746     );
5747
5748   AOP_OP_2 (ic);
5749   AOP_SET_LOCALS (ic);
5750
5751   /* if literal, literal on the right or
5752      if the right is in a pointer register and left
5753      is not */
5754   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5755       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5756     {
5757       operand *t = IC_RIGHT (ic);
5758       IC_RIGHT (ic) = IC_LEFT (ic);
5759       IC_LEFT (ic) = t;
5760     }
5761
5762   if (ifx &&                    /* !AOP_SIZE(result) */
5763       OP_SYMBOL (result) &&
5764       OP_SYMBOL (result)->regType == REG_CND)
5765     {
5766       symbol *tlbl;
5767       /* if they are both bit variables */
5768       if (AOP_TYPE (left) == AOP_CRY &&
5769           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5770         {
5771           if (AOP_TYPE (right) == AOP_LIT)
5772             {
5773               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5774               if (lit == 0L)
5775                 {
5776                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5777                   emitcode ("cpl", "c");
5778                 }
5779               else if (lit == 1L)
5780                 {
5781                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5782                 }
5783               else
5784                 {
5785                   emitcode ("clr", "c");
5786                 }
5787               /* AOP_TYPE(right) == AOP_CRY */
5788             }
5789           else
5790             {
5791               symbol *lbl = newiTempLabel (NULL);
5792               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5794               emitcode ("cpl", "c");
5795               emitcode ("", "!tlabeldef", (lbl->key + 100));
5796             }
5797           /* if true label then we jump if condition
5798              supplied is true */
5799           tlbl = newiTempLabel (NULL);
5800           if (IC_TRUE (ifx))
5801             {
5802               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5803               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5804             }
5805           else
5806             {
5807               emitcode ("jc", "!tlabel", tlbl->key + 100);
5808               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5809             }
5810           emitcode ("", "!tlabeldef", tlbl->key + 100);
5811         }
5812       else
5813         {
5814           tlbl = newiTempLabel (NULL);
5815           gencjneshort (left, right, tlbl);
5816           if (IC_TRUE (ifx))
5817             {
5818               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5819               emitcode ("", "!tlabeldef", tlbl->key + 100);
5820             }
5821           else
5822             {
5823               symbol *lbl = newiTempLabel (NULL);
5824               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5825               emitcode ("", "!tlabeldef", tlbl->key + 100);
5826               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5827               emitcode ("", "!tlabeldef", lbl->key + 100);
5828             }
5829         }
5830       /* mark the icode as generated */
5831       ifx->generated = 1;
5832
5833       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5834       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835       return;
5836     }
5837
5838   /* if they are both bit variables */
5839   if (AOP_TYPE (left) == AOP_CRY &&
5840       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5841     {
5842       if (AOP_TYPE (right) == AOP_LIT)
5843         {
5844           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5845           if (lit == 0L)
5846             {
5847               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5848               emitcode ("cpl", "c");
5849             }
5850           else if (lit == 1L)
5851             {
5852               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5853             }
5854           else
5855             {
5856               emitcode ("clr", "c");
5857             }
5858           /* AOP_TYPE(right) == AOP_CRY */
5859         }
5860       else
5861         {
5862           symbol *lbl = newiTempLabel (NULL);
5863           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5865           emitcode ("cpl", "c");
5866           emitcode ("", "!tlabeldef", (lbl->key + 100));
5867         }
5868
5869       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5871
5872       aopOp (result, ic, TRUE, FALSE);
5873
5874       /* c = 1 if egal */
5875       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5876         {
5877           outBitC (result);
5878           goto release;
5879         }
5880       if (ifx)
5881         {
5882           genIfxJump (ifx, "c");
5883           goto release;
5884         }
5885       /* if the result is used in an arithmetic operation
5886          then put the result in place */
5887       outBitC (result);
5888     }
5889   else
5890     {
5891       gencjne (left, right, newiTempLabel (NULL));
5892
5893       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5894       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5895
5896       aopOp (result, ic, TRUE, FALSE);
5897
5898       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5899         {
5900           aopPut (AOP (result), "a", 0);
5901           goto release;
5902         }
5903       if (ifx)
5904         {
5905           genIfxJump (ifx, "a");
5906           goto release;
5907         }
5908       /* if the result is used in an arithmetic operation
5909          then put the result in place */
5910       if (AOP_TYPE (result) != AOP_CRY)
5911         outAcc (result);
5912       /* leave the result in acc */
5913     }
5914
5915 release:
5916   freeAsmop (result, NULL, ic, TRUE);
5917 }
5918
5919 /*-----------------------------------------------------------------*/
5920 /* ifxForOp - returns the icode containing the ifx for operand     */
5921 /*-----------------------------------------------------------------*/
5922 static iCode *
5923 ifxForOp (operand * op, iCode * ic)
5924 {
5925   /* if true symbol then needs to be assigned */
5926   if (IS_TRUE_SYMOP (op))
5927     return NULL;
5928
5929   /* if this has register type condition and
5930      the next instruction is ifx with the same operand
5931      and live to of the operand is upto the ifx only then */
5932   if (ic->next &&
5933       ic->next->op == IFX &&
5934       IC_COND (ic->next)->key == op->key &&
5935       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5936     return ic->next;
5937
5938   return NULL;
5939 }
5940 /*-----------------------------------------------------------------*/
5941 /* hasInc - operand is incremented before any other use            */
5942 /*-----------------------------------------------------------------*/
5943 static iCode *
5944 hasInc (operand *op, iCode *ic, int osize)
5945 {
5946   sym_link *type = operandType(op);
5947   sym_link *retype = getSpec (type);
5948   iCode *lic = ic->next;
5949   int isize ;
5950   
5951   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5952   if (!IS_SYMOP(op)) return NULL;
5953
5954   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5955   if (IS_AGGREGATE(type->next)) return NULL;
5956   if (osize != (isize = getSize(type->next))) return NULL;
5957
5958   while (lic) {
5959       /* if operand of the form op = op + <sizeof *op> */
5960       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5961           isOperandEqual(IC_RESULT(lic),op) && 
5962           isOperandLiteral(IC_RIGHT(lic)) &&
5963           operandLitValue(IC_RIGHT(lic)) == isize) {
5964           return lic;
5965       }
5966       /* if the operand used or deffed */
5967       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5968           return NULL;
5969       }
5970       /* if GOTO or IFX */
5971       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5972       lic = lic->next;
5973   }
5974   return NULL;
5975 }
5976
5977 /*-----------------------------------------------------------------*/
5978 /* genAndOp - for && operation                                     */
5979 /*-----------------------------------------------------------------*/
5980 static void
5981 genAndOp (iCode * ic)
5982 {
5983   operand *left, *right, *result;
5984   symbol *tlbl;
5985
5986   D (emitcode (";", "genAndOp "););
5987
5988   /* note here that && operations that are in an
5989      if statement are taken away by backPatchLabels
5990      only those used in arthmetic operations remain */
5991   AOP_OP_2 (ic);
5992   AOP_SET_LOCALS (ic);
5993
5994   /* if both are bit variables */
5995   if (AOP_TYPE (left) == AOP_CRY &&
5996       AOP_TYPE (right) == AOP_CRY)
5997     {
5998       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5999       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6000       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002   
6003       aopOp (result,ic,FALSE, FALSE);
6004       outBitC (result);
6005     }
6006   else
6007     {
6008       tlbl = newiTempLabel (NULL);
6009       toBoolean (left);
6010       emitcode ("jz", "!tlabel", tlbl->key + 100);
6011       toBoolean (right);
6012       emitcode ("", "!tlabeldef", tlbl->key + 100);
6013       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6014       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6015   
6016       aopOp (result,ic,FALSE, FALSE);
6017       outBitAcc (result);
6018     }
6019     freeAsmop (result, NULL, ic, TRUE);
6020 }
6021
6022
6023 /*-----------------------------------------------------------------*/
6024 /* genOrOp - for || operation                                      */
6025 /*-----------------------------------------------------------------*/
6026 static void
6027 genOrOp (iCode * ic)
6028 {
6029   operand *left, *right, *result;
6030   symbol *tlbl;
6031
6032   D (emitcode (";", "genOrOp "););
6033
6034   /* note here that || operations that are in an
6035      if statement are taken away by backPatchLabels
6036      only those used in arthmetic operations remain */
6037   AOP_OP_2 (ic);
6038   AOP_SET_LOCALS (ic);
6039
6040   /* if both are bit variables */
6041   if (AOP_TYPE (left) == AOP_CRY &&
6042       AOP_TYPE (right) == AOP_CRY)
6043     {
6044       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6046       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6047       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6048   
6049       aopOp (result,ic,FALSE, FALSE);
6050       
6051       outBitC (result);
6052     }
6053   else
6054     {
6055       tlbl = newiTempLabel (NULL);
6056       toBoolean (left);
6057       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6058       toBoolean (right);
6059       emitcode ("", "!tlabeldef", tlbl->key + 100);
6060       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6061       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6062   
6063       aopOp (result,ic,FALSE, FALSE);
6064       
6065       outBitAcc (result);
6066     }
6067
6068   freeAsmop (result, NULL, ic, TRUE);
6069 }
6070
6071 /*-----------------------------------------------------------------*/
6072 /* isLiteralBit - test if lit == 2^n                               */
6073 /*-----------------------------------------------------------------*/
6074 static int
6075 isLiteralBit (unsigned long lit)
6076 {
6077   unsigned long pw[32] =
6078   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6079    0x100L, 0x200L, 0x400L, 0x800L,
6080    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6081    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6082    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6083    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6084    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6085   int idx;
6086
6087   for (idx = 0; idx < 32; idx++)
6088     if (lit == pw[idx])
6089       return idx + 1;
6090   return 0;
6091 }
6092
6093 /*-----------------------------------------------------------------*/
6094 /* continueIfTrue -                                                */
6095 /*-----------------------------------------------------------------*/
6096 static void
6097 continueIfTrue (iCode * ic)
6098 {
6099   if (IC_TRUE (ic))
6100     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6101   ic->generated = 1;
6102 }
6103
6104 /*-----------------------------------------------------------------*/
6105 /* jmpIfTrue -                                                     */
6106 /*-----------------------------------------------------------------*/
6107 static void
6108 jumpIfTrue (iCode * ic)
6109 {
6110   if (!IC_TRUE (ic))
6111     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6112   ic->generated = 1;
6113 }
6114
6115 /*-----------------------------------------------------------------*/
6116 /* jmpTrueOrFalse -                                                */
6117 /*-----------------------------------------------------------------*/
6118 static void
6119 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6120 {
6121   // ugly but optimized by peephole
6122   if (IC_TRUE (ic))
6123     {
6124       symbol *nlbl = newiTempLabel (NULL);
6125       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6126       emitcode ("", "!tlabeldef", tlbl->key + 100);
6127       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6128       emitcode ("", "!tlabeldef", nlbl->key + 100);
6129     }
6130   else
6131     {
6132       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6133       emitcode ("", "!tlabeldef", tlbl->key + 100);
6134     }
6135   ic->generated = 1;
6136 }
6137
6138 // Generate code to perform a bit-wise logic operation
6139 // on two operands in far space (assumed to already have been 
6140 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6141 // in far space. This requires pushing the result on the stack
6142 // then popping it into the result.
6143 static void
6144 genFarFarLogicOp(iCode *ic, char *logicOp)
6145 {
6146       int size, resultSize, compSize;
6147       int offset = 0;
6148       
6149       TR_AP("#5");
6150       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6151       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6152                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6153       
6154       _startLazyDPSEvaluation();
6155       for (size = compSize; (size--); offset++)
6156       {
6157           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6158           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6159           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6160           
6161           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6162           emitcode ("push", "acc");
6163       }
6164       _endLazyDPSEvaluation();
6165      
6166       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6167       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6168       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6169      
6170       resultSize = AOP_SIZE(IC_RESULT(ic));
6171
6172       ADJUST_PUSHED_RESULT(compSize, resultSize);
6173
6174       _startLazyDPSEvaluation();
6175       while (compSize--)
6176       {
6177           emitcode ("pop", "acc");
6178           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6179       }
6180       _endLazyDPSEvaluation();
6181       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6182 }
6183
6184
6185 /*-----------------------------------------------------------------*/
6186 /* genAnd  - code for and                                          */
6187 /*-----------------------------------------------------------------*/
6188 static void
6189 genAnd (iCode * ic, iCode * ifx)
6190 {
6191   operand *left, *right, *result;
6192   int size, offset = 0;
6193   unsigned long lit = 0L;
6194   int bytelit;
6195   char buff[10];
6196   bool pushResult;
6197
6198   D (emitcode (";", "genAnd "););
6199
6200   AOP_OP_3_NOFATAL (ic, pushResult);
6201   AOP_SET_LOCALS (ic);
6202
6203   if (pushResult)
6204   {
6205       genFarFarLogicOp(ic, "anl");
6206       return;
6207   }  
6208
6209 #ifdef DEBUG_TYPE
6210   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6211             AOP_TYPE (result),
6212             AOP_TYPE (left), AOP_TYPE (right));
6213   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6214             AOP_SIZE (result),
6215             AOP_SIZE (left), AOP_SIZE (right));
6216 #endif
6217
6218   /* if left is a literal & right is not then exchange them */
6219   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6220 #ifdef LOGIC_OPS_BROKEN      
6221     ||  AOP_NEEDSACC (left)
6222 #endif
6223     )
6224     {
6225       operand *tmp = right;
6226       right = left;
6227       left = tmp;
6228     }
6229
6230   /* if result = right then exchange them */
6231   if (sameRegs (AOP (result), AOP (right)))
6232     {
6233       operand *tmp = right;
6234       right = left;
6235       left = tmp;
6236     }
6237
6238   /* if right is bit then exchange them */
6239   if (AOP_TYPE (right) == AOP_CRY &&
6240       AOP_TYPE (left) != AOP_CRY)
6241     {
6242       operand *tmp = right;
6243       right = left;
6244       left = tmp;
6245     }
6246   if (AOP_TYPE (right) == AOP_LIT)
6247     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6248
6249   size = AOP_SIZE (result);
6250
6251   // if(bit & yy)
6252   // result = bit & yy;
6253   if (AOP_TYPE (left) == AOP_CRY)
6254     {
6255       // c = bit & literal;
6256       if (AOP_TYPE (right) == AOP_LIT)
6257         {
6258           if (lit & 1)
6259             {
6260               if (size && sameRegs (AOP (result), AOP (left)))
6261                 // no change
6262                 goto release;
6263               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6264             }
6265           else
6266             {
6267               // bit(result) = 0;
6268               if (size && (AOP_TYPE (result) == AOP_CRY))
6269                 {
6270                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6271                   goto release;
6272                 }
6273               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6274                 {
6275                   jumpIfTrue (ifx);
6276                   goto release;
6277                 }
6278               emitcode ("clr", "c");
6279             }
6280         }
6281       else
6282         {
6283           if (AOP_TYPE (right) == AOP_CRY)
6284             {
6285               // c = bit & bit;
6286               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6287               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6288             }
6289           else
6290             {
6291               // c = bit & val;
6292               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6293               // c = lsb
6294               emitcode ("rrc", "a");
6295               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6296             }
6297         }
6298       // bit = c
6299       // val = c
6300       if (size)
6301         outBitC (result);
6302       // if(bit & ...)
6303       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6304         genIfxJump (ifx, "c");
6305       goto release;
6306     }
6307
6308   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6309   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6310   if ((AOP_TYPE (right) == AOP_LIT) &&
6311       (AOP_TYPE (result) == AOP_CRY) &&
6312       (AOP_TYPE (left) != AOP_CRY))
6313     {
6314       int posbit = isLiteralBit (lit);
6315       /* left &  2^n */
6316       if (posbit)
6317         {
6318           posbit--;
6319           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6320           // bit = left & 2^n
6321           if (size)
6322             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6323           // if(left &  2^n)
6324           else
6325             {
6326               if (ifx)
6327                 {
6328                   SNPRINTF (buff, sizeof(buff), 
6329                             "acc.%d", posbit & 0x07);
6330                   genIfxJump (ifx, buff);
6331                 }
6332               else 
6333                   {
6334                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6335                   }
6336               goto release;
6337             }
6338         }
6339       else
6340         {
6341           symbol *tlbl = newiTempLabel (NULL);
6342           int sizel = AOP_SIZE (left);
6343           if (size)
6344             emitcode ("setb", "c");
6345           while (sizel--)
6346             {
6347               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6348                 {
6349                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6350                   // byte ==  2^n ?
6351                   if ((posbit = isLiteralBit (bytelit)) != 0)
6352                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6353                   else
6354                     {
6355                       if (bytelit != 0x0FFL)
6356                         emitcode ("anl", "a,%s",
6357                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6358                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6359                     }
6360                 }
6361               offset++;
6362             }
6363           // bit = left & literal
6364           if (size)
6365             {
6366               emitcode ("clr", "c");
6367               emitcode ("", "!tlabeldef", tlbl->key + 100);
6368             }
6369           // if(left & literal)
6370           else
6371             {
6372               if (ifx)
6373                 jmpTrueOrFalse (ifx, tlbl);
6374               goto release;
6375             }
6376         }
6377       outBitC (result);
6378       goto release;
6379     }
6380
6381   /* if left is same as result */
6382   if (sameRegs (AOP (result), AOP (left)))
6383     {
6384       for (; size--; offset++)
6385         {
6386           if (AOP_TYPE (right) == AOP_LIT)
6387             {
6388               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6389                 continue;
6390               else if (bytelit == 0)
6391                 aopPut (AOP (result), zero, offset);
6392               else if (IS_AOP_PREG (result))
6393                 {
6394                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6395                   emitcode ("anl", "a,%s",
6396                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6397                   aopPut (AOP (result), "a", offset);
6398                 }
6399               else
6400                 emitcode ("anl", "%s,%s",
6401                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6402                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6403             }
6404           else
6405             {
6406               if (AOP_TYPE (left) == AOP_ACC)
6407                 emitcode ("anl", "a,%s",
6408                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6409               else
6410                 {
6411                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6412                   if (IS_AOP_PREG (result))
6413                     {
6414                       emitcode ("anl", "a,%s",
6415                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6416                       aopPut (AOP (result), "a", offset);
6417                     }
6418                   else
6419                     emitcode ("anl", "%s,a",
6420                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6421                 }
6422             }
6423         }
6424     }
6425   else
6426     {
6427       // left & result in different registers
6428       if (AOP_TYPE (result) == AOP_CRY)
6429         {
6430           // result = bit
6431           // if(size), result in bit
6432           // if(!size && ifx), conditional oper: if(left & right)
6433           symbol *tlbl = newiTempLabel (NULL);
6434           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6435           if (size)
6436             emitcode ("setb", "c");
6437           while (sizer--)
6438             {
6439               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6440                 emitcode ("anl", "a,%s",
6441                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6442               } else {
6443                 if (AOP_TYPE(left)==AOP_ACC) {
6444                   emitcode("mov", "b,a");
6445                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6446                   emitcode("anl", "a,b");
6447                 }else {
6448                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6449                   emitcode ("anl", "a,%s",
6450                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6451                 }
6452               }
6453               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6454               offset++;
6455             }
6456           if (size)
6457             {
6458               CLRC;
6459               emitcode ("", "!tlabeldef", tlbl->key + 100);
6460               outBitC (result);
6461             }
6462           else if (ifx)
6463             jmpTrueOrFalse (ifx, tlbl);
6464         }
6465       else
6466         {
6467           for (; (size--); offset++)
6468             {
6469               // normal case
6470               // result = left & right
6471               if (AOP_TYPE (right) == AOP_LIT)
6472                 {
6473                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6474                     {
6475                       aopPut (AOP (result),
6476                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6477                               offset);
6478                       continue;
6479                     }
6480                   else if (bytelit == 0)
6481                     {
6482                       aopPut (AOP (result), zero, offset);
6483                       continue;
6484                     }
6485                   D (emitcode (";", "better literal AND."););
6486                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6487                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6488                                                     FALSE, FALSE, DP2_RESULT_REG));
6489
6490                 }
6491               else
6492                 {
6493                   // faster than result <- left, anl result,right
6494                   // and better if result is SFR
6495                   if (AOP_TYPE (left) == AOP_ACC)
6496                     {
6497                       emitcode ("anl", "a,%s", 
6498                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6499                     }
6500                   else
6501                     {
6502                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6503                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6504                       {
6505                           emitcode("mov", "b,a");
6506                           rOp = "b";
6507                       }
6508                         
6509                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6510                       emitcode ("anl", "a,%s", rOp);
6511                     }                   
6512                 }
6513               aopPut (AOP (result), "a", offset);
6514             }
6515         }
6516     }
6517
6518 release:
6519   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6520   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6521   freeAsmop (result, NULL, ic, TRUE);
6522 }
6523
6524
6525 /*-----------------------------------------------------------------*/
6526 /* genOr  - code for or                                            */
6527 /*-----------------------------------------------------------------*/
6528 static void
6529 genOr (iCode * ic, iCode * ifx)
6530 {
6531   operand *left, *right, *result;
6532   int size, offset = 0;
6533   unsigned long lit = 0L;
6534   bool     pushResult;
6535
6536   D (emitcode (";", "genOr "););
6537
6538   AOP_OP_3_NOFATAL (ic, pushResult);
6539   AOP_SET_LOCALS (ic);
6540
6541   if (pushResult)
6542   {
6543       genFarFarLogicOp(ic, "orl");
6544       return;
6545   }
6546
6547
6548 #ifdef DEBUG_TYPE
6549   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6550             AOP_TYPE (result),
6551             AOP_TYPE (left), AOP_TYPE (right));
6552   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6553             AOP_SIZE (result),
6554             AOP_SIZE (left), AOP_SIZE (right));
6555 #endif
6556
6557   /* if left is a literal & right is not then exchange them */
6558   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6559 #ifdef LOGIC_OPS_BROKEN
6560    || AOP_NEEDSACC (left) // I think this is a net loss now.
6561 #endif      
6562       )
6563     {
6564       operand *tmp = right;
6565       right = left;
6566       left = tmp;
6567     }
6568
6569   /* if result = right then exchange them */
6570   if (sameRegs (AOP (result), AOP (right)))
6571     {
6572       operand *tmp = right;
6573       right = left;
6574       left = tmp;
6575     }
6576
6577   /* if right is bit then exchange them */
6578   if (AOP_TYPE (right) == AOP_CRY &&
6579       AOP_TYPE (left) != AOP_CRY)
6580     {
6581       operand *tmp = right;
6582       right = left;
6583       left = tmp;
6584     }
6585   if (AOP_TYPE (right) == AOP_LIT)
6586     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6587
6588   size = AOP_SIZE (result);
6589
6590   // if(bit | yy)
6591   // xx = bit | yy;
6592   if (AOP_TYPE (left) == AOP_CRY)
6593     {
6594       if (AOP_TYPE (right) == AOP_LIT)
6595         {
6596           // c = bit & literal;
6597           if (lit)
6598             {
6599               // lit != 0 => result = 1
6600               if (AOP_TYPE (result) == AOP_CRY)
6601                 {
6602                   if (size)
6603                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6604                   else if (ifx)
6605                     continueIfTrue (ifx);
6606                   goto release;
6607                 }
6608               emitcode ("setb", "c");
6609             }
6610           else
6611             {
6612               // lit == 0 => result = left
6613               if (size && sameRegs (AOP (result), AOP (left)))
6614                 goto release;
6615               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6616             }
6617         }
6618       else
6619         {
6620           if (AOP_TYPE (right) == AOP_CRY)
6621             {
6622               // c = bit | bit;
6623               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6624               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6625             }
6626           else
6627             {
6628               // c = bit | val;
6629               symbol *tlbl = newiTempLabel (NULL);
6630               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6631                 emitcode ("setb", "c");
6632               emitcode ("jb", "%s,!tlabel",
6633                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6634               toBoolean (right);
6635               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6636               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6637                 {
6638                   jmpTrueOrFalse (ifx, tlbl);
6639                   goto release;
6640                 }
6641               else
6642                 {
6643                   CLRC;
6644                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6645                 }
6646             }
6647         }
6648       // bit = c
6649       // val = c
6650       if (size)
6651         outBitC (result);
6652       // if(bit | ...)
6653       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6654            genIfxJump (ifx, "c");
6655       goto release;
6656     }
6657
6658   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6659   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6660   if ((AOP_TYPE (right) == AOP_LIT) &&
6661       (AOP_TYPE (result) == AOP_CRY) &&
6662       (AOP_TYPE (left) != AOP_CRY))
6663     {
6664       if (lit)
6665         {
6666           // result = 1
6667           if (size)
6668             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6669           else
6670             continueIfTrue (ifx);
6671           goto release;
6672         }
6673       else
6674         {
6675           // lit = 0, result = boolean(left)
6676           if (size)
6677             emitcode ("setb", "c");
6678           toBoolean (right);
6679           if (size)
6680             {
6681               symbol *tlbl = newiTempLabel (NULL);
6682               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6683               CLRC;
6684               emitcode ("", "!tlabeldef", tlbl->key + 100);
6685             }
6686           else
6687             {
6688               genIfxJump (ifx, "a");
6689               goto release;
6690             }
6691         }
6692       outBitC (result);
6693       goto release;
6694     }
6695
6696   /* if left is same as result */
6697   if (sameRegs (AOP (result), AOP (left)))
6698     {
6699       for (; size--; offset++)
6700         {
6701           if (AOP_TYPE (right) == AOP_LIT)
6702             {
6703               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6704                 {
6705                   continue;
6706                 }
6707               else
6708                 {
6709                   if (IS_AOP_PREG (left))
6710                     {
6711                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6712                       emitcode ("orl", "a,%s",
6713                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6714                       aopPut (AOP (result), "a", offset);
6715                     }
6716                   else
6717                     {
6718                       emitcode ("orl", "%s,%s",
6719                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6720                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6721                     }
6722                 }
6723             }
6724           else
6725             {
6726               if (AOP_TYPE (left) == AOP_ACC)
6727                 {
6728                   emitcode ("orl", "a,%s",
6729                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6730                 }
6731               else
6732                 {
6733                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6734                   if (IS_AOP_PREG (left))
6735                     {
6736                       emitcode ("orl", "a,%s", 
6737                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6738                       aopPut (AOP (result), "a", offset);
6739                     }
6740                   else
6741                     {
6742                       emitcode ("orl", "%s,a",
6743                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6744                     }
6745                 }
6746             }
6747         }
6748     }
6749   else
6750     {
6751       // left & result in different registers
6752       if (AOP_TYPE (result) == AOP_CRY)
6753         {
6754           // result = bit
6755           // if(size), result in bit
6756           // if(!size && ifx), conditional oper: if(left | right)
6757           symbol *tlbl = newiTempLabel (NULL);
6758           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6759           if (size)
6760             emitcode ("setb", "c");
6761           while (sizer--)
6762             {
6763               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6764                 emitcode ("orl", "a,%s",
6765                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6766               } else {
6767                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6768                 emitcode ("orl", "a,%s",
6769                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6770               }
6771               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6772               offset++;
6773             }
6774           if (size)
6775             {
6776               CLRC;
6777               emitcode ("", "!tlabeldef", tlbl->key + 100);
6778               outBitC (result);
6779             }
6780           else if (ifx)
6781             jmpTrueOrFalse (ifx, tlbl);
6782         }
6783       else
6784         {
6785             _startLazyDPSEvaluation();
6786           for (; (size--); offset++)
6787             {
6788               // normal case
6789               // result = left & right
6790               if (AOP_TYPE (right) == AOP_LIT)
6791                 {
6792                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6793                     {
6794                       aopPut (AOP (result),
6795                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6796                               offset);
6797                       continue;
6798                     }
6799                   D (emitcode (";", "better literal OR."););
6800                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6801                   emitcode ("orl", "a, %s",
6802                             aopGet (AOP (right), offset,
6803                                     FALSE, FALSE, DP2_RESULT_REG));
6804
6805                 }
6806               else
6807                 {
6808                   // faster than result <- left, anl result,right
6809                   // and better if result is SFR
6810                   if (AOP_TYPE (left) == AOP_ACC)
6811                     {
6812                       emitcode ("orl", "a,%s",
6813                                 aopGet (AOP (right), offset,
6814                                         FALSE, FALSE, DP2_RESULT_REG));
6815                     }
6816                   else
6817                     {
6818                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6819                         
6820                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6821                       {
6822                           emitcode("mov", "b,a");
6823                           rOp = "b";
6824                       }
6825                         
6826                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6827                       emitcode ("orl", "a,%s", rOp);
6828                     }
6829                 }
6830               aopPut (AOP (result), "a", offset);
6831             }
6832             _endLazyDPSEvaluation();
6833         }
6834     }
6835
6836 release:
6837   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6838   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6839   freeAsmop (result, NULL, ic, TRUE);
6840 }
6841
6842 /*-----------------------------------------------------------------*/
6843 /* genXor - code for xclusive or                                   */
6844 /*-----------------------------------------------------------------*/
6845 static void
6846 genXor (iCode * ic, iCode * ifx)
6847 {
6848   operand *left, *right, *result;
6849   int size, offset = 0;
6850   unsigned long lit = 0L;
6851   bool pushResult;
6852
6853   D (emitcode (";", "genXor "););
6854
6855   AOP_OP_3_NOFATAL (ic, pushResult);
6856   AOP_SET_LOCALS (ic);
6857
6858   if (pushResult)
6859   {
6860       genFarFarLogicOp(ic, "xrl");
6861       return;
6862   }  
6863
6864 #ifdef DEBUG_TYPE
6865   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6866             AOP_TYPE (result),
6867             AOP_TYPE (left), AOP_TYPE (right));
6868   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6869             AOP_SIZE (result),
6870             AOP_SIZE (left), AOP_SIZE (right));
6871 #endif
6872
6873   /* if left is a literal & right is not ||
6874      if left needs acc & right does not */
6875   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6876 #ifdef LOGIC_OPS_BROKEN      
6877       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6878 #endif
6879      )
6880     {
6881       operand *tmp = right;
6882       right = left;
6883       left = tmp;
6884     }
6885
6886   /* if result = right then exchange them */
6887   if (sameRegs (AOP (result), AOP (right)))
6888     {
6889       operand *tmp = right;
6890       right = left;
6891       left = tmp;
6892     }
6893
6894   /* if right is bit then exchange them */
6895   if (AOP_TYPE (right) == AOP_CRY &&
6896       AOP_TYPE (left) != AOP_CRY)
6897     {
6898       operand *tmp = right;
6899       right = left;
6900       left = tmp;
6901     }
6902   if (AOP_TYPE (right) == AOP_LIT)
6903     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6904
6905   size = AOP_SIZE (result);
6906
6907   // if(bit ^ yy)
6908   // xx = bit ^ yy;
6909   if (AOP_TYPE (left) == AOP_CRY)
6910     {
6911       if (AOP_TYPE (right) == AOP_LIT)
6912         {
6913           // c = bit & literal;
6914           if (lit >> 1)
6915             {
6916               // lit>>1  != 0 => result = 1
6917               if (AOP_TYPE (result) == AOP_CRY)
6918                 {
6919                   if (size)
6920                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6921                   else if (ifx)
6922                     continueIfTrue (ifx);
6923                   goto release;
6924                 }
6925               emitcode ("setb", "c");
6926             }
6927           else
6928             {
6929               // lit == (0 or 1)
6930               if (lit == 0)
6931                 {
6932                   // lit == 0, result = left
6933                   if (size && sameRegs (AOP (result), AOP (left)))
6934                     goto release;
6935                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6936                 }
6937               else
6938                 {
6939                   // lit == 1, result = not(left)
6940                   if (size && sameRegs (AOP (result), AOP (left)))
6941                     {
6942                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6943                       goto release;
6944                     }
6945                   else
6946                     {
6947                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6948                       emitcode ("cpl", "c");
6949                     }
6950                 }
6951             }
6952
6953         }
6954       else
6955         {
6956           // right != literal
6957           symbol *tlbl = newiTempLabel (NULL);
6958           if (AOP_TYPE (right) == AOP_CRY)
6959             {
6960               // c = bit ^ bit;
6961               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6962             }
6963           else
6964             {
6965               int sizer = AOP_SIZE (right);
6966               // c = bit ^ val
6967               // if val>>1 != 0, result = 1
6968               emitcode ("setb", "c");
6969               while (sizer)
6970                 {
6971                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6972                   if (sizer == 1)
6973                     // test the msb of the lsb
6974                     emitcode ("anl", "a,#!constbyte",0xfe);
6975                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6976                   sizer--;
6977                 }
6978               // val = (0,1)
6979               emitcode ("rrc", "a");
6980             }
6981           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6982           emitcode ("cpl", "c");
6983           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6984         }
6985       // bit = c
6986       // val = c
6987       if (size)
6988         outBitC (result);
6989       // if(bit | ...)
6990       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6991         genIfxJump (ifx, "c");
6992       goto release;
6993     }
6994
6995   if (sameRegs (AOP (result), AOP (left)))
6996     {
6997       /* if left is same as result */
6998       for (; size--; offset++)
6999         {
7000           if (AOP_TYPE (right) == AOP_LIT)
7001             {
7002               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7003                 continue;
7004               else if (IS_AOP_PREG (left))
7005                 {
7006                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7007                   emitcode ("xrl", "a,%s",
7008                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7009                   aopPut (AOP (result), "a", offset);
7010                 }
7011               else
7012                 emitcode ("xrl", "%s,%s",
7013                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7014                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7015             }
7016           else
7017             {
7018               if (AOP_TYPE (left) == AOP_ACC)
7019                 emitcode ("xrl", "a,%s",
7020                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7021               else
7022                 {
7023                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7024                   if (IS_AOP_PREG (left))
7025                     {
7026                       emitcode ("xrl", "a,%s",
7027                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7028                       aopPut (AOP (result), "a", offset);
7029                     }
7030                   else
7031                     emitcode ("xrl", "%s,a",
7032                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7033                 }
7034             }
7035         }
7036     }
7037   else
7038     {
7039       // left & result in different registers
7040       if (AOP_TYPE (result) == AOP_CRY)
7041         {
7042           // result = bit
7043           // if(size), result in bit
7044           // if(!size && ifx), conditional oper: if(left ^ right)
7045           symbol *tlbl = newiTempLabel (NULL);
7046           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7047                   
7048           if (size)
7049             emitcode ("setb", "c");
7050           while (sizer--)
7051             {
7052               if ((AOP_TYPE (right) == AOP_LIT) &&
7053                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7054                 {
7055                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7056                 }
7057               else
7058                 {
7059                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7060                     emitcode ("xrl", "a,%s",
7061                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7062                   } else {
7063                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7064                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7065                       {
7066                           emitcode("mov", "b,a");
7067                           rOp = "b";
7068                       }
7069                         
7070                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7071                       emitcode ("xrl", "a,%s", rOp);                  
7072                   }
7073                 }
7074               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7075               offset++;
7076             }
7077           if (size)
7078             {
7079               CLRC;
7080               emitcode ("", "!tlabeldef", tlbl->key + 100);
7081               outBitC (result);
7082             }
7083           else if (ifx)
7084             jmpTrueOrFalse (ifx, tlbl);
7085         }
7086       else
7087         {
7088         for (; (size--); offset++)
7089           {
7090             // normal case
7091             // result = left & right
7092             if (AOP_TYPE (right) == AOP_LIT)
7093               {
7094                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7095                   {
7096                     aopPut (AOP (result),
7097                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7098                             offset);
7099                     continue;
7100                   }
7101                 D (emitcode (";", "better literal XOR."););
7102                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7103                 emitcode ("xrl", "a, %s",
7104                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7105               }
7106             else
7107               {
7108                 // faster than result <- left, anl result,right
7109                 // and better if result is SFR
7110                 if (AOP_TYPE (left) == AOP_ACC)
7111                   {
7112                     emitcode ("xrl", "a,%s",
7113                               aopGet (AOP (right), offset,
7114                                       FALSE, FALSE, DP2_RESULT_REG));
7115                   }
7116                 else
7117                   {
7118                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7119                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7120                       {
7121                           emitcode("mov", "b,a");
7122                           rOp = "b";
7123                       }
7124                         
7125                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7126                       emitcode ("xrl", "a,%s", rOp);
7127                   }
7128               }
7129             aopPut (AOP (result), "a", offset);
7130           }
7131         }
7132         
7133     }
7134
7135 release:
7136   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7137   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7138   freeAsmop (result, NULL, ic, TRUE);
7139 }
7140
7141 /*-----------------------------------------------------------------*/
7142 /* genInline - write the inline code out                           */
7143 /*-----------------------------------------------------------------*/
7144 static void
7145 genInline (iCode * ic)
7146 {
7147   char *buffer, *bp, *bp1;
7148
7149   D (emitcode (";", "genInline "); );
7150
7151   _G.inLine += (!options.asmpeep);
7152
7153   buffer = Safe_strdup(IC_INLINE(ic));
7154   bp = buffer;
7155   bp1 = buffer;
7156
7157   /* emit each line as a code */
7158   while (*bp)
7159     {
7160       if (*bp == '\n')
7161         {
7162           *bp++ = '\0';
7163           emitcode (bp1, "");
7164           bp1 = bp;
7165         }
7166       else
7167         {
7168           if (*bp == ':')
7169             {
7170               bp++;
7171               *bp = '\0';
7172               bp++;
7173               emitcode (bp1, "");
7174               bp1 = bp;
7175             }
7176           else
7177             bp++;
7178         }
7179     }
7180   if (bp1 != bp)
7181     emitcode (bp1, "");
7182   /*     emitcode("",buffer); */
7183   _G.inLine -= (!options.asmpeep);
7184 }
7185
7186 /*-----------------------------------------------------------------*/
7187 /* genRRC - rotate right with carry                                */
7188 /*-----------------------------------------------------------------*/
7189 static void
7190 genRRC (iCode * ic)
7191 {
7192   operand *left, *result;
7193   int     size, offset;
7194
7195   D (emitcode (";", "genRRC "););
7196
7197   /* rotate right with carry */
7198   left = IC_LEFT (ic);
7199   result = IC_RESULT (ic);
7200   aopOp (left, ic, FALSE, FALSE);
7201   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7202
7203   /* move it to the result */
7204   size = AOP_SIZE (result);
7205   offset = size - 1;
7206   CLRC;
7207
7208   _startLazyDPSEvaluation ();
7209   while (size--)
7210     {
7211       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7212       emitcode ("rrc", "a");
7213       if (AOP_SIZE (result) > 1)
7214         aopPut (AOP (result), "a", offset--);
7215     }
7216   _endLazyDPSEvaluation ();
7217
7218   /* now we need to put the carry into the
7219      highest order byte of the result */
7220   if (AOP_SIZE (result) > 1)
7221     {
7222       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7223     }
7224   emitcode ("mov", "acc.7,c");
7225   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7226   freeAsmop (left, NULL, ic, TRUE);
7227   freeAsmop (result, NULL, ic, TRUE);
7228 }
7229
7230 /*-----------------------------------------------------------------*/
7231 /* genRLC - generate code for rotate left with carry               */
7232 /*-----------------------------------------------------------------*/
7233 static void
7234 genRLC (iCode * ic)
7235 {
7236   operand *left, *result;
7237   int size, offset;
7238   char *l;
7239
7240   D (emitcode (";", "genRLC "););
7241
7242   /* rotate right with carry */
7243   left = IC_LEFT (ic);
7244   result = IC_RESULT (ic);
7245   aopOp (left, ic, FALSE, FALSE);
7246   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7247
7248   /* move it to the result */
7249   size = AOP_SIZE (result);
7250   offset = 0;
7251   if (size--)
7252     {
7253       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7254       MOVA (l);
7255       emitcode ("add", "a,acc");
7256       if (AOP_SIZE (result) > 1)
7257         {
7258           aopPut (AOP (result), "a", offset++);
7259         }
7260
7261       _startLazyDPSEvaluation ();
7262       while (size--)
7263         {
7264           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7265           MOVA (l);
7266           emitcode ("rlc", "a");
7267           if (AOP_SIZE (result) > 1)
7268             aopPut (AOP (result), "a", offset++);
7269         }
7270       _endLazyDPSEvaluation ();
7271     }
7272   /* now we need to put the carry into the
7273      highest order byte of the result */
7274   if (AOP_SIZE (result) > 1)
7275     {
7276       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7277       MOVA (l);
7278     }
7279   emitcode ("mov", "acc.0,c");
7280   aopPut (AOP (result), "a", 0);
7281   freeAsmop (left, NULL, ic, TRUE);
7282   freeAsmop (result, NULL, ic, TRUE);
7283 }
7284
7285 /*-----------------------------------------------------------------*/
7286 /* genGetHbit - generates code get highest order bit               */
7287 /*-----------------------------------------------------------------*/
7288 static void
7289 genGetHbit (iCode * ic)
7290 {
7291   operand *left, *result;
7292   left = IC_LEFT (ic);
7293   result = IC_RESULT (ic);
7294   aopOp (left, ic, FALSE, FALSE);
7295   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7296
7297   D (emitcode (";", "genGetHbit "););
7298
7299   /* get the highest order byte into a */
7300   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7301   if (AOP_TYPE (result) == AOP_CRY)
7302     {
7303       emitcode ("rlc", "a");
7304       outBitC (result);
7305     }
7306   else
7307     {
7308       emitcode ("rl", "a");
7309       emitcode ("anl", "a,#1");
7310       outAcc (result);
7311     }
7312
7313
7314   freeAsmop (left, NULL, ic, TRUE);
7315   freeAsmop (result, NULL, ic, TRUE);
7316 }
7317
7318 /*-----------------------------------------------------------------*/
7319 /* AccRol - rotate left accumulator by known count                 */
7320 /*-----------------------------------------------------------------*/
7321 static void
7322 AccRol (int shCount)
7323 {
7324   shCount &= 0x0007;            // shCount : 0..7
7325
7326   switch (shCount)
7327     {
7328     case 0:
7329       break;
7330     case 1:
7331       emitcode ("rl", "a");
7332       break;
7333     case 2:
7334       emitcode ("rl", "a");
7335       emitcode ("rl", "a");
7336       break;
7337     case 3:
7338       emitcode ("swap", "a");
7339       emitcode ("rr", "a");
7340       break;
7341     case 4:
7342       emitcode ("swap", "a");
7343       break;
7344     case 5:
7345       emitcode ("swap", "a");
7346       emitcode ("rl", "a");
7347       break;
7348     case 6:
7349       emitcode ("rr", "a");
7350       emitcode ("rr", "a");
7351       break;
7352     case 7:
7353       emitcode ("rr", "a");
7354       break;
7355     }
7356 }
7357
7358 /*-----------------------------------------------------------------*/
7359 /* AccLsh - left shift accumulator by known count                  */
7360 /*-----------------------------------------------------------------*/
7361 static void
7362 AccLsh (int shCount)
7363 {
7364   if (shCount != 0)
7365     {
7366       if (shCount == 1)
7367         emitcode ("add", "a,acc");
7368       else if (shCount == 2)
7369         {
7370           emitcode ("add", "a,acc");
7371           emitcode ("add", "a,acc");
7372         }
7373       else
7374         {
7375           /* rotate left accumulator */
7376           AccRol (shCount);
7377           /* and kill the lower order bits */
7378           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7379         }
7380     }
7381 }
7382
7383 /*-----------------------------------------------------------------*/
7384 /* AccRsh - right shift accumulator by known count                 */
7385 /*-----------------------------------------------------------------*/
7386 static void
7387 AccRsh (int shCount)
7388 {
7389   if (shCount != 0)
7390     {
7391       if (shCount == 1)
7392         {
7393           CLRC;
7394           emitcode ("rrc", "a");
7395         }
7396       else
7397         {
7398           /* rotate right accumulator */
7399           AccRol (8 - shCount);
7400           /* and kill the higher order bits */
7401           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7402         }
7403     }
7404 }
7405
7406 #ifdef BETTER_LITERAL_SHIFT
7407 /*-----------------------------------------------------------------*/
7408 /* AccSRsh - signed right shift accumulator by known count                 */
7409 /*-----------------------------------------------------------------*/
7410 static void
7411 AccSRsh (int shCount)
7412 {
7413   symbol *tlbl;
7414   if (shCount != 0)
7415     {
7416       if (shCount == 1)
7417         {
7418           emitcode ("mov", "c,acc.7");
7419           emitcode ("rrc", "a");
7420         }
7421       else if (shCount == 2)
7422         {
7423           emitcode ("mov", "c,acc.7");
7424           emitcode ("rrc", "a");
7425           emitcode ("mov", "c,acc.7");
7426           emitcode ("rrc", "a");
7427         }
7428       else
7429         {
7430           tlbl = newiTempLabel (NULL);
7431           /* rotate right accumulator */
7432           AccRol (8 - shCount);
7433           /* and kill the higher order bits */
7434           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7435           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7436           emitcode ("orl", "a,#!constbyte",
7437                     (unsigned char) ~SRMask[shCount]);
7438           emitcode ("", "!tlabeldef", tlbl->key + 100);
7439         }
7440     }
7441 }
7442 #endif
7443
7444 #ifdef BETTER_LITERAL_SHIFT
7445 /*-----------------------------------------------------------------*/
7446 /* shiftR1Left2Result - shift right one byte from left to result   */
7447 /*-----------------------------------------------------------------*/
7448 static void
7449 shiftR1Left2Result (operand * left, int offl,
7450                     operand * result, int offr,
7451                     int shCount, int sign)
7452 {
7453   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7454   /* shift right accumulator */
7455   if (sign)
7456     AccSRsh (shCount);
7457   else
7458     AccRsh (shCount);
7459   aopPut (AOP (result), "a", offr);
7460 }
7461 #endif
7462
7463 #ifdef BETTER_LITERAL_SHIFT
7464 /*-----------------------------------------------------------------*/
7465 /* shiftL1Left2Result - shift left one byte from left to result    */
7466 /*-----------------------------------------------------------------*/
7467 static void
7468 shiftL1Left2Result (operand * left, int offl,
7469                     operand * result, int offr, int shCount)
7470 {
7471   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7472   /* shift left accumulator */
7473   AccLsh (shCount);
7474   aopPut (AOP (result), "a", offr);
7475 }
7476 #endif
7477
7478 #ifdef BETTER_LITERAL_SHIFT
7479 /*-----------------------------------------------------------------*/
7480 /* movLeft2Result - move byte from left to result                  */
7481 /*-----------------------------------------------------------------*/
7482 static void
7483 movLeft2Result (operand * left, int offl,
7484                 operand * result, int offr, int sign)
7485 {
7486   char *l;
7487   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7488   {
7489       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7490
7491       if (*l == '@' && (IS_AOP_PREG (result)))
7492       {
7493           emitcode ("mov", "a,%s", l);
7494           aopPut (AOP (result), "a", offr);
7495       }
7496       else
7497       {
7498           if (!sign)
7499           {
7500             aopPut (AOP (result), l, offr);
7501           }
7502           else
7503             {
7504               /* MSB sign in acc.7 ! */
7505               if (getDataSize (left) == offl + 1)
7506                 {
7507                   emitcode ("mov", "a,%s", l);
7508                   aopPut (AOP (result), "a", offr);
7509                 }
7510             }
7511       }
7512   }
7513 }
7514 #endif
7515
7516 #ifdef BETTER_LITERAL_SHIFT
7517 /*-----------------------------------------------------------------*/
7518 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7519 /*-----------------------------------------------------------------*/
7520 static void
7521 AccAXRrl1 (char *x)
7522 {
7523   emitcode ("rrc", "a");
7524   emitcode ("xch", "a,%s", x);
7525   emitcode ("rrc", "a");
7526   emitcode ("xch", "a,%s", x);
7527 }
7528 #endif
7529
7530 #ifdef BETTER_LITERAL_SHIFT
7531 //REMOVE ME!!!
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7534 /*-----------------------------------------------------------------*/
7535 static void
7536 AccAXLrl1 (char *x)
7537 {
7538   emitcode ("xch", "a,%s", x);
7539   emitcode ("rlc", "a");
7540   emitcode ("xch", "a,%s", x);
7541   emitcode ("rlc", "a");
7542 }
7543 #endif
7544
7545 #ifdef BETTER_LITERAL_SHIFT
7546 /*-----------------------------------------------------------------*/
7547 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7548 /*-----------------------------------------------------------------*/
7549 static void
7550 AccAXLsh1 (char *x)
7551 {
7552   emitcode ("xch", "a,%s", x);
7553   emitcode ("add", "a,acc");
7554   emitcode ("xch", "a,%s", x);
7555   emitcode ("rlc", "a");
7556 }
7557 #endif
7558
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7562 /*-----------------------------------------------------------------*/
7563 static void
7564 AccAXLsh (char *x, int shCount)
7565 {
7566   switch (shCount)
7567     {
7568     case 0:
7569       break;
7570     case 1:
7571       AccAXLsh1 (x);
7572       break;
7573     case 2:
7574       AccAXLsh1 (x);
7575       AccAXLsh1 (x);
7576       break;
7577     case 3:
7578     case 4:
7579     case 5:                     // AAAAABBB:CCCCCDDD
7580
7581       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7582
7583       emitcode ("anl", "a,#!constbyte",
7584                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7585
7586       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7587
7588       AccRol (shCount);         // DDDCCCCC:BBB00000
7589
7590       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7591
7592       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7593
7594       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7595
7596       emitcode ("anl", "a,#!constbyte",
7597                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7598
7599       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7600
7601       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7602
7603       break;
7604     case 6:                     // AAAAAABB:CCCCCCDD
7605       emitcode ("anl", "a,#!constbyte",
7606                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7607       emitcode ("mov", "c,acc.0");      // c = B
7608       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7609 #if 0
7610       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7611       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7612 #else
7613       emitcode("rrc","a"); 
7614       emitcode("xch","a,%s", x); 
7615       emitcode("rrc","a"); 
7616       emitcode("mov","c,acc.0"); //<< get correct bit 
7617       emitcode("xch","a,%s", x); 
7618
7619       emitcode("rrc","a"); 
7620       emitcode("xch","a,%s", x); 
7621       emitcode("rrc","a"); 
7622       emitcode("xch","a,%s", x); 
7623 #endif
7624       break;
7625     case 7:                     // a:x <<= 7
7626
7627       emitcode ("anl", "a,#!constbyte",
7628                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7629
7630       emitcode ("mov", "c,acc.0");      // c = B
7631
7632       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7633
7634       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7635
7636       break;
7637     default:
7638       break;
7639     }
7640 }
7641 #endif
7642
7643 #ifdef BETTER_LITERAL_SHIFT
7644 //REMOVE ME!!!
7645 /*-----------------------------------------------------------------*/
7646 /* AccAXRsh - right shift a:x known count (0..7)                   */
7647 /*-----------------------------------------------------------------*/
7648 static void
7649 AccAXRsh (char *x, int shCount)
7650 {
7651   switch (shCount)
7652     {
7653     case 0:
7654       break;
7655     case 1:
7656       CLRC;
7657       AccAXRrl1 (x);            // 0->a:x
7658
7659       break;
7660     case 2:
7661       CLRC;
7662       AccAXRrl1 (x);            // 0->a:x
7663
7664       CLRC;
7665       AccAXRrl1 (x);            // 0->a:x
7666
7667       break;
7668     case 3:
7669     case 4:
7670     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7671
7672       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7673
7674       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7675
7676       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7677
7678       emitcode ("anl", "a,#!constbyte",
7679                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7680
7681       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7682
7683       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7684
7685       emitcode ("anl", "a,#!constbyte",
7686                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7687
7688       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7689
7690       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7691
7692       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7693
7694       break;
7695     case 6:                     // AABBBBBB:CCDDDDDD
7696
7697       emitcode ("mov", "c,acc.7");
7698       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7699
7700       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7701
7702       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7703
7704       emitcode ("anl", "a,#!constbyte",
7705                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7706
7707       break;
7708     case 7:                     // ABBBBBBB:CDDDDDDD
7709
7710       emitcode ("mov", "c,acc.7");      // c = A
7711
7712       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7713
7714       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7715
7716       emitcode ("anl", "a,#!constbyte",
7717                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7718
7719       break;
7720     default:
7721       break;
7722     }
7723 }
7724 #endif
7725
7726 #ifdef BETTER_LITERAL_SHIFT
7727 /*-----------------------------------------------------------------*/
7728 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7729 /*-----------------------------------------------------------------*/
7730 static void
7731 AccAXRshS (char *x, int shCount)
7732 {
7733   symbol *tlbl;
7734   switch (shCount)
7735     {
7736     case 0:
7737       break;
7738     case 1:
7739       emitcode ("mov", "c,acc.7");
7740       AccAXRrl1 (x);            // s->a:x
7741
7742       break;
7743     case 2:
7744       emitcode ("mov", "c,acc.7");
7745       AccAXRrl1 (x);            // s->a:x
7746
7747       emitcode ("mov", "c,acc.7");
7748       AccAXRrl1 (x);            // s->a:x
7749
7750       break;
7751     case 3:
7752     case 4:
7753     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7754
7755       tlbl = newiTempLabel (NULL);
7756       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7757
7758       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7759
7760       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7761
7762       emitcode ("anl", "a,#!constbyte",
7763                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7764
7765       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7766
7767       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7768
7769       emitcode ("anl", "a,#!constbyte",
7770                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7771
7772       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7773
7774       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7775
7776       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7777
7778       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7779       emitcode ("orl", "a,#!constbyte",
7780                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7781
7782       emitcode ("", "!tlabeldef", tlbl->key + 100);
7783       break;                    // SSSSAAAA:BBBCCCCC
7784
7785     case 6:                     // AABBBBBB:CCDDDDDD
7786
7787       tlbl = newiTempLabel (NULL);
7788       emitcode ("mov", "c,acc.7");
7789       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7790
7791       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7792
7793       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7794
7795       emitcode ("anl", "a,#!constbyte",
7796                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7797
7798       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7799       emitcode ("orl", "a,#!constbyte",
7800                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7801
7802       emitcode ("", "!tlabeldef", tlbl->key + 100);
7803       break;
7804     case 7:                     // ABBBBBBB:CDDDDDDD
7805
7806       tlbl = newiTempLabel (NULL);
7807       emitcode ("mov", "c,acc.7");      // c = A
7808
7809       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7810
7811       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7812
7813       emitcode ("anl", "a,#!constbyte",
7814                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7815
7816       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7817       emitcode ("orl", "a,#!constbyte",
7818                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7819
7820       emitcode ("", "!tlabeldef", tlbl->key + 100);
7821       break;
7822     default:
7823       break;
7824     }
7825 }
7826 #endif
7827
7828 #ifdef BETTER_LITERAL_SHIFT
7829 static void
7830 _loadLeftIntoAx(char    **lsb, 
7831                 operand *left, 
7832                 operand *result,
7833                 int     offl,
7834                 int     offr)
7835 {
7836   // Get the initial value from left into a pair of registers.
7837   // MSB must be in A, LSB can be any register.
7838   //
7839   // If the result is held in registers, it is an optimization
7840   // if the LSB can be held in the register which will hold the,
7841   // result LSB since this saves us from having to copy it into
7842   // the result following AccAXLsh.
7843   //
7844   // If the result is addressed indirectly, this is not a gain.
7845   if (AOP_NEEDSACC(result))
7846   {
7847        char *leftByte;
7848        
7849        _startLazyDPSEvaluation();
7850       if (AOP_TYPE(left) == AOP_DPTR2)
7851        {
7852            // Get MSB in A.
7853            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7854            // get LSB in DP2_RESULT_REG.
7855            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7856            assert(!strcmp(leftByte, DP2_RESULT_REG));
7857        }
7858        else
7859        {
7860            // get LSB into DP2_RESULT_REG
7861            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7862            if (strcmp(leftByte, DP2_RESULT_REG))
7863            {
7864                TR_AP("#7");
7865                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7866            }
7867            // And MSB in A.
7868            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7869            assert(strcmp(leftByte, DP2_RESULT_REG));
7870            MOVA(leftByte);
7871        }
7872        _endLazyDPSEvaluation();
7873        *lsb = DP2_RESULT_REG;
7874   }
7875   else
7876   {
7877       if (sameRegs (AOP (result), AOP (left)) &&
7878         ((offl + MSB16) == offr))
7879       {
7880           /* don't crash result[offr] */
7881           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7882           emitcode ("xch", "a,%s", 
7883                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7884       }
7885       else
7886       {
7887           movLeft2Result (left, offl, result, offr, 0);
7888           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7889       }
7890       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7891       assert(strcmp(*lsb,"a"));      
7892   }
7893 }
7894
7895 static void
7896 _storeAxResults(char    *lsb,
7897                 operand *result,
7898                 int     offr)
7899 {
7900   _startLazyDPSEvaluation();
7901   if (AOP_NEEDSACC(result))
7902   {
7903       /* We have to explicitly update the result LSB.
7904        */
7905       emitcode("xch","a,%s", lsb);
7906       aopPut(AOP(result), "a", offr);
7907       emitcode("mov","a,%s", lsb);
7908   }
7909   if (getDataSize (result) > 1)
7910   {
7911       aopPut (AOP (result), "a", offr + MSB16);
7912   }
7913   _endLazyDPSEvaluation();
7914 }
7915
7916 /*-----------------------------------------------------------------*/
7917 /* shiftL2Left2Result - shift left two bytes from left to result   */
7918 /*-----------------------------------------------------------------*/
7919 static void
7920 shiftL2Left2Result (operand * left, int offl,
7921                     operand * result, int offr, int shCount)
7922 {
7923   char *lsb;
7924
7925   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7926   
7927   AccAXLsh (lsb, shCount);
7928   
7929   _storeAxResults(lsb, result, offr);
7930 }
7931 #endif
7932
7933 #ifdef BETTER_LITERAL_SHIFT
7934 /*-----------------------------------------------------------------*/
7935 /* shiftR2Left2Result - shift right two bytes from left to result  */
7936 /*-----------------------------------------------------------------*/
7937 static void
7938 shiftR2Left2Result (operand * left, int offl,
7939                     operand * result, int offr,
7940                     int shCount, int sign)
7941 {
7942   char *lsb;
7943   
7944   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7945   
7946   /* a:x >> shCount (x = lsb(result)) */
7947   if (sign)
7948   {
7949      AccAXRshS(lsb, shCount);
7950   }
7951   else
7952   {
7953     AccAXRsh(lsb, shCount);
7954   }
7955   
7956   _storeAxResults(lsb, result, offr);
7957 }
7958 #endif
7959
7960 /*-----------------------------------------------------------------*/
7961 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7962 /*-----------------------------------------------------------------*/
7963 static void
7964 shiftLLeftOrResult (operand * left, int offl,
7965                     operand * result, int offr, int shCount)
7966 {
7967   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7968   /* shift left accumulator */
7969   AccLsh (shCount);
7970   /* or with result */
7971   emitcode ("orl", "a,%s",
7972             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7973   /* back to result */
7974   aopPut (AOP (result), "a", offr);
7975 }
7976
7977 #if 0
7978 //REMOVE ME!!!
7979 /*-----------------------------------------------------------------*/
7980 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7981 /*-----------------------------------------------------------------*/
7982 static void
7983 shiftRLeftOrResult (operand * left, int offl,
7984                     operand * result, int offr, int shCount)
7985 {
7986   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7987   /* shift right accumulator */
7988   AccRsh (shCount);
7989   /* or with result */
7990   emitcode ("orl", "a,%s",
7991             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7992   /* back to result */
7993   aopPut (AOP (result), "a", offr);
7994 }
7995 #endif
7996
7997 #ifdef BETTER_LITERAL_SHIFT
7998 /*-----------------------------------------------------------------*/
7999 /* genlshOne - left shift a one byte quantity by known count       */
8000 /*-----------------------------------------------------------------*/
8001 static void
8002 genlshOne (operand * result, operand * left, int shCount)
8003 {
8004   D (emitcode (";", "genlshOne "););
8005   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8006 }
8007 #endif
8008
8009 #ifdef BETTER_LITERAL_SHIFT
8010 /*-----------------------------------------------------------------*/
8011 /* genlshTwo - left shift two bytes by known amount != 0           */
8012 /*-----------------------------------------------------------------*/
8013 static void
8014 genlshTwo (operand * result, operand * left, int shCount)
8015 {
8016   int size;
8017
8018   D (emitcode (";", "genlshTwo "););
8019
8020   size = getDataSize (result);
8021
8022   /* if shCount >= 8 */
8023   if (shCount >= 8)
8024   {
8025       shCount -= 8;
8026
8027       _startLazyDPSEvaluation();
8028
8029       if (size > 1)
8030         {
8031           if (shCount)
8032           {
8033             _endLazyDPSEvaluation();
8034             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8035             aopPut (AOP (result), zero, LSB);       
8036           }
8037           else
8038           {
8039             movLeft2Result (left, LSB, result, MSB16, 0);
8040             aopPut (AOP (result), zero, LSB);
8041             _endLazyDPSEvaluation();
8042           }
8043         }
8044         else
8045         {
8046           aopPut (AOP (result), zero, LSB);
8047           _endLazyDPSEvaluation();
8048         }
8049   }
8050
8051   /*  1 <= shCount <= 7 */
8052   else
8053     {
8054       if (size == 1)
8055       {
8056         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8057       }
8058       else
8059       {
8060         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8061       }
8062     }
8063 }
8064 #endif
8065
8066 #if 0
8067 //REMOVE ME!!!
8068 /*-----------------------------------------------------------------*/
8069 /* shiftLLong - shift left one long from left to result            */
8070 /* offl = LSB or MSB16                                             */
8071 /*-----------------------------------------------------------------*/
8072 static void
8073 shiftLLong (operand * left, operand * result, int offr)
8074 {
8075   char *l;
8076   int size = AOP_SIZE (result);
8077
8078   if (size >= LSB + offr)
8079     {
8080       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8081       MOVA (l);
8082       emitcode ("add", "a,acc");
8083       if (sameRegs (AOP (left), AOP (result)) &&
8084           size >= MSB16 + offr && offr != LSB)
8085         emitcode ("xch", "a,%s",
8086                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8087       else
8088         aopPut (AOP (result), "a", LSB + offr);
8089     }
8090
8091   if (size >= MSB16 + offr)
8092     {
8093       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8094         {
8095           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8096         }
8097       emitcode ("rlc", "a");
8098       if (sameRegs (AOP (left), AOP (result)) &&
8099           size >= MSB24 + offr && offr != LSB)
8100         emitcode ("xch", "a,%s",
8101                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8102       else
8103         aopPut (AOP (result), "a", MSB16 + offr);
8104     }
8105
8106   if (size >= MSB24 + offr)
8107     {
8108       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8109         {
8110           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8111         }
8112       emitcode ("rlc", "a");
8113       if (sameRegs (AOP (left), AOP (result)) &&
8114           size >= MSB32 + offr && offr != LSB)
8115         emitcode ("xch", "a,%s",
8116                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8117       else
8118         aopPut (AOP (result), "a", MSB24 + offr);
8119     }
8120
8121   if (size > MSB32 + offr)
8122     {
8123       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8124         {
8125           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8126         }
8127       emitcode ("rlc", "a");
8128       aopPut (AOP (result), "a", MSB32 + offr);
8129     }
8130   if (offr != LSB)
8131     aopPut (AOP (result), zero, LSB);
8132 }
8133 #endif
8134
8135 #if 0
8136 //REMOVE ME!!!
8137 /*-----------------------------------------------------------------*/
8138 /* genlshFour - shift four byte by a known amount != 0             */
8139 /*-----------------------------------------------------------------*/
8140 static void
8141 genlshFour (operand * result, operand * left, int shCount)
8142 {
8143   int size;
8144
8145   D (emitcode (";", "genlshFour ");
8146     );
8147
8148   size = AOP_SIZE (result);
8149
8150   /* if shifting more that 3 bytes */
8151   if (shCount >= 24)
8152     {
8153       shCount -= 24;
8154       if (shCount)
8155         /* lowest order of left goes to the highest
8156            order of the destination */
8157         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8158       else
8159         movLeft2Result (left, LSB, result, MSB32, 0);
8160       aopPut (AOP (result), zero, LSB);
8161       aopPut (AOP (result), zero, MSB16);
8162       aopPut (AOP (result), zero, MSB24);
8163       return;
8164     }
8165
8166   /* more than two bytes */
8167   else if (shCount >= 16)
8168     {
8169       /* lower order two bytes goes to higher order two bytes */
8170       shCount -= 16;
8171       /* if some more remaining */
8172       if (shCount)
8173         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8174       else
8175         {
8176           movLeft2Result (left, MSB16, result, MSB32, 0);
8177           movLeft2Result (left, LSB, result, MSB24, 0);
8178         }
8179       aopPut (AOP (result), zero, MSB16);
8180       aopPut (AOP (result), zero, LSB);
8181       return;
8182     }
8183
8184   /* if more than 1 byte */
8185   else if (shCount >= 8)
8186     {
8187       /* lower order three bytes goes to higher order  three bytes */
8188       shCount -= 8;
8189       if (size == 2)
8190         {
8191           if (shCount)
8192             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8193           else
8194             movLeft2Result (left, LSB, result, MSB16, 0);
8195         }
8196       else
8197         {                       /* size = 4 */
8198           if (shCount == 0)
8199             {
8200               movLeft2Result (left, MSB24, result, MSB32, 0);
8201               movLeft2Result (left, MSB16, result, MSB24, 0);
8202               movLeft2Result (left, LSB, result, MSB16, 0);
8203               aopPut (AOP (result), zero, LSB);
8204             }
8205           else if (shCount == 1)
8206             shiftLLong (left, result, MSB16);
8207           else
8208             {
8209               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8210               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8211               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8212               aopPut (AOP (result), zero, LSB);
8213             }
8214         }
8215     }
8216
8217   /* 1 <= shCount <= 7 */
8218   else if (shCount <= 2)
8219     {
8220       shiftLLong (left, result, LSB);
8221       if (shCount == 2)
8222         shiftLLong (result, result, LSB);
8223     }
8224   /* 3 <= shCount <= 7, optimize */
8225   else
8226     {
8227       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8228       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8229       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8230     }
8231 }
8232 #endif
8233
8234 #ifdef BETTER_LITERAL_SHIFT
8235 /*-----------------------------------------------------------------*/
8236 /* genLeftShiftLiteral - left shifting by known count              */
8237 /*-----------------------------------------------------------------*/
8238 static bool
8239 genLeftShiftLiteral (operand * left,
8240                      operand * right,
8241                      operand * result,
8242                      iCode * ic)
8243 {
8244   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8245   int size;
8246
8247   size = getSize (operandType (result));
8248
8249   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8250
8251   /* We only handle certain easy cases so far. */
8252   if ((shCount != 0)
8253    && (shCount < (size * 8))
8254    && (size != 1)
8255    && (size != 2))
8256   {
8257       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8258       return FALSE;
8259   }
8260
8261   freeAsmop (right, NULL, ic, TRUE);
8262
8263   aopOp(left, ic, FALSE, FALSE);
8264   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8265
8266 #if 0 // debug spew
8267   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8268   {
8269         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8270         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8271         {
8272            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8273         }
8274   }
8275   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8276   {
8277         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8278         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8279         {
8280            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8281         }       
8282   }  
8283 #endif
8284   
8285 #if VIEW_SIZE
8286   emitcode ("; shift left ", "result %d, left %d", size,
8287             AOP_SIZE (left));
8288 #endif
8289
8290   /* I suppose that the left size >= result size */
8291   if (shCount == 0)
8292   {
8293         _startLazyDPSEvaluation();
8294         while (size--)
8295         {
8296           movLeft2Result (left, size, result, size, 0);
8297         }
8298         _endLazyDPSEvaluation();
8299   }
8300   else if (shCount >= (size * 8))
8301   {
8302     _startLazyDPSEvaluation();
8303     while (size--)
8304     {
8305       aopPut (AOP (result), zero, size);
8306     }
8307     _endLazyDPSEvaluation();
8308   }
8309   else
8310   {
8311       switch (size)
8312         {
8313         case 1:
8314           genlshOne (result, left, shCount);
8315           break;
8316
8317         case 2:
8318           genlshTwo (result, left, shCount);
8319           break;
8320 #if 0
8321         case 4:
8322           genlshFour (result, left, shCount);
8323           break;
8324 #endif
8325         default:
8326           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8327           break;
8328         }
8329     }
8330   freeAsmop (left, NULL, ic, TRUE);
8331   freeAsmop (result, NULL, ic, TRUE);
8332   return TRUE;
8333 }
8334 #endif
8335
8336 /*-----------------------------------------------------------------*/
8337 /* genLeftShift - generates code for left shifting                 */
8338 /*-----------------------------------------------------------------*/
8339 static void
8340 genLeftShift (iCode * ic)
8341 {
8342   operand *left, *right, *result;
8343   int size, offset;
8344   char *l;
8345   symbol *tlbl, *tlbl1;
8346
8347   D (emitcode (";", "genLeftShift "););
8348
8349   right = IC_RIGHT (ic);
8350   left = IC_LEFT (ic);
8351   result = IC_RESULT (ic);
8352
8353   aopOp (right, ic, FALSE, FALSE);
8354
8355
8356 #ifdef BETTER_LITERAL_SHIFT
8357   /* if the shift count is known then do it
8358      as efficiently as possible */
8359   if (AOP_TYPE (right) == AOP_LIT)
8360     {
8361       if (genLeftShiftLiteral (left, right, result, ic))
8362       {
8363         return;
8364       }
8365     }
8366 #endif
8367
8368   /* shift count is unknown then we have to form
8369      a loop get the loop count in B : Note: we take
8370      only the lower order byte since shifting
8371      more that 32 bits make no sense anyway, ( the
8372      largest size of an object can be only 32 bits ) */
8373
8374   if (AOP_TYPE (right) == AOP_LIT)
8375   {
8376       /* Really should be handled by genLeftShiftLiteral,
8377        * but since I'm too lazy to fix that today, at least we can make
8378        * some small improvement.
8379        */
8380        emitcode("mov", "b,#!constbyte",
8381                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8382   }
8383   else
8384   {
8385       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8386       emitcode ("inc", "b");
8387   }
8388   freeAsmop (right, NULL, ic, TRUE);
8389   aopOp (left, ic, FALSE, FALSE);
8390   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8391
8392   /* now move the left to the result if they are not the
8393      same */
8394   if (!sameRegs (AOP (left), AOP (result)) &&
8395       AOP_SIZE (result) > 1)
8396     {
8397
8398       size = AOP_SIZE (result);
8399       offset = 0;
8400       _startLazyDPSEvaluation ();
8401       while (size--)
8402         {
8403           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8404           if (*l == '@' && (IS_AOP_PREG (result)))
8405             {
8406
8407               emitcode ("mov", "a,%s", l);
8408               aopPut (AOP (result), "a", offset);
8409             }
8410           else
8411             aopPut (AOP (result), l, offset);
8412           offset++;
8413         }
8414       _endLazyDPSEvaluation ();
8415     }
8416
8417   tlbl = newiTempLabel (NULL);
8418   size = AOP_SIZE (result);
8419   offset = 0;
8420   tlbl1 = newiTempLabel (NULL);
8421
8422   /* if it is only one byte then */
8423   if (size == 1)
8424     {
8425       symbol *tlbl1 = newiTempLabel (NULL);
8426
8427       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8428       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8429       emitcode ("", "!tlabeldef", tlbl->key + 100);
8430       emitcode ("add", "a,acc");
8431       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8432       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8433       aopPut (AOP (result), "a", 0);
8434       goto release;
8435     }
8436
8437   reAdjustPreg (AOP (result));
8438
8439   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8440   emitcode ("", "!tlabeldef", tlbl->key + 100);
8441   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8442   emitcode ("add", "a,acc");
8443   aopPut (AOP (result), "a", offset++);
8444   _startLazyDPSEvaluation ();
8445   while (--size)
8446     {
8447       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8448       emitcode ("rlc", "a");
8449       aopPut (AOP (result), "a", offset++);
8450     }
8451   _endLazyDPSEvaluation ();
8452   reAdjustPreg (AOP (result));
8453
8454   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8455   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8456 release:
8457   freeAsmop (left, NULL, ic, TRUE);
8458   freeAsmop (result, NULL, ic, TRUE);
8459 }
8460
8461 #ifdef BETTER_LITERAL_SHIFT
8462 /*-----------------------------------------------------------------*/
8463 /* genrshOne - right shift a one byte quantity by known count      */
8464 /*-----------------------------------------------------------------*/
8465 static void
8466 genrshOne (operand * result, operand * left,
8467            int shCount, int sign)
8468 {
8469   D (emitcode (";", "genrshOne"););
8470   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8471 }
8472 #endif
8473
8474 #ifdef BETTER_LITERAL_SHIFT
8475 /*-----------------------------------------------------------------*/
8476 /* genrshTwo - right shift two bytes by known amount != 0          */
8477 /*-----------------------------------------------------------------*/
8478 static void
8479 genrshTwo (operand * result, operand * left,
8480            int shCount, int sign)
8481 {
8482   D (emitcode (";", "genrshTwo"););
8483
8484   /* if shCount >= 8 */
8485   if (shCount >= 8)
8486     {
8487       shCount -= 8;
8488       _startLazyDPSEvaluation();
8489       if (shCount)
8490       {
8491         shiftR1Left2Result (left, MSB16, result, LSB,
8492                             shCount, sign);
8493       }                     
8494       else
8495       {
8496         movLeft2Result (left, MSB16, result, LSB, sign);
8497       }
8498       addSign (result, MSB16, sign);
8499       _endLazyDPSEvaluation();
8500     }
8501
8502   /*  1 <= shCount <= 7 */
8503   else
8504   {
8505     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8506   }
8507 }
8508 #endif
8509
8510 /*-----------------------------------------------------------------*/
8511 /* shiftRLong - shift right one long from left to result           */
8512 /* offl = LSB or MSB16                                             */
8513 /*-----------------------------------------------------------------*/
8514 static void
8515 shiftRLong (operand * left, int offl,
8516             operand * result, int sign)
8517 {
8518   int isSameRegs=sameRegs(AOP(left),AOP(result));
8519
8520   if (isSameRegs && offl>1) {
8521     // we are in big trouble, but this shouldn't happen
8522     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8523   }
8524
8525   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8526   
8527   if (offl==MSB16) {
8528     // shift is > 8
8529     if (sign) {
8530       emitcode ("rlc", "a");
8531       emitcode ("subb", "a,acc");
8532       emitcode ("xch", "a,%s",
8533                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8534     } else {
8535       aopPut (AOP(result), zero, MSB32);
8536     }
8537   }
8538
8539   if (!sign) {
8540     emitcode ("clr", "c");
8541   } else {
8542     emitcode ("mov", "c,acc.7");
8543   }
8544
8545   emitcode ("rrc", "a");
8546
8547   if (isSameRegs && offl==MSB16) {
8548     emitcode ("xch",
8549               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8550   } else {
8551     aopPut (AOP (result), "a", MSB32);
8552     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8553   }
8554
8555   emitcode ("rrc", "a");
8556   if (isSameRegs && offl==1) {
8557     emitcode ("xch", "a,%s",
8558               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8559   } else {
8560     aopPut (AOP (result), "a", MSB24);
8561     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8562   }
8563   emitcode ("rrc", "a");
8564   aopPut (AOP (result), "a", MSB16 - offl);
8565
8566   if (offl == LSB)
8567     {
8568       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8569       emitcode ("rrc", "a");
8570       aopPut (AOP (result), "a", LSB);
8571     }
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* genrshFour - shift four byte by a known amount != 0             */
8576 /*-----------------------------------------------------------------*/
8577 static void
8578 genrshFour (operand * result, operand * left,
8579             int shCount, int sign)
8580 {
8581   D (emitcode (";", "genrshFour"););
8582
8583   /* if shifting more that 3 bytes */
8584   if (shCount >= 24)
8585     {
8586       shCount -= 24;
8587       _startLazyDPSEvaluation();
8588       if (shCount)
8589         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8590       else
8591         movLeft2Result (left, MSB32, result, LSB, sign);
8592       addSign (result, MSB16, sign);
8593       _endLazyDPSEvaluation();
8594     }
8595   else if (shCount >= 16)
8596     {
8597       shCount -= 16;
8598       _startLazyDPSEvaluation();
8599       if (shCount)
8600         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8601       else
8602         {
8603           movLeft2Result (left, MSB24, result, LSB, 0);
8604           movLeft2Result (left, MSB32, result, MSB16, sign);
8605         }
8606       addSign (result, MSB24, sign);
8607       _endLazyDPSEvaluation();
8608     }
8609   else if (shCount >= 8)
8610     {
8611       shCount -= 8;
8612       _startLazyDPSEvaluation();
8613       if (shCount == 1)
8614         {
8615             shiftRLong (left, MSB16, result, sign);
8616         }
8617       else if (shCount == 0)
8618         {
8619           movLeft2Result (left, MSB16, result, LSB, 0);
8620           movLeft2Result (left, MSB24, result, MSB16, 0);
8621           movLeft2Result (left, MSB32, result, MSB24, sign);
8622           addSign (result, MSB32, sign);
8623         }
8624       else
8625         {
8626           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8627           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8628           /* the last shift is signed */
8629           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8630           addSign (result, MSB32, sign);
8631         }
8632         _endLazyDPSEvaluation();
8633     }
8634   else
8635     {   
8636         /* 1 <= shCount <= 7 */
8637       if (shCount <= 2)
8638         {
8639           shiftRLong (left, LSB, result, sign);
8640           if (shCount == 2)
8641             shiftRLong (result, LSB, result, sign);
8642         }
8643       else
8644         {
8645           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8646           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8647           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8648         }
8649     }
8650 }
8651
8652 #ifdef BETTER_LITERAL_SHIFT
8653 /*-----------------------------------------------------------------*/
8654 /* genRightShiftLiteral - right shifting by known count            */
8655 /*-----------------------------------------------------------------*/
8656 static bool
8657 genRightShiftLiteral (operand * left,
8658                       operand * right,
8659                       operand * result,
8660                       iCode * ic,
8661                       int sign)
8662 {
8663   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8664   int size;
8665
8666   size = getSize (operandType (result));
8667
8668   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8669
8670   /* We only handle certain easy cases so far. */
8671   if ((shCount != 0)
8672    && (shCount < (size * 8))
8673    && (size != 1)
8674    && (size != 2)
8675    && (size != 4))
8676   {
8677       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8678       return FALSE;
8679   }
8680
8681   freeAsmop (right, NULL, ic, TRUE);
8682
8683   aopOp (left, ic, FALSE, FALSE);
8684   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8685
8686 #if VIEW_SIZE
8687   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8688             AOP_SIZE (left));
8689 #endif
8690
8691   /* test the LEFT size !!! */
8692
8693   /* I suppose that the left size >= result size */
8694   if (shCount == 0)
8695   {
8696       size = getDataSize (result);
8697       _startLazyDPSEvaluation();
8698       while (size--)
8699       {
8700         movLeft2Result (left, size, result, size, 0);
8701       }
8702       _endLazyDPSEvaluation();
8703   }
8704   else if (shCount >= (size * 8))
8705     {
8706       if (sign)
8707       {
8708         /* get sign in acc.7 */
8709         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8710       }
8711       addSign (result, LSB, sign);
8712     }
8713   else
8714     {
8715       switch (size)
8716         {
8717         case 1:
8718           genrshOne (result, left, shCount, sign);
8719           break;
8720
8721         case 2:
8722           genrshTwo (result, left, shCount, sign);
8723           break;
8724 #if 1
8725         case 4:
8726           genrshFour (result, left, shCount, sign);
8727           break;
8728 #endif    
8729         default:
8730           break;
8731         }
8732     }
8733   freeAsmop (left, NULL, ic, TRUE);
8734   freeAsmop (result, NULL, ic, TRUE);
8735   
8736   return TRUE;
8737 }
8738 #endif
8739
8740 /*-----------------------------------------------------------------*/
8741 /* genSignedRightShift - right shift of signed number              */
8742 /*-----------------------------------------------------------------*/
8743 static void
8744 genSignedRightShift (iCode * ic)
8745 {
8746   operand *right, *left, *result;
8747   int size, offset;
8748   char *l;
8749   symbol *tlbl, *tlbl1;
8750
8751   D (emitcode (";", "genSignedRightShift "););
8752
8753   /* we do it the hard way put the shift count in b
8754      and loop thru preserving the sign */
8755
8756   right = IC_RIGHT (ic);
8757   left = IC_LEFT (ic);
8758   result = IC_RESULT (ic);
8759
8760   aopOp (right, ic, FALSE, FALSE);
8761
8762 #ifdef BETTER_LITERAL_SHIFT
8763   if (AOP_TYPE (right) == AOP_LIT)
8764     {
8765       if (genRightShiftLiteral (left, right, result, ic, 1))
8766       {
8767         return;
8768       }
8769     }
8770 #endif
8771   /* shift count is unknown then we have to form
8772      a loop get the loop count in B : Note: we take
8773      only the lower order byte since shifting
8774      more that 32 bits make no sense anyway, ( the
8775      largest size of an object can be only 32 bits ) */
8776
8777   if (AOP_TYPE (right) == AOP_LIT)
8778   {
8779       /* Really should be handled by genRightShiftLiteral,
8780        * but since I'm too lazy to fix that today, at least we can make
8781        * some small improvement.
8782        */
8783        emitcode("mov", "b,#!constbyte",
8784                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8785   }
8786   else
8787   {
8788         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8789         emitcode ("inc", "b");
8790   }
8791   freeAsmop (right, NULL, ic, TRUE);
8792   aopOp (left, ic, FALSE, FALSE);
8793   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8794
8795   /* now move the left to the result if they are not the
8796      same */
8797   if (!sameRegs (AOP (left), AOP (result)) &&
8798       AOP_SIZE (result) > 1)
8799     {
8800
8801       size = AOP_SIZE (result);
8802       offset = 0;
8803       _startLazyDPSEvaluation ();
8804       while (size--)
8805         {
8806           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8807           if (*l == '@' && IS_AOP_PREG (result))
8808             {
8809
8810               emitcode ("mov", "a,%s", l);
8811               aopPut (AOP (result), "a", offset);
8812             }
8813           else
8814             aopPut (AOP (result), l, offset);
8815           offset++;
8816         }
8817       _endLazyDPSEvaluation ();
8818     }
8819
8820   /* mov the highest order bit to OVR */
8821   tlbl = newiTempLabel (NULL);
8822   tlbl1 = newiTempLabel (NULL);
8823
8824   size = AOP_SIZE (result);
8825   offset = size - 1;
8826   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8827   emitcode ("rlc", "a");
8828   emitcode ("mov", "ov,c");
8829   /* if it is only one byte then */
8830   if (size == 1)
8831     {
8832       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8833       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8834       emitcode ("", "!tlabeldef", tlbl->key + 100);
8835       emitcode ("mov", "c,ov");
8836       emitcode ("rrc", "a");
8837       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8838       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8839       aopPut (AOP (result), "a", 0);
8840       goto release;
8841     }
8842
8843   reAdjustPreg (AOP (result));
8844   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8845   emitcode ("", "!tlabeldef", tlbl->key + 100);
8846   emitcode ("mov", "c,ov");
8847   _startLazyDPSEvaluation ();
8848   while (size--)
8849     {
8850       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8851       emitcode ("rrc", "a");
8852       aopPut (AOP (result), "a", offset--);
8853     }
8854   _endLazyDPSEvaluation ();
8855   reAdjustPreg (AOP (result));
8856   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8857   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8858
8859 release:
8860   freeAsmop (left, NULL, ic, TRUE);
8861   freeAsmop (result, NULL, ic, TRUE);
8862 }
8863
8864 /*-----------------------------------------------------------------*/
8865 /* genRightShift - generate code for right shifting                */
8866 /*-----------------------------------------------------------------*/
8867 static void
8868 genRightShift (iCode * ic)
8869 {
8870   operand *right, *left, *result;
8871   sym_link *retype;
8872   int size, offset;
8873   char *l;
8874   symbol *tlbl, *tlbl1;
8875
8876   D (emitcode (";", "genRightShift "););
8877
8878   /* if signed then we do it the hard way preserve the
8879      sign bit moving it inwards */
8880   retype = getSpec (operandType (IC_RESULT (ic)));
8881
8882   if (!SPEC_USIGN (retype))
8883     {
8884       genSignedRightShift (ic);
8885       return;
8886     }
8887
8888   /* signed & unsigned types are treated the same : i.e. the
8889      signed is NOT propagated inwards : quoting from the
8890      ANSI - standard : "for E1 >> E2, is equivalent to division
8891      by 2**E2 if unsigned or if it has a non-negative value,
8892      otherwise the result is implementation defined ", MY definition
8893      is that the sign does not get propagated */
8894
8895   right = IC_RIGHT (ic);
8896   left = IC_LEFT (ic);
8897   result = IC_RESULT (ic);
8898
8899   aopOp (right, ic, FALSE, FALSE);
8900
8901 #ifdef BETTER_LITERAL_SHIFT
8902   /* if the shift count is known then do it
8903      as efficiently as possible */
8904   if (AOP_TYPE (right) == AOP_LIT)
8905     {
8906       if (genRightShiftLiteral (left, right, result, ic, 0))
8907       {
8908         return;
8909       }
8910     }
8911 #endif
8912
8913   /* shift count is unknown then we have to form
8914      a loop get the loop count in B : Note: we take
8915      only the lower order byte since shifting
8916      more that 32 bits make no sense anyway, ( the
8917      largest size of an object can be only 32 bits ) */
8918   
8919   if (AOP_TYPE (right) == AOP_LIT)
8920   {
8921       /* Really should be handled by genRightShiftLiteral,
8922        * but since I'm too lazy to fix that today, at least we can make
8923        * some small improvement.
8924        */
8925        emitcode("mov", "b,#!constbyte",
8926                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8927   }
8928   else
8929   {
8930       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8931       emitcode ("inc", "b");
8932   }
8933   freeAsmop (right, NULL, ic, TRUE);
8934   aopOp (left, ic, FALSE, FALSE);
8935   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8936
8937   /* now move the left to the result if they are not the
8938      same */
8939   if (!sameRegs (AOP (left), AOP (result)) &&
8940       AOP_SIZE (result) > 1)
8941     {
8942
8943       size = AOP_SIZE (result);
8944       offset = 0;
8945       _startLazyDPSEvaluation ();
8946       while (size--)
8947         {
8948           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8949           if (*l == '@' && IS_AOP_PREG (result))
8950             {
8951
8952               emitcode ("mov", "a,%s", l);
8953               aopPut (AOP (result), "a", offset);
8954             }
8955           else
8956             aopPut (AOP (result), l, offset);
8957           offset++;
8958         }
8959       _endLazyDPSEvaluation ();
8960     }
8961
8962   tlbl = newiTempLabel (NULL);
8963   tlbl1 = newiTempLabel (NULL);
8964   size = AOP_SIZE (result);
8965   offset = size - 1;
8966
8967   /* if it is only one byte then */
8968   if (size == 1)
8969     {
8970       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8971       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8972       emitcode ("", "!tlabeldef", tlbl->key + 100);
8973       CLRC;
8974       emitcode ("rrc", "a");
8975       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8976       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8977       aopPut (AOP (result), "a", 0);
8978       goto release;
8979     }
8980
8981   reAdjustPreg (AOP (result));
8982   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8983   emitcode ("", "!tlabeldef", tlbl->key + 100);
8984   CLRC;
8985   _startLazyDPSEvaluation ();
8986   while (size--)
8987     {
8988       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8989       emitcode ("rrc", "a");
8990       aopPut (AOP (result), "a", offset--);
8991     }
8992   _endLazyDPSEvaluation ();
8993   reAdjustPreg (AOP (result));
8994
8995   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8996   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8997
8998 release:
8999   freeAsmop (left, NULL, ic, TRUE);
9000   freeAsmop (result, NULL, ic, TRUE);
9001 }
9002
9003
9004 /*-----------------------------------------------------------------*/
9005 /* emitPtrByteGet - emits code to get a byte into A through a      */
9006 /*                  pointer register (R0, R1, or DPTR). The        */
9007 /*                  original value of A can be preserved in B.     */
9008 /*-----------------------------------------------------------------*/
9009 static void
9010 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9011 {
9012   switch (p_type)
9013     {
9014     case IPOINTER:
9015     case POINTER:
9016       if (preserveAinB)
9017         emitcode ("mov", "b,a");
9018       emitcode ("mov", "a,@%s", rname);
9019       break;
9020
9021     case PPOINTER:
9022       if (preserveAinB)
9023         emitcode ("mov", "b,a");
9024       emitcode ("movx", "a,@%s", rname);
9025       break;
9026       
9027     case FPOINTER:
9028       if (preserveAinB)
9029         emitcode ("mov", "b,a");
9030       emitcode ("movx", "a,@dptr");
9031       break;
9032
9033     case CPOINTER:
9034       if (preserveAinB)
9035         emitcode ("mov", "b,a");
9036       emitcode ("clr", "a");
9037       emitcode ("movc", "a,@a+dptr");
9038       break;
9039
9040     case GPOINTER:
9041       if (preserveAinB)
9042         {
9043           emitcode ("push", "b");
9044           emitcode ("push", "acc");
9045         }
9046       emitcode ("lcall", "__gptrget");
9047       if (preserveAinB)
9048         emitcode ("pop", "b");
9049       break;
9050     }
9051 }
9052
9053 /*-----------------------------------------------------------------*/
9054 /* emitPtrByteSet - emits code to set a byte from src through a    */
9055 /*                  pointer register (R0, R1, or DPTR).            */
9056 /*-----------------------------------------------------------------*/
9057 static void
9058 emitPtrByteSet (char *rname, int p_type, char *src)
9059 {
9060   switch (p_type)
9061     {
9062     case IPOINTER:
9063     case POINTER:
9064       if (*src=='@')
9065         {
9066           MOVA (src);
9067           emitcode ("mov", "@%s,a", rname);
9068         }
9069       else
9070         emitcode ("mov", "@%s,%s", rname, src);
9071       break;
9072
9073     case PPOINTER:
9074       MOVA (src);
9075       emitcode ("movx", "@%s,a", rname);
9076       break;
9077       
9078     case FPOINTER:
9079       MOVA (src);
9080       emitcode ("movx", "@dptr,a");
9081       break;
9082
9083     case GPOINTER:
9084       MOVA (src);
9085       emitcode ("lcall", "__gptrput");
9086       break;
9087     }
9088 }
9089
9090 /*-----------------------------------------------------------------*/
9091 /* genUnpackBits - generates code for unpacking bits               */
9092 /*-----------------------------------------------------------------*/
9093 static void
9094 genUnpackBits (operand * result, char *rname, int ptype)
9095 {
9096   int offset = 0;       /* result byte offset */
9097   int rsize;            /* result size */
9098   int rlen = 0;         /* remaining bitfield length */
9099   sym_link *etype;      /* bitfield type information */
9100   int blen;             /* bitfield length */
9101   int bstr;             /* bitfield starting bit within byte */
9102
9103   D(emitcode (";     genUnpackBits",""));
9104
9105   etype = getSpec (operandType (result));
9106   rsize = getSize (operandType (result));
9107   blen = SPEC_BLEN (etype);
9108   bstr = SPEC_BSTR (etype);
9109
9110   /* If the bitfield length is less than a byte */
9111   if (blen < 8)
9112     {
9113       emitPtrByteGet (rname, ptype, FALSE);
9114       AccRsh (bstr);
9115       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9116       aopPut (AOP (result), "a", offset++);
9117       goto finish;
9118     }
9119
9120   /* Bit field did not fit in a byte. Copy all
9121      but the partial byte at the end.  */
9122   for (rlen=blen;rlen>=8;rlen-=8)
9123     {
9124       emitPtrByteGet (rname, ptype, FALSE);
9125       aopPut (AOP (result), "a", offset++);
9126       if (rlen>8)
9127         emitcode ("inc", "%s", rname);
9128     }
9129
9130   /* Handle the partial byte at the end */
9131   if (rlen)
9132     {
9133       emitPtrByteGet (rname, ptype, FALSE);
9134       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9135       aopPut (AOP (result), "a", offset++);
9136     }
9137
9138 finish:
9139   if (offset < rsize)
9140     {
9141       rsize -= offset;
9142       while (rsize--)
9143         aopPut (AOP (result), zero, offset++);
9144     }
9145 }
9146
9147
9148 /*-----------------------------------------------------------------*/
9149 /* genDataPointerGet - generates code when ptr offset is known     */
9150 /*-----------------------------------------------------------------*/
9151 static void
9152 genDataPointerGet (operand * left,
9153                    operand * result,
9154                    iCode * ic)
9155 {
9156   char *l;
9157   char buff[256];
9158   int size, offset = 0;
9159   aopOp (result, ic, TRUE, FALSE);
9160
9161   /* get the string representation of the name */
9162   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9163   size = AOP_SIZE (result);
9164   _startLazyDPSEvaluation ();
9165   while (size--)
9166     {
9167         if (offset)
9168         {
9169             SNPRINTF (buff, sizeof(buff), 
9170                       "(%s + %d)", l + 1, offset);
9171         }
9172         else
9173         {
9174             SNPRINTF (buff, sizeof(buff), 
9175                       "%s", l + 1);
9176         }
9177       aopPut (AOP (result), buff, offset++);
9178     }
9179   _endLazyDPSEvaluation ();
9180
9181   freeAsmop (left, NULL, ic, TRUE);
9182   freeAsmop (result, NULL, ic, TRUE);
9183 }
9184
9185 /*-----------------------------------------------------------------*/
9186 /* genNearPointerGet - emitcode for near pointer fetch             */
9187 /*-----------------------------------------------------------------*/
9188 static void
9189 genNearPointerGet (operand * left,
9190                    operand * result,
9191                    iCode * ic,
9192                    iCode *pi)
9193 {
9194   asmop *aop = NULL;
9195   regs *preg;
9196   char *rname;
9197   sym_link *rtype, *retype, *letype;
9198   sym_link *ltype = operandType (left);
9199   char buff[80];
9200
9201   rtype = operandType (result);
9202   retype = getSpec (rtype);
9203   letype = getSpec (ltype);
9204
9205   aopOp (left, ic, FALSE, FALSE);
9206
9207   /* if left is rematerialisable and
9208      result is not bit variable type and
9209      the left is pointer to data space i.e
9210      lower 128 bytes of space */
9211   if (AOP_TYPE (left) == AOP_IMMD &&
9212       !IS_BITVAR (retype) &&
9213       !IS_BITVAR (letype) &&
9214       DCL_TYPE (ltype) == POINTER)
9215     {
9216       genDataPointerGet (left, result, ic);
9217       return;
9218     }
9219
9220   /* if the value is already in a pointer register
9221      then don't need anything more */
9222   if (!AOP_INPREG (AOP (left)))
9223     {
9224       /* otherwise get a free pointer register */
9225       aop = newAsmop (0);
9226       preg = getFreePtr (ic, &aop, FALSE);
9227       emitcode ("mov", "%s,%s",
9228                 preg->name,
9229                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9230       rname = preg->name;
9231     }
9232   else
9233     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9234
9235   freeAsmop (left, NULL, ic, TRUE);
9236   aopOp (result, ic, FALSE, FALSE);
9237
9238   /* if bitfield then unpack the bits */
9239   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9240     genUnpackBits (result, rname, POINTER);
9241   else
9242     {
9243       /* we have can just get the values */
9244       int size = AOP_SIZE (result);
9245       int offset = 0;
9246
9247       while (size--)
9248         {
9249           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9250             {
9251
9252               emitcode ("mov", "a,@%s", rname);
9253               aopPut (AOP (result), "a", offset);
9254             }
9255           else
9256             {
9257               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9258               aopPut (AOP (result), buff, offset);
9259             }
9260           offset++;
9261           if (size || pi)
9262             {
9263                 emitcode ("inc", "%s", rname);
9264             }
9265         }
9266     }
9267
9268   /* now some housekeeping stuff */
9269   if (aop)
9270     {
9271       /* we had to allocate for this iCode */
9272       if (pi) { /* post increment present */
9273         aopPut(AOP ( left ),rname,0);
9274       }
9275       freeAsmop (NULL, aop, ic, TRUE);
9276     }
9277   else
9278     {
9279       /* we did not allocate which means left
9280          already in a pointer register, then
9281          if size > 0 && this could be used again
9282          we have to point it back to where it
9283          belongs */
9284       if (AOP_SIZE (result) > 1 &&
9285           !OP_SYMBOL (left)->remat &&
9286           (OP_SYMBOL (left)->liveTo > ic->seq ||
9287            ic->depth) &&
9288           !pi)
9289         {
9290           int size = AOP_SIZE (result) - 1;
9291           while (size--)
9292             emitcode ("dec", "%s", rname);
9293         }
9294     }
9295
9296   /* done */
9297   freeAsmop (result, NULL, ic, TRUE);
9298   if (pi) pi->generated = 1;
9299 }
9300
9301 /*-----------------------------------------------------------------*/
9302 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9303 /*-----------------------------------------------------------------*/
9304 static void
9305 genPagedPointerGet (operand * left,
9306                     operand * result,
9307                     iCode * ic,
9308                     iCode * pi)
9309 {
9310   asmop *aop = NULL;
9311   regs *preg;
9312   char *rname;
9313   sym_link *rtype, *retype, *letype;
9314
9315   rtype = operandType (result);
9316   retype = getSpec (rtype);
9317   letype = getSpec (operandType (left));
9318   aopOp (left, ic, FALSE, FALSE);
9319
9320   /* if the value is already in a pointer register
9321      then don't need anything more */
9322   if (!AOP_INPREG (AOP (left)))
9323     {
9324       /* otherwise get a free pointer register */
9325       aop = newAsmop (0);
9326       preg = getFreePtr (ic, &aop, FALSE);
9327       emitcode ("mov", "%s,%s",
9328                 preg->name,
9329                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9330       rname = preg->name;
9331     }
9332   else
9333     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9334
9335   freeAsmop (left, NULL, ic, TRUE);
9336   aopOp (result, ic, FALSE, FALSE);
9337
9338   /* if bitfield then unpack the bits */
9339   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9340     genUnpackBits (result, rname, PPOINTER);
9341   else
9342     {
9343       /* we have can just get the values */
9344       int size = AOP_SIZE (result);
9345       int offset = 0;
9346
9347       while (size--)
9348         {
9349
9350           emitcode ("movx", "a,@%s", rname);
9351           aopPut (AOP (result), "a", offset);
9352
9353           offset++;
9354
9355           if (size || pi)
9356             emitcode ("inc", "%s", rname);
9357         }
9358     }
9359
9360   /* now some housekeeping stuff */
9361   if (aop)
9362     {
9363       /* we had to allocate for this iCode */
9364       if (pi) aopPut ( AOP (left), rname, 0);
9365       freeAsmop (NULL, aop, ic, TRUE);
9366     }
9367   else
9368     {
9369       /* we did not allocate which means left
9370          already in a pointer register, then
9371          if size > 0 && this could be used again
9372          we have to point it back to where it
9373          belongs */
9374       if (AOP_SIZE (result) > 1 &&
9375           !OP_SYMBOL (left)->remat &&
9376           (OP_SYMBOL (left)->liveTo > ic->seq ||
9377            ic->depth) &&
9378           !pi)
9379         {
9380           int size = AOP_SIZE (result) - 1;
9381           while (size--)
9382             emitcode ("dec", "%s", rname);
9383         }
9384     }
9385
9386   /* done */
9387   freeAsmop (result, NULL, ic, TRUE);
9388   if (pi) pi->generated = 1;
9389 }
9390
9391 /*-----------------------------------------------------------------*/
9392 /* genFarPointerGet - gget value from far space                    */
9393 /*-----------------------------------------------------------------*/
9394 static void
9395 genFarPointerGet (operand * left,
9396                   operand * result, iCode * ic, iCode *pi)
9397 {
9398     int size, offset, dopi=1;
9399   sym_link *retype = getSpec (operandType (result));
9400   sym_link *letype = getSpec (operandType (left));
9401   D (emitcode (";", "genFarPointerGet"););
9402
9403   aopOp (left, ic, FALSE, FALSE);
9404
9405   /* if the operand is already in dptr
9406      then we do nothing else we move the value to dptr */
9407   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9408     {
9409       /* if this is remateriazable */
9410       if (AOP_TYPE (left) == AOP_IMMD)
9411         {
9412           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9413         }
9414       else
9415         {
9416           /* we need to get it byte by byte */
9417           _startLazyDPSEvaluation ();
9418           if (AOP_TYPE (left) != AOP_DPTR)
9419             {
9420               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9421               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9422               if (options.model == MODEL_FLAT24)
9423                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9424             }
9425           else
9426             {
9427               /* We need to generate a load to DPTR indirect through DPTR. */
9428               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9429               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9430               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9431               if (options.model == MODEL_FLAT24)
9432                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9433               emitcode ("pop", "dph");
9434               emitcode ("pop", "dpl");
9435               dopi =0;
9436             }
9437           _endLazyDPSEvaluation ();
9438         }
9439     }
9440   /* so dptr know contains the address */
9441   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9442
9443   /* if bit then unpack */
9444   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9445       if (AOP_INDPTRn(left)) {
9446           genSetDPTR(AOP(left)->aopu.dptr);
9447       }
9448       genUnpackBits (result, "dptr", FPOINTER);
9449       if (AOP_INDPTRn(left)) {
9450           genSetDPTR(0);
9451       }
9452   } else
9453     {
9454       size = AOP_SIZE (result);
9455       offset = 0;
9456
9457       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9458           while (size--) {
9459               genSetDPTR(AOP(left)->aopu.dptr);
9460               emitcode ("movx", "a,@dptr");
9461               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9462                   emitcode ("inc", "dptr");
9463               genSetDPTR (0);
9464               aopPut (AOP (result), "a", offset++);
9465           }
9466       } else {
9467           _startLazyDPSEvaluation ();
9468           while (size--) {
9469               if (AOP_INDPTRn(left)) {
9470                   genSetDPTR(AOP(left)->aopu.dptr);
9471               } else {
9472                   genSetDPTR (0);
9473               }
9474               _flushLazyDPS ();
9475               
9476               emitcode ("movx", "a,@dptr");
9477               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9478                   emitcode ("inc", "dptr");
9479               
9480               aopPut (AOP (result), "a", offset++);
9481           }
9482           _endLazyDPSEvaluation ();
9483       }
9484     }
9485   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9486       if (!AOP_INDPTRn(left)) {
9487           _startLazyDPSEvaluation ();
9488           aopPut ( AOP (left), "dpl", 0);
9489           aopPut ( AOP (left), "dph", 1);
9490           if (options.model == MODEL_FLAT24)
9491               aopPut ( AOP (left), "dpx", 2);
9492           _endLazyDPSEvaluation ();
9493       }
9494     pi->generated = 1;
9495   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9496              AOP_SIZE(result) > 1 &&
9497              IS_SYMOP(left) &&
9498              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9499       
9500       size = AOP_SIZE (result) - 1;
9501       if (AOP_INDPTRn(left)) {
9502           genSetDPTR(AOP(left)->aopu.dptr);
9503       }
9504       while (size--) emitcode ("lcall","__decdptr");
9505       if (AOP_INDPTRn(left)) {
9506           genSetDPTR(0);
9507       }
9508   }
9509
9510   freeAsmop (left, NULL, ic, TRUE);
9511   freeAsmop (result, NULL, ic, TRUE);
9512 }
9513
9514 /*-----------------------------------------------------------------*/
9515 /* genCodePointerGet - get value from code space                  */
9516 /*-----------------------------------------------------------------*/
9517 static void
9518 genCodePointerGet (operand * left,
9519                     operand * result, iCode * ic, iCode *pi)
9520 {
9521   int size, offset, dopi=1;
9522   sym_link *retype = getSpec (operandType (result));
9523
9524   aopOp (left, ic, FALSE, FALSE);
9525
9526   /* if the operand is already in dptr
9527      then we do nothing else we move the value to dptr */
9528   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9529     {
9530       /* if this is remateriazable */
9531       if (AOP_TYPE (left) == AOP_IMMD)
9532         {
9533           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9534         }
9535       else
9536         {                       /* we need to get it byte by byte */
9537           _startLazyDPSEvaluation ();
9538           if (AOP_TYPE (left) != AOP_DPTR)
9539             {
9540               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9541               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9542               if (options.model == MODEL_FLAT24)
9543                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9544             }
9545           else
9546             {
9547               /* We need to generate a load to DPTR indirect through DPTR. */
9548               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9549               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9550               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9551               if (options.model == MODEL_FLAT24)
9552                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9553               emitcode ("pop", "dph");
9554               emitcode ("pop", "dpl");
9555               dopi=0;
9556             }
9557           _endLazyDPSEvaluation ();
9558         }
9559     }
9560   /* so dptr know contains the address */
9561   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9562
9563   /* if bit then unpack */
9564   if (IS_BITVAR (retype)) {
9565       if (AOP_INDPTRn(left)) {
9566           genSetDPTR(AOP(left)->aopu.dptr);
9567       }
9568       genUnpackBits (result, "dptr", CPOINTER);
9569       if (AOP_INDPTRn(left)) {
9570           genSetDPTR(0);
9571       }
9572   } else
9573     {
9574       size = AOP_SIZE (result);
9575       offset = 0;
9576       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9577           while (size--) {
9578               genSetDPTR(AOP(left)->aopu.dptr);
9579               emitcode ("clr", "a");
9580               emitcode ("movc", "a,@a+dptr");
9581               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9582                   emitcode ("inc", "dptr");
9583               genSetDPTR (0);
9584               aopPut (AOP (result), "a", offset++);
9585           }
9586       } else {
9587           _startLazyDPSEvaluation ();
9588           while (size--)
9589               {
9590                   if (AOP_INDPTRn(left)) {
9591                       genSetDPTR(AOP(left)->aopu.dptr);
9592                   } else {
9593                       genSetDPTR (0);
9594                   }
9595                   _flushLazyDPS ();
9596                   
9597                   emitcode ("clr", "a");
9598                   emitcode ("movc", "a,@a+dptr");
9599                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9600                       emitcode ("inc", "dptr");
9601                   aopPut (AOP (result), "a", offset++);
9602               }
9603           _endLazyDPSEvaluation ();
9604       }
9605     }
9606   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9607       if (!AOP_INDPTRn(left)) {
9608           _startLazyDPSEvaluation ();
9609           
9610           aopPut ( AOP (left), "dpl", 0);
9611           aopPut ( AOP (left), "dph", 1);
9612           if (options.model == MODEL_FLAT24)
9613               aopPut ( AOP (left), "dpx", 2);
9614
9615           _endLazyDPSEvaluation ();
9616       }
9617       pi->generated = 1;
9618   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9619              AOP_SIZE(result) > 1 &&
9620              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9621       
9622       size = AOP_SIZE (result) - 1;
9623       if (AOP_INDPTRn(left)) {
9624           genSetDPTR(AOP(left)->aopu.dptr);
9625       }
9626       while (size--) emitcode ("lcall","__decdptr");
9627       if (AOP_INDPTRn(left)) {
9628           genSetDPTR(0);
9629       }
9630   }
9631   
9632   freeAsmop (left, NULL, ic, TRUE);
9633   freeAsmop (result, NULL, ic, TRUE);
9634 }
9635
9636 /*-----------------------------------------------------------------*/
9637 /* genGenPointerGet - gget value from generic pointer space        */
9638 /*-----------------------------------------------------------------*/
9639 static void
9640 genGenPointerGet (operand * left,
9641                   operand * result, iCode * ic, iCode * pi)
9642 {
9643   int size, offset;
9644   sym_link *retype = getSpec (operandType (result));
9645   sym_link *letype = getSpec (operandType (left));
9646
9647   D (emitcode (";", "genGenPointerGet "); );
9648
9649   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9650
9651   /* if the operand is already in dptr
9652      then we do nothing else we move the value to dptr */
9653   if (AOP_TYPE (left) != AOP_STR)
9654     {
9655       /* if this is remateriazable */
9656       if (AOP_TYPE (left) == AOP_IMMD)
9657         {
9658           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9659           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9660             {
9661                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9662             }
9663             else
9664             {
9665                 emitcode ("mov", "b,#%d", pointerCode (retype));
9666             }
9667         }
9668       else
9669         {                       /* we need to get it byte by byte */
9670             _startLazyDPSEvaluation ();
9671             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9672             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9673             if (options.model == MODEL_FLAT24) {
9674                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9675                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9676             } else {
9677                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9678             }
9679             _endLazyDPSEvaluation ();
9680         }
9681     }
9682
9683   /* so dptr-b now contains the address */
9684   _G.bInUse++;
9685   aopOp (result, ic, FALSE, TRUE);
9686   _G.bInUse--;
9687
9688   /* if bit then unpack */
9689   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9690   {
9691     genUnpackBits (result, "dptr", GPOINTER);
9692   }
9693   else
9694     {
9695         size = AOP_SIZE (result);
9696         offset = 0;
9697
9698         while (size--)
9699         {
9700             if (size)
9701             {
9702                 // Get two bytes at a time, results in _AP & A.
9703                 // dptr will be incremented ONCE by __gptrgetWord.
9704                 //
9705                 // Note: any change here must be coordinated
9706                 // with the implementation of __gptrgetWord
9707                 // in device/lib/_gptrget.c
9708                 emitcode ("lcall", "__gptrgetWord");
9709                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9710                 aopPut (AOP (result), "a", offset++);
9711                 size--;
9712             }
9713             else
9714             {
9715                 // Only one byte to get.
9716                 emitcode ("lcall", "__gptrget");
9717                 aopPut (AOP (result), "a", offset++);
9718             }
9719             
9720             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9721             {
9722                 emitcode ("inc", "dptr");
9723             }
9724         }
9725     }
9726
9727   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9728     _startLazyDPSEvaluation ();
9729       
9730     aopPut ( AOP (left), "dpl", 0);
9731     aopPut ( AOP (left), "dph", 1);
9732     if (options.model == MODEL_FLAT24) {
9733         aopPut ( AOP (left), "dpx", 2);
9734         aopPut ( AOP (left), "b", 3);   
9735     } else  aopPut ( AOP (left), "b", 2);       
9736     
9737     _endLazyDPSEvaluation ();
9738       
9739     pi->generated = 1;
9740   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9741              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9742       
9743       size = AOP_SIZE (result) - 1;
9744       while (size--) emitcode ("lcall","__decdptr");
9745   }
9746
9747   freeAsmop (left, NULL, ic, TRUE);
9748   freeAsmop (result, NULL, ic, TRUE);
9749 }
9750
9751 /*-----------------------------------------------------------------*/
9752 /* genPointerGet - generate code for pointer get                   */
9753 /*-----------------------------------------------------------------*/
9754 static void
9755 genPointerGet (iCode * ic, iCode *pi)
9756 {
9757   operand *left, *result;
9758   sym_link *type, *etype;
9759   int p_type;
9760
9761   D (emitcode (";", "genPointerGet ");
9762     );
9763
9764   left = IC_LEFT (ic);
9765   result = IC_RESULT (ic);
9766
9767   /* depending on the type of pointer we need to
9768      move it to the correct pointer register */
9769   type = operandType (left);
9770   etype = getSpec (type);
9771   /* if left is of type of pointer then it is simple */
9772   if (IS_PTR (type) && !IS_FUNC (type->next))
9773     p_type = DCL_TYPE (type);
9774   else
9775     {
9776       /* we have to go by the storage class */
9777       p_type = PTR_TYPE (SPEC_OCLS (etype));
9778     }
9779   /* special case when cast remat */
9780   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9781       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9782           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9783           type = operandType (left);
9784           p_type = DCL_TYPE (type);
9785   }
9786   /* now that we have the pointer type we assign
9787      the pointer values */
9788   switch (p_type)
9789     {
9790
9791     case POINTER:
9792     case IPOINTER:
9793       genNearPointerGet (left, result, ic, pi);
9794       break;
9795
9796     case PPOINTER:
9797       genPagedPointerGet (left, result, ic, pi);
9798       break;
9799
9800     case FPOINTER:
9801       genFarPointerGet (left, result, ic, pi);
9802       break;
9803
9804     case CPOINTER:
9805       genCodePointerGet (left, result, ic, pi);
9806       break;
9807
9808     case GPOINTER:
9809       genGenPointerGet (left, result, ic, pi);
9810       break;
9811     }
9812
9813 }
9814
9815 /*-----------------------------------------------------------------*/
9816 /* genPackBits - generates code for packed bit storage             */
9817 /*-----------------------------------------------------------------*/
9818 static void
9819 genPackBits (sym_link * etype,
9820              operand * right,
9821              char *rname, int p_type)
9822 {
9823   int offset = 0;       /* source byte offset */
9824   int rlen = 0;         /* remaining bitfield length */
9825   int blen;             /* bitfield length */
9826   int bstr;             /* bitfield starting bit within byte */
9827   int litval;           /* source literal value (if AOP_LIT) */
9828   unsigned char mask;   /* bitmask within current byte */
9829
9830   D(emitcode (";     genPackBits",""));
9831
9832   blen = SPEC_BLEN (etype);
9833   bstr = SPEC_BSTR (etype);
9834
9835   /* If the bitfield length is less than a byte */
9836   if (blen < 8)
9837     {
9838       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9839               (unsigned char) (0xFF >> (8 - bstr)));
9840
9841       if (AOP_TYPE (right) == AOP_LIT)
9842         {
9843           /* Case with a bitfield length <8 and literal source
9844           */
9845           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9846           litval <<= bstr;
9847           litval &= (~mask) & 0xff;
9848           emitPtrByteGet (rname, p_type, FALSE);
9849           if ((mask|litval)!=0xff)
9850             emitcode ("anl","a,#!constbyte", mask);
9851           if (litval)
9852             emitcode ("orl","a,#!constbyte", litval);
9853         }
9854       else
9855         {
9856           if ((blen==1) && (p_type!=GPOINTER))
9857             {
9858               /* Case with a bitfield length == 1 and no generic pointer
9859               */
9860               if (AOP_TYPE (right) == AOP_CRY)
9861                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9862               else
9863                 {
9864                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9865                   emitcode ("rrc","a");
9866                 }
9867               emitPtrByteGet (rname, p_type, FALSE);
9868               emitcode ("mov","acc.%d,c",bstr);
9869             }
9870           else
9871             {
9872               /* Case with a bitfield length < 8 and arbitrary source
9873               */
9874               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9875               /* shift and mask source value */
9876               AccLsh (bstr);
9877               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9878
9879               /* transfer A to B and get next byte */
9880               emitPtrByteGet (rname, p_type, TRUE);
9881
9882               emitcode ("anl", "a,#!constbyte", mask);
9883               emitcode ("orl", "a,b");
9884               if (p_type == GPOINTER)
9885                 emitcode ("pop", "b");
9886            }
9887         }
9888
9889       emitPtrByteSet (rname, p_type, "a");
9890       return;
9891     }
9892
9893   /* Bit length is greater than 7 bits. In this case, copy  */
9894   /* all except the partial byte at the end                 */
9895   for (rlen=blen;rlen>=8;rlen-=8)
9896     {
9897       emitPtrByteSet (rname, p_type, 
9898                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9899       if (rlen>8)
9900         emitcode ("inc", "%s", rname);
9901     }
9902
9903   /* If there was a partial byte at the end */
9904   if (rlen)
9905     {
9906       mask = (((unsigned char) -1 << rlen) & 0xff);
9907       
9908       if (AOP_TYPE (right) == AOP_LIT)
9909         {
9910           /* Case with partial byte and literal source
9911           */
9912           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9913           litval >>= (blen-rlen);
9914           litval &= (~mask) & 0xff;
9915           emitPtrByteGet (rname, p_type, FALSE);
9916           if ((mask|litval)!=0xff)
9917             emitcode ("anl","a,#!constbyte", mask);
9918           if (litval)
9919             emitcode ("orl","a,#!constbyte", litval);
9920         }
9921       else
9922         {
9923           /* Case with partial byte and arbitrary source
9924           */
9925           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9926           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9927
9928           /* transfer A to B and get next byte */
9929           emitPtrByteGet (rname, p_type, TRUE);
9930
9931           emitcode ("anl", "a,#!constbyte", mask);
9932           emitcode ("orl", "a,b");
9933           if (p_type == GPOINTER)
9934             emitcode ("pop", "b");
9935         }
9936       emitPtrByteSet (rname, p_type, "a");
9937     }
9938
9939 }
9940
9941
9942 /*-----------------------------------------------------------------*/
9943 /* genDataPointerSet - remat pointer to data space                 */
9944 /*-----------------------------------------------------------------*/
9945 static void
9946 genDataPointerSet (operand * right,
9947                    operand * result,
9948                    iCode * ic)
9949 {
9950   int size, offset = 0;
9951   char *l, buff[256];
9952
9953   aopOp (right, ic, FALSE, FALSE);
9954
9955   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9956   size = AOP_SIZE (right);
9957   while (size--)
9958     {
9959       if (offset)
9960         {
9961             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9962         }
9963       else
9964         {
9965             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9966         }
9967         
9968       emitcode ("mov", "%s,%s", buff,
9969                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9970     }
9971
9972   freeAsmop (right, NULL, ic, TRUE);
9973   freeAsmop (result, NULL, ic, TRUE);
9974 }
9975
9976 /*-----------------------------------------------------------------*/
9977 /* genNearPointerSet - emitcode for near pointer put                */
9978 /*-----------------------------------------------------------------*/
9979 static void
9980 genNearPointerSet (operand * right,
9981                    operand * result,
9982                    iCode * ic,
9983                    iCode * pi)
9984 {
9985   asmop *aop = NULL;
9986   char *rname, *l;
9987   sym_link *retype, *letype;
9988   sym_link *ptype = operandType (result);
9989
9990   retype = getSpec (operandType (right));
9991   letype = getSpec (ptype);
9992
9993   aopOp (result, ic, FALSE, FALSE);
9994
9995   /* if the result is rematerializable &
9996      in data space & not a bit variable */
9997   if (AOP_TYPE (result) == AOP_IMMD &&
9998       DCL_TYPE (ptype) == POINTER &&
9999       !IS_BITVAR (retype) &&
10000       !IS_BITVAR (letype))
10001     {
10002       genDataPointerSet (right, result, ic);
10003       return;
10004     }
10005
10006   /* if the value is already in a pointer register
10007      then don't need anything more */
10008   if (!AOP_INPREG (AOP (result)))
10009     {
10010       /* otherwise get a free pointer register */
10011       regs *preg;
10012         
10013       aop = newAsmop (0);
10014       preg = getFreePtr (ic, &aop, FALSE);
10015       emitcode ("mov", "%s,%s",
10016                 preg->name,
10017                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10018       rname = preg->name;
10019     }
10020   else
10021     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10022
10023   aopOp (right, ic, FALSE, FALSE);
10024
10025   /* if bitfield then unpack the bits */
10026   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10027     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10028   else
10029     {
10030       /* we have can just get the values */
10031       int size = AOP_SIZE (right);
10032       int offset = 0;
10033
10034       while (size--)
10035         {
10036           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10037           if (*l == '@')
10038             {
10039               MOVA (l);
10040               emitcode ("mov", "@%s,a", rname);
10041             }
10042           else
10043             emitcode ("mov", "@%s,%s", rname, l);
10044           if (size || pi)
10045             emitcode ("inc", "%s", rname);
10046           offset++;
10047         }
10048     }
10049
10050   /* now some housekeeping stuff */
10051   if (aop)
10052     {
10053       /* we had to allocate for this iCode */
10054       if (pi) aopPut (AOP (result),rname,0);
10055       freeAsmop (NULL, aop, ic, TRUE);
10056     }
10057   else
10058     {
10059       /* we did not allocate which means left
10060          already in a pointer register, then
10061          if size > 0 && this could be used again
10062          we have to point it back to where it
10063          belongs */
10064       if (AOP_SIZE (right) > 1 &&
10065           !OP_SYMBOL (result)->remat &&
10066           (OP_SYMBOL (result)->liveTo > ic->seq ||
10067            ic->depth) &&
10068           !pi)
10069         {
10070           int size = AOP_SIZE (right) - 1;
10071           while (size--)
10072             emitcode ("dec", "%s", rname);
10073         }
10074     }
10075
10076   /* done */
10077   if (pi) pi->generated = 1;
10078   freeAsmop (result, NULL, ic, TRUE);
10079   freeAsmop (right, NULL, ic, TRUE);
10080
10081
10082 }
10083
10084 /*-----------------------------------------------------------------*/
10085 /* genPagedPointerSet - emitcode for Paged pointer put             */
10086 /*-----------------------------------------------------------------*/
10087 static void
10088 genPagedPointerSet (operand * right,
10089                     operand * result,
10090                     iCode * ic,
10091                     iCode *pi)
10092 {
10093   asmop *aop = NULL;
10094   char *rname;
10095   sym_link *retype, *letype;
10096
10097   retype = getSpec (operandType (right));
10098   letype = getSpec (operandType (result));
10099
10100   aopOp (result, ic, FALSE, FALSE);
10101
10102   /* if the value is already in a pointer register
10103      then don't need anything more */
10104   if (!AOP_INPREG (AOP (result)))
10105     {
10106       /* otherwise get a free pointer register */
10107       regs *preg;
10108         
10109       aop = newAsmop (0);
10110       preg = getFreePtr (ic, &aop, FALSE);
10111       emitcode ("mov", "%s,%s",
10112                 preg->name,
10113                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10114       rname = preg->name;
10115     }
10116   else
10117     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10118
10119   aopOp (right, ic, FALSE, FALSE);
10120
10121   /* if bitfield then unpack the bits */
10122   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10123     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10124   else
10125     {
10126       /* we have can just get the values */
10127       int size = AOP_SIZE (right);
10128       int offset = 0;
10129
10130       while (size--)
10131         {
10132           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10133
10134           emitcode ("movx", "@%s,a", rname);
10135
10136           if (size || pi)
10137             emitcode ("inc", "%s", rname);
10138
10139           offset++;
10140         }
10141     }
10142
10143   /* now some housekeeping stuff */
10144   if (aop)
10145     {
10146       if (pi) aopPut (AOP (result),rname,0);
10147       /* we had to allocate for this iCode */
10148       freeAsmop (NULL, aop, ic, TRUE);
10149     }
10150   else
10151     {
10152       /* we did not allocate which means left
10153          already in a pointer register, then
10154          if size > 0 && this could be used again
10155          we have to point it back to where it
10156          belongs */
10157       if (AOP_SIZE (right) > 1 &&
10158           !OP_SYMBOL (result)->remat &&
10159           (OP_SYMBOL (result)->liveTo > ic->seq ||
10160            ic->depth) &&
10161           !pi)
10162         {
10163           int size = AOP_SIZE (right) - 1;
10164           while (size--)
10165             emitcode ("dec", "%s", rname);
10166         }
10167     }
10168
10169   /* done */
10170   if (pi) pi->generated = 1;
10171   freeAsmop (result, NULL, ic, TRUE);
10172   freeAsmop (right, NULL, ic, TRUE);
10173
10174
10175 }
10176
10177 /*-----------------------------------------------------------------*/
10178 /* genFarPointerSet - set value from far space                     */
10179 /*-----------------------------------------------------------------*/
10180 static void
10181 genFarPointerSet (operand * right,
10182                   operand * result, iCode * ic, iCode *pi)
10183 {
10184   int size, offset, dopi=1;
10185   sym_link *retype = getSpec (operandType (right));
10186   sym_link *letype = getSpec (operandType (result));
10187
10188   aopOp (result, ic, FALSE, FALSE);
10189
10190   /* if the operand is already in dptr
10191      then we do nothing else we move the value to dptr */
10192   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10193     {
10194       /* if this is remateriazable */
10195       if (AOP_TYPE (result) == AOP_IMMD)
10196         emitcode ("mov", "dptr,%s", 
10197                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10198       else
10199         {
10200           /* we need to get it byte by byte */
10201           _startLazyDPSEvaluation ();
10202           if (AOP_TYPE (result) != AOP_DPTR)
10203             {
10204               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10205               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10206               if (options.model == MODEL_FLAT24)
10207                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10208             }
10209           else
10210             {
10211               /* We need to generate a load to DPTR indirect through DPTR. */
10212               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10213                 
10214               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10215               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10216               if (options.model == MODEL_FLAT24)
10217                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10218               emitcode ("pop", "dph");
10219               emitcode ("pop", "dpl");
10220               dopi=0;
10221             }
10222           _endLazyDPSEvaluation ();
10223         }
10224     }
10225   /* so dptr know contains the address */
10226   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10227
10228   /* if bit then unpack */
10229   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10230       if (AOP_INDPTRn(result)) {
10231           genSetDPTR(AOP(result)->aopu.dptr);
10232       }
10233       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10234       if (AOP_INDPTRn(result)) {
10235           genSetDPTR(0);
10236       }
10237   } else {
10238       size = AOP_SIZE (right);
10239       offset = 0;
10240       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10241           while (size--) {
10242               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10243               
10244               genSetDPTR(AOP(result)->aopu.dptr);
10245               emitcode ("movx", "@dptr,a");
10246               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10247                   emitcode ("inc", "dptr");
10248               genSetDPTR (0);
10249           }
10250       } else {
10251           _startLazyDPSEvaluation ();
10252           while (size--) {
10253               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10254               
10255               if (AOP_INDPTRn(result)) {
10256                   genSetDPTR(AOP(result)->aopu.dptr);
10257               } else {
10258                   genSetDPTR (0);
10259               }
10260               _flushLazyDPS ();
10261               
10262               emitcode ("movx", "@dptr,a");
10263               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10264                   emitcode ("inc", "dptr");
10265           }
10266           _endLazyDPSEvaluation ();
10267       }
10268   }
10269   
10270   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10271       if (!AOP_INDPTRn(result)) {
10272           _startLazyDPSEvaluation ();
10273           
10274           aopPut (AOP(result),"dpl",0);
10275           aopPut (AOP(result),"dph",1);
10276           if (options.model == MODEL_FLAT24)
10277               aopPut (AOP(result),"dpx",2);
10278
10279           _endLazyDPSEvaluation ();
10280       }
10281       pi->generated=1;
10282   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10283              AOP_SIZE(right) > 1 &&
10284              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10285       
10286       size = AOP_SIZE (right) - 1;
10287       if (AOP_INDPTRn(result)) {
10288           genSetDPTR(AOP(result)->aopu.dptr);
10289       } 
10290       while (size--) emitcode ("lcall","__decdptr");
10291       if (AOP_INDPTRn(result)) {
10292           genSetDPTR(0);
10293       }
10294   }
10295   freeAsmop (result, NULL, ic, TRUE);
10296   freeAsmop (right, NULL, ic, TRUE);
10297 }
10298
10299 /*-----------------------------------------------------------------*/
10300 /* genGenPointerSet - set value from generic pointer space         */
10301 /*-----------------------------------------------------------------*/
10302 static void
10303 genGenPointerSet (operand * right,
10304                   operand * result, iCode * ic, iCode *pi)
10305 {
10306   int size, offset;
10307   sym_link *retype = getSpec (operandType (right));
10308   sym_link *letype = getSpec (operandType (result));
10309
10310   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10311
10312   /* if the operand is already in dptr
10313      then we do nothing else we move the value to dptr */
10314   if (AOP_TYPE (result) != AOP_STR)
10315     {
10316       _startLazyDPSEvaluation ();
10317       /* if this is remateriazable */
10318       if (AOP_TYPE (result) == AOP_IMMD)
10319         {
10320           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10321           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10322           {
10323               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10324           }
10325           else
10326           {
10327               emitcode ("mov", 
10328                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10329           }
10330         }
10331       else
10332         {                       /* we need to get it byte by byte */
10333           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10334           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10335           if (options.model == MODEL_FLAT24) {
10336             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10337             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10338           } else {
10339             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10340           }
10341         }
10342       _endLazyDPSEvaluation ();
10343     }
10344   /* so dptr + b now contains the address */
10345   _G.bInUse++;
10346   aopOp (right, ic, FALSE, TRUE);
10347   _G.bInUse--;
10348     
10349
10350   /* if bit then unpack */
10351   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10352     {
10353         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10354     }
10355   else
10356     {
10357         size = AOP_SIZE (right);
10358         offset = 0;
10359
10360         _startLazyDPSEvaluation ();
10361         while (size--)
10362         {
10363             if (size)
10364             {
10365                 // Set two bytes at a time, passed in _AP & A.
10366                 // dptr will be incremented ONCE by __gptrputWord.
10367                 //
10368                 // Note: any change here must be coordinated
10369                 // with the implementation of __gptrputWord
10370                 // in device/lib/_gptrput.c
10371                 emitcode("mov", "_ap, %s", 
10372                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10373                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10374                 
10375                 genSetDPTR (0);
10376                 _flushLazyDPS ();
10377                 emitcode ("lcall", "__gptrputWord");
10378                 size--;
10379             }
10380             else
10381             {
10382                 // Only one byte to put.
10383                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10384
10385                 genSetDPTR (0);
10386                 _flushLazyDPS ();               
10387                 emitcode ("lcall", "__gptrput");
10388             }
10389             
10390             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10391             {
10392                 emitcode ("inc", "dptr");
10393             }
10394         }
10395         _endLazyDPSEvaluation ();
10396     }
10397
10398   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10399       _startLazyDPSEvaluation ();
10400       
10401       aopPut (AOP(result),"dpl",0);
10402       aopPut (AOP(result),"dph",1);
10403       if (options.model == MODEL_FLAT24) {
10404           aopPut (AOP(result),"dpx",2);
10405           aopPut (AOP(result),"b",3);
10406       } else {
10407           aopPut (AOP(result),"b",2);
10408       }
10409       _endLazyDPSEvaluation ();
10410       
10411       pi->generated=1;
10412   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10413              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10414       
10415       size = AOP_SIZE (right) - 1;
10416       while (size--) emitcode ("lcall","__decdptr");
10417   }
10418   freeAsmop (result, NULL, ic, TRUE);
10419   freeAsmop (right, NULL, ic, TRUE);
10420 }
10421
10422 /*-----------------------------------------------------------------*/
10423 /* genPointerSet - stores the value into a pointer location        */
10424 /*-----------------------------------------------------------------*/
10425 static void
10426 genPointerSet (iCode * ic, iCode *pi)
10427 {
10428   operand *right, *result;
10429   sym_link *type, *etype;
10430   int p_type;
10431
10432   D (emitcode (";", "genPointerSet "););
10433
10434   right = IC_RIGHT (ic);
10435   result = IC_RESULT (ic);
10436
10437   /* depending on the type of pointer we need to
10438      move it to the correct pointer register */
10439   type = operandType (result);
10440   etype = getSpec (type);
10441   /* if left is of type of pointer then it is simple */
10442   if (IS_PTR (type) && !IS_FUNC (type->next))
10443     {
10444       p_type = DCL_TYPE (type);
10445     }
10446   else
10447     {
10448       /* we have to go by the storage class */
10449       p_type = PTR_TYPE (SPEC_OCLS (etype));
10450     }
10451   /* special case when cast remat */
10452   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10453       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10454           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10455           type = operandType (result);
10456           p_type = DCL_TYPE (type);
10457   }
10458
10459   /* now that we have the pointer type we assign
10460      the pointer values */
10461   switch (p_type)
10462     {
10463
10464     case POINTER:
10465     case IPOINTER:
10466       genNearPointerSet (right, result, ic, pi);
10467       break;
10468
10469     case PPOINTER:
10470       genPagedPointerSet (right, result, ic, pi);
10471       break;
10472
10473     case FPOINTER:
10474       genFarPointerSet (right, result, ic, pi);
10475       break;
10476
10477     case GPOINTER:
10478       genGenPointerSet (right, result, ic, pi);
10479       break;
10480
10481     default:
10482       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10483               "genPointerSet: illegal pointer type");
10484     }
10485
10486 }
10487
10488 /*-----------------------------------------------------------------*/
10489 /* genIfx - generate code for Ifx statement                        */
10490 /*-----------------------------------------------------------------*/
10491 static void
10492 genIfx (iCode * ic, iCode * popIc)
10493 {
10494   operand *cond = IC_COND (ic);
10495   int isbit = 0;
10496
10497   D (emitcode (";", "genIfx "););
10498
10499   aopOp (cond, ic, FALSE, FALSE);
10500
10501   /* get the value into acc */
10502   if (AOP_TYPE (cond) != AOP_CRY)
10503     {
10504         toBoolean (cond);
10505     }
10506   else
10507     {
10508         isbit = 1;
10509     }
10510     
10511   /* the result is now in the accumulator */
10512   freeAsmop (cond, NULL, ic, TRUE);
10513
10514   /* if there was something to be popped then do it */
10515   if (popIc)
10516     genIpop (popIc);
10517
10518   /* if the condition is  a bit variable */
10519   if (isbit && IS_ITEMP (cond) &&
10520       SPIL_LOC (cond))
10521     {
10522         genIfxJump (ic, SPIL_LOC (cond)->rname);
10523     }
10524   else if (isbit && !IS_ITEMP (cond))
10525     {
10526         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10527     }
10528   else
10529     {
10530         genIfxJump (ic, "a");
10531     }
10532
10533   ic->generated = 1;
10534 }
10535
10536 /*-----------------------------------------------------------------*/
10537 /* genAddrOf - generates code for address of                       */
10538 /*-----------------------------------------------------------------*/
10539 static void
10540 genAddrOf (iCode * ic)
10541 {
10542   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10543   int size, offset;
10544
10545   D (emitcode (";", "genAddrOf ");
10546     );
10547
10548   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10549
10550   /* if the operand is on the stack then we
10551      need to get the stack offset of this
10552      variable */
10553   if (sym->onStack) {
10554       
10555       /* if 10 bit stack */
10556       if (options.stack10bit) {
10557           char buff[10];
10558           int  offset;
10559           
10560           tsprintf(buff, sizeof(buff), 
10561                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10562           /* if it has an offset then we need to compute it */
10563 /*        emitcode ("subb", "a,#!constbyte", */
10564 /*                  -((sym->stack < 0) ? */
10565 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10566 /*                    ((short) sym->stack)) & 0xff); */
10567 /*        emitcode ("mov","b,a"); */
10568 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10569 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10570 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10571           if (sym->stack) {
10572               emitcode ("mov", "a,_bpx");
10573               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10574                                              ((char) (sym->stack - _G.nRegsSaved)) :
10575                                              ((char) sym->stack )) & 0xff);
10576               emitcode ("mov", "b,a");
10577               emitcode ("mov", "a,_bpx+1");
10578               
10579               offset = (((sym->stack < 0) ? 
10580                          ((short) (sym->stack - _G.nRegsSaved)) :
10581                          ((short) sym->stack )) >> 8) & 0xff;
10582           
10583               emitcode ("addc","a,#!constbyte", offset);
10584
10585               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10586               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10587               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10588           } else {
10589               /* we can just move _bp */
10590               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10591               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10592               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10593           }       
10594       } else {
10595           /* if it has an offset then we need to compute it */
10596           if (sym->stack) {
10597               emitcode ("mov", "a,_bp");
10598               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10599               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10600           } else {
10601               /* we can just move _bp */
10602               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10603           }
10604           /* fill the result with zero */
10605           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10606           
10607           
10608           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10609               fprintf (stderr,
10610                        "*** warning: pointer to stack var truncated.\n");
10611           }
10612
10613           offset = 1;
10614           while (size--) {
10615               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10616           }      
10617       }
10618       goto release;
10619   }
10620
10621   /* object not on stack then we need the name */
10622   size = AOP_SIZE (IC_RESULT (ic));
10623   offset = 0;
10624
10625   while (size--)
10626     {
10627       char s[SDCC_NAME_MAX];
10628       if (offset) {
10629           switch (offset) {
10630           case 1:
10631               tsprintf(s, sizeof(s), "#!his",sym->rname);
10632               break;
10633           case 2:
10634               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10635               break;
10636           case 3:
10637               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10638               break;
10639           default: /* should not need this (just in case) */
10640               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10641                        sym->rname,
10642                        offset * 8);
10643           }
10644       } 
10645       else
10646       {
10647           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10648       }
10649         
10650       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10651     }
10652
10653 release:
10654   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10655
10656 }
10657
10658 #if 0 // obsolete, and buggy for != xdata
10659 /*-----------------------------------------------------------------*/
10660 /* genArrayInit - generates code for address of                       */
10661 /*-----------------------------------------------------------------*/
10662 static void
10663 genArrayInit (iCode * ic)
10664 {
10665     literalList *iLoop;
10666     int         ix, count;
10667     int         elementSize = 0, eIndex;
10668     unsigned    val, lastVal;
10669     sym_link    *type;
10670     operand     *left=IC_LEFT(ic);
10671     
10672     D (emitcode (";", "genArrayInit "););
10673
10674     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10675     
10676     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10677     {
10678         // Load immediate value into DPTR.
10679         emitcode("mov", "dptr, %s",
10680              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10681     }
10682     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10683     {
10684 #if 0
10685       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10686               "Unexpected operand to genArrayInit.\n");
10687       exit(1);
10688 #else
10689       // a regression because of SDCCcse.c:1.52
10690       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10691       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10692       if (options.model == MODEL_FLAT24)
10693         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10694 #endif
10695     }
10696     
10697     type = operandType(IC_LEFT(ic));
10698     
10699     if (type && type->next)
10700     {
10701         elementSize = getSize(type->next);
10702     }
10703     else
10704     {
10705         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10706                                 "can't determine element size in genArrayInit.\n");
10707         exit(1);
10708     }
10709     
10710     iLoop = IC_ARRAYILIST(ic);
10711     lastVal = 0xffff;
10712     
10713     while (iLoop)
10714     {
10715         bool firstpass = TRUE;
10716         
10717         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10718                  iLoop->count, (int)iLoop->literalValue, elementSize);
10719         
10720         ix = iLoop->count;
10721         
10722         while (ix)
10723         {
10724             symbol *tlbl = NULL;
10725             
10726             count = ix > 256 ? 256 : ix;
10727             
10728             if (count > 1)
10729             {
10730                 tlbl = newiTempLabel (NULL);
10731                 if (firstpass || (count & 0xff))
10732                 {
10733                     emitcode("mov", "b, #!constbyte", count & 0xff);
10734                 }
10735                 
10736                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10737             }
10738             
10739             firstpass = FALSE;
10740                 
10741             for (eIndex = 0; eIndex < elementSize; eIndex++)
10742             {
10743                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10744                 if (val != lastVal)
10745                 {
10746                     emitcode("mov", "a, #!constbyte", val);
10747                     lastVal = val;
10748                 }
10749                 
10750                 emitcode("movx", "@dptr, a");
10751                 emitcode("inc", "dptr");
10752             }
10753             
10754             if (count > 1)
10755             {
10756                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10757             }
10758             
10759             ix -= count;
10760         }
10761         
10762         iLoop = iLoop->next;
10763     }
10764     
10765     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10766 }
10767 #endif
10768
10769 /*-----------------------------------------------------------------*/
10770 /* genFarFarAssign - assignment when both are in far space         */
10771 /*-----------------------------------------------------------------*/
10772 static void
10773 genFarFarAssign (operand * result, operand * right, iCode * ic)
10774 {
10775   int size = AOP_SIZE (right);
10776   int offset = 0;
10777   symbol *rSym = NULL;
10778
10779   if (size == 1)
10780   {
10781       /* quick & easy case. */
10782       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10783       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10784       freeAsmop (right, NULL, ic, FALSE);
10785       /* now assign DPTR to result */
10786       _G.accInUse++;
10787       aopOp(result, ic, FALSE, FALSE);
10788       _G.accInUse--;
10789       aopPut(AOP(result), "a", 0);
10790       freeAsmop(result, NULL, ic, FALSE);
10791       return;
10792   }
10793   
10794   /* See if we've got an underlying symbol to abuse. */
10795   if (IS_SYMOP(result) && OP_SYMBOL(result))
10796   {
10797       if (IS_TRUE_SYMOP(result))
10798       {
10799           rSym = OP_SYMBOL(result);
10800       }
10801       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10802       {
10803           rSym = OP_SYMBOL(result)->usl.spillLoc;
10804       }
10805   }
10806              
10807   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10808   {
10809       /* We can use the '390 auto-toggle feature to good effect here. */
10810       
10811       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10812       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10813       emitcode ("mov", "dptr,#%s", rSym->rname); 
10814       /* DP2 = result, DP1 = right, DP1 is current. */
10815       while (size)
10816       {
10817           emitcode("movx", "a,@dptr");
10818           emitcode("movx", "@dptr,a");
10819           if (--size)
10820           {
10821                emitcode("inc", "dptr");
10822                emitcode("inc", "dptr");
10823           }
10824       }
10825       emitcode("mov", "dps,#0");
10826       freeAsmop (right, NULL, ic, FALSE);
10827 #if 0
10828 some alternative code for processors without auto-toggle
10829 no time to test now, so later well put in...kpb
10830         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10831         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10832         emitcode ("mov", "dptr,#%s", rSym->rname); 
10833         /* DP2 = result, DP1 = right, DP1 is current. */
10834         while (size)
10835         {
10836           --size;
10837           emitcode("movx", "a,@dptr");
10838           if (size)
10839             emitcode("inc", "dptr");
10840           emitcode("inc", "dps");
10841           emitcode("movx", "@dptr,a");
10842           if (size)
10843             emitcode("inc", "dptr");
10844           emitcode("inc", "dps");
10845         }
10846         emitcode("mov", "dps,#0");
10847         freeAsmop (right, NULL, ic, FALSE);
10848 #endif
10849   }
10850   else
10851   {
10852       D (emitcode (";", "genFarFarAssign"););
10853       aopOp (result, ic, TRUE, TRUE);
10854
10855       _startLazyDPSEvaluation ();
10856       
10857       while (size--)
10858         {
10859           aopPut (AOP (result),
10860                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10861           offset++;
10862         }
10863       _endLazyDPSEvaluation ();
10864       freeAsmop (result, NULL, ic, FALSE);
10865       freeAsmop (right, NULL, ic, FALSE);
10866   }
10867 }
10868
10869 /*-----------------------------------------------------------------*/
10870 /* genAssign - generate code for assignment                        */
10871 /*-----------------------------------------------------------------*/
10872 static void
10873 genAssign (iCode * ic)
10874 {
10875   operand *result, *right;
10876   int size, offset;
10877   unsigned long lit = 0L;
10878
10879   D (emitcode (";", "genAssign ");
10880     );
10881
10882   result = IC_RESULT (ic);
10883   right = IC_RIGHT (ic);
10884
10885   /* if they are the same */
10886   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10887     return;
10888
10889   aopOp (right, ic, FALSE, FALSE);
10890
10891   emitcode (";", "genAssign: resultIsFar = %s",
10892             isOperandInFarSpace (result) ?
10893             "TRUE" : "FALSE");
10894
10895   /* special case both in far space */
10896   if ((AOP_TYPE (right) == AOP_DPTR ||
10897        AOP_TYPE (right) == AOP_DPTR2) &&
10898   /* IS_TRUE_SYMOP(result)       && */
10899       isOperandInFarSpace (result))
10900     {
10901       genFarFarAssign (result, right, ic);
10902       return;
10903     }
10904
10905   aopOp (result, ic, TRUE, FALSE);
10906
10907   /* if they are the same registers */
10908   if (sameRegs (AOP (right), AOP (result)))
10909     goto release;
10910
10911   /* if the result is a bit */
10912   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10913     {
10914       /* if the right size is a literal then
10915          we know what the value is */
10916       if (AOP_TYPE (right) == AOP_LIT)
10917         {
10918           if (((int) operandLitValue (right)))
10919             aopPut (AOP (result), one, 0);
10920           else
10921             aopPut (AOP (result), zero, 0);
10922           goto release;
10923         }
10924
10925       /* the right is also a bit variable */
10926       if (AOP_TYPE (right) == AOP_CRY)
10927         {
10928           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10929           aopPut (AOP (result), "c", 0);
10930           goto release;
10931         }
10932
10933       /* we need to or */
10934       toBoolean (right);
10935       aopPut (AOP (result), "a", 0);
10936       goto release;
10937     }
10938
10939   /* bit variables done */
10940   /* general case */
10941   size = AOP_SIZE (result);
10942   offset = 0;
10943   if (AOP_TYPE (right) == AOP_LIT)
10944     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10945
10946   if ((size > 1) &&
10947       (AOP_TYPE (result) != AOP_REG) &&
10948       (AOP_TYPE (right) == AOP_LIT) &&
10949       !IS_FLOAT (operandType (right)))
10950     {
10951       _startLazyDPSEvaluation ();
10952       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10953         {
10954           aopPut (AOP (result),
10955                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10956                   offset);
10957           offset++;
10958           size--;
10959         }
10960       /* And now fill the rest with zeros. */
10961       if (size)
10962         {
10963           emitcode ("clr", "a");
10964         }
10965       while (size--)
10966         {
10967           aopPut (AOP (result), "a", offset++);
10968         }
10969       _endLazyDPSEvaluation ();
10970     }
10971   else
10972     {
10973       _startLazyDPSEvaluation ();
10974       while (size--)
10975         {
10976           aopPut (AOP (result),
10977                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10978                   offset);
10979           offset++;
10980         }
10981       _endLazyDPSEvaluation ();
10982     }
10983
10984 release:
10985   freeAsmop (right, NULL, ic, FALSE);
10986   freeAsmop (result, NULL, ic, TRUE);
10987 }
10988
10989 /*-----------------------------------------------------------------*/
10990 /* genJumpTab - generates code for jump table                      */
10991 /*-----------------------------------------------------------------*/
10992 static void
10993 genJumpTab (iCode * ic)
10994 {
10995   symbol *jtab;
10996   char *l;
10997
10998   D (emitcode (";", "genJumpTab ");
10999     );
11000
11001   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11002   /* get the condition into accumulator */
11003   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11004   MOVA (l);
11005   /* multiply by four! */
11006   emitcode ("add", "a,acc");
11007   emitcode ("add", "a,acc");
11008   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11009
11010   jtab = newiTempLabel (NULL);
11011   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11012   emitcode ("jmp", "@a+dptr");
11013   emitcode ("", "!tlabeldef", jtab->key + 100);
11014   /* now generate the jump labels */
11015   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11016        jtab = setNextItem (IC_JTLABELS (ic)))
11017     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11018
11019 }
11020
11021 /*-----------------------------------------------------------------*/
11022 /* genCast - gen code for casting                                  */
11023 /*-----------------------------------------------------------------*/
11024 static void
11025 genCast (iCode * ic)
11026 {
11027   operand *result = IC_RESULT (ic);
11028   sym_link *ctype = operandType (IC_LEFT (ic));
11029   sym_link *rtype = operandType (IC_RIGHT (ic));
11030   operand *right = IC_RIGHT (ic);
11031   int size, offset;
11032
11033   D (emitcode (";", "genCast "););
11034
11035   /* if they are equivalent then do nothing */
11036   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11037     return;
11038
11039   aopOp (right, ic, FALSE, FALSE);
11040   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11041
11042   /* if the result is a bit */
11043   if (IS_BITVAR (OP_SYMBOL (result)->type)
11044       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11045     {
11046       /* if the right size is a literal then
11047          we know what the value is */
11048       if (AOP_TYPE (right) == AOP_LIT)
11049         {
11050           if (((int) operandLitValue (right)))
11051             aopPut (AOP (result), one, 0);
11052           else
11053             aopPut (AOP (result), zero, 0);
11054
11055           goto release;
11056         }
11057
11058       /* the right is also a bit variable */
11059       if (AOP_TYPE (right) == AOP_CRY)
11060         {
11061           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11062           aopPut (AOP (result), "c", 0);
11063           goto release;
11064         }
11065
11066       /* we need to or */
11067       toBoolean (right);
11068       aopPut (AOP (result), "a", 0);
11069       goto release;
11070     }
11071
11072   /* if they are the same size : or less */
11073   if (AOP_SIZE (result) <= AOP_SIZE (right))
11074     {
11075
11076       /* if they are in the same place */
11077       if (sameRegs (AOP (right), AOP (result)))
11078         goto release;
11079
11080       /* if they in different places then copy */
11081       size = AOP_SIZE (result);
11082       offset = 0;
11083       _startLazyDPSEvaluation ();
11084       while (size--)
11085         {
11086           aopPut (AOP (result),
11087                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11088                   offset);
11089           offset++;
11090         }
11091       _endLazyDPSEvaluation ();
11092       goto release;
11093     }
11094
11095
11096   /* if the result is of type pointer */
11097   if (IS_PTR (ctype))
11098     {
11099
11100       int p_type;
11101       sym_link *type = operandType (right);
11102
11103       /* pointer to generic pointer */
11104       if (IS_GENPTR (ctype))
11105         {
11106           if (IS_PTR (type))
11107             {
11108               p_type = DCL_TYPE (type);
11109             }
11110           else
11111             {
11112 #if OLD_CAST_BEHAVIOR
11113               /* KV: we are converting a non-pointer type to
11114                * a generic pointer. This (ifdef'd out) code
11115                * says that the resulting generic pointer
11116                * should have the same class as the storage
11117                * location of the non-pointer variable.
11118                *
11119                * For example, converting an int (which happens
11120                * to be stored in DATA space) to a pointer results
11121                * in a DATA generic pointer; if the original int
11122                * in XDATA space, so will be the resulting pointer.
11123                *
11124                * I don't like that behavior, and thus this change:
11125                * all such conversions will be forced to XDATA and
11126                * throw a warning. If you want some non-XDATA
11127                * type, or you want to suppress the warning, you
11128                * must go through an intermediate cast, like so:
11129                *
11130                * char _generic *gp = (char _xdata *)(intVar);
11131                */
11132               sym_link *etype = getSpec (type);
11133
11134               /* we have to go by the storage class */
11135               if (SPEC_OCLS (etype) != generic)
11136                 {
11137                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11138                 }
11139               else
11140 #endif
11141                 {
11142                   /* Converting unknown class (i.e. register variable)
11143                    * to generic pointer. This is not good, but
11144                    * we'll make a guess (and throw a warning).
11145                    */
11146                   p_type = FPOINTER;
11147                   werror (W_INT_TO_GEN_PTR_CAST);
11148                 }
11149             }
11150
11151           /* the first two bytes are known */
11152           size = GPTRSIZE - 1;
11153           offset = 0;
11154           _startLazyDPSEvaluation ();
11155           while (size--)
11156             {
11157               aopPut (AOP (result),
11158                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11159                       offset);
11160               offset++;
11161             }
11162           _endLazyDPSEvaluation ();
11163
11164           /* the last byte depending on type */
11165             {
11166                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11167                 char gpValStr[10];
11168             
11169                 if (gpVal == -1)
11170                 {
11171                     // pointerTypeToGPByte will have bitched.
11172                     exit(1);
11173                 }
11174             
11175                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11176                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11177             }
11178           goto release;
11179         }
11180
11181       /* just copy the pointers */
11182       size = AOP_SIZE (result);
11183       offset = 0;
11184       _startLazyDPSEvaluation ();
11185       while (size--)
11186         {
11187           aopPut (AOP (result),
11188                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11189                   offset);
11190           offset++;
11191         }
11192       _endLazyDPSEvaluation ();
11193       goto release;
11194     }
11195
11196   /* so we now know that the size of destination is greater
11197      than the size of the source */
11198   /* we move to result for the size of source */
11199   size = AOP_SIZE (right);
11200   offset = 0;
11201   _startLazyDPSEvaluation ();
11202   while (size--)
11203     {
11204       aopPut (AOP (result),
11205               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11206               offset);
11207       offset++;
11208     }
11209   _endLazyDPSEvaluation ();
11210
11211   /* now depending on the sign of the source && destination */
11212   size = AOP_SIZE (result) - AOP_SIZE (right);
11213   /* if unsigned or not an integral type */
11214   /* also, if the source is a bit, we don't need to sign extend, because
11215    * it can't possibly have set the sign bit.
11216    */
11217   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11218     {
11219       while (size--)
11220         {
11221           aopPut (AOP (result), zero, offset++);
11222         }
11223     }
11224   else
11225     {
11226       /* we need to extend the sign :{ */
11227       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11228                         FALSE, FALSE, NULL));
11229       emitcode ("rlc", "a");
11230       emitcode ("subb", "a,acc");
11231       while (size--)
11232         aopPut (AOP (result), "a", offset++);
11233     }
11234
11235   /* we are done hurray !!!! */
11236
11237 release:
11238   freeAsmop (right, NULL, ic, TRUE);
11239   freeAsmop (result, NULL, ic, TRUE);
11240
11241 }
11242
11243 /*-----------------------------------------------------------------*/
11244 /* genDjnz - generate decrement & jump if not zero instrucion      */
11245 /*-----------------------------------------------------------------*/
11246 static int
11247 genDjnz (iCode * ic, iCode * ifx)
11248 {
11249   symbol *lbl, *lbl1;
11250   if (!ifx)
11251     return 0;
11252
11253   /* if the if condition has a false label
11254      then we cannot save */
11255   if (IC_FALSE (ifx))
11256     return 0;
11257
11258   /* if the minus is not of the form
11259      a = a - 1 */
11260   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11261       !IS_OP_LITERAL (IC_RIGHT (ic)))
11262     return 0;
11263
11264   if (operandLitValue (IC_RIGHT (ic)) != 1)
11265     return 0;
11266
11267   /* if the size of this greater than one then no
11268      saving */
11269   if (getSize (operandType (IC_RESULT (ic))) > 1)
11270     return 0;
11271
11272   /* otherwise we can save BIG */
11273   D(emitcode(";", "genDjnz"););
11274
11275   lbl = newiTempLabel (NULL);
11276   lbl1 = newiTempLabel (NULL);
11277
11278   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11279
11280   if (AOP_NEEDSACC(IC_RESULT(ic)))
11281   {
11282       /* If the result is accessed indirectly via
11283        * the accumulator, we must explicitly write
11284        * it back after the decrement.
11285        */
11286       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11287       
11288       if (strcmp(rByte, "a"))
11289       {
11290            /* Something is hopelessly wrong */
11291            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11292                    __FILE__, __LINE__);
11293            /* We can just give up; the generated code will be inefficient,
11294             * but what the hey.
11295             */
11296            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11297            return 0;
11298       }
11299       emitcode ("dec", "%s", rByte);
11300       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11301       emitcode ("jnz", "!tlabel", lbl->key + 100);
11302   }
11303   else if (IS_AOP_PREG (IC_RESULT (ic)))
11304     {
11305       emitcode ("dec", "%s",
11306                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11307       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11308       emitcode ("jnz", "!tlabel", lbl->key + 100);
11309     }
11310   else
11311     {
11312       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11313                 lbl->key + 100);
11314     }
11315   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11316   emitcode ("", "!tlabeldef", lbl->key + 100);
11317   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11318   emitcode ("", "!tlabeldef", lbl1->key + 100);
11319
11320   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11321   ifx->generated = 1;
11322   return 1;
11323 }
11324
11325 /*-----------------------------------------------------------------*/
11326 /* genReceive - generate code for a receive iCode                  */
11327 /*-----------------------------------------------------------------*/
11328 static void
11329 genReceive (iCode * ic)
11330 {
11331     int size = getSize (operandType (IC_RESULT (ic)));
11332     int offset = 0;
11333     int rb1off ;
11334     
11335     D (emitcode (";", "genReceive "););
11336
11337     if (ic->argreg == 1) 
11338     {
11339         /* first parameter */
11340         if (AOP_IS_STR(IC_RESULT(ic)))
11341         {
11342             /* Nothing to do: it's already in the proper place. */
11343             return;
11344         }
11345         else
11346         {
11347             bool useDp2;
11348             
11349             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11350                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11351                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11352             
11353             _G.accInUse++;
11354             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11355             _G.accInUse--; 
11356             
11357             /* Sanity checking... */
11358             if (AOP_USESDPTR(IC_RESULT(ic)))
11359             {
11360                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11361                         "genReceive got unexpected DPTR.");
11362             }
11363             assignResultValue (IC_RESULT (ic));
11364         }
11365     } 
11366     else 
11367     { 
11368         /* second receive onwards */
11369         /* this gets a little tricky since unused recevies will be
11370          eliminated, we have saved the reg in the type field . and
11371          we use that to figure out which register to use */
11372         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11373         rb1off = ic->argreg;
11374         while (size--) 
11375         {
11376             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11377         }
11378     }
11379     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11380 }
11381
11382 /*-----------------------------------------------------------------*/
11383 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11384 /*-----------------------------------------------------------------*/
11385 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11386 {
11387     operand *from , *to , *count;
11388     symbol *lbl;
11389     bitVect *rsave;
11390     int i;
11391
11392     /* we know it has to be 3 parameters */
11393     assert (nparms == 3);
11394     
11395     rsave = newBitVect(16);
11396     /* save DPTR if it needs to be saved */
11397     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11398             if (bitVectBitValue(ic->rMask,i))
11399                     rsave = bitVectSetBit(rsave,i);
11400     }
11401     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11402                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11403     savermask(rsave);
11404     
11405     to = parms[0];
11406     from = parms[1];
11407     count = parms[2];
11408
11409     aopOp (from, ic->next, FALSE, FALSE);
11410
11411     /* get from into DPTR1 */
11412     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11413     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11414     if (options.model == MODEL_FLAT24) {
11415         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11416     }
11417
11418     freeAsmop (from, NULL, ic, FALSE);
11419     aopOp (to, ic, FALSE, FALSE);
11420     /* get "to" into DPTR */
11421     /* if the operand is already in dptr
11422        then we do nothing else we move the value to dptr */
11423     if (AOP_TYPE (to) != AOP_STR) {
11424         /* if already in DPTR then we need to push */
11425         if (AOP_TYPE(to) == AOP_DPTR) {
11426             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11427             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11428             if (options.model == MODEL_FLAT24)
11429                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11430             emitcode ("pop", "dph");
11431             emitcode ("pop", "dpl");        
11432         } else {
11433             _startLazyDPSEvaluation ();
11434             /* if this is remateriazable */
11435             if (AOP_TYPE (to) == AOP_IMMD) {
11436                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11437             } else {                    /* we need to get it byte by byte */
11438                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11439                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11440                 if (options.model == MODEL_FLAT24) {
11441                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11442                 }
11443             }
11444             _endLazyDPSEvaluation ();
11445         }
11446     }
11447     freeAsmop (to, NULL, ic, FALSE);
11448     _G.dptrInUse = _G.dptr1InUse = 1;
11449     aopOp (count, ic->next->next, FALSE,FALSE);
11450     lbl =newiTempLabel(NULL);
11451
11452     /* now for the actual copy */
11453     if (AOP_TYPE(count) == AOP_LIT && 
11454         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11455         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11456         if (fromc) {
11457             emitcode ("lcall","__bi_memcpyc2x_s");
11458         } else {
11459             emitcode ("lcall","__bi_memcpyx2x_s");
11460         }
11461         freeAsmop (count, NULL, ic, FALSE);
11462     } else {
11463         symbol *lbl1 = newiTempLabel(NULL);
11464         
11465         emitcode (";"," Auto increment but no djnz");
11466         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11467         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11468         freeAsmop (count, NULL, ic, FALSE);
11469         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11470         emitcode ("","!tlabeldef",lbl->key+100);
11471         if (fromc) {
11472             emitcode ("clr","a");
11473             emitcode ("movc", "a,@a+dptr");
11474         } else 
11475             emitcode ("movx", "a,@dptr");
11476         emitcode ("movx", "@dptr,a");
11477         emitcode ("inc", "dptr");
11478         emitcode ("inc", "dptr");
11479         emitcode ("mov","a,b");
11480         emitcode ("orl","a,_ap");
11481         emitcode ("jz","!tlabel",lbl1->key+100);
11482         emitcode ("mov","a,_ap");
11483         emitcode ("add","a,#!constbyte",0xFF);
11484         emitcode ("mov","_ap,a");
11485         emitcode ("mov","a,b");
11486         emitcode ("addc","a,#!constbyte",0xFF);
11487         emitcode ("mov","b,a");
11488         emitcode ("sjmp","!tlabel",lbl->key+100);
11489         emitcode ("","!tlabeldef",lbl1->key+100);
11490     }
11491     emitcode ("mov", "dps,#0"); 
11492     _G.dptrInUse = _G.dptr1InUse = 0;
11493     unsavermask(rsave);
11494
11495 }
11496
11497 /*-----------------------------------------------------------------*/
11498 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11499 /*-----------------------------------------------------------------*/
11500 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11501 {
11502     operand *from , *to , *count;
11503     symbol *lbl,*lbl2;
11504     bitVect *rsave;
11505     int i;
11506
11507     /* we know it has to be 3 parameters */
11508     assert (nparms == 3);
11509     
11510     rsave = newBitVect(16);
11511     /* save DPTR if it needs to be saved */
11512     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11513             if (bitVectBitValue(ic->rMask,i))
11514                     rsave = bitVectSetBit(rsave,i);
11515     }
11516     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11517                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11518     savermask(rsave);
11519     
11520     to = parms[0];
11521     from = parms[1];
11522     count = parms[2];
11523
11524     aopOp (from, ic->next, FALSE, FALSE);
11525
11526     /* get from into DPTR1 */
11527     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11528     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11529     if (options.model == MODEL_FLAT24) {
11530         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11531     }
11532
11533     freeAsmop (from, NULL, ic, FALSE);
11534     aopOp (to, ic, FALSE, FALSE);
11535     /* get "to" into DPTR */
11536     /* if the operand is already in dptr
11537        then we do nothing else we move the value to dptr */
11538     if (AOP_TYPE (to) != AOP_STR) {
11539         /* if already in DPTR then we need to push */
11540         if (AOP_TYPE(to) == AOP_DPTR) {
11541             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11542             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11543             if (options.model == MODEL_FLAT24)
11544                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11545             emitcode ("pop", "dph");
11546             emitcode ("pop", "dpl");        
11547         } else {
11548             _startLazyDPSEvaluation ();
11549             /* if this is remateriazable */
11550             if (AOP_TYPE (to) == AOP_IMMD) {
11551                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11552             } else {                    /* we need to get it byte by byte */
11553                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11554                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11555                 if (options.model == MODEL_FLAT24) {
11556                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11557                 }
11558             }
11559             _endLazyDPSEvaluation ();
11560         }
11561     }
11562     freeAsmop (to, NULL, ic, FALSE);
11563     _G.dptrInUse = _G.dptr1InUse = 1;
11564     aopOp (count, ic->next->next, FALSE,FALSE);
11565     lbl =newiTempLabel(NULL);
11566     lbl2 =newiTempLabel(NULL);
11567
11568     /* now for the actual compare */
11569     if (AOP_TYPE(count) == AOP_LIT && 
11570         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11571         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11572         if (fromc)
11573             emitcode("lcall","__bi_memcmpc2x_s");
11574         else
11575             emitcode("lcall","__bi_memcmpx2x_s");
11576         freeAsmop (count, NULL, ic, FALSE);
11577         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11578         aopPut(AOP(IC_RESULT(ic)),"a",0);
11579         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11580     } else {
11581         symbol *lbl1 = newiTempLabel(NULL);
11582
11583         emitcode("push","ar0");         
11584         emitcode (";"," Auto increment but no djnz");
11585         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11586         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11587         freeAsmop (count, NULL, ic, FALSE);
11588         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11589         emitcode ("","!tlabeldef",lbl->key+100);
11590         if (fromc) {
11591             emitcode ("clr","a");
11592             emitcode ("movc", "a,@a+dptr");
11593         } else 
11594             emitcode ("movx", "a,@dptr");
11595         emitcode ("mov","r0,a");
11596         emitcode ("movx", "a,@dptr");
11597         emitcode ("clr","c");
11598         emitcode ("subb","a,r0");
11599         emitcode ("jnz","!tlabel",lbl2->key+100);
11600         emitcode ("inc", "dptr");
11601         emitcode ("inc", "dptr");
11602         emitcode ("mov","a,b");
11603         emitcode ("orl","a,_ap");
11604         emitcode ("jz","!tlabel",lbl1->key+100);
11605         emitcode ("mov","a,_ap");
11606         emitcode ("add","a,#!constbyte",0xFF);
11607         emitcode ("mov","_ap,a");
11608         emitcode ("mov","a,b");
11609         emitcode ("addc","a,#!constbyte",0xFF);
11610         emitcode ("mov","b,a");
11611         emitcode ("sjmp","!tlabel",lbl->key+100);
11612         emitcode ("","!tlabeldef",lbl1->key+100);
11613         emitcode ("clr","a");
11614         emitcode ("","!tlabeldef",lbl2->key+100);
11615         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11616         aopPut(AOP(IC_RESULT(ic)),"a",0);
11617         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11618         emitcode("pop","ar0");
11619         emitcode ("mov", "dps,#0");      
11620     }
11621     _G.dptrInUse = _G.dptr1InUse = 0;
11622     unsavermask(rsave);
11623
11624 }
11625
11626 /*-----------------------------------------------------------------*/
11627 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11628 /* port, first parameter output area second parameter pointer to   */
11629 /* port third parameter count                                      */
11630 /*-----------------------------------------------------------------*/
11631 static void genInp( iCode *ic, int nparms, operand **parms)
11632 {
11633     operand *from , *to , *count;
11634     symbol *lbl;
11635     bitVect *rsave;
11636     int i;
11637
11638     /* we know it has to be 3 parameters */
11639     assert (nparms == 3);
11640     
11641     rsave = newBitVect(16);
11642     /* save DPTR if it needs to be saved */
11643     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11644             if (bitVectBitValue(ic->rMask,i))
11645                     rsave = bitVectSetBit(rsave,i);
11646     }
11647     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11648                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11649     savermask(rsave);
11650     
11651     to = parms[0];
11652     from = parms[1];
11653     count = parms[2];
11654
11655     aopOp (from, ic->next, FALSE, FALSE);
11656
11657     /* get from into DPTR1 */
11658     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11659     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11660     if (options.model == MODEL_FLAT24) {
11661         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11662     }
11663
11664     freeAsmop (from, NULL, ic, FALSE);
11665     aopOp (to, ic, FALSE, FALSE);
11666     /* get "to" into DPTR */
11667     /* if the operand is already in dptr
11668        then we do nothing else we move the value to dptr */
11669     if (AOP_TYPE (to) != AOP_STR) {
11670         /* if already in DPTR then we need to push */
11671         if (AOP_TYPE(to) == AOP_DPTR) {
11672             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11673             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11674             if (options.model == MODEL_FLAT24)
11675                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11676             emitcode ("pop", "dph");
11677             emitcode ("pop", "dpl");        
11678         } else {
11679             _startLazyDPSEvaluation ();
11680             /* if this is remateriazable */
11681             if (AOP_TYPE (to) == AOP_IMMD) {
11682                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11683             } else {                    /* we need to get it byte by byte */
11684                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11685                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11686                 if (options.model == MODEL_FLAT24) {
11687                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11688                 }
11689             }
11690             _endLazyDPSEvaluation ();
11691         }
11692     }
11693     freeAsmop (to, NULL, ic, FALSE);
11694
11695     _G.dptrInUse = _G.dptr1InUse = 1;
11696     aopOp (count, ic->next->next, FALSE,FALSE);
11697     lbl =newiTempLabel(NULL);
11698
11699     /* now for the actual copy */
11700     if (AOP_TYPE(count) == AOP_LIT && 
11701         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11702         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11703         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11704         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11705         freeAsmop (count, NULL, ic, FALSE);
11706         emitcode ("","!tlabeldef",lbl->key+100);
11707         emitcode ("movx", "a,@dptr");   /* read data from port */
11708         emitcode ("dec","dps");         /* switch to DPTR */
11709         emitcode ("movx", "@dptr,a");   /* save into location */
11710         emitcode ("inc", "dptr");       /* point to next area */
11711         emitcode ("inc","dps");         /* switch to DPTR2 */
11712         emitcode ("djnz","b,!tlabel",lbl->key+100);
11713     } else {
11714         symbol *lbl1 = newiTempLabel(NULL);
11715         
11716         emitcode (";"," Auto increment but no djnz");
11717         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11718         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11719         freeAsmop (count, NULL, ic, FALSE);
11720         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11721         emitcode ("","!tlabeldef",lbl->key+100);
11722         emitcode ("movx", "a,@dptr");
11723         emitcode ("dec","dps");         /* switch to DPTR */
11724         emitcode ("movx", "@dptr,a");
11725         emitcode ("inc", "dptr");
11726         emitcode ("inc","dps");         /* switch to DPTR2 */
11727 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11728 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11729         emitcode ("mov","a,b");
11730         emitcode ("orl","a,_ap");
11731         emitcode ("jz","!tlabel",lbl1->key+100);
11732         emitcode ("mov","a,_ap");
11733         emitcode ("add","a,#!constbyte",0xFF);
11734         emitcode ("mov","_ap,a");
11735         emitcode ("mov","a,b");
11736         emitcode ("addc","a,#!constbyte",0xFF);
11737         emitcode ("mov","b,a");
11738         emitcode ("sjmp","!tlabel",lbl->key+100);
11739         emitcode ("","!tlabeldef",lbl1->key+100);
11740     }
11741     emitcode ("mov", "dps,#0"); 
11742     _G.dptrInUse = _G.dptr1InUse = 0;
11743     unsavermask(rsave);
11744
11745 }
11746
11747 /*-----------------------------------------------------------------*/
11748 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11749 /* port, first parameter output area second parameter pointer to   */
11750 /* port third parameter count                                      */
11751 /*-----------------------------------------------------------------*/
11752 static void genOutp( iCode *ic, int nparms, operand **parms)
11753 {
11754     operand *from , *to , *count;
11755     symbol *lbl;
11756     bitVect *rsave;
11757     int i;
11758
11759     /* we know it has to be 3 parameters */
11760     assert (nparms == 3);
11761     
11762     rsave = newBitVect(16);
11763     /* save DPTR if it needs to be saved */
11764     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11765             if (bitVectBitValue(ic->rMask,i))
11766                     rsave = bitVectSetBit(rsave,i);
11767     }
11768     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11769                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11770     savermask(rsave);
11771     
11772     to = parms[0];
11773     from = parms[1];
11774     count = parms[2];
11775
11776     aopOp (from, ic->next, FALSE, FALSE);
11777
11778     /* get from into DPTR1 */
11779     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11780     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11781     if (options.model == MODEL_FLAT24) {
11782         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11783     }
11784
11785     freeAsmop (from, NULL, ic, FALSE);
11786     aopOp (to, ic, FALSE, FALSE);
11787     /* get "to" into DPTR */
11788     /* if the operand is already in dptr
11789        then we do nothing else we move the value to dptr */
11790     if (AOP_TYPE (to) != AOP_STR) {
11791         /* if already in DPTR then we need to push */
11792         if (AOP_TYPE(to) == AOP_DPTR) {
11793             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11794             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11795             if (options.model == MODEL_FLAT24)
11796                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11797             emitcode ("pop", "dph");
11798             emitcode ("pop", "dpl");        
11799         } else {
11800             _startLazyDPSEvaluation ();
11801             /* if this is remateriazable */
11802             if (AOP_TYPE (to) == AOP_IMMD) {
11803                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11804             } else {                    /* we need to get it byte by byte */
11805                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11806                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11807                 if (options.model == MODEL_FLAT24) {
11808                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11809                 }
11810             }
11811             _endLazyDPSEvaluation ();
11812         }
11813     }
11814     freeAsmop (to, NULL, ic, FALSE);
11815
11816     _G.dptrInUse = _G.dptr1InUse = 1;
11817     aopOp (count, ic->next->next, FALSE,FALSE);
11818     lbl =newiTempLabel(NULL);
11819
11820     /* now for the actual copy */
11821     if (AOP_TYPE(count) == AOP_LIT && 
11822         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11823         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11824         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11825         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11826         emitcode ("","!tlabeldef",lbl->key+100);
11827         emitcode ("movx", "a,@dptr");   /* read data from port */
11828         emitcode ("inc","dps");         /* switch to DPTR2 */
11829         emitcode ("movx", "@dptr,a");   /* save into location */
11830         emitcode ("inc", "dptr");       /* point to next area */
11831         emitcode ("dec","dps");         /* switch to DPTR */
11832         emitcode ("djnz","b,!tlabel",lbl->key+100);
11833         freeAsmop (count, NULL, ic, FALSE);
11834     } else {
11835         symbol *lbl1 = newiTempLabel(NULL);
11836         
11837         emitcode (";"," Auto increment but no djnz");
11838         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11839         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11840         freeAsmop (count, NULL, ic, FALSE);
11841         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11842         emitcode ("","!tlabeldef",lbl->key+100);
11843         emitcode ("movx", "a,@dptr");
11844         emitcode ("inc", "dptr");
11845         emitcode ("inc","dps");         /* switch to DPTR2 */
11846         emitcode ("movx", "@dptr,a");
11847         emitcode ("dec","dps");         /* switch to DPTR */
11848         emitcode ("mov","a,b");
11849         emitcode ("orl","a,_ap");
11850         emitcode ("jz","!tlabel",lbl1->key+100);
11851         emitcode ("mov","a,_ap");
11852         emitcode ("add","a,#!constbyte",0xFF);
11853         emitcode ("mov","_ap,a");
11854         emitcode ("mov","a,b");
11855         emitcode ("addc","a,#!constbyte",0xFF);
11856         emitcode ("mov","b,a");
11857         emitcode ("sjmp","!tlabel",lbl->key+100);
11858         emitcode ("","!tlabeldef",lbl1->key+100);
11859     }
11860     emitcode ("mov", "dps,#0"); 
11861     _G.dptrInUse = _G.dptr1InUse = 0;
11862     unsavermask(rsave);
11863
11864 }
11865
11866 /*-----------------------------------------------------------------*/
11867 /* genSwapW - swap lower & high order bytes                        */
11868 /*-----------------------------------------------------------------*/
11869 static void genSwapW(iCode *ic, int nparms, operand **parms)
11870 {
11871     operand *dest;
11872     operand *src;
11873     assert (nparms==1);
11874
11875     src = parms[0];
11876     dest=IC_RESULT(ic);
11877
11878     assert(getSize(operandType(src))==2);
11879
11880     aopOp (src, ic, FALSE, FALSE);
11881     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11882     _G.accInUse++;
11883     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11884     _G.accInUse--;
11885     freeAsmop (src, NULL, ic, FALSE);
11886     
11887     aopOp (dest,ic, FALSE, FALSE);
11888     aopPut(AOP(dest),"b",0);
11889     aopPut(AOP(dest),"a",1);
11890     freeAsmop (dest, NULL, ic, FALSE);    
11891 }
11892
11893 /*-----------------------------------------------------------------*/
11894 /* genMemsetX - gencode for memSetX data                           */
11895 /*-----------------------------------------------------------------*/
11896 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11897 {
11898     operand *to , *val , *count;
11899     symbol *lbl;
11900     char *l;
11901     int i;
11902     bitVect *rsave;
11903
11904     /* we know it has to be 3 parameters */
11905     assert (nparms == 3);
11906     
11907     to = parms[0];
11908     val = parms[1];
11909     count = parms[2];
11910         
11911     /* save DPTR if it needs to be saved */
11912     rsave = newBitVect(16);
11913     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11914             if (bitVectBitValue(ic->rMask,i))
11915                     rsave = bitVectSetBit(rsave,i);
11916     }
11917     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11918                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11919     savermask(rsave);
11920
11921     aopOp (to, ic, FALSE, FALSE);
11922     /* get "to" into DPTR */
11923     /* if the operand is already in dptr
11924        then we do nothing else we move the value to dptr */
11925     if (AOP_TYPE (to) != AOP_STR) {
11926         /* if already in DPTR then we need to push */
11927         if (AOP_TYPE(to) == AOP_DPTR) {
11928             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11929             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11930             if (options.model == MODEL_FLAT24)
11931                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11932             emitcode ("pop", "dph");
11933             emitcode ("pop", "dpl");        
11934         } else {
11935             _startLazyDPSEvaluation ();
11936             /* if this is remateriazable */
11937             if (AOP_TYPE (to) == AOP_IMMD) {
11938                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11939             } else {                    /* we need to get it byte by byte */
11940                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11941                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11942                 if (options.model == MODEL_FLAT24) {
11943                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11944                 }
11945             }
11946             _endLazyDPSEvaluation ();
11947         }
11948     }
11949     freeAsmop (to, NULL, ic, FALSE);
11950
11951     aopOp (val, ic->next->next, FALSE,FALSE);
11952     aopOp (count, ic->next->next, FALSE,FALSE);    
11953     lbl =newiTempLabel(NULL);
11954     /* now for the actual copy */
11955     if (AOP_TYPE(count) == AOP_LIT && 
11956         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11957         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11958         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11959         MOVA(l);
11960         emitcode ("","!tlabeldef",lbl->key+100);
11961         emitcode ("movx", "@dptr,a");
11962         emitcode ("inc", "dptr");
11963         emitcode ("djnz","b,!tlabel",lbl->key+100);
11964     } else {
11965         symbol *lbl1 = newiTempLabel(NULL);
11966         
11967         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11968         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11969         emitcode ("","!tlabeldef",lbl->key+100);
11970         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11971         emitcode ("movx", "@dptr,a");
11972         emitcode ("inc", "dptr");
11973         emitcode ("mov","a,b");
11974         emitcode ("orl","a,_ap");
11975         emitcode ("jz","!tlabel",lbl1->key+100);
11976         emitcode ("mov","a,_ap");
11977         emitcode ("add","a,#!constbyte",0xFF);
11978         emitcode ("mov","_ap,a");
11979         emitcode ("mov","a,b");
11980         emitcode ("addc","a,#!constbyte",0xFF);
11981         emitcode ("mov","b,a");
11982         emitcode ("sjmp","!tlabel",lbl->key+100);
11983         emitcode ("","!tlabeldef",lbl1->key+100);
11984     }
11985     freeAsmop (count, NULL, ic, FALSE);
11986     unsavermask(rsave);
11987 }
11988
11989 /*-----------------------------------------------------------------*/
11990 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11991 /*-----------------------------------------------------------------*/
11992 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11993 {
11994         bitVect *rsave ;
11995         operand *pnum, *result;
11996         int i;
11997     
11998         assert (nparms==1);
11999         /* save registers that need to be saved */
12000         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12001                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12002     
12003         pnum = parms[0]; 
12004         aopOp (pnum, ic, FALSE, FALSE);
12005         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12006         freeAsmop (pnum, NULL, ic, FALSE);
12007         emitcode ("lcall","NatLib_LoadPrimitive");
12008         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12009         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12010             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12011                 for (i = (size-1) ; i >= 0 ; i-- ) {
12012                         emitcode ("push","a%s",javaRet[i]);
12013                 }
12014                 for (i=0; i < size ; i++ ) {
12015                         emitcode ("pop","a%s",
12016                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12017                 }
12018         } else {
12019                 for (i = 0 ; i < size ; i++ ) {
12020                         aopPut(AOP(result),javaRet[i],i);
12021                 }
12022         }    
12023         freeAsmop (result, NULL, ic, FALSE);
12024         unsavermask(rsave);
12025 }
12026
12027 /*-----------------------------------------------------------------*/
12028 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12029 /*-----------------------------------------------------------------*/
12030 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12031 {
12032         bitVect *rsave ;
12033         operand *pnum, *result;
12034         int size = 3;
12035         int i;
12036     
12037         assert (nparms==1);
12038         /* save registers that need to be saved */
12039         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12040                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12041     
12042         pnum = parms[0]; 
12043         aopOp (pnum, ic, FALSE, FALSE);
12044         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12045         freeAsmop (pnum, NULL, ic, FALSE);
12046         emitcode ("lcall","NatLib_LoadPointer");
12047         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12048         if (AOP_TYPE(result)!=AOP_STR) {
12049                 for (i = 0 ; i < size ; i++ ) {
12050                         aopPut(AOP(result),fReturn[i],i);
12051                 }
12052         }    
12053         freeAsmop (result, NULL, ic, FALSE);
12054         unsavermask(rsave);
12055 }
12056
12057 /*-----------------------------------------------------------------*/
12058 /* genNatLibInstallStateBlock -                                    */
12059 /*-----------------------------------------------------------------*/
12060 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12061                                        operand **parms, const char *name)
12062 {
12063         bitVect *rsave ;
12064         operand *psb, *handle;
12065         assert (nparms==2);
12066
12067         /* save registers that need to be saved */
12068         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12069                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12070         psb = parms[0];
12071         handle = parms[1];
12072
12073         /* put pointer to state block into DPTR1 */
12074         aopOp (psb, ic, FALSE, FALSE);
12075         if (AOP_TYPE (psb) == AOP_IMMD) {
12076                 emitcode ("mov","dps,#1");
12077                 emitcode ("mov", "dptr,%s",
12078                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12079                 emitcode ("mov","dps,#0");
12080         } else {
12081                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12082                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12083                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12084         }
12085         freeAsmop (psb, NULL, ic, FALSE);
12086
12087         /* put libraryID into DPTR */
12088         emitcode ("mov","dptr,#LibraryID");
12089
12090         /* put handle into r3:r2 */
12091         aopOp (handle, ic, FALSE, FALSE);
12092         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12093                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12094                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12095                 emitcode ("pop","ar3");
12096                 emitcode ("pop","ar2");
12097         } else {        
12098                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12099                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12100         }
12101         freeAsmop (psb, NULL, ic, FALSE);
12102
12103         /* make the call */
12104         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12105
12106         /* put return value into place*/
12107         _G.accInUse++;
12108         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12109         _G.accInUse--;
12110         aopPut(AOP(IC_RESULT(ic)),"a",0);
12111         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12112         unsavermask(rsave);
12113 }
12114
12115 /*-----------------------------------------------------------------*/
12116 /* genNatLibRemoveStateBlock -                                     */
12117 /*-----------------------------------------------------------------*/
12118 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12119 {
12120         bitVect *rsave ;
12121
12122         assert(nparms==0);
12123
12124         /* save registers that need to be saved */
12125         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12126                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12127
12128         /* put libraryID into DPTR */
12129         emitcode ("mov","dptr,#LibraryID");
12130         /* make the call */
12131         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12132         unsavermask(rsave);
12133 }
12134
12135 /*-----------------------------------------------------------------*/
12136 /* genNatLibGetStateBlock -                                        */
12137 /*-----------------------------------------------------------------*/
12138 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12139                                    operand **parms,const char *name)
12140 {
12141         bitVect *rsave ;
12142         symbol *lbl = newiTempLabel(NULL);
12143         
12144         assert(nparms==0);
12145         /* save registers that need to be saved */
12146         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12147                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12148
12149         /* put libraryID into DPTR */
12150         emitcode ("mov","dptr,#LibraryID");
12151         /* make the call */
12152         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12153         emitcode ("jnz","!tlabel",lbl->key+100);
12154
12155         /* put return value into place */
12156         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12157         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12158                 emitcode ("push","ar3");
12159                 emitcode ("push","ar2");
12160                 emitcode ("pop","%s",
12161                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12162                 emitcode ("pop","%s",
12163                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12164         } else {
12165                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12166                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12167         }
12168         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12169         emitcode ("","!tlabeldef",lbl->key+100);
12170         unsavermask(rsave);
12171 }
12172
12173 /*-----------------------------------------------------------------*/
12174 /* genMMMalloc -                                                   */
12175 /*-----------------------------------------------------------------*/
12176 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12177                          int size, const char *name)
12178 {
12179         bitVect *rsave ;
12180         operand *bsize;
12181         symbol *rsym;
12182         symbol *lbl = newiTempLabel(NULL);
12183
12184         assert (nparms == 1);
12185         /* save registers that need to be saved */
12186         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12187                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12188         
12189         bsize=parms[0];
12190         aopOp (bsize,ic,FALSE,FALSE);
12191
12192         /* put the size in R4-R2 */
12193         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12194                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12195                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12196                 if (size==3) {
12197                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12198                         emitcode("pop","ar4");
12199                 }
12200                 emitcode("pop","ar3");
12201                 emitcode("pop","ar2");          
12202         } else {
12203                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12204                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12205                 if (size==3) {
12206                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12207                 }
12208         }
12209         freeAsmop (bsize, NULL, ic, FALSE);
12210
12211         /* make the call */
12212         emitcode ("lcall","MM_%s",name);
12213         emitcode ("jz","!tlabel",lbl->key+100);
12214         emitcode ("mov","r2,#!constbyte",0xff);
12215         emitcode ("mov","r3,#!constbyte",0xff);
12216         emitcode ("","!tlabeldef",lbl->key+100);
12217         /* we don't care about the pointer : we just save the handle */
12218         rsym = OP_SYMBOL(IC_RESULT(ic));
12219         if (rsym->liveFrom != rsym->liveTo) {
12220                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12221                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12222                         emitcode ("push","ar3");
12223                         emitcode ("push","ar2");
12224                         emitcode ("pop","%s",
12225                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12226                         emitcode ("pop","%s",
12227                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12228                 } else {
12229                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12230                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12231                 }
12232                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12233         }
12234         unsavermask(rsave);
12235 }
12236
12237 /*-----------------------------------------------------------------*/
12238 /* genMMDeref -                                                    */
12239 /*-----------------------------------------------------------------*/
12240 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12241 {
12242         bitVect *rsave ;
12243         operand *handle;
12244
12245         assert (nparms == 1);
12246         /* save registers that need to be saved */
12247         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12248                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12249         
12250         handle=parms[0];
12251         aopOp (handle,ic,FALSE,FALSE);
12252
12253         /* put the size in R4-R2 */
12254         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12255                 emitcode("push","%s",
12256                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12257                 emitcode("push","%s",
12258                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12259                 emitcode("pop","ar3");
12260                 emitcode("pop","ar2");          
12261         } else {
12262                 emitcode ("mov","r2,%s",
12263                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12264                 emitcode ("mov","r3,%s",
12265                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12266         }
12267         freeAsmop (handle, NULL, ic, FALSE);
12268
12269         /* make the call */
12270         emitcode ("lcall","MM_Deref");
12271         
12272         {
12273                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12274                 if (rsym->liveFrom != rsym->liveTo) {                   
12275                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12276                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12277                             _startLazyDPSEvaluation ();
12278                             
12279                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12280                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12281                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12282
12283                             _endLazyDPSEvaluation ();
12284                             
12285                         }
12286                 }
12287         }
12288         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12289         unsavermask(rsave);
12290 }
12291
12292 /*-----------------------------------------------------------------*/
12293 /* genMMUnrestrictedPersist -                                      */
12294 /*-----------------------------------------------------------------*/
12295 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12296 {
12297         bitVect *rsave ;
12298         operand *handle;
12299
12300         assert (nparms == 1);
12301         /* save registers that need to be saved */
12302         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12303                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12304         
12305         handle=parms[0];
12306         aopOp (handle,ic,FALSE,FALSE);
12307
12308         /* put the size in R3-R2 */
12309         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12310                 emitcode("push","%s",
12311                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12312                 emitcode("push","%s",
12313                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12314                 emitcode("pop","ar3");
12315                 emitcode("pop","ar2");          
12316         } else {
12317                 emitcode ("mov","r2,%s",
12318                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12319                 emitcode ("mov","r3,%s",
12320                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12321         }
12322         freeAsmop (handle, NULL, ic, FALSE);
12323
12324         /* make the call */
12325         emitcode ("lcall","MM_UnrestrictedPersist");
12326
12327         {
12328                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12329                 if (rsym->liveFrom != rsym->liveTo) {   
12330                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12331                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12332                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12333                 }
12334         }
12335         unsavermask(rsave);
12336 }
12337
12338 /*-----------------------------------------------------------------*/
12339 /* genSystemExecJavaProcess -                                      */
12340 /*-----------------------------------------------------------------*/
12341 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12342 {
12343         bitVect *rsave ;
12344         operand *handle, *pp;
12345
12346         assert (nparms==2);
12347         /* save registers that need to be saved */
12348         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12349                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12350         
12351         pp = parms[0];
12352         handle = parms[1];
12353         
12354         /* put the handle in R3-R2 */
12355         aopOp (handle,ic,FALSE,FALSE);
12356         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12357                 emitcode("push","%s",
12358                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12359                 emitcode("push","%s",
12360                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12361                 emitcode("pop","ar3");
12362                 emitcode("pop","ar2");          
12363         } else {
12364                 emitcode ("mov","r2,%s",
12365                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12366                 emitcode ("mov","r3,%s",
12367                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12368         }
12369         freeAsmop (handle, NULL, ic, FALSE);
12370         
12371         /* put pointer in DPTR */
12372         aopOp (pp,ic,FALSE,FALSE);
12373         if (AOP_TYPE(pp) == AOP_IMMD) {
12374                 emitcode ("mov", "dptr,%s",
12375                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12376         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12377                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12378                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12379                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12380         }
12381         freeAsmop (handle, NULL, ic, FALSE);
12382
12383         /* make the call */
12384         emitcode ("lcall","System_ExecJavaProcess");
12385         
12386         /* put result in place */
12387         {
12388                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12389                 if (rsym->liveFrom != rsym->liveTo) {   
12390                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12391                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12392                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12393                 }
12394         }
12395         
12396         unsavermask(rsave);
12397 }
12398
12399 /*-----------------------------------------------------------------*/
12400 /* genSystemRTCRegisters -                                         */
12401 /*-----------------------------------------------------------------*/
12402 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12403                                   char *name)
12404 {
12405         bitVect *rsave ;
12406         operand *pp;
12407
12408         assert (nparms==1);
12409         /* save registers that need to be saved */
12410         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12411                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12412         
12413         pp=parms[0];
12414         /* put pointer in DPTR */
12415         aopOp (pp,ic,FALSE,FALSE);
12416         if (AOP_TYPE (pp) == AOP_IMMD) {
12417                 emitcode ("mov","dps,#1");
12418                 emitcode ("mov", "dptr,%s", 
12419                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12420                 emitcode ("mov","dps,#0");
12421         } else {
12422                 emitcode ("mov","dpl1,%s",
12423                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12424                 emitcode ("mov","dph1,%s",
12425                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12426                 emitcode ("mov","dpx1,%s",
12427                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12428         }
12429         freeAsmop (pp, NULL, ic, FALSE);
12430
12431         /* make the call */
12432         emitcode ("lcall","System_%sRTCRegisters",name);
12433
12434         unsavermask(rsave);
12435 }
12436
12437 /*-----------------------------------------------------------------*/
12438 /* genSystemThreadSleep -                                          */
12439 /*-----------------------------------------------------------------*/
12440 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12441 {
12442         bitVect *rsave ;
12443         operand *to, *s;
12444
12445         assert (nparms==1);
12446         /* save registers that need to be saved */
12447         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12448                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12449
12450         to = parms[0];
12451         aopOp(to,ic,FALSE,FALSE);
12452         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12453             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12454                 emitcode ("push","%s",
12455                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12456                 emitcode ("push","%s",
12457                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12458                 emitcode ("push","%s",
12459                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12460                 emitcode ("push","%s",
12461                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12462                 emitcode ("pop","ar3");
12463                 emitcode ("pop","ar2");
12464                 emitcode ("pop","ar1");
12465                 emitcode ("pop","ar0");
12466         } else {
12467                 emitcode ("mov","r0,%s",
12468                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12469                 emitcode ("mov","r1,%s",
12470                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12471                 emitcode ("mov","r2,%s",
12472                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12473                 emitcode ("mov","r3,%s",
12474                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12475         }
12476         freeAsmop (to, NULL, ic, FALSE);
12477
12478         /* suspend in acc */
12479         s = parms[1];
12480         aopOp(s,ic,FALSE,FALSE);
12481         emitcode ("mov","a,%s",
12482                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12483         freeAsmop (s, NULL, ic, FALSE);
12484
12485         /* make the call */
12486         emitcode ("lcall","System_%s",name);
12487
12488         unsavermask(rsave);
12489 }
12490
12491 /*-----------------------------------------------------------------*/
12492 /* genSystemThreadResume -                                         */
12493 /*-----------------------------------------------------------------*/
12494 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12495 {
12496         bitVect *rsave ;
12497         operand *tid,*pid;
12498
12499         assert (nparms==2);
12500         /* save registers that need to be saved */
12501         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12502                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12503         
12504         tid = parms[0];
12505         pid = parms[1];
12506         
12507         /* PID in R0 */
12508         aopOp(pid,ic,FALSE,FALSE);
12509         emitcode ("mov","r0,%s",
12510                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12511         freeAsmop (pid, NULL, ic, FALSE);
12512         
12513         /* tid into ACC */
12514         aopOp(tid,ic,FALSE,FALSE);
12515         emitcode ("mov","a,%s",
12516                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12517         freeAsmop (tid, NULL, ic, FALSE);
12518         
12519         emitcode ("lcall","System_ThreadResume");
12520
12521         /* put result into place */
12522         {
12523                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12524                 if (rsym->liveFrom != rsym->liveTo) {   
12525                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12526                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12527                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12528                 }
12529         }
12530         unsavermask(rsave);
12531 }
12532
12533 /*-----------------------------------------------------------------*/
12534 /* genSystemProcessResume -                                        */
12535 /*-----------------------------------------------------------------*/
12536 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12537 {
12538         bitVect *rsave ;
12539         operand *pid;
12540
12541         assert (nparms==1);
12542         /* save registers that need to be saved */
12543         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12544                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12545         
12546         pid = parms[0];
12547         
12548         /* pid into ACC */
12549         aopOp(pid,ic,FALSE,FALSE);
12550         emitcode ("mov","a,%s",
12551                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12552         freeAsmop (pid, NULL, ic, FALSE);
12553         
12554         emitcode ("lcall","System_ProcessResume");
12555
12556         unsavermask(rsave);
12557 }
12558
12559 /*-----------------------------------------------------------------*/
12560 /* genSystem -                                                     */
12561 /*-----------------------------------------------------------------*/
12562 static void genSystem (iCode *ic,int nparms,char *name)
12563 {
12564         assert(nparms == 0);
12565
12566         emitcode ("lcall","System_%s",name);
12567 }
12568
12569 /*-----------------------------------------------------------------*/
12570 /* genSystemPoll -                                                  */
12571 /*-----------------------------------------------------------------*/
12572 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12573 {
12574         bitVect *rsave ;
12575         operand *fp;
12576
12577         assert (nparms==1);
12578         /* save registers that need to be saved */
12579         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12580                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12581
12582         fp = parms[0];
12583         aopOp (fp,ic,FALSE,FALSE);
12584         if (AOP_TYPE (fp) == AOP_IMMD) {
12585                 emitcode ("mov", "dptr,%s", 
12586                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12587         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12588                 emitcode ("mov","dpl,%s",
12589                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12590                 emitcode ("mov","dph,%s",
12591                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12592                 emitcode ("mov","dpx,%s",
12593                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12594         }
12595         freeAsmop (fp, NULL, ic, FALSE);
12596
12597         emitcode ("lcall","System_%sPoll",name);
12598
12599         /* put result into place */
12600         {
12601                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12602                 if (rsym->liveFrom != rsym->liveTo) {   
12603                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12604                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12605                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12606                 }
12607         }
12608         unsavermask(rsave);
12609 }
12610
12611 /*-----------------------------------------------------------------*/
12612 /* genSystemGetCurrentID -                                         */
12613 /*-----------------------------------------------------------------*/
12614 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12615 {
12616         assert (nparms==0);
12617
12618         emitcode ("lcall","System_GetCurrent%sId",name);
12619         /* put result into place */
12620         {
12621                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12622                 if (rsym->liveFrom != rsym->liveTo) {   
12623                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12624                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12625                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12626                 }
12627         }
12628 }
12629
12630 /*-----------------------------------------------------------------*/
12631 /* genDummyRead - generate code for dummy read of volatiles        */
12632 /*-----------------------------------------------------------------*/
12633 static void
12634 genDummyRead (iCode * ic)
12635 {
12636   operand *right;
12637   int size, offset;
12638
12639   D(emitcode(";     genDummyRead",""));
12640
12641   right = IC_RIGHT (ic);
12642
12643   aopOp (right, ic, FALSE, FALSE);
12644
12645   /* if the result is a bit */
12646   if (AOP_TYPE (right) == AOP_CRY)
12647     {
12648       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12649       goto release;
12650     }
12651
12652   /* bit variables done */
12653   /* general case */
12654   size = AOP_SIZE (right);
12655   offset = 0;
12656   while (size--)
12657     {
12658       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12659       offset++;
12660     }
12661
12662 release:
12663   freeAsmop (right, NULL, ic, TRUE);
12664 }
12665
12666 /*-----------------------------------------------------------------*/
12667 /* genBuiltIn - calls the appropriate function to  generating code */
12668 /* for a built in function                                         */
12669 /*-----------------------------------------------------------------*/
12670 static void genBuiltIn (iCode *ic)
12671 {
12672         operand *bi_parms[MAX_BUILTIN_ARGS];
12673         int nbi_parms;
12674         iCode *bi_iCode;
12675         symbol *bif;
12676
12677         /* get all the arguments for a built in function */
12678         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12679
12680         /* which function is it */
12681         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12682         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12683                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12684         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12685                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12686         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12687                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12688         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12689                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12690         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12691                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12692         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12693                 genInp(bi_iCode,nbi_parms,bi_parms);
12694         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12695                 genOutp(bi_iCode,nbi_parms,bi_parms);
12696         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12697                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12698                 /* JavaNative builtIns */               
12699         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12700                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12701         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12702                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12703         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12704                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12705         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12706                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12707         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12708                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12709         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12710                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12711         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12712                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12713         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12714                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12715         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12716                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12717         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12718                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12719         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12720                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12721         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12722                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12723         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12724                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12725         } else if (strcmp(bif->name,"MM_Free")==0) {
12726                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12727         } else if (strcmp(bif->name,"MM_Deref")==0) {
12728                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12729         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12730                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12731         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12732                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12733         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12734                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12735         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12736                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12737         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12738                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12739         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12740                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12741         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12742                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12743         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12744                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12745         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12746                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12747         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12748                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12749         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12750                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12751         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12752                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12753         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12754                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12755         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12756                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12757         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12758                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12759         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12760                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12761         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12762                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12763         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12764                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12765         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12766                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12767         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12768                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12769         } else {
12770                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12771                 return ;
12772         }
12773         return ;    
12774 }
12775
12776 /*-----------------------------------------------------------------*/
12777 /* gen390Code - generate code for Dallas 390 based controllers     */
12778 /*-----------------------------------------------------------------*/
12779 void
12780 gen390Code (iCode * lic)
12781 {
12782   iCode *ic;
12783   int cln = 0;
12784
12785   lineHead = lineCurr = NULL;
12786   dptrn[1][0] = "dpl1";
12787   dptrn[1][1] = "dph1";
12788   dptrn[1][2] = "dpx1";
12789   
12790   if (options.model == MODEL_FLAT24) {
12791     fReturnSizeDS390 = 5;
12792     fReturn = fReturn24;
12793   } else {
12794     fReturnSizeDS390 = 4;
12795     fReturn = fReturn16;
12796     options.stack10bit=0;
12797   }
12798 #if 1
12799   /* print the allocation information */
12800   if (allocInfo && currFunc)
12801     printAllocInfo (currFunc, codeOutFile);
12802 #endif
12803   /* if debug information required */
12804   if (options.debug && currFunc)
12805     {
12806       debugFile->writeFunction(currFunc);
12807       _G.debugLine = 1;
12808       if (IS_STATIC (currFunc->etype))
12809         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12810       else
12811         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12812       _G.debugLine = 0;
12813     }
12814   /* stack pointer name */
12815   if (options.useXstack)
12816     spname = "_spx";
12817   else
12818     spname = "sp";
12819
12820
12821   for (ic = lic; ic; ic = ic->next)
12822     {
12823
12824       if (ic->lineno && cln != ic->lineno)
12825         {
12826           if (options.debug)
12827             {
12828               _G.debugLine = 1;
12829               emitcode ("", "C$%s$%d$%d$%d ==.",
12830                         FileBaseName (ic->filename), ic->lineno,
12831                         ic->level, ic->block);
12832               _G.debugLine = 0;
12833             }
12834           if (!options.noCcodeInAsm) {
12835             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12836                       printCLine(ic->filename, ic->lineno));
12837           }
12838           cln = ic->lineno;
12839         }
12840       if (options.iCodeInAsm) {
12841         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12842       }
12843       /* if the result is marked as
12844          spilt and rematerializable or code for
12845          this has already been generated then
12846          do nothing */
12847       if (resultRemat (ic) || ic->generated)
12848         continue;
12849
12850       /* depending on the operation */
12851       switch (ic->op)
12852         {
12853         case '!':
12854           genNot (ic);
12855           break;
12856
12857         case '~':
12858           genCpl (ic);
12859           break;
12860
12861         case UNARYMINUS:
12862           genUminus (ic);
12863           break;
12864
12865         case IPUSH:
12866           genIpush (ic);
12867           break;
12868
12869         case IPOP:
12870           /* IPOP happens only when trying to restore a
12871              spilt live range, if there is an ifx statement
12872              following this pop then the if statement might
12873              be using some of the registers being popped which
12874              would destory the contents of the register so
12875              we need to check for this condition and handle it */
12876           if (ic->next &&
12877               ic->next->op == IFX &&
12878               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12879             genIfx (ic->next, ic);
12880           else
12881             genIpop (ic);
12882           break;
12883
12884         case CALL:
12885           genCall (ic);
12886           break;
12887
12888         case PCALL:
12889           genPcall (ic);
12890           break;
12891
12892         case FUNCTION:
12893           genFunction (ic);
12894           break;
12895
12896         case ENDFUNCTION:
12897           genEndFunction (ic);
12898           break;
12899
12900         case RETURN:
12901           genRet (ic);
12902           break;
12903
12904         case LABEL:
12905           genLabel (ic);
12906           break;
12907
12908         case GOTO:
12909           genGoto (ic);
12910           break;
12911
12912         case '+':
12913           genPlus (ic);
12914           break;
12915
12916         case '-':
12917           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12918             genMinus (ic);
12919           break;
12920
12921         case '*':
12922           genMult (ic);
12923           break;
12924
12925         case '/':
12926           genDiv (ic);
12927           break;
12928
12929         case '%':
12930           genMod (ic);
12931           break;
12932
12933         case '>':
12934           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12935           break;
12936
12937         case '<':
12938           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12939           break;
12940
12941         case LE_OP:
12942         case GE_OP:
12943         case NE_OP:
12944
12945           /* note these two are xlated by algebraic equivalence
12946              during parsing SDCC.y */
12947           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12948                   "got '>=' or '<=' shouldn't have come here");
12949           break;
12950
12951         case EQ_OP:
12952           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12953           break;
12954
12955         case AND_OP:
12956           genAndOp (ic);
12957           break;
12958
12959         case OR_OP:
12960           genOrOp (ic);
12961           break;
12962
12963         case '^':
12964           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12965           break;
12966
12967         case '|':
12968           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12969           break;
12970
12971         case BITWISEAND:
12972           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12973           break;
12974
12975         case INLINEASM:
12976           genInline (ic);
12977           break;
12978
12979         case RRC:
12980           genRRC (ic);
12981           break;
12982
12983         case RLC:
12984           genRLC (ic);
12985           break;
12986
12987         case GETHBIT:
12988           genGetHbit (ic);
12989           break;
12990
12991         case LEFT_OP:
12992           genLeftShift (ic);
12993           break;
12994
12995         case RIGHT_OP:
12996           genRightShift (ic);
12997           break;
12998
12999         case GET_VALUE_AT_ADDRESS:
13000           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13001           break;
13002
13003         case '=':
13004           if (POINTER_SET (ic))
13005             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13006           else
13007             genAssign (ic);
13008           break;
13009
13010         case IFX:
13011           genIfx (ic, NULL);
13012           break;
13013
13014         case ADDRESS_OF:
13015           genAddrOf (ic);
13016           break;
13017
13018         case JUMPTABLE:
13019           genJumpTab (ic);
13020           break;
13021
13022         case CAST:
13023           genCast (ic);
13024           break;
13025
13026         case RECEIVE:
13027           genReceive (ic);
13028           break;
13029
13030         case SEND:
13031           if (ic->builtinSEND) genBuiltIn(ic);
13032           else addSet (&_G.sendSet, ic);
13033           break;
13034
13035         case DUMMY_READ_VOLATILE:
13036           genDummyRead (ic);
13037           break;
13038
13039 #if 0 // obsolete, and buggy for != xdata
13040         case ARRAYINIT:
13041             genArrayInit(ic);
13042             break;
13043 #endif
13044             
13045         default:
13046           ic = ic;
13047         }
13048     }
13049
13050
13051   /* now we are ready to call the
13052      peep hole optimizer */
13053   if (!options.nopeep)
13054     peepHole (&lineHead);
13055
13056   /* now do the actual printing */
13057   printLine (lineHead, codeOutFile);
13058   return;
13059 }