411e019f03b3c693e230c15740ede0341f316d9f
[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     emitcode ("clr", "ea");
2903
2904   /* here we need to generate the equates for the
2905      register bank if required */
2906   if (FUNC_REGBANK (ftype) != rbank)
2907     {
2908       int i;
2909
2910       rbank = FUNC_REGBANK (ftype);
2911       for (i = 0; i < ds390_nRegs; i++)
2912         {
2913           if (regs390[i].print) {
2914               if (strcmp (regs390[i].base, "0") == 0)
2915                   emitcode ("", "%s !equ !constbyte",
2916                             regs390[i].dname,
2917                             8 * rbank + regs390[i].offset);
2918               else
2919                   emitcode ("", "%s !equ %s + !constbyte",
2920                             regs390[i].dname,
2921                             regs390[i].base,
2922                             8 * rbank + regs390[i].offset);
2923           }
2924         }
2925     }
2926
2927   /* if this is an interrupt service routine then
2928      save acc, b, dpl, dph  */
2929   if (IFFUNC_ISISR (sym->type))
2930       { /* is ISR */
2931       if (!inExcludeList ("acc"))
2932         emitcode ("push", "acc");
2933       if (!inExcludeList ("b"))
2934         emitcode ("push", "b");
2935       if (!inExcludeList ("dpl"))
2936         emitcode ("push", "dpl");
2937       if (!inExcludeList ("dph"))
2938         emitcode ("push", "dph");
2939       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2940         {
2941           emitcode ("push", "dpx");
2942           /* Make sure we're using standard DPTR */
2943           emitcode ("push", "dps");
2944           emitcode ("mov", "dps,#0");
2945           if (options.stack10bit)
2946             {
2947               /* This ISR could conceivably use DPTR2. Better save it. */
2948               emitcode ("push", "dpl1");
2949               emitcode ("push", "dph1");
2950               emitcode ("push", "dpx1");
2951               emitcode ("push",  DP2_RESULT_REG);
2952             }
2953         }
2954       /* if this isr has no bank i.e. is going to
2955          run with bank 0 , then we need to save more
2956          registers :-) */
2957       if (!FUNC_REGBANK (sym->type))
2958         {
2959             int i;
2960
2961           /* if this function does not call any other
2962              function then we can be economical and
2963              save only those registers that are used */
2964           if (!IFFUNC_HASFCALL(sym->type))
2965             {
2966
2967               /* if any registers used */
2968               if (sym->regsUsed)
2969                 {
2970                   /* save the registers used */
2971                   for (i = 0; i < sym->regsUsed->size; i++)
2972                     {
2973                       if (bitVectBitValue (sym->regsUsed, i) ||
2974                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2975                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2976                     }
2977                 }
2978
2979             }
2980           else
2981             {
2982               /* this function has  a function call cannot
2983                  determines register usage so we will have to push the
2984                  entire bank */
2985               saveRBank (0, ic, FALSE);
2986               if (options.parms_in_bank1) {
2987                   for (i=0; i < 8 ; i++ ) {
2988                       emitcode ("push","%s",rb1regs[i]);
2989                   }
2990               }
2991             }
2992         }
2993         else
2994         {
2995             /* This ISR uses a non-zero bank.
2996              *
2997              * We assume that the bank is available for our
2998              * exclusive use.
2999              *
3000              * However, if this ISR calls a function which uses some
3001              * other bank, we must save that bank entirely.
3002              */
3003             unsigned long banksToSave = 0;
3004             
3005             if (IFFUNC_HASFCALL(sym->type))
3006             {
3007
3008 #define MAX_REGISTER_BANKS 4
3009
3010                 iCode *i;
3011                 int ix;
3012
3013                 for (i = ic; i; i = i->next)
3014                 {
3015                     if (i->op == ENDFUNCTION)
3016                     {
3017                         /* we got to the end OK. */
3018                         break;
3019                     }
3020                     
3021                     if (i->op == CALL)
3022                     {
3023                         sym_link *dtype;
3024                         
3025                         dtype = operandType (IC_LEFT(i));
3026                         if (dtype 
3027                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3028                         {
3029                              /* Mark this bank for saving. */
3030                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3031                              {
3032                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3033                              }
3034                              else
3035                              {
3036                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3037                              }
3038                              
3039                              /* And note that we don't need to do it in 
3040                               * genCall.
3041                               */
3042                              i->bankSaved = 1;
3043                         }
3044                     }
3045                     if (i->op == PCALL)
3046                     {
3047                         /* This is a mess; we have no idea what
3048                          * register bank the called function might
3049                          * use.
3050                          *
3051                          * The only thing I can think of to do is
3052                          * throw a warning and hope.
3053                          */
3054                         werror(W_FUNCPTR_IN_USING_ISR);   
3055                     }
3056                 }
3057
3058                 if (banksToSave && options.useXstack)
3059                 {
3060                     /* Since we aren't passing it an ic, 
3061                      * saveRBank will assume r0 is available to abuse.
3062                      *
3063                      * So switch to our (trashable) bank now, so
3064                      * the caller's R0 isn't trashed.
3065                      */
3066                     emitcode ("push", "psw");
3067                     emitcode ("mov", "psw,#!constbyte", 
3068                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3069                     switchedPSW = TRUE;
3070                 }
3071                 
3072                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3073                 {
3074                      if (banksToSave & (1 << ix))
3075                      {
3076                          saveRBank(ix, NULL, FALSE);
3077                      }
3078                 }
3079             }
3080             // TODO: this needs a closer look
3081             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3082         }
3083     }
3084   else
3085     {
3086       /* if callee-save to be used for this function
3087          then save the registers being used in this function */
3088       if (IFFUNC_CALLEESAVES(sym->type))
3089         {
3090           int i;
3091
3092           /* if any registers used */
3093           if (sym->regsUsed)
3094             {
3095               /* save the registers used */
3096               for (i = 0; i < sym->regsUsed->size; i++)
3097                 {
3098                   if (bitVectBitValue (sym->regsUsed, i) ||
3099                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3100                     {
3101                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3102                       _G.nRegsSaved++;
3103                     }
3104                 }
3105             }
3106         }
3107     }
3108
3109   /* set the register bank to the desired value */
3110   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3111    && !switchedPSW)
3112     {
3113       emitcode ("push", "psw");
3114       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3115     }
3116
3117   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3118        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3119       if (options.stack10bit) {
3120           emitcode ("push","_bpx");
3121           emitcode ("push","_bpx+1");
3122           emitcode ("mov","_bpx,%s",spname);
3123           emitcode ("mov","_bpx+1,esp");
3124           adjustEsp("_bpx+1");
3125       } else {
3126           if (options.useXstack) {
3127               emitcode ("mov", "r0,%s", spname);
3128               emitcode ("mov", "a,_bp");
3129               emitcode ("movx", "@r0,a");
3130               emitcode ("inc", "%s", spname);
3131           } else {
3132               /* set up the stack */
3133               emitcode ("push", "_bp"); /* save the callers stack  */
3134           }
3135           emitcode ("mov", "_bp,%s", spname);
3136       }
3137   }
3138
3139   /* adjust the stack for the function */
3140   if (sym->stack) {
3141       int i = sym->stack;
3142       if (options.stack10bit) {
3143           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3144           assert (sym->recvSize <= 4);
3145           if (sym->stack <= 8) {
3146               while (i--) emitcode ("push","acc");
3147           } else {
3148               PROTECT_SP;
3149               emitcode ("mov","a,sp");
3150               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3151               emitcode ("mov","sp,a");
3152               emitcode ("mov","a,esp");
3153               adjustEsp("a");
3154               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3155               emitcode ("mov","esp,a");
3156               UNPROTECT_SP;
3157           }
3158       } else {
3159           if (i > 256)
3160               werror (W_STACK_OVERFLOW, sym->name);
3161           
3162           if (i > 3 && sym->recvSize < 4) {
3163               
3164               emitcode ("mov", "a,sp");
3165               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3166               emitcode ("mov", "sp,a");
3167               
3168           } else
3169               while (i--)
3170                   emitcode ("inc", "sp");
3171       }
3172   }
3173
3174   if (sym->xstack)
3175     {
3176
3177       emitcode ("mov", "a,_spx");
3178       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3179       emitcode ("mov", "_spx,a");
3180     }
3181
3182 }
3183
3184 /*-----------------------------------------------------------------*/
3185 /* genEndFunction - generates epilogue for functions               */
3186 /*-----------------------------------------------------------------*/
3187 static void
3188 genEndFunction (iCode * ic)
3189 {
3190   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3191
3192   D (emitcode (";", "genEndFunction "););
3193
3194   if (IFFUNC_ISNAKED(sym->type))
3195   {
3196       emitcode(";", "naked function: no epilogue.");
3197       return;
3198   }
3199
3200   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3201        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3202
3203       if (options.stack10bit) {
3204           PROTECT_SP;     
3205           emitcode ("mov", "sp,_bpx", spname);
3206           emitcode ("mov", "esp,_bpx+1", spname);
3207           UNPROTECT_SP;
3208       } else {
3209           emitcode ("mov", "%s,_bp", spname);
3210       }
3211   }
3212
3213   /* if use external stack but some variables were
3214      added to the local stack then decrement the
3215      local stack */
3216   if (options.useXstack && sym->stack) {
3217       emitcode ("mov", "a,sp");
3218       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3219       emitcode ("mov", "sp,a");
3220   }
3221
3222
3223   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3224        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3225
3226       if (options.useXstack) {
3227           emitcode ("mov", "r0,%s", spname);
3228           emitcode ("movx", "a,@r0");
3229           emitcode ("mov", "_bp,a");
3230           emitcode ("dec", "%s", spname);
3231       } else {
3232           if (options.stack10bit) {
3233               emitcode ("pop", "_bpx+1");
3234               emitcode ("pop", "_bpx");
3235           } else {
3236               emitcode ("pop", "_bp");
3237           }
3238       }
3239   }
3240
3241   /* restore the register bank  */
3242   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3243   {
3244     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3245      || !options.useXstack)
3246     {
3247         /* Special case of ISR using non-zero bank with useXstack
3248          * is handled below.
3249          */
3250         emitcode ("pop", "psw");
3251     }
3252   } 
3253
3254   if (IFFUNC_ISISR (sym->type))
3255       { /* is ISR */  
3256
3257       /* now we need to restore the registers */
3258       /* if this isr has no bank i.e. is going to
3259          run with bank 0 , then we need to save more
3260          registers :-) */
3261       if (!FUNC_REGBANK (sym->type))
3262         {
3263             int i;
3264           /* if this function does not call any other
3265              function then we can be economical and
3266              save only those registers that are used */
3267           if (!IFFUNC_HASFCALL(sym->type))
3268             {
3269
3270               /* if any registers used */
3271               if (sym->regsUsed)
3272                 {
3273                   /* save the registers used */
3274                   for (i = sym->regsUsed->size; i >= 0; i--)
3275                     {
3276                       if (bitVectBitValue (sym->regsUsed, i) ||
3277                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3278                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3279                     }
3280                 }
3281
3282             }
3283           else
3284             {
3285               /* this function has  a function call cannot
3286                  determines register usage so we will have to pop the
3287                  entire bank */
3288               if (options.parms_in_bank1) {
3289                   for (i = 7 ; i >= 0 ; i-- ) {
3290                       emitcode ("pop","%s",rb1regs[i]);
3291                   }
3292               }
3293               unsaveRBank (0, ic, FALSE);
3294             }
3295         }
3296         else
3297         {
3298             /* This ISR uses a non-zero bank.
3299              *
3300              * Restore any register banks saved by genFunction
3301              * in reverse order.
3302              */
3303             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3304             int ix;
3305           
3306             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3307             {
3308                 if (savedBanks & (1 << ix))
3309                 {
3310                     unsaveRBank(ix, NULL, FALSE);
3311                 }
3312             }
3313             
3314             if (options.useXstack)
3315             {
3316                 /* Restore bank AFTER calling unsaveRBank,
3317                  * since it can trash r0.
3318                  */
3319                 emitcode ("pop", "psw");
3320             }
3321         }
3322
3323       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3324         {
3325           if (options.stack10bit)
3326             {
3327               emitcode ("pop", DP2_RESULT_REG);
3328               emitcode ("pop", "dpx1");
3329               emitcode ("pop", "dph1");
3330               emitcode ("pop", "dpl1");
3331             }
3332           emitcode ("pop", "dps");
3333           emitcode ("pop", "dpx");
3334         }
3335       if (!inExcludeList ("dph"))
3336         emitcode ("pop", "dph");
3337       if (!inExcludeList ("dpl"))
3338         emitcode ("pop", "dpl");
3339       if (!inExcludeList ("b"))
3340         emitcode ("pop", "b");
3341       if (!inExcludeList ("acc"))
3342         emitcode ("pop", "acc");
3343
3344       if (IFFUNC_ISCRITICAL (sym->type))
3345         emitcode ("setb", "ea");
3346
3347       /* if debug then send end of function */
3348       if (options.debug && currFunc) {
3349           _G.debugLine = 1;
3350           emitcode ("", "C$%s$%d$%d$%d ==.",
3351                     FileBaseName (ic->filename), currFunc->lastLine,
3352                     ic->level, ic->block);
3353           if (IS_STATIC (currFunc->etype))
3354             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3355           else
3356             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3357           _G.debugLine = 0;
3358         }
3359
3360       emitcode ("reti", "");
3361     }
3362   else
3363     {
3364       if (IFFUNC_ISCRITICAL (sym->type))
3365         emitcode ("setb", "ea");
3366
3367       if (IFFUNC_CALLEESAVES(sym->type))
3368         {
3369           int i;
3370
3371           /* if any registers used */
3372           if (sym->regsUsed)
3373             {
3374               /* save the registers used */
3375               for (i = sym->regsUsed->size; i >= 0; i--)
3376                 {
3377                   if (bitVectBitValue (sym->regsUsed, i) ||
3378                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3379                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3380                 }
3381             }
3382
3383         }
3384
3385       /* if debug then send end of function */
3386       if (options.debug && currFunc)
3387         {
3388           _G.debugLine = 1;
3389           emitcode ("", "C$%s$%d$%d$%d ==.",
3390                     FileBaseName (ic->filename), currFunc->lastLine,
3391                     ic->level, ic->block);
3392           if (IS_STATIC (currFunc->etype))
3393             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3394           else
3395             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3396           _G.debugLine = 0;
3397         }
3398
3399       emitcode ("ret", "");
3400     }
3401
3402 }
3403
3404 /*-----------------------------------------------------------------*/
3405 /* genJavaNativeRet - generate code for return JavaNative          */
3406 /*-----------------------------------------------------------------*/
3407 static void genJavaNativeRet(iCode *ic)
3408 {
3409     int i, size;
3410
3411     aopOp (IC_LEFT (ic), ic, FALSE, 
3412            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3413     size = AOP_SIZE (IC_LEFT (ic));
3414
3415     assert (size <= 4);
3416
3417     /* it is assigned to GPR0-R3 then push them */
3418     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3419         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3420         for (i = 0 ; i < size ; i++ ) {
3421             emitcode ("push","%s",
3422                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3423         }
3424         for (i = (size-1) ; i >= 0 ; i--) {
3425             emitcode ("pop","a%s",javaRet[i]);
3426         }
3427     } else {
3428         for (i = 0 ; i < size ; i++) 
3429             emitcode ("mov","%s,%s",javaRet[i],
3430                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3431     }
3432     for (i = size ; i < 4 ; i++ )
3433             emitcode ("mov","%s,#0",javaRet[i]);
3434     return;
3435 }
3436
3437 /*-----------------------------------------------------------------*/
3438 /* genRet - generate code for return statement                     */
3439 /*-----------------------------------------------------------------*/
3440 static void
3441 genRet (iCode * ic)
3442 {
3443   int size, offset = 0, pushed = 0;
3444
3445   D (emitcode (";", "genRet "););
3446
3447   /* if we have no return value then
3448      just generate the "ret" */
3449   if (!IC_LEFT (ic))
3450     goto jumpret;
3451
3452   /* if this is a JavaNative function then return 
3453      value in different register */
3454   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3455       genJavaNativeRet(ic);
3456       goto jumpret;
3457   }
3458   /* we have something to return then
3459      move the return value into place */
3460   aopOp (IC_LEFT (ic), ic, FALSE, 
3461          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3462   size = AOP_SIZE (IC_LEFT (ic));
3463
3464   _startLazyDPSEvaluation ();
3465   while (size--)
3466     {
3467       char *l;
3468       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3469         {
3470           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3471                       FALSE, TRUE, NULL);
3472           emitcode ("push", "%s", l);
3473           pushed++;
3474         }
3475       else
3476         {
3477           /* Since A is the last element of fReturn,
3478            * is is OK to clobber it in the aopGet.
3479            */
3480           l = aopGet (AOP (IC_LEFT (ic)), offset,
3481                       FALSE, FALSE, NULL);
3482           if (strcmp (fReturn[offset], l))
3483             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3484         }
3485     }
3486   _endLazyDPSEvaluation ();
3487
3488   if (pushed)
3489     {
3490       while (pushed)
3491         {
3492           pushed--;
3493           if (strcmp (fReturn[pushed], "a"))
3494             emitcode ("pop", fReturn[pushed]);
3495           else
3496             emitcode ("pop", "acc");
3497         }
3498     }
3499   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3500
3501 jumpret:
3502   /* generate a jump to the return label
3503      if the next is not the return statement */
3504   if (!(ic->next && ic->next->op == LABEL &&
3505         IC_LABEL (ic->next) == returnLabel))
3506
3507     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3508
3509 }
3510
3511 /*-----------------------------------------------------------------*/
3512 /* genLabel - generates a label                                    */
3513 /*-----------------------------------------------------------------*/
3514 static void
3515 genLabel (iCode * ic)
3516 {
3517   /* special case never generate */
3518   if (IC_LABEL (ic) == entryLabel)
3519     return;
3520
3521   D (emitcode (";", "genLabel ");
3522     );
3523
3524   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3525 }
3526
3527 /*-----------------------------------------------------------------*/
3528 /* genGoto - generates a ljmp                                      */
3529 /*-----------------------------------------------------------------*/
3530 static void
3531 genGoto (iCode * ic)
3532 {
3533   D (emitcode (";", "genGoto ");
3534     );
3535   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3536 }
3537
3538 /*-----------------------------------------------------------------*/
3539 /* findLabelBackwards: walks back through the iCode chain looking  */
3540 /* for the given label. Returns number of iCode instructions     */
3541 /* between that label and given ic.          */
3542 /* Returns zero if label not found.          */
3543 /*-----------------------------------------------------------------*/
3544 static int
3545 findLabelBackwards (iCode * ic, int key)
3546 {
3547   int count = 0;
3548
3549   while (ic->prev)
3550     {
3551       ic = ic->prev;
3552       count++;
3553
3554       /* If we have any pushes or pops, we cannot predict the distance.
3555          I don't like this at all, this should be dealt with in the 
3556          back-end */
3557       if (ic->op == IPUSH || ic->op == IPOP) {
3558         return 0;
3559       }
3560
3561       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3562         {
3563           /* printf("findLabelBackwards = %d\n", count); */
3564           return count;
3565         }
3566     }
3567
3568   return 0;
3569 }
3570
3571 /*-----------------------------------------------------------------*/
3572 /* genPlusIncr :- does addition with increment if possible         */
3573 /*-----------------------------------------------------------------*/
3574 static bool
3575 genPlusIncr (iCode * ic)
3576 {
3577   unsigned int icount;
3578   unsigned int size = getDataSize (IC_RESULT (ic));
3579
3580   /* will try to generate an increment */
3581   /* if the right side is not a literal
3582      we cannot */
3583   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3584     return FALSE;
3585
3586   /* if the literal value of the right hand side
3587      is greater than 4 then it is not worth it */
3588   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3589     return FALSE;
3590
3591   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3592       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3593       while (icount--) {
3594           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3595       }
3596       return TRUE;
3597   }
3598   /* if increment 16 bits in register */
3599   if (
3600        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3601        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3602        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3603        (size > 1) &&
3604        (icount == 1))
3605     {
3606       symbol  *tlbl;
3607       int     emitTlbl;
3608       int     labelRange;
3609       char    *l;
3610
3611       /* If the next instruction is a goto and the goto target
3612        * is <= 5 instructions previous to this, we can generate
3613        * jumps straight to that target.
3614        */
3615       if (ic->next && ic->next->op == GOTO
3616           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3617           && labelRange <= 5)
3618         {
3619           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3620           tlbl = IC_LABEL (ic->next);
3621           emitTlbl = 0;
3622         }
3623       else
3624         {
3625           tlbl = newiTempLabel (NULL);
3626           emitTlbl = 1;
3627         }
3628         
3629       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3630       emitcode ("inc", "%s", l);
3631       
3632       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3633           IS_AOP_PREG (IC_RESULT (ic)))
3634       {   
3635         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3636       }
3637       else
3638       {
3639           emitcode ("clr", "a");
3640           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3641       }
3642
3643       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3644       emitcode ("inc", "%s", l);
3645       if (size > 2)
3646         {
3647             if (!strcmp(l, "acc"))
3648             {
3649                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3650             }
3651             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3652                      IS_AOP_PREG (IC_RESULT (ic)))
3653             {
3654                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3655             }
3656             else
3657             {
3658                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3659             }
3660
3661             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3662             emitcode ("inc", "%s", l);
3663         }
3664       if (size > 3)
3665         {
3666             if (!strcmp(l, "acc"))
3667             {
3668                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3669             }
3670             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3671                      IS_AOP_PREG (IC_RESULT (ic)))
3672             {
3673                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3674             }
3675             else
3676             {
3677                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3678             }
3679
3680             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3681             emitcode ("inc", "%s", l);  }
3682
3683       if (emitTlbl)
3684         {
3685           emitcode ("", "!tlabeldef", tlbl->key + 100);
3686         }
3687       return TRUE;
3688     }
3689
3690   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3691       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3692       options.model == MODEL_FLAT24 ) {
3693
3694       switch (size) {
3695       case 3:
3696           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3697       case 2:
3698           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3699       case 1:
3700           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3701           break;
3702       }
3703       while (icount--) emitcode ("inc","dptr");      
3704       return TRUE;
3705   }
3706
3707   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3708       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3709       icount <= 5 ) {
3710       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3711       while (icount--) emitcode ("inc","dptr");
3712       emitcode ("mov","dps,#0");
3713       return TRUE;
3714   }
3715
3716   /* if the sizes are greater than 1 then we cannot */
3717   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718       AOP_SIZE (IC_LEFT (ic)) > 1)
3719     return FALSE;
3720
3721   /* we can if the aops of the left & result match or
3722      if they are in registers and the registers are the
3723      same */
3724   if (
3725        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3728     {
3729
3730       if (icount > 3)
3731         {
3732           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3733           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3734           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3735         }
3736       else
3737         {
3738
3739           _startLazyDPSEvaluation ();
3740           while (icount--)
3741             {
3742               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3743             }
3744           _endLazyDPSEvaluation ();
3745         }
3746
3747       return TRUE;
3748     }
3749
3750   return FALSE;
3751 }
3752
3753 /*-----------------------------------------------------------------*/
3754 /* outBitAcc - output a bit in acc                                 */
3755 /*-----------------------------------------------------------------*/
3756 static void
3757 outBitAcc (operand * result)
3758 {
3759   symbol *tlbl = newiTempLabel (NULL);
3760   /* if the result is a bit */
3761   if (AOP_TYPE (result) == AOP_CRY)
3762     {
3763       aopPut (AOP (result), "a", 0);
3764     }
3765   else
3766     {
3767       emitcode ("jz", "!tlabel", tlbl->key + 100);
3768       emitcode ("mov", "a,%s", one);
3769       emitcode ("", "!tlabeldef", tlbl->key + 100);
3770       outAcc (result);
3771     }
3772 }
3773
3774 /*-----------------------------------------------------------------*/
3775 /* genPlusBits - generates code for addition of two bits           */
3776 /*-----------------------------------------------------------------*/
3777 static void
3778 genPlusBits (iCode * ic)
3779 {
3780   D (emitcode (";", "genPlusBits "););
3781     
3782   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3783     {
3784       symbol *lbl = newiTempLabel (NULL);
3785       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787       emitcode ("cpl", "c");
3788       emitcode ("", "!tlabeldef", (lbl->key + 100));
3789       outBitC (IC_RESULT (ic));
3790     }
3791   else
3792     {
3793       emitcode ("clr", "a");
3794       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3795       emitcode ("rlc", "a");
3796       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3797       emitcode ("addc", "a,#0");
3798       outAcc (IC_RESULT (ic));
3799     }
3800 }
3801
3802 static void
3803 adjustArithmeticResult (iCode * ic)
3804 {
3805   if (opIsGptr (IC_RESULT (ic)) &&
3806       opIsGptr (IC_LEFT (ic)) &&
3807       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3808     {
3809       aopPut (AOP (IC_RESULT (ic)),
3810               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3811               GPTRSIZE - 1);
3812     }
3813
3814   if (opIsGptr (IC_RESULT (ic)) &&
3815       opIsGptr (IC_RIGHT (ic)) &&
3816       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3817     {
3818       aopPut (AOP (IC_RESULT (ic)),
3819             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3820               GPTRSIZE - 1);
3821     }
3822
3823   if (opIsGptr (IC_RESULT (ic)) &&
3824       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3825       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3826       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3827       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3828     {
3829       char buff[5];
3830       SNPRINTF (buff, sizeof(buff), 
3831                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3832       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3833     }
3834 }
3835
3836 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3837 // generates the result if possible. If result is generated, returns TRUE; otherwise
3838 // returns false and caller must deal with fact that result isn't aopOp'd.
3839 bool aopOp3(iCode * ic)
3840 {
3841     bool dp1InUse, dp2InUse;
3842     bool useDp2;
3843     
3844     // First, generate the right opcode. DPTR may be used if neither left nor result are
3845     // of type AOP_STR.
3846     
3847 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3848 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3849 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3850 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3851 //      );
3852 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3853 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3854 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3855 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3856 //      );
3857     
3858     // Right uses DPTR unless left or result is an AOP_STR; however,
3859     // if right is an AOP_STR, it must use DPTR regardless.
3860     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3861      && !AOP_IS_STR(IC_RIGHT(ic)))
3862     {
3863         useDp2 = TRUE;
3864     }
3865     else
3866     {
3867         useDp2 = FALSE;
3868     }
3869         
3870     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3871     
3872     // if the right used DPTR, left MUST use DPTR2.
3873     // if the right used DPTR2, left MUST use DPTR.
3874     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3875     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3876     // enabling us to assign DPTR to result.
3877      
3878     if (AOP_USESDPTR(IC_RIGHT(ic)))
3879     {
3880         useDp2 = TRUE;
3881     }
3882     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3883     {
3884         useDp2 = FALSE;
3885     }
3886     else
3887     {
3888         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3889         {
3890             useDp2 = TRUE;
3891         }
3892         else
3893         {
3894             useDp2 = FALSE;
3895         }
3896     }
3897
3898     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3899     
3900     // We've op'd the left & right. So, if left or right are the same operand as result, 
3901     // we know aopOp will succeed, and we can just do it & bail.
3902     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3903         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3904     {
3905 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3906         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3907         return TRUE;
3908     }
3909     
3910     // Note which dptrs are currently in use.
3911     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3912     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3913     
3914     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3915     // generate it.
3916     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3917     {
3918         return FALSE;
3919     }
3920     
3921     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3922     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3923     {
3924         return FALSE;
3925     }
3926     
3927     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3928     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3929     {
3930         return FALSE;
3931     }
3932
3933     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3934
3935     // Some sanity checking...
3936     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3937     {
3938         fprintf(stderr,
3939                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3940                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3941         emitcode(";", ">>> unexpected DPTR here.");
3942     }
3943     
3944     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3945     {
3946         fprintf(stderr,
3947                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3948                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3949         emitcode(";", ">>> unexpected DPTR2 here.");
3950     }    
3951     
3952     return TRUE;
3953 }
3954
3955 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3956 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3957 // will be set TRUE. The caller must then handle the case specially, noting
3958 // that the IC_RESULT operand is not aopOp'd.
3959 // 
3960 #define AOP_OP_3_NOFATAL(ic, rc) \
3961             do { rc = !aopOp3(ic); } while (0)
3962
3963 // aopOp the left & right operands of an ic.
3964 #define AOP_OP_2(ic) \
3965     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3966     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3967
3968 // convienience macro.
3969 #define AOP_SET_LOCALS(ic) \
3970     left = IC_LEFT(ic); \
3971     right = IC_RIGHT(ic); \
3972     result = IC_RESULT(ic);
3973
3974
3975 // Given an integer value of pushedSize bytes on the stack,
3976 // adjust it to be resultSize bytes, either by discarding
3977 // the most significant bytes or by zero-padding.
3978 //
3979 // On exit from this macro, pushedSize will have been adjusted to
3980 // equal resultSize, and ACC may be trashed.
3981 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3982       /* If the pushed data is bigger than the result,          \
3983        * simply discard unused bytes. Icky, but works.          \
3984        */                                                       \
3985       while (pushedSize > resultSize)                           \
3986       {                                                         \
3987           D (emitcode (";", "discarding unused result byte."););\
3988           emitcode ("pop", "acc");                              \
3989           pushedSize--;                                         \
3990       }                                                         \
3991       if (pushedSize < resultSize)                              \
3992       {                                                         \
3993           emitcode ("clr", "a");                                \
3994           /* Conversly, we haven't pushed enough here.          \
3995            * just zero-pad, and all is well.                    \
3996            */                                                   \
3997           while (pushedSize < resultSize)                       \
3998           {                                                     \
3999               emitcode("push", "acc");                          \
4000               pushedSize++;                                     \
4001           }                                                     \
4002       }                                                         \
4003       assert(pushedSize == resultSize);
4004
4005 /*-----------------------------------------------------------------*/
4006 /* genPlus - generates code for addition                           */
4007 /*-----------------------------------------------------------------*/
4008 static void
4009 genPlus (iCode * ic)
4010 {
4011   int size, offset = 0;
4012   bool pushResult;
4013   int rSize;
4014
4015   D (emitcode (";", "genPlus "););
4016
4017   /* special cases :- */
4018   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4019       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4020       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4021       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4022       if (size <= 9) {
4023           while (size--) emitcode ("inc","dptr");
4024       } else {
4025           emitcode ("mov","a,dpl");
4026           emitcode ("add","a,#!constbyte",size & 0xff);
4027           emitcode ("mov","dpl,a");
4028           emitcode ("mov","a,dph");
4029           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4030           emitcode ("mov","dph,a");
4031           emitcode ("mov","a,dpx");
4032           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4033           emitcode ("mov","dpx,a");
4034       }
4035       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4036       return ;
4037   }
4038   if ( IS_SYMOP(IC_LEFT(ic)) && 
4039        OP_SYMBOL(IC_LEFT(ic))->remat &&
4040        isOperandInFarSpace(IC_RIGHT(ic))) {
4041       operand *op = IC_RIGHT(ic);
4042       IC_RIGHT(ic) = IC_LEFT(ic);
4043       IC_LEFT(ic) = op;
4044   }
4045                 
4046   AOP_OP_3_NOFATAL (ic, pushResult);
4047     
4048   if (pushResult)
4049     {
4050       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4051     }
4052
4053   if (!pushResult)
4054     {
4055       /* if literal, literal on the right or
4056          if left requires ACC or right is already
4057          in ACC */
4058       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4059        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4060           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4061         {
4062           operand *t = IC_RIGHT (ic);
4063           IC_RIGHT (ic) = IC_LEFT (ic);
4064           IC_LEFT (ic) = t;
4065           emitcode (";", "Swapped plus args.");
4066         }
4067
4068       /* if both left & right are in bit
4069          space */
4070       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4071           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4072         {
4073           genPlusBits (ic);
4074           goto release;
4075         }
4076
4077       /* if left in bit space & right literal */
4078       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4079           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4080         {
4081           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4082           /* if result in bit space */
4083           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4084             {
4085               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4086                 emitcode ("cpl", "c");
4087               outBitC (IC_RESULT (ic));
4088             }
4089           else
4090             {
4091               size = getDataSize (IC_RESULT (ic));
4092               _startLazyDPSEvaluation ();
4093               while (size--)
4094                 {
4095                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4096                   emitcode ("addc", "a,#0");
4097                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4098                 }
4099               _endLazyDPSEvaluation ();
4100             }
4101           goto release;
4102         }
4103
4104       /* if I can do an increment instead
4105          of add then GOOD for ME */
4106       if (genPlusIncr (ic) == TRUE)
4107         {
4108           emitcode (";", "did genPlusIncr");
4109           goto release;
4110         }
4111
4112     }
4113   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4114
4115   _startLazyDPSEvaluation ();
4116   while (size--)
4117     {
4118       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4119         {
4120           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4121           if (offset == 0)
4122             emitcode ("add", "a,%s",
4123                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4124           else
4125             emitcode ("addc", "a,%s",
4126                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4127         }
4128       else
4129         {
4130           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4131           {
4132               /* right is going to use ACC or we would have taken the
4133                * above branch.
4134                */
4135               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4136        TR_AP("#3");
4137               D(emitcode(";", "+ AOP_ACC special case."););
4138               emitcode("xch", "a, %s", DP2_RESULT_REG);
4139           }
4140           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4141           if (offset == 0)
4142           {
4143             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4144             {
4145          TR_AP("#4");
4146                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4147             }
4148             else
4149             {
4150                 emitcode ("add", "a,%s",
4151                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4152                                   DP2_RESULT_REG));
4153             }
4154           }
4155           else
4156           {
4157             emitcode ("addc", "a,%s",
4158                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4159                           DP2_RESULT_REG));
4160           }
4161         }
4162       if (!pushResult)
4163         {
4164           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4165         }
4166       else
4167         {
4168           emitcode ("push", "acc");
4169         }
4170       offset++;
4171     }
4172   _endLazyDPSEvaluation ();
4173
4174   if (pushResult)
4175     {
4176       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4177
4178       size = getDataSize (IC_LEFT (ic));
4179       rSize = getDataSize (IC_RESULT (ic));
4180
4181       ADJUST_PUSHED_RESULT(size, rSize);
4182
4183       _startLazyDPSEvaluation ();
4184       while (size--)
4185         {
4186           emitcode ("pop", "acc");
4187           aopPut (AOP (IC_RESULT (ic)), "a", size);
4188         }
4189       _endLazyDPSEvaluation ();
4190     }
4191
4192   adjustArithmeticResult (ic);
4193
4194 release:
4195   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4196   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4197   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4198 }
4199
4200 /*-----------------------------------------------------------------*/
4201 /* genMinusDec :- does subtraction with deccrement if possible     */
4202 /*-----------------------------------------------------------------*/
4203 static bool
4204 genMinusDec (iCode * ic)
4205 {
4206   unsigned int icount;
4207   unsigned int size = getDataSize (IC_RESULT (ic));
4208
4209   /* will try to generate an increment */
4210   /* if the right side is not a literal
4211      we cannot */
4212   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4213     return FALSE;
4214
4215   /* if the literal value of the right hand side
4216      is greater than 4 then it is not worth it */
4217   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4218     return FALSE;
4219
4220   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4221       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4222       while (icount--) {
4223           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4224       }
4225       return TRUE;
4226   }
4227   /* if decrement 16 bits in register */
4228   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4229       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4230       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4231       (size > 1) &&
4232       (icount == 1))
4233     {
4234       symbol *tlbl;
4235       int    emitTlbl;
4236       int    labelRange;
4237       char   *l;
4238
4239       /* If the next instruction is a goto and the goto target
4240          * is <= 5 instructions previous to this, we can generate
4241          * jumps straight to that target.
4242        */
4243       if (ic->next && ic->next->op == GOTO
4244           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4245           && labelRange <= 5)
4246         {
4247           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4248           tlbl = IC_LABEL (ic->next);
4249           emitTlbl = 0;
4250         }
4251       else
4252         {
4253           tlbl = newiTempLabel (NULL);
4254           emitTlbl = 1;
4255         }
4256
4257       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4258       emitcode ("dec", "%s", l);
4259  
4260       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4261           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4262           IS_AOP_PREG (IC_RESULT (ic)))
4263       {     
4264           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4265       }
4266       else
4267       {
4268           emitcode ("mov", "a,#!constbyte",0xff);
4269           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4270       }
4271       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4272       emitcode ("dec", "%s", l);
4273       if (size > 2)
4274         {
4275             if (!strcmp(l, "acc"))
4276             {
4277                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4278             }
4279             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4280                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4281                      IS_AOP_PREG (IC_RESULT (ic)))
4282             {       
4283                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4284             }
4285             else
4286             {
4287                 emitcode ("mov", "a,#!constbyte",0xff);
4288                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4289             }
4290             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4291             emitcode ("dec", "%s", l);
4292         }
4293       if (size > 3)
4294         {
4295             if (!strcmp(l, "acc"))
4296             {
4297                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4298             }
4299             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4300                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4301                      IS_AOP_PREG (IC_RESULT (ic)))
4302             {       
4303                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4304             }
4305             else
4306             {
4307                 emitcode ("mov", "a,#!constbyte",0xff);
4308                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4309             }       
4310             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4311             emitcode ("dec", "%s", l);
4312         }
4313       if (emitTlbl)
4314         {
4315           emitcode ("", "!tlabeldef", tlbl->key + 100);
4316         }
4317       return TRUE;
4318     }
4319
4320   /* if the sizes are greater than 1 then we cannot */
4321   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4322       AOP_SIZE (IC_LEFT (ic)) > 1)
4323     return FALSE;
4324
4325   /* we can if the aops of the left & result match or
4326      if they are in registers and the registers are the
4327      same */
4328   if (
4329        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4330        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4331        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4332     {
4333
4334       _startLazyDPSEvaluation ();
4335       while (icount--)
4336         {
4337           emitcode ("dec", "%s",
4338                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4339         }
4340       _endLazyDPSEvaluation ();
4341
4342       return TRUE;
4343     }
4344
4345   return FALSE;
4346 }
4347
4348 /*-----------------------------------------------------------------*/
4349 /* addSign - complete with sign                                    */
4350 /*-----------------------------------------------------------------*/
4351 static void
4352 addSign (operand * result, int offset, int sign)
4353 {
4354   int size = (getDataSize (result) - offset);
4355   if (size > 0)
4356     {
4357       _startLazyDPSEvaluation();
4358       if (sign)
4359         {
4360           emitcode ("rlc", "a");
4361           emitcode ("subb", "a,acc");
4362           while (size--)
4363           {
4364             aopPut (AOP (result), "a", offset++);
4365           }
4366         }
4367       else
4368       {
4369         while (size--)
4370         {
4371           aopPut (AOP (result), zero, offset++);
4372         }
4373       }
4374       _endLazyDPSEvaluation();
4375     }
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genMinusBits - generates code for subtraction  of two bits      */
4380 /*-----------------------------------------------------------------*/
4381 static void
4382 genMinusBits (iCode * ic)
4383 {
4384   symbol *lbl = newiTempLabel (NULL);
4385
4386   D (emitcode (";", "genMinusBits "););
4387
4388   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4389     {
4390       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4391       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4392       emitcode ("cpl", "c");
4393       emitcode ("", "!tlabeldef", (lbl->key + 100));
4394       outBitC (IC_RESULT (ic));
4395     }
4396   else
4397     {
4398       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4399       emitcode ("subb", "a,acc");
4400       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4401       emitcode ("inc", "a");
4402       emitcode ("", "!tlabeldef", (lbl->key + 100));
4403       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4404       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4405     }
4406 }
4407
4408 /*-----------------------------------------------------------------*/
4409 /* genMinus - generates code for subtraction                       */
4410 /*-----------------------------------------------------------------*/
4411 static void
4412 genMinus (iCode * ic)
4413 {
4414     int size, offset = 0;
4415     int rSize;
4416     long lit = 0L;
4417     bool pushResult;
4418
4419     D (emitcode (";", "genMinus "););
4420
4421     AOP_OP_3_NOFATAL(ic, pushResult);   
4422
4423     if (!pushResult)
4424     {
4425       /* special cases :- */
4426       /* if both left & right are in bit space */
4427       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4428           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4429         {
4430           genMinusBits (ic);
4431           goto release;
4432         }
4433
4434       /* if I can do an decrement instead
4435          of subtract then GOOD for ME */
4436       if (genMinusDec (ic) == TRUE)
4437         goto release;
4438
4439     }
4440
4441   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4442
4443   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4444     {
4445       CLRC;
4446     }
4447   else
4448     {
4449       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4450       lit = -lit;
4451     }
4452
4453
4454   /* if literal, add a,#-lit, else normal subb */
4455   _startLazyDPSEvaluation ();
4456   while (size--) {
4457       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4458           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4459               emitcode ("mov","b,%s",
4460                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4461               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4462               emitcode ("subb","a,b");
4463           } else {
4464               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4465               emitcode ("subb", "a,%s",
4466                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4467                                 DP2_RESULT_REG));
4468           }
4469       } else {
4470           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4471           /* first add without previous c */
4472           if (!offset) {
4473               if (!size && lit==-1) {
4474                   emitcode ("dec", "a");
4475               } else {
4476                   emitcode ("add", "a,#!constbyte",
4477                             (unsigned int) (lit & 0x0FFL));
4478               }
4479           } else {
4480               emitcode ("addc", "a,#!constbyte",
4481                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4482           }
4483       }
4484       
4485       if (pushResult) {
4486           emitcode ("push", "acc");
4487       } else {
4488           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4489       }
4490       offset++;
4491   }
4492   _endLazyDPSEvaluation ();
4493   
4494   if (pushResult)
4495     {
4496       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4497
4498       size = getDataSize (IC_LEFT (ic));
4499       rSize = getDataSize (IC_RESULT (ic));
4500
4501       ADJUST_PUSHED_RESULT(size, rSize);
4502
4503       _startLazyDPSEvaluation ();
4504       while (size--)
4505         {
4506           emitcode ("pop", "acc");
4507           aopPut (AOP (IC_RESULT (ic)), "a", size);
4508         }
4509       _endLazyDPSEvaluation ();
4510     }
4511
4512   adjustArithmeticResult (ic);
4513
4514 release:
4515   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4518 }
4519
4520
4521 /*-----------------------------------------------------------------*/
4522 /* genMultbits :- multiplication of bits                           */
4523 /*-----------------------------------------------------------------*/
4524 static void
4525 genMultbits (operand * left,
4526              operand * right,
4527              operand * result,
4528              iCode   * ic)
4529 {
4530   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4531   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4532   aopOp(result, ic, TRUE, FALSE);
4533   outBitC (result);
4534 }
4535
4536
4537 /*-----------------------------------------------------------------*/
4538 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4539 /*-----------------------------------------------------------------*/
4540 static void
4541 genMultOneByte (operand * left,
4542                 operand * right,
4543                 operand * result,
4544                 iCode   * ic)
4545 {
4546   sym_link *opetype = operandType (result);
4547   symbol *lbl;
4548
4549
4550   /* (if two literals: the value is computed before) */
4551   /* if one literal, literal on the right */
4552   if (AOP_TYPE (left) == AOP_LIT)
4553     {
4554       operand *t = right;
4555       right = left;
4556       left = t;
4557       emitcode (";", "swapped left and right");
4558     }
4559
4560   if (SPEC_USIGN(opetype)
4561       // ignore the sign of left and right, what else can we do?
4562       || (SPEC_USIGN(operandType(left)) && 
4563           SPEC_USIGN(operandType(right)))) {
4564     // just an unsigned 8*8=8/16 multiply
4565     //emitcode (";","unsigned");
4566     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4567     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4568     emitcode ("mul", "ab");
4569    
4570     _G.accInUse++; _G.bInUse++;
4571     aopOp(result, ic, TRUE, FALSE);
4572       
4573       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4574       {
4575           // this should never happen
4576           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4577                    AOP_SIZE(result), __FILE__, lineno);
4578           exit (1);
4579       }      
4580       
4581     aopPut (AOP (result), "a", 0);
4582     _G.accInUse--; _G.bInUse--;
4583     if (AOP_SIZE(result)==2) 
4584     {
4585       aopPut (AOP (result), "b", 1);
4586     }
4587     return;
4588   }
4589
4590   // we have to do a signed multiply
4591
4592   emitcode (";", "signed");
4593   emitcode ("clr", "F0"); // reset sign flag
4594   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4595
4596   lbl=newiTempLabel(NULL);
4597   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4598   // left side is negative, 8-bit two's complement, this fails for -128
4599   emitcode ("setb", "F0"); // set sign flag
4600   emitcode ("cpl", "a");
4601   emitcode ("inc", "a");
4602
4603   emitcode ("", "!tlabeldef", lbl->key+100);
4604
4605   /* if literal */
4606   if (AOP_TYPE(right)==AOP_LIT) {
4607     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4608     /* AND literal negative */
4609     if ((int) val < 0) {
4610       emitcode ("cpl", "F0"); // complement sign flag
4611       emitcode ("mov", "b,#!constbyte", -val);
4612     } else {
4613       emitcode ("mov", "b,#!constbyte", val);
4614     }
4615   } else {
4616     lbl=newiTempLabel(NULL);
4617     emitcode ("mov", "b,a");
4618     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4619     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4620     // right side is negative, 8-bit two's complement
4621     emitcode ("cpl", "F0"); // complement sign flag
4622     emitcode ("cpl", "a");
4623     emitcode ("inc", "a");
4624     emitcode ("", "!tlabeldef", lbl->key+100);
4625   }
4626   emitcode ("mul", "ab");
4627     
4628   _G.accInUse++;_G.bInUse++;
4629   aopOp(result, ic, TRUE, FALSE);
4630     
4631   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4632   {
4633     // this should never happen
4634       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4635                AOP_SIZE(result), __FILE__, lineno);
4636       exit (1);
4637   }    
4638     
4639   lbl=newiTempLabel(NULL);
4640   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4641   // only ONE op was negative, we have to do a 8/16-bit two's complement
4642   emitcode ("cpl", "a"); // lsb
4643   if (AOP_SIZE(result)==1) {
4644     emitcode ("inc", "a");
4645   } else {
4646     emitcode ("add", "a,#1");
4647     emitcode ("xch", "a,b");
4648     emitcode ("cpl", "a"); // msb
4649     emitcode ("addc", "a,#0");
4650     emitcode ("xch", "a,b");
4651   }
4652
4653   emitcode ("", "!tlabeldef", lbl->key+100);
4654   aopPut (AOP (result), "a", 0);
4655   _G.accInUse--;_G.bInUse--;
4656   if (AOP_SIZE(result)==2) {
4657     aopPut (AOP (result), "b", 1);
4658   }
4659 }
4660
4661 /*-----------------------------------------------------------------*/
4662 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4663 /*-----------------------------------------------------------------*/
4664 static void genMultTwoByte (operand *left, operand *right, 
4665                             operand *result, iCode *ic)
4666 {
4667         sym_link *retype = getSpec(operandType(right));
4668         sym_link *letype = getSpec(operandType(left));
4669         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4670         symbol *lbl;
4671
4672         if (AOP_TYPE (left) == AOP_LIT) {
4673                 operand *t = right;
4674                 right = left;
4675                 left = t;
4676         }
4677         /* save EA bit in F1 */
4678         lbl = newiTempLabel(NULL);
4679         emitcode ("setb","F1");
4680         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4681         emitcode ("clr","F1");
4682         emitcode("","!tlabeldef",lbl->key+100);
4683
4684         /* load up MB with right */
4685         if (!umult) {
4686                 emitcode("clr","F0");
4687                 if (AOP_TYPE(right) == AOP_LIT) {
4688                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4689                         if (val < 0) {
4690                                 emitcode("setb","F0");
4691                                 val = -val;
4692                         }
4693                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4694                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4695                 } else {
4696                         lbl = newiTempLabel(NULL);
4697                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4698                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4699                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4700                         emitcode ("xch", "a,b");
4701                         emitcode ("cpl","a");
4702                         emitcode ("add", "a,#1");
4703                         emitcode ("xch", "a,b");
4704                         emitcode ("cpl", "a"); // msb
4705                         emitcode ("addc", "a,#0");
4706                         emitcode ("setb","F0");
4707                         emitcode ("","!tlabeldef",lbl->key+100);
4708                         emitcode ("mov","mb,b");
4709                         emitcode ("mov","mb,a");
4710                 }
4711         } else {
4712                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4713                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4714         }
4715         /* load up MA with left */
4716         if (!umult) {
4717                 lbl = newiTempLabel(NULL);
4718                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4719                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4720                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4721                 emitcode ("xch", "a,b");
4722                 emitcode ("cpl","a");
4723                 emitcode ("add", "a,#1");
4724                 emitcode ("xch", "a,b");
4725                 emitcode ("cpl", "a"); // msb
4726                 emitcode ("addc","a,#0");
4727                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4728                 emitcode ("setb","F0");
4729                 emitcode ("","!tlabeldef",lbl->key+100);
4730                 emitcode ("mov","ma,b");
4731                 emitcode ("mov","ma,a");
4732         } else {
4733                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4734                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4735         }
4736         /* wait for multiplication to finish */
4737         lbl = newiTempLabel(NULL);
4738         emitcode("","!tlabeldef", lbl->key+100);
4739         emitcode("mov","a,mcnt1");
4740         emitcode("anl","a,#!constbyte",0x80);
4741         emitcode("jnz","!tlabel",lbl->key+100);
4742         
4743         freeAsmop (left, NULL, ic, TRUE);
4744         freeAsmop (right, NULL, ic,TRUE);
4745         aopOp(result, ic, TRUE, FALSE);
4746
4747         /* if unsigned then simple */   
4748         if (umult) {
4749                 emitcode ("mov","a,ma");
4750                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4751                 emitcode ("mov","a,ma");
4752                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4753                 aopPut(AOP(result),"ma",1);
4754                 aopPut(AOP(result),"ma",0);
4755         } else {
4756                 emitcode("push","ma");
4757                 emitcode("push","ma");
4758                 emitcode("push","ma");
4759                 MOVA("ma");
4760                 /* negate result if needed */
4761                 lbl = newiTempLabel(NULL);      
4762                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4763                 emitcode("cpl","a");
4764                 emitcode("add","a,#1");
4765                 emitcode("","!tlabeldef", lbl->key+100);
4766                 if (AOP_TYPE(result) == AOP_ACC)
4767                 {
4768                     D(emitcode(";", "ACC special case."););
4769                     /* We know result is the only live aop, and 
4770                      * it's obviously not a DPTR2, so AP is available.
4771                      */
4772                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4773                 }
4774                 else
4775                 {
4776                     aopPut(AOP(result),"a",0);
4777                 }
4778             
4779                 emitcode("pop","acc");
4780                 lbl = newiTempLabel(NULL);      
4781                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4782                 emitcode("cpl","a");
4783                 emitcode("addc","a,#0");
4784                 emitcode("","!tlabeldef", lbl->key+100);
4785                 aopPut(AOP(result),"a",1);
4786                 emitcode("pop","acc");
4787                 if (AOP_SIZE(result) >= 3) {
4788                         lbl = newiTempLabel(NULL);      
4789                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4790                         emitcode("cpl","a");
4791                         emitcode("addc","a,#0");                        
4792                         emitcode("","!tlabeldef", lbl->key+100);
4793                         aopPut(AOP(result),"a",2);
4794                 }
4795                 emitcode("pop","acc");
4796                 if (AOP_SIZE(result) >= 4) {
4797                         lbl = newiTempLabel(NULL);      
4798                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4799                         emitcode("cpl","a");
4800                         emitcode("addc","a,#0");                        
4801                         emitcode("","!tlabeldef", lbl->key+100);
4802                         aopPut(AOP(result),"a",3);
4803                 }
4804                 if (AOP_TYPE(result) == AOP_ACC)
4805                 {
4806                     /* We stashed the result away above. */
4807                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4808                 }           
4809                 
4810         }
4811         freeAsmop (result, NULL, ic, TRUE);
4812
4813         /* restore EA bit in F1 */
4814         lbl = newiTempLabel(NULL);
4815         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4816         emitcode ("setb","EA");
4817         emitcode("","!tlabeldef",lbl->key+100);
4818         return ;
4819 }
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genMult - generates code for multiplication                     */
4823 /*-----------------------------------------------------------------*/
4824 static void
4825 genMult (iCode * ic)
4826 {
4827   operand *left = IC_LEFT (ic);
4828   operand *right = IC_RIGHT (ic);
4829   operand *result = IC_RESULT (ic);
4830
4831   D (emitcode (";", "genMult "););
4832
4833   /* assign the amsops */
4834   AOP_OP_2 (ic);
4835
4836   /* special cases first */
4837   /* both are bits */
4838   if (AOP_TYPE (left) == AOP_CRY &&
4839       AOP_TYPE (right) == AOP_CRY)
4840     {
4841       genMultbits (left, right, result, ic);
4842       goto release;
4843     }
4844
4845   /* if both are of size == 1 */
4846   if (AOP_SIZE (left) == 1 &&
4847       AOP_SIZE (right) == 1)
4848     {
4849       genMultOneByte (left, right, result, ic);
4850       goto release;
4851     }
4852
4853   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4854           /* use the ds390 ARITHMETIC accel UNIT */
4855           genMultTwoByte (left, right, result, ic);
4856           return ;
4857   }
4858   /* should have been converted to function call */
4859   assert (0);
4860
4861 release:
4862   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864   freeAsmop (result, NULL, ic, TRUE);
4865 }
4866
4867 /*-----------------------------------------------------------------*/
4868 /* genDivbits :- division of bits                                  */
4869 /*-----------------------------------------------------------------*/
4870 static void
4871 genDivbits (operand * left,
4872             operand * right,
4873             operand * result,
4874             iCode   * ic)
4875 {
4876
4877   char *l;
4878
4879   /* the result must be bit */
4880   LOAD_AB_FOR_DIV (left, right, l);
4881   emitcode ("div", "ab");
4882   emitcode ("rrc", "a");
4883   aopOp(result, ic, TRUE, FALSE);
4884     
4885   aopPut (AOP (result), "c", 0);
4886 }
4887
4888 /*-----------------------------------------------------------------*/
4889 /* genDivOneByte : 8 bit division                                  */
4890 /*-----------------------------------------------------------------*/
4891 static void
4892 genDivOneByte (operand * left,
4893                operand * right,
4894                operand * result,
4895                iCode   * ic)
4896 {
4897   sym_link *opetype = operandType (result);
4898   char *l;
4899   symbol *lbl;
4900   int size, offset;
4901
4902   offset = 1;
4903   /* signed or unsigned */
4904   if (SPEC_USIGN (opetype))
4905     {
4906         /* unsigned is easy */
4907         LOAD_AB_FOR_DIV (left, right, l);
4908         emitcode ("div", "ab");
4909
4910         _G.accInUse++;
4911         aopOp(result, ic, TRUE, FALSE);
4912         aopPut (AOP (result), "a", 0);
4913         _G.accInUse--;
4914
4915         size = AOP_SIZE (result) - 1;
4916         
4917         while (size--)
4918         {
4919             aopPut (AOP (result), zero, offset++);
4920         }
4921       return;
4922     }
4923
4924   /* signed is a little bit more difficult */
4925
4926   /* save the signs of the operands */
4927   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4928   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4929   emitcode ("push", "acc");     /* save it on the stack */
4930
4931   /* now sign adjust for both left & right */
4932   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4933   lbl = newiTempLabel (NULL);
4934   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4935   emitcode ("cpl", "a");
4936   emitcode ("inc", "a");
4937   emitcode ("", "!tlabeldef", (lbl->key + 100));
4938   emitcode ("mov", "b,a");
4939
4940   /* sign adjust left side */
4941   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4942
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
4949   /* now the division */
4950   emitcode ("nop", "; workaround for DS80C390 div bug.");
4951   emitcode ("div", "ab");
4952   /* we are interested in the lower order
4953      only */
4954   emitcode ("mov", "b,a");
4955   lbl = newiTempLabel (NULL);
4956   emitcode ("pop", "acc");
4957   /* if there was an over flow we don't
4958      adjust the sign of the result */
4959   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4960   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4961   CLRC;
4962   emitcode ("clr", "a");
4963   emitcode ("subb", "a,b");
4964   emitcode ("mov", "b,a");
4965   emitcode ("", "!tlabeldef", (lbl->key + 100));
4966
4967   /* now we are done */
4968   _G.accInUse++;     _G.bInUse++;
4969     aopOp(result, ic, TRUE, FALSE);
4970     
4971     aopPut (AOP (result), "b", 0);
4972     
4973     size = AOP_SIZE (result) - 1;
4974     
4975     if (size > 0)
4976     {
4977       emitcode ("mov", "c,b.7");
4978       emitcode ("subb", "a,acc");
4979     }
4980     while (size--)
4981     {
4982         aopPut (AOP (result), "a", offset++);
4983     }
4984     _G.accInUse--;     _G.bInUse--;
4985
4986 }
4987
4988 /*-----------------------------------------------------------------*/
4989 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4990 /*-----------------------------------------------------------------*/
4991 static void genDivTwoByte (operand *left, operand *right, 
4992                             operand *result, iCode *ic)
4993 {
4994         sym_link *retype = getSpec(operandType(right));
4995         sym_link *letype = getSpec(operandType(left));
4996         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4997         symbol *lbl;
4998
4999         /* save EA bit in F1 */
5000         lbl = newiTempLabel(NULL);
5001         emitcode ("setb","F1");
5002         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5003         emitcode ("clr","F1");
5004         emitcode("","!tlabeldef",lbl->key+100);
5005
5006         /* load up MA with left */
5007         if (!umult) {
5008                 emitcode("clr","F0");
5009                 lbl = newiTempLabel(NULL);
5010                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5011                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5012                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5013                 emitcode ("xch", "a,b");
5014                 emitcode ("cpl","a");
5015                 emitcode ("add", "a,#1");
5016                 emitcode ("xch", "a,b");
5017                 emitcode ("cpl", "a"); // msb
5018                 emitcode ("addc","a,#0");
5019                 emitcode ("setb","F0");
5020                 emitcode ("","!tlabeldef",lbl->key+100);
5021                 emitcode ("mov","ma,b");
5022                 emitcode ("mov","ma,a");
5023         } else {
5024                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5026         }
5027
5028         /* load up MB with right */
5029         if (!umult) {
5030                 if (AOP_TYPE(right) == AOP_LIT) {
5031                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5032                         if (val < 0) {
5033                                 lbl = newiTempLabel(NULL);
5034                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035                                 emitcode("setb","F0");
5036                                 emitcode ("","!tlabeldef",lbl->key+100);
5037                                 val = -val;
5038                         } 
5039                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5040                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5041                 } else {
5042                         lbl = newiTempLabel(NULL);
5043                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5044                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5045                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5046                         emitcode ("xch", "a,b");
5047                         emitcode ("cpl","a");
5048                         emitcode ("add", "a,#1");
5049                         emitcode ("xch", "a,b");
5050                         emitcode ("cpl", "a"); // msb
5051                         emitcode ("addc", "a,#0");
5052                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5053                         emitcode ("setb","F0");
5054                         emitcode ("","!tlabeldef",lbl->key+100);
5055                         emitcode ("mov","mb,b");
5056                         emitcode ("mov","mb,a");
5057                 }
5058         } else {
5059                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5060                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5061         }
5062
5063         /* wait for multiplication to finish */
5064         lbl = newiTempLabel(NULL);
5065         emitcode("","!tlabeldef", lbl->key+100);
5066         emitcode("mov","a,mcnt1");
5067         emitcode("anl","a,#!constbyte",0x80);
5068         emitcode("jnz","!tlabel",lbl->key+100);
5069         
5070         freeAsmop (left, NULL, ic, TRUE);
5071         freeAsmop (right, NULL, ic,TRUE);
5072         aopOp(result, ic, TRUE, FALSE);
5073
5074         /* if unsigned then simple */   
5075         if (umult) {
5076                 aopPut(AOP(result),"ma",1);
5077                 aopPut(AOP(result),"ma",0);
5078         } else {
5079                 emitcode("push","ma");
5080                 MOVA("ma");
5081                 /* negate result if needed */
5082                 lbl = newiTempLabel(NULL);      
5083                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5084                 emitcode("cpl","a");
5085                 emitcode("add","a,#1");
5086                 emitcode("","!tlabeldef", lbl->key+100);
5087                 aopPut(AOP(result),"a",0);
5088                 emitcode("pop","acc");
5089                 lbl = newiTempLabel(NULL);      
5090                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5091                 emitcode("cpl","a");
5092                 emitcode("addc","a,#0");
5093                 emitcode("","!tlabeldef", lbl->key+100);
5094                 aopPut(AOP(result),"a",1);
5095         }
5096         freeAsmop (result, NULL, ic, TRUE);
5097         /* restore EA bit in F1 */
5098         lbl = newiTempLabel(NULL);
5099         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5100         emitcode ("setb","EA");
5101         emitcode("","!tlabeldef",lbl->key+100);
5102         return ;
5103 }
5104
5105 /*-----------------------------------------------------------------*/
5106 /* genDiv - generates code for division                            */
5107 /*-----------------------------------------------------------------*/
5108 static void
5109 genDiv (iCode * ic)
5110 {
5111   operand *left = IC_LEFT (ic);
5112   operand *right = IC_RIGHT (ic);
5113   operand *result = IC_RESULT (ic);
5114
5115   D (emitcode (";", "genDiv "););
5116
5117   /* assign the amsops */
5118   AOP_OP_2 (ic);
5119
5120   /* special cases first */
5121   /* both are bits */
5122   if (AOP_TYPE (left) == AOP_CRY &&
5123       AOP_TYPE (right) == AOP_CRY)
5124     {
5125       genDivbits (left, right, result, ic);
5126       goto release;
5127     }
5128
5129   /* if both are of size == 1 */
5130   if (AOP_SIZE (left) == 1 &&
5131       AOP_SIZE (right) == 1)
5132     {
5133       genDivOneByte (left, right, result, ic);
5134       goto release;
5135     }
5136
5137   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5138           /* use the ds390 ARITHMETIC accel UNIT */
5139           genDivTwoByte (left, right, result, ic);
5140           return ;
5141   }
5142   /* should have been converted to function call */
5143   assert (0);
5144 release:
5145   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5146   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5147   freeAsmop (result, NULL, ic, TRUE);
5148 }
5149
5150 /*-----------------------------------------------------------------*/
5151 /* genModbits :- modulus of bits                                   */
5152 /*-----------------------------------------------------------------*/
5153 static void
5154 genModbits (operand * left,
5155             operand * right,
5156             operand * result,
5157             iCode   * ic)
5158 {
5159
5160   char *l;
5161
5162   /* the result must be bit */
5163   LOAD_AB_FOR_DIV (left, right, l);
5164   emitcode ("div", "ab");
5165   emitcode ("mov", "a,b");
5166   emitcode ("rrc", "a");
5167   aopOp(result, ic, TRUE, FALSE);
5168   aopPut (AOP (result), "c", 0);
5169 }
5170
5171 /*-----------------------------------------------------------------*/
5172 /* genModOneByte : 8 bit modulus                                   */
5173 /*-----------------------------------------------------------------*/
5174 static void
5175 genModOneByte (operand * left,
5176                operand * right,
5177                operand * result,
5178                iCode   * ic)
5179 {
5180   sym_link *opetype = operandType (result);
5181   char *l;
5182   symbol *lbl;
5183
5184   /* signed or unsigned */
5185   if (SPEC_USIGN (opetype))
5186     {
5187       /* unsigned is easy */
5188       LOAD_AB_FOR_DIV (left, right, l);
5189       emitcode ("div", "ab");
5190       aopOp(result, ic, TRUE, FALSE);   
5191       aopPut (AOP (result), "b", 0);
5192       return;
5193     }
5194
5195   /* signed is a little bit more difficult */
5196
5197   /* save the signs of the operands */
5198   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5199
5200   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5201   emitcode ("push", "acc");     /* save it on the stack */
5202
5203   /* now sign adjust for both left & right */
5204   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5205
5206   lbl = newiTempLabel (NULL);
5207   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5208   emitcode ("cpl", "a");
5209   emitcode ("inc", "a");
5210   emitcode ("", "!tlabeldef", (lbl->key + 100));
5211   emitcode ("mov", "b,a");
5212
5213   /* sign adjust left side */
5214   MOVA (aopGet (AOP (left), 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
5222   /* now the multiplication */
5223   emitcode ("nop", "; workaround for DS80C390 div bug.");
5224   emitcode ("div", "ab");
5225   /* we are interested in the lower order
5226      only */
5227   lbl = newiTempLabel (NULL);
5228   emitcode ("pop", "acc");
5229   /* if there was an over flow we don't
5230      adjust the sign of the result */
5231   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5232   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5233   CLRC;
5234   emitcode ("clr", "a");
5235   emitcode ("subb", "a,b");
5236   emitcode ("mov", "b,a");
5237   emitcode ("", "!tlabeldef", (lbl->key + 100));
5238   
5239   _G.bInUse++;
5240   /* now we are done */
5241   aopOp(result, ic, TRUE, FALSE);    
5242   aopPut (AOP (result), "b", 0);
5243   _G.bInUse--;
5244
5245 }
5246
5247 /*-----------------------------------------------------------------*/
5248 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5249 /*-----------------------------------------------------------------*/
5250 static void genModTwoByte (operand *left, operand *right, 
5251                             operand *result, iCode *ic)
5252 {
5253         sym_link *retype = getSpec(operandType(right));
5254         sym_link *letype = getSpec(operandType(left));
5255         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5256         symbol *lbl;
5257
5258         /* load up MA with left */
5259         /* save EA bit in F1 */
5260         lbl = newiTempLabel(NULL);
5261         emitcode ("setb","F1");
5262         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5263         emitcode ("clr","F1");
5264         emitcode("","!tlabeldef",lbl->key+100);
5265
5266         if (!umult) {
5267                 lbl = newiTempLabel(NULL);
5268                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5269                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5270                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5271                 emitcode ("xch", "a,b");
5272                 emitcode ("cpl","a");
5273                 emitcode ("add", "a,#1");
5274                 emitcode ("xch", "a,b");
5275                 emitcode ("cpl", "a"); // msb
5276                 emitcode ("addc","a,#0");
5277                 emitcode ("","!tlabeldef",lbl->key+100);
5278                 emitcode ("mov","ma,b");
5279                 emitcode ("mov","ma,a");
5280         } else {
5281                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5282                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5283         }
5284
5285         /* load up MB with right */
5286         if (!umult) {
5287                 if (AOP_TYPE(right) == AOP_LIT) {
5288                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5289                         if (val < 0) {
5290                                 val = -val;
5291                         } 
5292                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5293                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5294                 } else {
5295                         lbl = newiTempLabel(NULL);
5296                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5297                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5298                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5299                         emitcode ("xch", "a,b");
5300                         emitcode ("cpl","a");
5301                         emitcode ("add", "a,#1");
5302                         emitcode ("xch", "a,b");
5303                         emitcode ("cpl", "a"); // msb
5304                         emitcode ("addc", "a,#0");
5305                         emitcode ("","!tlabeldef",lbl->key+100);
5306                         emitcode ("mov","mb,b");
5307                         emitcode ("mov","mb,a");
5308                 }
5309         } else {
5310                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5311                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5312         }
5313
5314         /* wait for multiplication to finish */
5315         lbl = newiTempLabel(NULL);
5316         emitcode("","!tlabeldef", lbl->key+100);
5317         emitcode("mov","a,mcnt1");
5318         emitcode("anl","a,#!constbyte",0x80);
5319         emitcode("jnz","!tlabel",lbl->key+100);
5320         
5321         freeAsmop (left, NULL, ic, TRUE);
5322         freeAsmop (right, NULL, ic,TRUE);
5323         aopOp(result, ic, TRUE, FALSE);
5324
5325         aopPut(AOP(result),"mb",1);
5326         aopPut(AOP(result),"mb",0);
5327         freeAsmop (result, NULL, ic, TRUE);
5328
5329         /* restore EA bit in F1 */
5330         lbl = newiTempLabel(NULL);
5331         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5332         emitcode ("setb","EA");
5333         emitcode("","!tlabeldef",lbl->key+100);
5334         return ;
5335 }
5336
5337 /*-----------------------------------------------------------------*/
5338 /* genMod - generates code for division                            */
5339 /*-----------------------------------------------------------------*/
5340 static void
5341 genMod (iCode * ic)
5342 {
5343   operand *left = IC_LEFT (ic);
5344   operand *right = IC_RIGHT (ic);
5345   operand *result = IC_RESULT (ic);
5346
5347   D (emitcode (";", "genMod "); );
5348
5349   /* assign the amsops */
5350   AOP_OP_2 (ic);
5351
5352   /* special cases first */
5353   /* both are bits */
5354   if (AOP_TYPE (left) == AOP_CRY &&
5355       AOP_TYPE (right) == AOP_CRY)
5356     {
5357       genModbits (left, right, result, ic);
5358       goto release;
5359     }
5360
5361   /* if both are of size == 1 */
5362   if (AOP_SIZE (left) == 1 &&
5363       AOP_SIZE (right) == 1)
5364     {
5365       genModOneByte (left, right, result, ic);
5366       goto release;
5367     }
5368
5369   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5370           /* use the ds390 ARITHMETIC accel UNIT */
5371           genModTwoByte (left, right, result, ic);
5372           return ;
5373   }
5374
5375   /* should have been converted to function call */
5376   assert (0);
5377
5378 release:
5379   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5380   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381   freeAsmop (result, NULL, ic, TRUE);
5382 }
5383
5384 /*-----------------------------------------------------------------*/
5385 /* genIfxJump :- will create a jump depending on the ifx           */
5386 /*-----------------------------------------------------------------*/
5387 static void
5388 genIfxJump (iCode * ic, char *jval)
5389 {
5390   symbol *jlbl;
5391   symbol *tlbl = newiTempLabel (NULL);
5392   char *inst;
5393
5394   D (emitcode (";", "genIfxJump"););
5395
5396   /* if true label then we jump if condition
5397      supplied is true */
5398   if (IC_TRUE (ic))
5399     {
5400       jlbl = IC_TRUE (ic);
5401       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5402                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5403     }
5404   else
5405     {
5406       /* false label is present */
5407       jlbl = IC_FALSE (ic);
5408       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5409                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5410     }
5411   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5412     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5413   else
5414     emitcode (inst, "!tlabel", tlbl->key + 100);
5415   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5416   emitcode ("", "!tlabeldef", tlbl->key + 100);
5417
5418   /* mark the icode as generated */
5419   ic->generated = 1;
5420 }
5421
5422 /*-----------------------------------------------------------------*/
5423 /* genCmp :- greater or less than comparison                       */
5424 /*-----------------------------------------------------------------*/
5425 static void
5426 genCmp (operand * left, operand * right,
5427         iCode * ic, iCode * ifx, int sign)
5428 {
5429   int size, offset = 0;
5430   unsigned long lit = 0L;
5431   operand *result;
5432
5433   D (emitcode (";", "genCmp"););
5434
5435   result = IC_RESULT (ic);
5436
5437   /* if left & right are bit variables */
5438   if (AOP_TYPE (left) == AOP_CRY &&
5439       AOP_TYPE (right) == AOP_CRY)
5440     {
5441       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5442       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5443     }
5444   else
5445     {
5446       /* subtract right from left if at the
5447          end the carry flag is set then we know that
5448          left is greater than right */
5449       size = max (AOP_SIZE (left), AOP_SIZE (right));
5450
5451       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5452       if ((size == 1) && !sign 
5453           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5454         {
5455           symbol *lbl = newiTempLabel (NULL);
5456           emitcode ("cjne", "%s,%s,!tlabel",
5457                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5458                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5459                     lbl->key + 100);
5460           emitcode ("", "!tlabeldef", lbl->key + 100);
5461         }
5462       else
5463         {
5464           if (AOP_TYPE (right) == AOP_LIT)
5465             {
5466               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5467               /* optimize if(x < 0) or if(x >= 0) */
5468               if (lit == 0L)
5469                 {
5470                   if (!sign)
5471                     {
5472                       CLRC;
5473                     }
5474                   else
5475                     {
5476                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5477
5478                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5480
5481                       aopOp (result, ic, FALSE, FALSE);
5482
5483                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5484                         {
5485                           freeAsmop (result, NULL, ic, TRUE);
5486                           genIfxJump (ifx, "acc.7");
5487                           return;
5488                         }
5489                       else
5490                         {
5491                           emitcode ("rlc", "a");
5492                         }
5493                       goto release_freedLR;
5494                     }
5495                   goto release;
5496                 }
5497             }
5498           CLRC;
5499           while (size--)
5500             {
5501               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5502               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5503               // emitcode (";", "genCmp #2");
5504               if (sign && (size == 0))
5505                 {
5506                   // emitcode (";", "genCmp #3");
5507                   emitcode ("xrl", "a,#!constbyte",0x80);
5508                   if (AOP_TYPE (right) == AOP_LIT)
5509                     {
5510                       unsigned long lit = (unsigned long)
5511                       floatFromVal (AOP (right)->aopu.aop_lit);
5512                       // emitcode (";", "genCmp #3.1");
5513                       emitcode ("subb", "a,#!constbyte",
5514                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5515                     }
5516                   else
5517                     {
5518                       // emitcode (";", "genCmp #3.2");
5519                       saveAccWarn = 0;  
5520                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5521                       saveAccWarn = DEFAULT_ACC_WARNING;
5522                       emitcode ("xrl", "b,#!constbyte",0x80);
5523                       emitcode ("subb", "a,b");
5524                     }
5525                 }
5526               else
5527                 {
5528                   const char *s;
5529
5530                   // emitcode (";", "genCmp #4");
5531                   saveAccWarn = 0;
5532                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5533                   saveAccWarn = DEFAULT_ACC_WARNING;
5534
5535                   emitcode ("subb", "a,%s", s);
5536                 }
5537             }
5538         }
5539     }
5540
5541 release:
5542 /* Don't need the left & right operands any more; do need the result. */
5543   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5545
5546   aopOp (result, ic, FALSE, FALSE);
5547
5548 release_freedLR:
5549
5550   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5551     {
5552       outBitC (result);
5553     }
5554   else
5555     {
5556       /* if the result is used in the next
5557          ifx conditional branch then generate
5558          code a little differently */
5559       if (ifx)
5560         {
5561           genIfxJump (ifx, "c");
5562         }
5563       else
5564         {
5565           outBitC (result);
5566         }
5567       /* leave the result in acc */
5568     }
5569   freeAsmop (result, NULL, ic, TRUE);
5570 }
5571
5572 /*-----------------------------------------------------------------*/
5573 /* genCmpGt :- greater than comparison                             */
5574 /*-----------------------------------------------------------------*/
5575 static void
5576 genCmpGt (iCode * ic, iCode * ifx)
5577 {
5578   operand *left, *right;
5579   sym_link *letype, *retype;
5580   int sign;
5581
5582   D (emitcode (";", "genCmpGt ");
5583     );
5584
5585   left = IC_LEFT (ic);
5586   right = IC_RIGHT (ic);
5587
5588   letype = getSpec (operandType (left));
5589   retype = getSpec (operandType (right));
5590   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5591
5592   /* assign the left & right amsops */
5593   AOP_OP_2 (ic);
5594
5595   genCmp (right, left, ic, ifx, sign);
5596 }
5597
5598 /*-----------------------------------------------------------------*/
5599 /* genCmpLt - less than comparisons                                */
5600 /*-----------------------------------------------------------------*/
5601 static void
5602 genCmpLt (iCode * ic, iCode * ifx)
5603 {
5604   operand *left, *right;
5605   sym_link *letype, *retype;
5606   int sign;
5607
5608   D (emitcode (";", "genCmpLt "););
5609
5610   left = IC_LEFT (ic);
5611   right = IC_RIGHT (ic);
5612
5613   letype = getSpec (operandType (left));
5614   retype = getSpec (operandType (right));
5615   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5616
5617   /* assign the left & right amsops */
5618   AOP_OP_2 (ic);
5619
5620   genCmp (left, right, ic, ifx, sign);
5621 }
5622
5623 /*-----------------------------------------------------------------*/
5624 /* gencjneshort - compare and jump if not equal                    */
5625 /*-----------------------------------------------------------------*/
5626 static void
5627 gencjneshort (operand * left, operand * right, symbol * lbl)
5628 {
5629   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5630   int offset = 0;
5631   unsigned long lit = 0L;
5632
5633   D (emitcode (";", "gencjneshort");
5634     );
5635
5636   /* if the left side is a literal or
5637      if the right is in a pointer register and left
5638      is not */
5639   if ((AOP_TYPE (left) == AOP_LIT) ||
5640       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5641     {
5642       operand *t = right;
5643       right = left;
5644       left = t;
5645     }
5646
5647   if (AOP_TYPE (right) == AOP_LIT)
5648     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5649
5650   if (opIsGptr (left) || opIsGptr (right))
5651     {
5652       /* We are comparing a generic pointer to something.
5653        * Exclude the generic type byte from the comparison.
5654        */
5655       size--;
5656       D (emitcode (";", "cjneshort: generic ptr special case."););
5657     }
5658
5659
5660   /* if the right side is a literal then anything goes */
5661   if (AOP_TYPE (right) == AOP_LIT &&
5662       AOP_TYPE (left) != AOP_DIR)
5663     {
5664       while (size--)
5665         {
5666           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5667           emitcode ("cjne", "a,%s,!tlabel",
5668                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5669                     lbl->key + 100);
5670           offset++;
5671         }
5672     }
5673
5674   /* if the right side is in a register or in direct space or
5675      if the left is a pointer register & right is not */
5676   else if (AOP_TYPE (right) == AOP_REG ||
5677            AOP_TYPE (right) == AOP_DIR ||
5678            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5679            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5680     {
5681       while (size--)
5682         {
5683           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5684           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5685               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5686             emitcode ("jnz", "!tlabel", lbl->key + 100);
5687           else
5688             emitcode ("cjne", "a,%s,!tlabel",
5689                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5690                       lbl->key + 100);
5691           offset++;
5692         }
5693     }
5694   else
5695     {
5696       /* right is a pointer reg need both a & b */
5697       while (size--)
5698         {
5699           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5700           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5701           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5702           offset++;
5703         }
5704     }
5705 }
5706
5707 /*-----------------------------------------------------------------*/
5708 /* gencjne - compare and jump if not equal                         */
5709 /*-----------------------------------------------------------------*/
5710 static void
5711 gencjne (operand * left, operand * right, symbol * lbl)
5712 {
5713   symbol *tlbl = newiTempLabel (NULL);
5714
5715   D (emitcode (";", "gencjne");
5716     );
5717
5718   gencjneshort (left, right, lbl);
5719
5720   emitcode ("mov", "a,%s", one);
5721   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5722   emitcode ("", "!tlabeldef", lbl->key + 100);
5723   emitcode ("clr", "a");
5724   emitcode ("", "!tlabeldef", tlbl->key + 100);
5725 }
5726
5727 /*-----------------------------------------------------------------*/
5728 /* genCmpEq - generates code for equal to                          */
5729 /*-----------------------------------------------------------------*/
5730 static void
5731 genCmpEq (iCode * ic, iCode * ifx)
5732 {
5733   operand *left, *right, *result;
5734
5735   D (emitcode (";", "genCmpEq ");
5736     );
5737
5738   AOP_OP_2 (ic);
5739   AOP_SET_LOCALS (ic);
5740
5741   /* if literal, literal on the right or
5742      if the right is in a pointer register and left
5743      is not */
5744   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5745       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5746     {
5747       operand *t = IC_RIGHT (ic);
5748       IC_RIGHT (ic) = IC_LEFT (ic);
5749       IC_LEFT (ic) = t;
5750     }
5751
5752   if (ifx &&                    /* !AOP_SIZE(result) */
5753       OP_SYMBOL (result) &&
5754       OP_SYMBOL (result)->regType == REG_CND)
5755     {
5756       symbol *tlbl;
5757       /* if they are both bit variables */
5758       if (AOP_TYPE (left) == AOP_CRY &&
5759           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5760         {
5761           if (AOP_TYPE (right) == AOP_LIT)
5762             {
5763               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5764               if (lit == 0L)
5765                 {
5766                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5767                   emitcode ("cpl", "c");
5768                 }
5769               else if (lit == 1L)
5770                 {
5771                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5772                 }
5773               else
5774                 {
5775                   emitcode ("clr", "c");
5776                 }
5777               /* AOP_TYPE(right) == AOP_CRY */
5778             }
5779           else
5780             {
5781               symbol *lbl = newiTempLabel (NULL);
5782               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5783               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5784               emitcode ("cpl", "c");
5785               emitcode ("", "!tlabeldef", (lbl->key + 100));
5786             }
5787           /* if true label then we jump if condition
5788              supplied is true */
5789           tlbl = newiTempLabel (NULL);
5790           if (IC_TRUE (ifx))
5791             {
5792               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5793               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5794             }
5795           else
5796             {
5797               emitcode ("jc", "!tlabel", tlbl->key + 100);
5798               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799             }
5800           emitcode ("", "!tlabeldef", tlbl->key + 100);
5801         }
5802       else
5803         {
5804           tlbl = newiTempLabel (NULL);
5805           gencjneshort (left, right, tlbl);
5806           if (IC_TRUE (ifx))
5807             {
5808               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5809               emitcode ("", "!tlabeldef", tlbl->key + 100);
5810             }
5811           else
5812             {
5813               symbol *lbl = newiTempLabel (NULL);
5814               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5815               emitcode ("", "!tlabeldef", tlbl->key + 100);
5816               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5817               emitcode ("", "!tlabeldef", lbl->key + 100);
5818             }
5819         }
5820       /* mark the icode as generated */
5821       ifx->generated = 1;
5822
5823       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5824       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5825       return;
5826     }
5827
5828   /* if they are both bit variables */
5829   if (AOP_TYPE (left) == AOP_CRY &&
5830       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5831     {
5832       if (AOP_TYPE (right) == AOP_LIT)
5833         {
5834           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5835           if (lit == 0L)
5836             {
5837               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838               emitcode ("cpl", "c");
5839             }
5840           else if (lit == 1L)
5841             {
5842               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5843             }
5844           else
5845             {
5846               emitcode ("clr", "c");
5847             }
5848           /* AOP_TYPE(right) == AOP_CRY */
5849         }
5850       else
5851         {
5852           symbol *lbl = newiTempLabel (NULL);
5853           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5854           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5855           emitcode ("cpl", "c");
5856           emitcode ("", "!tlabeldef", (lbl->key + 100));
5857         }
5858
5859       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5860       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5861
5862       aopOp (result, ic, TRUE, FALSE);
5863
5864       /* c = 1 if egal */
5865       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5866         {
5867           outBitC (result);
5868           goto release;
5869         }
5870       if (ifx)
5871         {
5872           genIfxJump (ifx, "c");
5873           goto release;
5874         }
5875       /* if the result is used in an arithmetic operation
5876          then put the result in place */
5877       outBitC (result);
5878     }
5879   else
5880     {
5881       gencjne (left, right, newiTempLabel (NULL));
5882
5883       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5885
5886       aopOp (result, ic, TRUE, FALSE);
5887
5888       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5889         {
5890           aopPut (AOP (result), "a", 0);
5891           goto release;
5892         }
5893       if (ifx)
5894         {
5895           genIfxJump (ifx, "a");
5896           goto release;
5897         }
5898       /* if the result is used in an arithmetic operation
5899          then put the result in place */
5900       if (AOP_TYPE (result) != AOP_CRY)
5901         outAcc (result);
5902       /* leave the result in acc */
5903     }
5904
5905 release:
5906   freeAsmop (result, NULL, ic, TRUE);
5907 }
5908
5909 /*-----------------------------------------------------------------*/
5910 /* ifxForOp - returns the icode containing the ifx for operand     */
5911 /*-----------------------------------------------------------------*/
5912 static iCode *
5913 ifxForOp (operand * op, iCode * ic)
5914 {
5915   /* if true symbol then needs to be assigned */
5916   if (IS_TRUE_SYMOP (op))
5917     return NULL;
5918
5919   /* if this has register type condition and
5920      the next instruction is ifx with the same operand
5921      and live to of the operand is upto the ifx only then */
5922   if (ic->next &&
5923       ic->next->op == IFX &&
5924       IC_COND (ic->next)->key == op->key &&
5925       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5926     return ic->next;
5927
5928   return NULL;
5929 }
5930 /*-----------------------------------------------------------------*/
5931 /* hasInc - operand is incremented before any other use            */
5932 /*-----------------------------------------------------------------*/
5933 static iCode *
5934 hasInc (operand *op, iCode *ic, int osize)
5935 {
5936   sym_link *type = operandType(op);
5937   sym_link *retype = getSpec (type);
5938   iCode *lic = ic->next;
5939   int isize ;
5940   
5941   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5942   if (!IS_SYMOP(op)) return NULL;
5943
5944   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5945   if (IS_AGGREGATE(type->next)) return NULL;
5946   if (osize != (isize = getSize(type->next))) return NULL;
5947
5948   while (lic) {
5949       /* if operand of the form op = op + <sizeof *op> */
5950       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5951           isOperandEqual(IC_RESULT(lic),op) && 
5952           isOperandLiteral(IC_RIGHT(lic)) &&
5953           operandLitValue(IC_RIGHT(lic)) == isize) {
5954           return lic;
5955       }
5956       /* if the operand used or deffed */
5957       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5958           return NULL;
5959       }
5960       /* if GOTO or IFX */
5961       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5962       lic = lic->next;
5963   }
5964   return NULL;
5965 }
5966
5967 /*-----------------------------------------------------------------*/
5968 /* genAndOp - for && operation                                     */
5969 /*-----------------------------------------------------------------*/
5970 static void
5971 genAndOp (iCode * ic)
5972 {
5973   operand *left, *right, *result;
5974   symbol *tlbl;
5975
5976   D (emitcode (";", "genAndOp "););
5977
5978   /* note here that && operations that are in an
5979      if statement are taken away by backPatchLabels
5980      only those used in arthmetic operations remain */
5981   AOP_OP_2 (ic);
5982   AOP_SET_LOCALS (ic);
5983
5984   /* if both are bit variables */
5985   if (AOP_TYPE (left) == AOP_CRY &&
5986       AOP_TYPE (right) == AOP_CRY)
5987     {
5988       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5989       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5990       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5991       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5992   
5993       aopOp (result,ic,FALSE, FALSE);
5994       outBitC (result);
5995     }
5996   else
5997     {
5998       tlbl = newiTempLabel (NULL);
5999       toBoolean (left);
6000       emitcode ("jz", "!tlabel", tlbl->key + 100);
6001       toBoolean (right);
6002       emitcode ("", "!tlabeldef", tlbl->key + 100);
6003       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005   
6006       aopOp (result,ic,FALSE, FALSE);
6007       outBitAcc (result);
6008     }
6009     freeAsmop (result, NULL, ic, TRUE);
6010 }
6011
6012
6013 /*-----------------------------------------------------------------*/
6014 /* genOrOp - for || operation                                      */
6015 /*-----------------------------------------------------------------*/
6016 static void
6017 genOrOp (iCode * ic)
6018 {
6019   operand *left, *right, *result;
6020   symbol *tlbl;
6021
6022   D (emitcode (";", "genOrOp "););
6023
6024   /* note here that || operations that are in an
6025      if statement are taken away by backPatchLabels
6026      only those used in arthmetic operations remain */
6027   AOP_OP_2 (ic);
6028   AOP_SET_LOCALS (ic);
6029
6030   /* if both are bit variables */
6031   if (AOP_TYPE (left) == AOP_CRY &&
6032       AOP_TYPE (right) == AOP_CRY)
6033     {
6034       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6035       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6036       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6037       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6038   
6039       aopOp (result,ic,FALSE, FALSE);
6040       
6041       outBitC (result);
6042     }
6043   else
6044     {
6045       tlbl = newiTempLabel (NULL);
6046       toBoolean (left);
6047       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6048       toBoolean (right);
6049       emitcode ("", "!tlabeldef", tlbl->key + 100);
6050       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6051       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6052   
6053       aopOp (result,ic,FALSE, FALSE);
6054       
6055       outBitAcc (result);
6056     }
6057
6058   freeAsmop (result, NULL, ic, TRUE);
6059 }
6060
6061 /*-----------------------------------------------------------------*/
6062 /* isLiteralBit - test if lit == 2^n                               */
6063 /*-----------------------------------------------------------------*/
6064 static int
6065 isLiteralBit (unsigned long lit)
6066 {
6067   unsigned long pw[32] =
6068   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6069    0x100L, 0x200L, 0x400L, 0x800L,
6070    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6071    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6072    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6073    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6074    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6075   int idx;
6076
6077   for (idx = 0; idx < 32; idx++)
6078     if (lit == pw[idx])
6079       return idx + 1;
6080   return 0;
6081 }
6082
6083 /*-----------------------------------------------------------------*/
6084 /* continueIfTrue -                                                */
6085 /*-----------------------------------------------------------------*/
6086 static void
6087 continueIfTrue (iCode * ic)
6088 {
6089   if (IC_TRUE (ic))
6090     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6091   ic->generated = 1;
6092 }
6093
6094 /*-----------------------------------------------------------------*/
6095 /* jmpIfTrue -                                                     */
6096 /*-----------------------------------------------------------------*/
6097 static void
6098 jumpIfTrue (iCode * ic)
6099 {
6100   if (!IC_TRUE (ic))
6101     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6102   ic->generated = 1;
6103 }
6104
6105 /*-----------------------------------------------------------------*/
6106 /* jmpTrueOrFalse -                                                */
6107 /*-----------------------------------------------------------------*/
6108 static void
6109 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6110 {
6111   // ugly but optimized by peephole
6112   if (IC_TRUE (ic))
6113     {
6114       symbol *nlbl = newiTempLabel (NULL);
6115       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6116       emitcode ("", "!tlabeldef", tlbl->key + 100);
6117       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6118       emitcode ("", "!tlabeldef", nlbl->key + 100);
6119     }
6120   else
6121     {
6122       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6123       emitcode ("", "!tlabeldef", tlbl->key + 100);
6124     }
6125   ic->generated = 1;
6126 }
6127
6128 // Generate code to perform a bit-wise logic operation
6129 // on two operands in far space (assumed to already have been 
6130 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6131 // in far space. This requires pushing the result on the stack
6132 // then popping it into the result.
6133 static void
6134 genFarFarLogicOp(iCode *ic, char *logicOp)
6135 {
6136       int size, resultSize, compSize;
6137       int offset = 0;
6138       
6139       TR_AP("#5");
6140       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6141       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6142                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6143       
6144       _startLazyDPSEvaluation();
6145       for (size = compSize; (size--); offset++)
6146       {
6147           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6148           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6149           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6150           
6151           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6152           emitcode ("push", "acc");
6153       }
6154       _endLazyDPSEvaluation();
6155      
6156       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6157       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6158       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6159      
6160       resultSize = AOP_SIZE(IC_RESULT(ic));
6161
6162       ADJUST_PUSHED_RESULT(compSize, resultSize);
6163
6164       _startLazyDPSEvaluation();
6165       while (compSize--)
6166       {
6167           emitcode ("pop", "acc");
6168           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6169       }
6170       _endLazyDPSEvaluation();
6171       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6172 }
6173
6174
6175 /*-----------------------------------------------------------------*/
6176 /* genAnd  - code for and                                          */
6177 /*-----------------------------------------------------------------*/
6178 static void
6179 genAnd (iCode * ic, iCode * ifx)
6180 {
6181   operand *left, *right, *result;
6182   int size, offset = 0;
6183   unsigned long lit = 0L;
6184   int bytelit;
6185   char buff[10];
6186   bool pushResult;
6187
6188   D (emitcode (";", "genAnd "););
6189
6190   AOP_OP_3_NOFATAL (ic, pushResult);
6191   AOP_SET_LOCALS (ic);
6192
6193   if (pushResult)
6194   {
6195       genFarFarLogicOp(ic, "anl");
6196       return;
6197   }  
6198
6199 #ifdef DEBUG_TYPE
6200   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6201             AOP_TYPE (result),
6202             AOP_TYPE (left), AOP_TYPE (right));
6203   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6204             AOP_SIZE (result),
6205             AOP_SIZE (left), AOP_SIZE (right));
6206 #endif
6207
6208   /* if left is a literal & right is not then exchange them */
6209   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6210 #ifdef LOGIC_OPS_BROKEN      
6211     ||  AOP_NEEDSACC (left)
6212 #endif
6213     )
6214     {
6215       operand *tmp = right;
6216       right = left;
6217       left = tmp;
6218     }
6219
6220   /* if result = right then exchange them */
6221   if (sameRegs (AOP (result), AOP (right)))
6222     {
6223       operand *tmp = right;
6224       right = left;
6225       left = tmp;
6226     }
6227
6228   /* if right is bit then exchange them */
6229   if (AOP_TYPE (right) == AOP_CRY &&
6230       AOP_TYPE (left) != AOP_CRY)
6231     {
6232       operand *tmp = right;
6233       right = left;
6234       left = tmp;
6235     }
6236   if (AOP_TYPE (right) == AOP_LIT)
6237     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6238
6239   size = AOP_SIZE (result);
6240
6241   // if(bit & yy)
6242   // result = bit & yy;
6243   if (AOP_TYPE (left) == AOP_CRY)
6244     {
6245       // c = bit & literal;
6246       if (AOP_TYPE (right) == AOP_LIT)
6247         {
6248           if (lit & 1)
6249             {
6250               if (size && sameRegs (AOP (result), AOP (left)))
6251                 // no change
6252                 goto release;
6253               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6254             }
6255           else
6256             {
6257               // bit(result) = 0;
6258               if (size && (AOP_TYPE (result) == AOP_CRY))
6259                 {
6260                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6261                   goto release;
6262                 }
6263               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6264                 {
6265                   jumpIfTrue (ifx);
6266                   goto release;
6267                 }
6268               emitcode ("clr", "c");
6269             }
6270         }
6271       else
6272         {
6273           if (AOP_TYPE (right) == AOP_CRY)
6274             {
6275               // c = bit & bit;
6276               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6277               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6278             }
6279           else
6280             {
6281               // c = bit & val;
6282               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6283               // c = lsb
6284               emitcode ("rrc", "a");
6285               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6286             }
6287         }
6288       // bit = c
6289       // val = c
6290       if (size)
6291         outBitC (result);
6292       // if(bit & ...)
6293       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294         genIfxJump (ifx, "c");
6295       goto release;
6296     }
6297
6298   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6299   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6300   if ((AOP_TYPE (right) == AOP_LIT) &&
6301       (AOP_TYPE (result) == AOP_CRY) &&
6302       (AOP_TYPE (left) != AOP_CRY))
6303     {
6304       int posbit = isLiteralBit (lit);
6305       /* left &  2^n */
6306       if (posbit)
6307         {
6308           posbit--;
6309           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6310           // bit = left & 2^n
6311           if (size)
6312             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6313           // if(left &  2^n)
6314           else
6315             {
6316               if (ifx)
6317                 {
6318                   SNPRINTF (buff, sizeof(buff), 
6319                             "acc.%d", posbit & 0x07);
6320                   genIfxJump (ifx, buff);
6321                 }
6322               else 
6323                   {
6324                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6325                   }
6326               goto release;
6327             }
6328         }
6329       else
6330         {
6331           symbol *tlbl = newiTempLabel (NULL);
6332           int sizel = AOP_SIZE (left);
6333           if (size)
6334             emitcode ("setb", "c");
6335           while (sizel--)
6336             {
6337               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6338                 {
6339                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6340                   // byte ==  2^n ?
6341                   if ((posbit = isLiteralBit (bytelit)) != 0)
6342                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6343                   else
6344                     {
6345                       if (bytelit != 0x0FFL)
6346                         emitcode ("anl", "a,%s",
6347                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6348                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6349                     }
6350                 }
6351               offset++;
6352             }
6353           // bit = left & literal
6354           if (size)
6355             {
6356               emitcode ("clr", "c");
6357               emitcode ("", "!tlabeldef", tlbl->key + 100);
6358             }
6359           // if(left & literal)
6360           else
6361             {
6362               if (ifx)
6363                 jmpTrueOrFalse (ifx, tlbl);
6364               goto release;
6365             }
6366         }
6367       outBitC (result);
6368       goto release;
6369     }
6370
6371   /* if left is same as result */
6372   if (sameRegs (AOP (result), AOP (left)))
6373     {
6374       for (; size--; offset++)
6375         {
6376           if (AOP_TYPE (right) == AOP_LIT)
6377             {
6378               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6379                 continue;
6380               else if (bytelit == 0)
6381                 aopPut (AOP (result), zero, offset);
6382               else if (IS_AOP_PREG (result))
6383                 {
6384                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6385                   emitcode ("anl", "a,%s",
6386                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6387                   aopPut (AOP (result), "a", offset);
6388                 }
6389               else
6390                 emitcode ("anl", "%s,%s",
6391                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6392                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6393             }
6394           else
6395             {
6396               if (AOP_TYPE (left) == AOP_ACC)
6397                 emitcode ("anl", "a,%s",
6398                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6399               else
6400                 {
6401                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6402                   if (IS_AOP_PREG (result))
6403                     {
6404                       emitcode ("anl", "a,%s",
6405                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6406                       aopPut (AOP (result), "a", offset);
6407                     }
6408                   else
6409                     emitcode ("anl", "%s,a",
6410                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6411                 }
6412             }
6413         }
6414     }
6415   else
6416     {
6417       // left & result in different registers
6418       if (AOP_TYPE (result) == AOP_CRY)
6419         {
6420           // result = bit
6421           // if(size), result in bit
6422           // if(!size && ifx), conditional oper: if(left & right)
6423           symbol *tlbl = newiTempLabel (NULL);
6424           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6425           if (size)
6426             emitcode ("setb", "c");
6427           while (sizer--)
6428             {
6429               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6430                 emitcode ("anl", "a,%s",
6431                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6432               } else {
6433                 if (AOP_TYPE(left)==AOP_ACC) {
6434                   emitcode("mov", "b,a");
6435                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6436                   emitcode("anl", "a,b");
6437                 }else {
6438                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6439                   emitcode ("anl", "a,%s",
6440                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6441                 }
6442               }
6443               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6444               offset++;
6445             }
6446           if (size)
6447             {
6448               CLRC;
6449               emitcode ("", "!tlabeldef", tlbl->key + 100);
6450               outBitC (result);
6451             }
6452           else if (ifx)
6453             jmpTrueOrFalse (ifx, tlbl);
6454         }
6455       else
6456         {
6457           for (; (size--); offset++)
6458             {
6459               // normal case
6460               // result = left & right
6461               if (AOP_TYPE (right) == AOP_LIT)
6462                 {
6463                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6464                     {
6465                       aopPut (AOP (result),
6466                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6467                               offset);
6468                       continue;
6469                     }
6470                   else if (bytelit == 0)
6471                     {
6472                       aopPut (AOP (result), zero, offset);
6473                       continue;
6474                     }
6475                   D (emitcode (";", "better literal AND."););
6476                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6477                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6478                                                     FALSE, FALSE, DP2_RESULT_REG));
6479
6480                 }
6481               else
6482                 {
6483                   // faster than result <- left, anl result,right
6484                   // and better if result is SFR
6485                   if (AOP_TYPE (left) == AOP_ACC)
6486                     {
6487                       emitcode ("anl", "a,%s", 
6488                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6489                     }
6490                   else
6491                     {
6492                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6493                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6494                       {
6495                           emitcode("mov", "b,a");
6496                           rOp = "b";
6497                       }
6498                         
6499                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6500                       emitcode ("anl", "a,%s", rOp);
6501                     }                   
6502                 }
6503               aopPut (AOP (result), "a", offset);
6504             }
6505         }
6506     }
6507
6508 release:
6509   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511   freeAsmop (result, NULL, ic, TRUE);
6512 }
6513
6514
6515 /*-----------------------------------------------------------------*/
6516 /* genOr  - code for or                                            */
6517 /*-----------------------------------------------------------------*/
6518 static void
6519 genOr (iCode * ic, iCode * ifx)
6520 {
6521   operand *left, *right, *result;
6522   int size, offset = 0;
6523   unsigned long lit = 0L;
6524   bool     pushResult;
6525
6526   D (emitcode (";", "genOr "););
6527
6528   AOP_OP_3_NOFATAL (ic, pushResult);
6529   AOP_SET_LOCALS (ic);
6530
6531   if (pushResult)
6532   {
6533       genFarFarLogicOp(ic, "orl");
6534       return;
6535   }
6536
6537
6538 #ifdef DEBUG_TYPE
6539   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6540             AOP_TYPE (result),
6541             AOP_TYPE (left), AOP_TYPE (right));
6542   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6543             AOP_SIZE (result),
6544             AOP_SIZE (left), AOP_SIZE (right));
6545 #endif
6546
6547   /* if left is a literal & right is not then exchange them */
6548   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6549 #ifdef LOGIC_OPS_BROKEN
6550    || AOP_NEEDSACC (left) // I think this is a net loss now.
6551 #endif      
6552       )
6553     {
6554       operand *tmp = right;
6555       right = left;
6556       left = tmp;
6557     }
6558
6559   /* if result = right then exchange them */
6560   if (sameRegs (AOP (result), AOP (right)))
6561     {
6562       operand *tmp = right;
6563       right = left;
6564       left = tmp;
6565     }
6566
6567   /* if right is bit then exchange them */
6568   if (AOP_TYPE (right) == AOP_CRY &&
6569       AOP_TYPE (left) != AOP_CRY)
6570     {
6571       operand *tmp = right;
6572       right = left;
6573       left = tmp;
6574     }
6575   if (AOP_TYPE (right) == AOP_LIT)
6576     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6577
6578   size = AOP_SIZE (result);
6579
6580   // if(bit | yy)
6581   // xx = bit | yy;
6582   if (AOP_TYPE (left) == AOP_CRY)
6583     {
6584       if (AOP_TYPE (right) == AOP_LIT)
6585         {
6586           // c = bit & literal;
6587           if (lit)
6588             {
6589               // lit != 0 => result = 1
6590               if (AOP_TYPE (result) == AOP_CRY)
6591                 {
6592                   if (size)
6593                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6594                   else if (ifx)
6595                     continueIfTrue (ifx);
6596                   goto release;
6597                 }
6598               emitcode ("setb", "c");
6599             }
6600           else
6601             {
6602               // lit == 0 => result = left
6603               if (size && sameRegs (AOP (result), AOP (left)))
6604                 goto release;
6605               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6606             }
6607         }
6608       else
6609         {
6610           if (AOP_TYPE (right) == AOP_CRY)
6611             {
6612               // c = bit | bit;
6613               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6614               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6615             }
6616           else
6617             {
6618               // c = bit | val;
6619               symbol *tlbl = newiTempLabel (NULL);
6620               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6621                 emitcode ("setb", "c");
6622               emitcode ("jb", "%s,!tlabel",
6623                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6624               toBoolean (right);
6625               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6626               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627                 {
6628                   jmpTrueOrFalse (ifx, tlbl);
6629                   goto release;
6630                 }
6631               else
6632                 {
6633                   CLRC;
6634                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6635                 }
6636             }
6637         }
6638       // bit = c
6639       // val = c
6640       if (size)
6641         outBitC (result);
6642       // if(bit | ...)
6643       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6644            genIfxJump (ifx, "c");
6645       goto release;
6646     }
6647
6648   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6649   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6650   if ((AOP_TYPE (right) == AOP_LIT) &&
6651       (AOP_TYPE (result) == AOP_CRY) &&
6652       (AOP_TYPE (left) != AOP_CRY))
6653     {
6654       if (lit)
6655         {
6656           // result = 1
6657           if (size)
6658             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6659           else
6660             continueIfTrue (ifx);
6661           goto release;
6662         }
6663       else
6664         {
6665           // lit = 0, result = boolean(left)
6666           if (size)
6667             emitcode ("setb", "c");
6668           toBoolean (right);
6669           if (size)
6670             {
6671               symbol *tlbl = newiTempLabel (NULL);
6672               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6673               CLRC;
6674               emitcode ("", "!tlabeldef", tlbl->key + 100);
6675             }
6676           else
6677             {
6678               genIfxJump (ifx, "a");
6679               goto release;
6680             }
6681         }
6682       outBitC (result);
6683       goto release;
6684     }
6685
6686   /* if left is same as result */
6687   if (sameRegs (AOP (result), AOP (left)))
6688     {
6689       for (; size--; offset++)
6690         {
6691           if (AOP_TYPE (right) == AOP_LIT)
6692             {
6693               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6694                 {
6695                   continue;
6696                 }
6697               else
6698                 {
6699                   if (IS_AOP_PREG (left))
6700                     {
6701                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6702                       emitcode ("orl", "a,%s",
6703                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6704                       aopPut (AOP (result), "a", offset);
6705                     }
6706                   else
6707                     {
6708                       emitcode ("orl", "%s,%s",
6709                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6710                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6711                     }
6712                 }
6713             }
6714           else
6715             {
6716               if (AOP_TYPE (left) == AOP_ACC)
6717                 {
6718                   emitcode ("orl", "a,%s",
6719                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6720                 }
6721               else
6722                 {
6723                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6724                   if (IS_AOP_PREG (left))
6725                     {
6726                       emitcode ("orl", "a,%s", 
6727                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6728                       aopPut (AOP (result), "a", offset);
6729                     }
6730                   else
6731                     {
6732                       emitcode ("orl", "%s,a",
6733                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6734                     }
6735                 }
6736             }
6737         }
6738     }
6739   else
6740     {
6741       // left & result in different registers
6742       if (AOP_TYPE (result) == AOP_CRY)
6743         {
6744           // result = bit
6745           // if(size), result in bit
6746           // if(!size && ifx), conditional oper: if(left | right)
6747           symbol *tlbl = newiTempLabel (NULL);
6748           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6749           if (size)
6750             emitcode ("setb", "c");
6751           while (sizer--)
6752             {
6753               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6754                 emitcode ("orl", "a,%s",
6755                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6756               } else {
6757                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6758                 emitcode ("orl", "a,%s",
6759                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6760               }
6761               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6762               offset++;
6763             }
6764           if (size)
6765             {
6766               CLRC;
6767               emitcode ("", "!tlabeldef", tlbl->key + 100);
6768               outBitC (result);
6769             }
6770           else if (ifx)
6771             jmpTrueOrFalse (ifx, tlbl);
6772         }
6773       else
6774         {
6775             _startLazyDPSEvaluation();
6776           for (; (size--); offset++)
6777             {
6778               // normal case
6779               // result = left & right
6780               if (AOP_TYPE (right) == AOP_LIT)
6781                 {
6782                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6783                     {
6784                       aopPut (AOP (result),
6785                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6786                               offset);
6787                       continue;
6788                     }
6789                   D (emitcode (";", "better literal OR."););
6790                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6791                   emitcode ("orl", "a, %s",
6792                             aopGet (AOP (right), offset,
6793                                     FALSE, FALSE, DP2_RESULT_REG));
6794
6795                 }
6796               else
6797                 {
6798                   // faster than result <- left, anl result,right
6799                   // and better if result is SFR
6800                   if (AOP_TYPE (left) == AOP_ACC)
6801                     {
6802                       emitcode ("orl", "a,%s",
6803                                 aopGet (AOP (right), offset,
6804                                         FALSE, FALSE, DP2_RESULT_REG));
6805                     }
6806                   else
6807                     {
6808                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6809                         
6810                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6811                       {
6812                           emitcode("mov", "b,a");
6813                           rOp = "b";
6814                       }
6815                         
6816                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817                       emitcode ("orl", "a,%s", rOp);
6818                     }
6819                 }
6820               aopPut (AOP (result), "a", offset);
6821             }
6822             _endLazyDPSEvaluation();
6823         }
6824     }
6825
6826 release:
6827   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829   freeAsmop (result, NULL, ic, TRUE);
6830 }
6831
6832 /*-----------------------------------------------------------------*/
6833 /* genXor - code for xclusive or                                   */
6834 /*-----------------------------------------------------------------*/
6835 static void
6836 genXor (iCode * ic, iCode * ifx)
6837 {
6838   operand *left, *right, *result;
6839   int size, offset = 0;
6840   unsigned long lit = 0L;
6841   bool pushResult;
6842
6843   D (emitcode (";", "genXor "););
6844
6845   AOP_OP_3_NOFATAL (ic, pushResult);
6846   AOP_SET_LOCALS (ic);
6847
6848   if (pushResult)
6849   {
6850       genFarFarLogicOp(ic, "xrl");
6851       return;
6852   }  
6853
6854 #ifdef DEBUG_TYPE
6855   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6856             AOP_TYPE (result),
6857             AOP_TYPE (left), AOP_TYPE (right));
6858   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6859             AOP_SIZE (result),
6860             AOP_SIZE (left), AOP_SIZE (right));
6861 #endif
6862
6863   /* if left is a literal & right is not ||
6864      if left needs acc & right does not */
6865   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6866 #ifdef LOGIC_OPS_BROKEN      
6867       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6868 #endif
6869      )
6870     {
6871       operand *tmp = right;
6872       right = left;
6873       left = tmp;
6874     }
6875
6876   /* if result = right then exchange them */
6877   if (sameRegs (AOP (result), AOP (right)))
6878     {
6879       operand *tmp = right;
6880       right = left;
6881       left = tmp;
6882     }
6883
6884   /* if right is bit then exchange them */
6885   if (AOP_TYPE (right) == AOP_CRY &&
6886       AOP_TYPE (left) != AOP_CRY)
6887     {
6888       operand *tmp = right;
6889       right = left;
6890       left = tmp;
6891     }
6892   if (AOP_TYPE (right) == AOP_LIT)
6893     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6894
6895   size = AOP_SIZE (result);
6896
6897   // if(bit ^ yy)
6898   // xx = bit ^ yy;
6899   if (AOP_TYPE (left) == AOP_CRY)
6900     {
6901       if (AOP_TYPE (right) == AOP_LIT)
6902         {
6903           // c = bit & literal;
6904           if (lit >> 1)
6905             {
6906               // lit>>1  != 0 => result = 1
6907               if (AOP_TYPE (result) == AOP_CRY)
6908                 {
6909                   if (size)
6910                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6911                   else if (ifx)
6912                     continueIfTrue (ifx);
6913                   goto release;
6914                 }
6915               emitcode ("setb", "c");
6916             }
6917           else
6918             {
6919               // lit == (0 or 1)
6920               if (lit == 0)
6921                 {
6922                   // lit == 0, result = left
6923                   if (size && sameRegs (AOP (result), AOP (left)))
6924                     goto release;
6925                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6926                 }
6927               else
6928                 {
6929                   // lit == 1, result = not(left)
6930                   if (size && sameRegs (AOP (result), AOP (left)))
6931                     {
6932                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6933                       goto release;
6934                     }
6935                   else
6936                     {
6937                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6938                       emitcode ("cpl", "c");
6939                     }
6940                 }
6941             }
6942
6943         }
6944       else
6945         {
6946           // right != literal
6947           symbol *tlbl = newiTempLabel (NULL);
6948           if (AOP_TYPE (right) == AOP_CRY)
6949             {
6950               // c = bit ^ bit;
6951               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6952             }
6953           else
6954             {
6955               int sizer = AOP_SIZE (right);
6956               // c = bit ^ val
6957               // if val>>1 != 0, result = 1
6958               emitcode ("setb", "c");
6959               while (sizer)
6960                 {
6961                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6962                   if (sizer == 1)
6963                     // test the msb of the lsb
6964                     emitcode ("anl", "a,#!constbyte",0xfe);
6965                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6966                   sizer--;
6967                 }
6968               // val = (0,1)
6969               emitcode ("rrc", "a");
6970             }
6971           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6972           emitcode ("cpl", "c");
6973           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6974         }
6975       // bit = c
6976       // val = c
6977       if (size)
6978         outBitC (result);
6979       // if(bit | ...)
6980       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6981         genIfxJump (ifx, "c");
6982       goto release;
6983     }
6984
6985   if (sameRegs (AOP (result), AOP (left)))
6986     {
6987       /* if left is same as result */
6988       for (; size--; offset++)
6989         {
6990           if (AOP_TYPE (right) == AOP_LIT)
6991             {
6992               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6993                 continue;
6994               else if (IS_AOP_PREG (left))
6995                 {
6996                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6997                   emitcode ("xrl", "a,%s",
6998                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6999                   aopPut (AOP (result), "a", offset);
7000                 }
7001               else
7002                 emitcode ("xrl", "%s,%s",
7003                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7004                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7005             }
7006           else
7007             {
7008               if (AOP_TYPE (left) == AOP_ACC)
7009                 emitcode ("xrl", "a,%s",
7010                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7011               else
7012                 {
7013                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7014                   if (IS_AOP_PREG (left))
7015                     {
7016                       emitcode ("xrl", "a,%s",
7017                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7018                       aopPut (AOP (result), "a", offset);
7019                     }
7020                   else
7021                     emitcode ("xrl", "%s,a",
7022                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7023                 }
7024             }
7025         }
7026     }
7027   else
7028     {
7029       // left & result in different registers
7030       if (AOP_TYPE (result) == AOP_CRY)
7031         {
7032           // result = bit
7033           // if(size), result in bit
7034           // if(!size && ifx), conditional oper: if(left ^ right)
7035           symbol *tlbl = newiTempLabel (NULL);
7036           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7037                   
7038           if (size)
7039             emitcode ("setb", "c");
7040           while (sizer--)
7041             {
7042               if ((AOP_TYPE (right) == AOP_LIT) &&
7043                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7044                 {
7045                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7046                 }
7047               else
7048                 {
7049                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7050                     emitcode ("xrl", "a,%s",
7051                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7052                   } else {
7053                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7054                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7055                       {
7056                           emitcode("mov", "b,a");
7057                           rOp = "b";
7058                       }
7059                         
7060                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7061                       emitcode ("xrl", "a,%s", rOp);                  
7062                   }
7063                 }
7064               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7065               offset++;
7066             }
7067           if (size)
7068             {
7069               CLRC;
7070               emitcode ("", "!tlabeldef", tlbl->key + 100);
7071               outBitC (result);
7072             }
7073           else if (ifx)
7074             jmpTrueOrFalse (ifx, tlbl);
7075         }
7076       else
7077         {
7078         for (; (size--); offset++)
7079           {
7080             // normal case
7081             // result = left & right
7082             if (AOP_TYPE (right) == AOP_LIT)
7083               {
7084                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7085                   {
7086                     aopPut (AOP (result),
7087                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7088                             offset);
7089                     continue;
7090                   }
7091                 D (emitcode (";", "better literal XOR."););
7092                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7093                 emitcode ("xrl", "a, %s",
7094                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7095               }
7096             else
7097               {
7098                 // faster than result <- left, anl result,right
7099                 // and better if result is SFR
7100                 if (AOP_TYPE (left) == AOP_ACC)
7101                   {
7102                     emitcode ("xrl", "a,%s",
7103                               aopGet (AOP (right), offset,
7104                                       FALSE, FALSE, DP2_RESULT_REG));
7105                   }
7106                 else
7107                   {
7108                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7109                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7110                       {
7111                           emitcode("mov", "b,a");
7112                           rOp = "b";
7113                       }
7114                         
7115                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7116                       emitcode ("xrl", "a,%s", rOp);
7117                   }
7118               }
7119             aopPut (AOP (result), "a", offset);
7120           }
7121         }
7122         
7123     }
7124
7125 release:
7126   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7127   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7128   freeAsmop (result, NULL, ic, TRUE);
7129 }
7130
7131 /*-----------------------------------------------------------------*/
7132 /* genInline - write the inline code out                           */
7133 /*-----------------------------------------------------------------*/
7134 static void
7135 genInline (iCode * ic)
7136 {
7137   char *buffer, *bp, *bp1;
7138
7139   D (emitcode (";", "genInline "); );
7140
7141   _G.inLine += (!options.asmpeep);
7142
7143   buffer = Safe_strdup(IC_INLINE(ic));
7144   bp = buffer;
7145   bp1 = buffer;
7146
7147   /* emit each line as a code */
7148   while (*bp)
7149     {
7150       if (*bp == '\n')
7151         {
7152           *bp++ = '\0';
7153           emitcode (bp1, "");
7154           bp1 = bp;
7155         }
7156       else
7157         {
7158           if (*bp == ':')
7159             {
7160               bp++;
7161               *bp = '\0';
7162               bp++;
7163               emitcode (bp1, "");
7164               bp1 = bp;
7165             }
7166           else
7167             bp++;
7168         }
7169     }
7170   if (bp1 != bp)
7171     emitcode (bp1, "");
7172   /*     emitcode("",buffer); */
7173   _G.inLine -= (!options.asmpeep);
7174 }
7175
7176 /*-----------------------------------------------------------------*/
7177 /* genRRC - rotate right with carry                                */
7178 /*-----------------------------------------------------------------*/
7179 static void
7180 genRRC (iCode * ic)
7181 {
7182   operand *left, *result;
7183   int     size, offset;
7184
7185   D (emitcode (";", "genRRC "););
7186
7187   /* rotate right with carry */
7188   left = IC_LEFT (ic);
7189   result = IC_RESULT (ic);
7190   aopOp (left, ic, FALSE, FALSE);
7191   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7192
7193   /* move it to the result */
7194   size = AOP_SIZE (result);
7195   offset = size - 1;
7196   CLRC;
7197
7198   _startLazyDPSEvaluation ();
7199   while (size--)
7200     {
7201       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7202       emitcode ("rrc", "a");
7203       if (AOP_SIZE (result) > 1)
7204         aopPut (AOP (result), "a", offset--);
7205     }
7206   _endLazyDPSEvaluation ();
7207
7208   /* now we need to put the carry into the
7209      highest order byte of the result */
7210   if (AOP_SIZE (result) > 1)
7211     {
7212       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7213     }
7214   emitcode ("mov", "acc.7,c");
7215   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7216   freeAsmop (left, NULL, ic, TRUE);
7217   freeAsmop (result, NULL, ic, TRUE);
7218 }
7219
7220 /*-----------------------------------------------------------------*/
7221 /* genRLC - generate code for rotate left with carry               */
7222 /*-----------------------------------------------------------------*/
7223 static void
7224 genRLC (iCode * ic)
7225 {
7226   operand *left, *result;
7227   int size, offset;
7228   char *l;
7229
7230   D (emitcode (";", "genRLC "););
7231
7232   /* rotate right with carry */
7233   left = IC_LEFT (ic);
7234   result = IC_RESULT (ic);
7235   aopOp (left, ic, FALSE, FALSE);
7236   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7237
7238   /* move it to the result */
7239   size = AOP_SIZE (result);
7240   offset = 0;
7241   if (size--)
7242     {
7243       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7244       MOVA (l);
7245       emitcode ("add", "a,acc");
7246       if (AOP_SIZE (result) > 1)
7247         {
7248           aopPut (AOP (result), "a", offset++);
7249         }
7250
7251       _startLazyDPSEvaluation ();
7252       while (size--)
7253         {
7254           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7255           MOVA (l);
7256           emitcode ("rlc", "a");
7257           if (AOP_SIZE (result) > 1)
7258             aopPut (AOP (result), "a", offset++);
7259         }
7260       _endLazyDPSEvaluation ();
7261     }
7262   /* now we need to put the carry into the
7263      highest order byte of the result */
7264   if (AOP_SIZE (result) > 1)
7265     {
7266       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7267       MOVA (l);
7268     }
7269   emitcode ("mov", "acc.0,c");
7270   aopPut (AOP (result), "a", 0);
7271   freeAsmop (left, NULL, ic, TRUE);
7272   freeAsmop (result, NULL, ic, TRUE);
7273 }
7274
7275 /*-----------------------------------------------------------------*/
7276 /* genGetHbit - generates code get highest order bit               */
7277 /*-----------------------------------------------------------------*/
7278 static void
7279 genGetHbit (iCode * ic)
7280 {
7281   operand *left, *result;
7282   left = IC_LEFT (ic);
7283   result = IC_RESULT (ic);
7284   aopOp (left, ic, FALSE, FALSE);
7285   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7286
7287   D (emitcode (";", "genGetHbit "););
7288
7289   /* get the highest order byte into a */
7290   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7291   if (AOP_TYPE (result) == AOP_CRY)
7292     {
7293       emitcode ("rlc", "a");
7294       outBitC (result);
7295     }
7296   else
7297     {
7298       emitcode ("rl", "a");
7299       emitcode ("anl", "a,#1");
7300       outAcc (result);
7301     }
7302
7303
7304   freeAsmop (left, NULL, ic, TRUE);
7305   freeAsmop (result, NULL, ic, TRUE);
7306 }
7307
7308 /*-----------------------------------------------------------------*/
7309 /* AccRol - rotate left accumulator by known count                 */
7310 /*-----------------------------------------------------------------*/
7311 static void
7312 AccRol (int shCount)
7313 {
7314   shCount &= 0x0007;            // shCount : 0..7
7315
7316   switch (shCount)
7317     {
7318     case 0:
7319       break;
7320     case 1:
7321       emitcode ("rl", "a");
7322       break;
7323     case 2:
7324       emitcode ("rl", "a");
7325       emitcode ("rl", "a");
7326       break;
7327     case 3:
7328       emitcode ("swap", "a");
7329       emitcode ("rr", "a");
7330       break;
7331     case 4:
7332       emitcode ("swap", "a");
7333       break;
7334     case 5:
7335       emitcode ("swap", "a");
7336       emitcode ("rl", "a");
7337       break;
7338     case 6:
7339       emitcode ("rr", "a");
7340       emitcode ("rr", "a");
7341       break;
7342     case 7:
7343       emitcode ("rr", "a");
7344       break;
7345     }
7346 }
7347
7348 /*-----------------------------------------------------------------*/
7349 /* AccLsh - left shift accumulator by known count                  */
7350 /*-----------------------------------------------------------------*/
7351 static void
7352 AccLsh (int shCount)
7353 {
7354   if (shCount != 0)
7355     {
7356       if (shCount == 1)
7357         emitcode ("add", "a,acc");
7358       else if (shCount == 2)
7359         {
7360           emitcode ("add", "a,acc");
7361           emitcode ("add", "a,acc");
7362         }
7363       else
7364         {
7365           /* rotate left accumulator */
7366           AccRol (shCount);
7367           /* and kill the lower order bits */
7368           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7369         }
7370     }
7371 }
7372
7373 /*-----------------------------------------------------------------*/
7374 /* AccRsh - right shift accumulator by known count                 */
7375 /*-----------------------------------------------------------------*/
7376 static void
7377 AccRsh (int shCount)
7378 {
7379   if (shCount != 0)
7380     {
7381       if (shCount == 1)
7382         {
7383           CLRC;
7384           emitcode ("rrc", "a");
7385         }
7386       else
7387         {
7388           /* rotate right accumulator */
7389           AccRol (8 - shCount);
7390           /* and kill the higher order bits */
7391           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7392         }
7393     }
7394 }
7395
7396 #ifdef BETTER_LITERAL_SHIFT
7397 /*-----------------------------------------------------------------*/
7398 /* AccSRsh - signed right shift accumulator by known count                 */
7399 /*-----------------------------------------------------------------*/
7400 static void
7401 AccSRsh (int shCount)
7402 {
7403   symbol *tlbl;
7404   if (shCount != 0)
7405     {
7406       if (shCount == 1)
7407         {
7408           emitcode ("mov", "c,acc.7");
7409           emitcode ("rrc", "a");
7410         }
7411       else if (shCount == 2)
7412         {
7413           emitcode ("mov", "c,acc.7");
7414           emitcode ("rrc", "a");
7415           emitcode ("mov", "c,acc.7");
7416           emitcode ("rrc", "a");
7417         }
7418       else
7419         {
7420           tlbl = newiTempLabel (NULL);
7421           /* rotate right accumulator */
7422           AccRol (8 - shCount);
7423           /* and kill the higher order bits */
7424           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7425           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7426           emitcode ("orl", "a,#!constbyte",
7427                     (unsigned char) ~SRMask[shCount]);
7428           emitcode ("", "!tlabeldef", tlbl->key + 100);
7429         }
7430     }
7431 }
7432 #endif
7433
7434 #ifdef BETTER_LITERAL_SHIFT
7435 /*-----------------------------------------------------------------*/
7436 /* shiftR1Left2Result - shift right one byte from left to result   */
7437 /*-----------------------------------------------------------------*/
7438 static void
7439 shiftR1Left2Result (operand * left, int offl,
7440                     operand * result, int offr,
7441                     int shCount, int sign)
7442 {
7443   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444   /* shift right accumulator */
7445   if (sign)
7446     AccSRsh (shCount);
7447   else
7448     AccRsh (shCount);
7449   aopPut (AOP (result), "a", offr);
7450 }
7451 #endif
7452
7453 #ifdef BETTER_LITERAL_SHIFT
7454 /*-----------------------------------------------------------------*/
7455 /* shiftL1Left2Result - shift left one byte from left to result    */
7456 /*-----------------------------------------------------------------*/
7457 static void
7458 shiftL1Left2Result (operand * left, int offl,
7459                     operand * result, int offr, int shCount)
7460 {
7461   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7462   /* shift left accumulator */
7463   AccLsh (shCount);
7464   aopPut (AOP (result), "a", offr);
7465 }
7466 #endif
7467
7468 #ifdef BETTER_LITERAL_SHIFT
7469 /*-----------------------------------------------------------------*/
7470 /* movLeft2Result - move byte from left to result                  */
7471 /*-----------------------------------------------------------------*/
7472 static void
7473 movLeft2Result (operand * left, int offl,
7474                 operand * result, int offr, int sign)
7475 {
7476   char *l;
7477   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7478   {
7479       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7480
7481       if (*l == '@' && (IS_AOP_PREG (result)))
7482       {
7483           emitcode ("mov", "a,%s", l);
7484           aopPut (AOP (result), "a", offr);
7485       }
7486       else
7487       {
7488           if (!sign)
7489           {
7490             aopPut (AOP (result), l, offr);
7491           }
7492           else
7493             {
7494               /* MSB sign in acc.7 ! */
7495               if (getDataSize (left) == offl + 1)
7496                 {
7497                   emitcode ("mov", "a,%s", l);
7498                   aopPut (AOP (result), "a", offr);
7499                 }
7500             }
7501       }
7502   }
7503 }
7504 #endif
7505
7506 #ifdef BETTER_LITERAL_SHIFT
7507 /*-----------------------------------------------------------------*/
7508 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7509 /*-----------------------------------------------------------------*/
7510 static void
7511 AccAXRrl1 (char *x)
7512 {
7513   emitcode ("rrc", "a");
7514   emitcode ("xch", "a,%s", x);
7515   emitcode ("rrc", "a");
7516   emitcode ("xch", "a,%s", x);
7517 }
7518 #endif
7519
7520 #ifdef BETTER_LITERAL_SHIFT
7521 //REMOVE ME!!!
7522 /*-----------------------------------------------------------------*/
7523 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7524 /*-----------------------------------------------------------------*/
7525 static void
7526 AccAXLrl1 (char *x)
7527 {
7528   emitcode ("xch", "a,%s", x);
7529   emitcode ("rlc", "a");
7530   emitcode ("xch", "a,%s", x);
7531   emitcode ("rlc", "a");
7532 }
7533 #endif
7534
7535 #ifdef BETTER_LITERAL_SHIFT
7536 /*-----------------------------------------------------------------*/
7537 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7538 /*-----------------------------------------------------------------*/
7539 static void
7540 AccAXLsh1 (char *x)
7541 {
7542   emitcode ("xch", "a,%s", x);
7543   emitcode ("add", "a,acc");
7544   emitcode ("xch", "a,%s", x);
7545   emitcode ("rlc", "a");
7546 }
7547 #endif
7548
7549 #ifdef BETTER_LITERAL_SHIFT
7550 /*-----------------------------------------------------------------*/
7551 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7552 /*-----------------------------------------------------------------*/
7553 static void
7554 AccAXLsh (char *x, int shCount)
7555 {
7556   switch (shCount)
7557     {
7558     case 0:
7559       break;
7560     case 1:
7561       AccAXLsh1 (x);
7562       break;
7563     case 2:
7564       AccAXLsh1 (x);
7565       AccAXLsh1 (x);
7566       break;
7567     case 3:
7568     case 4:
7569     case 5:                     // AAAAABBB:CCCCCDDD
7570
7571       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7572
7573       emitcode ("anl", "a,#!constbyte",
7574                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7575
7576       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7577
7578       AccRol (shCount);         // DDDCCCCC:BBB00000
7579
7580       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7581
7582       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7583
7584       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7585
7586       emitcode ("anl", "a,#!constbyte",
7587                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7588
7589       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7590
7591       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7592
7593       break;
7594     case 6:                     // AAAAAABB:CCCCCCDD
7595       emitcode ("anl", "a,#!constbyte",
7596                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7597       emitcode ("mov", "c,acc.0");      // c = B
7598       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7599 #if 0
7600       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7601       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7602 #else
7603       emitcode("rrc","a"); 
7604       emitcode("xch","a,%s", x); 
7605       emitcode("rrc","a"); 
7606       emitcode("mov","c,acc.0"); //<< get correct bit 
7607       emitcode("xch","a,%s", x); 
7608
7609       emitcode("rrc","a"); 
7610       emitcode("xch","a,%s", x); 
7611       emitcode("rrc","a"); 
7612       emitcode("xch","a,%s", x); 
7613 #endif
7614       break;
7615     case 7:                     // a:x <<= 7
7616
7617       emitcode ("anl", "a,#!constbyte",
7618                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7619
7620       emitcode ("mov", "c,acc.0");      // c = B
7621
7622       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7623
7624       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7625
7626       break;
7627     default:
7628       break;
7629     }
7630 }
7631 #endif
7632
7633 #ifdef BETTER_LITERAL_SHIFT
7634 //REMOVE ME!!!
7635 /*-----------------------------------------------------------------*/
7636 /* AccAXRsh - right shift a:x known count (0..7)                   */
7637 /*-----------------------------------------------------------------*/
7638 static void
7639 AccAXRsh (char *x, int shCount)
7640 {
7641   switch (shCount)
7642     {
7643     case 0:
7644       break;
7645     case 1:
7646       CLRC;
7647       AccAXRrl1 (x);            // 0->a:x
7648
7649       break;
7650     case 2:
7651       CLRC;
7652       AccAXRrl1 (x);            // 0->a:x
7653
7654       CLRC;
7655       AccAXRrl1 (x);            // 0->a:x
7656
7657       break;
7658     case 3:
7659     case 4:
7660     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7661
7662       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7663
7664       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7665
7666       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7667
7668       emitcode ("anl", "a,#!constbyte",
7669                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7670
7671       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7672
7673       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7674
7675       emitcode ("anl", "a,#!constbyte",
7676                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7677
7678       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7679
7680       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7681
7682       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7683
7684       break;
7685     case 6:                     // AABBBBBB:CCDDDDDD
7686
7687       emitcode ("mov", "c,acc.7");
7688       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7689
7690       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7691
7692       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7693
7694       emitcode ("anl", "a,#!constbyte",
7695                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7696
7697       break;
7698     case 7:                     // ABBBBBBB:CDDDDDDD
7699
7700       emitcode ("mov", "c,acc.7");      // c = A
7701
7702       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7703
7704       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7705
7706       emitcode ("anl", "a,#!constbyte",
7707                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7708
7709       break;
7710     default:
7711       break;
7712     }
7713 }
7714 #endif
7715
7716 #ifdef BETTER_LITERAL_SHIFT
7717 /*-----------------------------------------------------------------*/
7718 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7719 /*-----------------------------------------------------------------*/
7720 static void
7721 AccAXRshS (char *x, int shCount)
7722 {
7723   symbol *tlbl;
7724   switch (shCount)
7725     {
7726     case 0:
7727       break;
7728     case 1:
7729       emitcode ("mov", "c,acc.7");
7730       AccAXRrl1 (x);            // s->a:x
7731
7732       break;
7733     case 2:
7734       emitcode ("mov", "c,acc.7");
7735       AccAXRrl1 (x);            // s->a:x
7736
7737       emitcode ("mov", "c,acc.7");
7738       AccAXRrl1 (x);            // s->a:x
7739
7740       break;
7741     case 3:
7742     case 4:
7743     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7744
7745       tlbl = newiTempLabel (NULL);
7746       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7747
7748       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7749
7750       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7751
7752       emitcode ("anl", "a,#!constbyte",
7753                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7754
7755       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7756
7757       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7758
7759       emitcode ("anl", "a,#!constbyte",
7760                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7761
7762       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7763
7764       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7765
7766       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7767
7768       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7769       emitcode ("orl", "a,#!constbyte",
7770                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7771
7772       emitcode ("", "!tlabeldef", tlbl->key + 100);
7773       break;                    // SSSSAAAA:BBBCCCCC
7774
7775     case 6:                     // AABBBBBB:CCDDDDDD
7776
7777       tlbl = newiTempLabel (NULL);
7778       emitcode ("mov", "c,acc.7");
7779       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7780
7781       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7782
7783       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7787
7788       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789       emitcode ("orl", "a,#!constbyte",
7790                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7791
7792       emitcode ("", "!tlabeldef", tlbl->key + 100);
7793       break;
7794     case 7:                     // ABBBBBBB:CDDDDDDD
7795
7796       tlbl = newiTempLabel (NULL);
7797       emitcode ("mov", "c,acc.7");      // c = A
7798
7799       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7800
7801       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7802
7803       emitcode ("anl", "a,#!constbyte",
7804                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7805
7806       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7807       emitcode ("orl", "a,#!constbyte",
7808                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7809
7810       emitcode ("", "!tlabeldef", tlbl->key + 100);
7811       break;
7812     default:
7813       break;
7814     }
7815 }
7816 #endif
7817
7818 #ifdef BETTER_LITERAL_SHIFT
7819 static void
7820 _loadLeftIntoAx(char    **lsb, 
7821                 operand *left, 
7822                 operand *result,
7823                 int     offl,
7824                 int     offr)
7825 {
7826   // Get the initial value from left into a pair of registers.
7827   // MSB must be in A, LSB can be any register.
7828   //
7829   // If the result is held in registers, it is an optimization
7830   // if the LSB can be held in the register which will hold the,
7831   // result LSB since this saves us from having to copy it into
7832   // the result following AccAXLsh.
7833   //
7834   // If the result is addressed indirectly, this is not a gain.
7835   if (AOP_NEEDSACC(result))
7836   {
7837        char *leftByte;
7838        
7839        _startLazyDPSEvaluation();
7840       if (AOP_TYPE(left) == AOP_DPTR2)
7841        {
7842            // Get MSB in A.
7843            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7844            // get LSB in DP2_RESULT_REG.
7845            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7846            assert(!strcmp(leftByte, DP2_RESULT_REG));
7847        }
7848        else
7849        {
7850            // get LSB into DP2_RESULT_REG
7851            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7852            if (strcmp(leftByte, DP2_RESULT_REG))
7853            {
7854                TR_AP("#7");
7855                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7856            }
7857            // And MSB in A.
7858            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7859            assert(strcmp(leftByte, DP2_RESULT_REG));
7860            MOVA(leftByte);
7861        }
7862        _endLazyDPSEvaluation();
7863        *lsb = DP2_RESULT_REG;
7864   }
7865   else
7866   {
7867       if (sameRegs (AOP (result), AOP (left)) &&
7868         ((offl + MSB16) == offr))
7869       {
7870           /* don't crash result[offr] */
7871           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7872           emitcode ("xch", "a,%s", 
7873                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7874       }
7875       else
7876       {
7877           movLeft2Result (left, offl, result, offr, 0);
7878           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7879       }
7880       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7881       assert(strcmp(*lsb,"a"));      
7882   }
7883 }
7884
7885 static void
7886 _storeAxResults(char    *lsb,
7887                 operand *result,
7888                 int     offr)
7889 {
7890   _startLazyDPSEvaluation();
7891   if (AOP_NEEDSACC(result))
7892   {
7893       /* We have to explicitly update the result LSB.
7894        */
7895       emitcode("xch","a,%s", lsb);
7896       aopPut(AOP(result), "a", offr);
7897       emitcode("mov","a,%s", lsb);
7898   }
7899   if (getDataSize (result) > 1)
7900   {
7901       aopPut (AOP (result), "a", offr + MSB16);
7902   }
7903   _endLazyDPSEvaluation();
7904 }
7905
7906 /*-----------------------------------------------------------------*/
7907 /* shiftL2Left2Result - shift left two bytes from left to result   */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 shiftL2Left2Result (operand * left, int offl,
7911                     operand * result, int offr, int shCount)
7912 {
7913   char *lsb;
7914
7915   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7916   
7917   AccAXLsh (lsb, shCount);
7918   
7919   _storeAxResults(lsb, result, offr);
7920 }
7921 #endif
7922
7923 #ifdef BETTER_LITERAL_SHIFT
7924 /*-----------------------------------------------------------------*/
7925 /* shiftR2Left2Result - shift right two bytes from left to result  */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 shiftR2Left2Result (operand * left, int offl,
7929                     operand * result, int offr,
7930                     int shCount, int sign)
7931 {
7932   char *lsb;
7933   
7934   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7935   
7936   /* a:x >> shCount (x = lsb(result)) */
7937   if (sign)
7938   {
7939      AccAXRshS(lsb, shCount);
7940   }
7941   else
7942   {
7943     AccAXRsh(lsb, shCount);
7944   }
7945   
7946   _storeAxResults(lsb, result, offr);
7947 }
7948 #endif
7949
7950 /*-----------------------------------------------------------------*/
7951 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7952 /*-----------------------------------------------------------------*/
7953 static void
7954 shiftLLeftOrResult (operand * left, int offl,
7955                     operand * result, int offr, int shCount)
7956 {
7957   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7958   /* shift left accumulator */
7959   AccLsh (shCount);
7960   /* or with result */
7961   emitcode ("orl", "a,%s",
7962             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7963   /* back to result */
7964   aopPut (AOP (result), "a", offr);
7965 }
7966
7967 #if 0
7968 //REMOVE ME!!!
7969 /*-----------------------------------------------------------------*/
7970 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7971 /*-----------------------------------------------------------------*/
7972 static void
7973 shiftRLeftOrResult (operand * left, int offl,
7974                     operand * result, int offr, int shCount)
7975 {
7976   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7977   /* shift right accumulator */
7978   AccRsh (shCount);
7979   /* or with result */
7980   emitcode ("orl", "a,%s",
7981             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7982   /* back to result */
7983   aopPut (AOP (result), "a", offr);
7984 }
7985 #endif
7986
7987 #ifdef BETTER_LITERAL_SHIFT
7988 /*-----------------------------------------------------------------*/
7989 /* genlshOne - left shift a one byte quantity by known count       */
7990 /*-----------------------------------------------------------------*/
7991 static void
7992 genlshOne (operand * result, operand * left, int shCount)
7993 {
7994   D (emitcode (";", "genlshOne "););
7995   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7996 }
7997 #endif
7998
7999 #ifdef BETTER_LITERAL_SHIFT
8000 /*-----------------------------------------------------------------*/
8001 /* genlshTwo - left shift two bytes by known amount != 0           */
8002 /*-----------------------------------------------------------------*/
8003 static void
8004 genlshTwo (operand * result, operand * left, int shCount)
8005 {
8006   int size;
8007
8008   D (emitcode (";", "genlshTwo "););
8009
8010   size = getDataSize (result);
8011
8012   /* if shCount >= 8 */
8013   if (shCount >= 8)
8014   {
8015       shCount -= 8;
8016
8017       _startLazyDPSEvaluation();
8018
8019       if (size > 1)
8020         {
8021           if (shCount)
8022           {
8023             _endLazyDPSEvaluation();
8024             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8025             aopPut (AOP (result), zero, LSB);       
8026           }
8027           else
8028           {
8029             movLeft2Result (left, LSB, result, MSB16, 0);
8030             aopPut (AOP (result), zero, LSB);
8031             _endLazyDPSEvaluation();
8032           }
8033         }
8034         else
8035         {
8036           aopPut (AOP (result), zero, LSB);
8037           _endLazyDPSEvaluation();
8038         }
8039   }
8040
8041   /*  1 <= shCount <= 7 */
8042   else
8043     {
8044       if (size == 1)
8045       {
8046         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8047       }
8048       else
8049       {
8050         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8051       }
8052     }
8053 }
8054 #endif
8055
8056 #if 0
8057 //REMOVE ME!!!
8058 /*-----------------------------------------------------------------*/
8059 /* shiftLLong - shift left one long from left to result            */
8060 /* offl = LSB or MSB16                                             */
8061 /*-----------------------------------------------------------------*/
8062 static void
8063 shiftLLong (operand * left, operand * result, int offr)
8064 {
8065   char *l;
8066   int size = AOP_SIZE (result);
8067
8068   if (size >= LSB + offr)
8069     {
8070       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8071       MOVA (l);
8072       emitcode ("add", "a,acc");
8073       if (sameRegs (AOP (left), AOP (result)) &&
8074           size >= MSB16 + offr && offr != LSB)
8075         emitcode ("xch", "a,%s",
8076                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8077       else
8078         aopPut (AOP (result), "a", LSB + offr);
8079     }
8080
8081   if (size >= MSB16 + offr)
8082     {
8083       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8084         {
8085           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8086         }
8087       emitcode ("rlc", "a");
8088       if (sameRegs (AOP (left), AOP (result)) &&
8089           size >= MSB24 + offr && offr != LSB)
8090         emitcode ("xch", "a,%s",
8091                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8092       else
8093         aopPut (AOP (result), "a", MSB16 + offr);
8094     }
8095
8096   if (size >= MSB24 + offr)
8097     {
8098       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8099         {
8100           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8101         }
8102       emitcode ("rlc", "a");
8103       if (sameRegs (AOP (left), AOP (result)) &&
8104           size >= MSB32 + offr && offr != LSB)
8105         emitcode ("xch", "a,%s",
8106                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8107       else
8108         aopPut (AOP (result), "a", MSB24 + offr);
8109     }
8110
8111   if (size > MSB32 + offr)
8112     {
8113       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8114         {
8115           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8116         }
8117       emitcode ("rlc", "a");
8118       aopPut (AOP (result), "a", MSB32 + offr);
8119     }
8120   if (offr != LSB)
8121     aopPut (AOP (result), zero, LSB);
8122 }
8123 #endif
8124
8125 #if 0
8126 //REMOVE ME!!!
8127 /*-----------------------------------------------------------------*/
8128 /* genlshFour - shift four byte by a known amount != 0             */
8129 /*-----------------------------------------------------------------*/
8130 static void
8131 genlshFour (operand * result, operand * left, int shCount)
8132 {
8133   int size;
8134
8135   D (emitcode (";", "genlshFour ");
8136     );
8137
8138   size = AOP_SIZE (result);
8139
8140   /* if shifting more that 3 bytes */
8141   if (shCount >= 24)
8142     {
8143       shCount -= 24;
8144       if (shCount)
8145         /* lowest order of left goes to the highest
8146            order of the destination */
8147         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8148       else
8149         movLeft2Result (left, LSB, result, MSB32, 0);
8150       aopPut (AOP (result), zero, LSB);
8151       aopPut (AOP (result), zero, MSB16);
8152       aopPut (AOP (result), zero, MSB24);
8153       return;
8154     }
8155
8156   /* more than two bytes */
8157   else if (shCount >= 16)
8158     {
8159       /* lower order two bytes goes to higher order two bytes */
8160       shCount -= 16;
8161       /* if some more remaining */
8162       if (shCount)
8163         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8164       else
8165         {
8166           movLeft2Result (left, MSB16, result, MSB32, 0);
8167           movLeft2Result (left, LSB, result, MSB24, 0);
8168         }
8169       aopPut (AOP (result), zero, MSB16);
8170       aopPut (AOP (result), zero, LSB);
8171       return;
8172     }
8173
8174   /* if more than 1 byte */
8175   else if (shCount >= 8)
8176     {
8177       /* lower order three bytes goes to higher order  three bytes */
8178       shCount -= 8;
8179       if (size == 2)
8180         {
8181           if (shCount)
8182             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183           else
8184             movLeft2Result (left, LSB, result, MSB16, 0);
8185         }
8186       else
8187         {                       /* size = 4 */
8188           if (shCount == 0)
8189             {
8190               movLeft2Result (left, MSB24, result, MSB32, 0);
8191               movLeft2Result (left, MSB16, result, MSB24, 0);
8192               movLeft2Result (left, LSB, result, MSB16, 0);
8193               aopPut (AOP (result), zero, LSB);
8194             }
8195           else if (shCount == 1)
8196             shiftLLong (left, result, MSB16);
8197           else
8198             {
8199               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8200               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8201               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8202               aopPut (AOP (result), zero, LSB);
8203             }
8204         }
8205     }
8206
8207   /* 1 <= shCount <= 7 */
8208   else if (shCount <= 2)
8209     {
8210       shiftLLong (left, result, LSB);
8211       if (shCount == 2)
8212         shiftLLong (result, result, LSB);
8213     }
8214   /* 3 <= shCount <= 7, optimize */
8215   else
8216     {
8217       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8218       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8219       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8220     }
8221 }
8222 #endif
8223
8224 #ifdef BETTER_LITERAL_SHIFT
8225 /*-----------------------------------------------------------------*/
8226 /* genLeftShiftLiteral - left shifting by known count              */
8227 /*-----------------------------------------------------------------*/
8228 static bool
8229 genLeftShiftLiteral (operand * left,
8230                      operand * right,
8231                      operand * result,
8232                      iCode * ic)
8233 {
8234   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8235   int size;
8236
8237   size = getSize (operandType (result));
8238
8239   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8240
8241   /* We only handle certain easy cases so far. */
8242   if ((shCount != 0)
8243    && (shCount < (size * 8))
8244    && (size != 1)
8245    && (size != 2))
8246   {
8247       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8248       return FALSE;
8249   }
8250
8251   freeAsmop (right, NULL, ic, TRUE);
8252
8253   aopOp(left, ic, FALSE, FALSE);
8254   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8255
8256 #if 0 // debug spew
8257   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8258   {
8259         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8260         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8261         {
8262            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8263         }
8264   }
8265   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8266   {
8267         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8268         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8269         {
8270            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8271         }       
8272   }  
8273 #endif
8274   
8275 #if VIEW_SIZE
8276   emitcode ("; shift left ", "result %d, left %d", size,
8277             AOP_SIZE (left));
8278 #endif
8279
8280   /* I suppose that the left size >= result size */
8281   if (shCount == 0)
8282   {
8283         _startLazyDPSEvaluation();
8284         while (size--)
8285         {
8286           movLeft2Result (left, size, result, size, 0);
8287         }
8288         _endLazyDPSEvaluation();
8289   }
8290   else if (shCount >= (size * 8))
8291   {
8292     _startLazyDPSEvaluation();
8293     while (size--)
8294     {
8295       aopPut (AOP (result), zero, size);
8296     }
8297     _endLazyDPSEvaluation();
8298   }
8299   else
8300   {
8301       switch (size)
8302         {
8303         case 1:
8304           genlshOne (result, left, shCount);
8305           break;
8306
8307         case 2:
8308           genlshTwo (result, left, shCount);
8309           break;
8310 #if 0
8311         case 4:
8312           genlshFour (result, left, shCount);
8313           break;
8314 #endif
8315         default:
8316           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8317           break;
8318         }
8319     }
8320   freeAsmop (left, NULL, ic, TRUE);
8321   freeAsmop (result, NULL, ic, TRUE);
8322   return TRUE;
8323 }
8324 #endif
8325
8326 /*-----------------------------------------------------------------*/
8327 /* genLeftShift - generates code for left shifting                 */
8328 /*-----------------------------------------------------------------*/
8329 static void
8330 genLeftShift (iCode * ic)
8331 {
8332   operand *left, *right, *result;
8333   int size, offset;
8334   char *l;
8335   symbol *tlbl, *tlbl1;
8336
8337   D (emitcode (";", "genLeftShift "););
8338
8339   right = IC_RIGHT (ic);
8340   left = IC_LEFT (ic);
8341   result = IC_RESULT (ic);
8342
8343   aopOp (right, ic, FALSE, FALSE);
8344
8345
8346 #ifdef BETTER_LITERAL_SHIFT
8347   /* if the shift count is known then do it
8348      as efficiently as possible */
8349   if (AOP_TYPE (right) == AOP_LIT)
8350     {
8351       if (genLeftShiftLiteral (left, right, result, ic))
8352       {
8353         return;
8354       }
8355     }
8356 #endif
8357
8358   /* shift count is unknown then we have to form
8359      a loop get the loop count in B : Note: we take
8360      only the lower order byte since shifting
8361      more that 32 bits make no sense anyway, ( the
8362      largest size of an object can be only 32 bits ) */
8363
8364   if (AOP_TYPE (right) == AOP_LIT)
8365   {
8366       /* Really should be handled by genLeftShiftLiteral,
8367        * but since I'm too lazy to fix that today, at least we can make
8368        * some small improvement.
8369        */
8370        emitcode("mov", "b,#!constbyte",
8371                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8372   }
8373   else
8374   {
8375       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8376       emitcode ("inc", "b");
8377   }
8378   freeAsmop (right, NULL, ic, TRUE);
8379   aopOp (left, ic, FALSE, FALSE);
8380   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8381
8382   /* now move the left to the result if they are not the
8383      same */
8384   if (!sameRegs (AOP (left), AOP (result)) &&
8385       AOP_SIZE (result) > 1)
8386     {
8387
8388       size = AOP_SIZE (result);
8389       offset = 0;
8390       _startLazyDPSEvaluation ();
8391       while (size--)
8392         {
8393           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8394           if (*l == '@' && (IS_AOP_PREG (result)))
8395             {
8396
8397               emitcode ("mov", "a,%s", l);
8398               aopPut (AOP (result), "a", offset);
8399             }
8400           else
8401             aopPut (AOP (result), l, offset);
8402           offset++;
8403         }
8404       _endLazyDPSEvaluation ();
8405     }
8406
8407   tlbl = newiTempLabel (NULL);
8408   size = AOP_SIZE (result);
8409   offset = 0;
8410   tlbl1 = newiTempLabel (NULL);
8411
8412   /* if it is only one byte then */
8413   if (size == 1)
8414     {
8415       symbol *tlbl1 = newiTempLabel (NULL);
8416
8417       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8418       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8419       emitcode ("", "!tlabeldef", tlbl->key + 100);
8420       emitcode ("add", "a,acc");
8421       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8422       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8423       aopPut (AOP (result), "a", 0);
8424       goto release;
8425     }
8426
8427   reAdjustPreg (AOP (result));
8428
8429   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8430   emitcode ("", "!tlabeldef", tlbl->key + 100);
8431   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8432   emitcode ("add", "a,acc");
8433   aopPut (AOP (result), "a", offset++);
8434   _startLazyDPSEvaluation ();
8435   while (--size)
8436     {
8437       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8438       emitcode ("rlc", "a");
8439       aopPut (AOP (result), "a", offset++);
8440     }
8441   _endLazyDPSEvaluation ();
8442   reAdjustPreg (AOP (result));
8443
8444   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8445   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8446 release:
8447   freeAsmop (left, NULL, ic, TRUE);
8448   freeAsmop (result, NULL, ic, TRUE);
8449 }
8450
8451 #ifdef BETTER_LITERAL_SHIFT
8452 /*-----------------------------------------------------------------*/
8453 /* genrshOne - right shift a one byte quantity by known count      */
8454 /*-----------------------------------------------------------------*/
8455 static void
8456 genrshOne (operand * result, operand * left,
8457            int shCount, int sign)
8458 {
8459   D (emitcode (";", "genrshOne"););
8460   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8461 }
8462 #endif
8463
8464 #ifdef BETTER_LITERAL_SHIFT
8465 /*-----------------------------------------------------------------*/
8466 /* genrshTwo - right shift two bytes by known amount != 0          */
8467 /*-----------------------------------------------------------------*/
8468 static void
8469 genrshTwo (operand * result, operand * left,
8470            int shCount, int sign)
8471 {
8472   D (emitcode (";", "genrshTwo"););
8473
8474   /* if shCount >= 8 */
8475   if (shCount >= 8)
8476     {
8477       shCount -= 8;
8478       _startLazyDPSEvaluation();
8479       if (shCount)
8480       {
8481         shiftR1Left2Result (left, MSB16, result, LSB,
8482                             shCount, sign);
8483       }                     
8484       else
8485       {
8486         movLeft2Result (left, MSB16, result, LSB, sign);
8487       }
8488       addSign (result, MSB16, sign);
8489       _endLazyDPSEvaluation();
8490     }
8491
8492   /*  1 <= shCount <= 7 */
8493   else
8494   {
8495     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8496   }
8497 }
8498 #endif
8499
8500 /*-----------------------------------------------------------------*/
8501 /* shiftRLong - shift right one long from left to result           */
8502 /* offl = LSB or MSB16                                             */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 shiftRLong (operand * left, int offl,
8506             operand * result, int sign)
8507 {
8508   int isSameRegs=sameRegs(AOP(left),AOP(result));
8509
8510   if (isSameRegs && offl>1) {
8511     // we are in big trouble, but this shouldn't happen
8512     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8513   }
8514
8515   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8516   
8517   if (offl==MSB16) {
8518     // shift is > 8
8519     if (sign) {
8520       emitcode ("rlc", "a");
8521       emitcode ("subb", "a,acc");
8522       emitcode ("xch", "a,%s",
8523                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8524     } else {
8525       aopPut (AOP(result), zero, MSB32);
8526     }
8527   }
8528
8529   if (!sign) {
8530     emitcode ("clr", "c");
8531   } else {
8532     emitcode ("mov", "c,acc.7");
8533   }
8534
8535   emitcode ("rrc", "a");
8536
8537   if (isSameRegs && offl==MSB16) {
8538     emitcode ("xch",
8539               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8540   } else {
8541     aopPut (AOP (result), "a", MSB32);
8542     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8543   }
8544
8545   emitcode ("rrc", "a");
8546   if (isSameRegs && offl==1) {
8547     emitcode ("xch", "a,%s",
8548               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8549   } else {
8550     aopPut (AOP (result), "a", MSB24);
8551     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8552   }
8553   emitcode ("rrc", "a");
8554   aopPut (AOP (result), "a", MSB16 - offl);
8555
8556   if (offl == LSB)
8557     {
8558       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8559       emitcode ("rrc", "a");
8560       aopPut (AOP (result), "a", LSB);
8561     }
8562 }
8563
8564 /*-----------------------------------------------------------------*/
8565 /* genrshFour - shift four byte by a known amount != 0             */
8566 /*-----------------------------------------------------------------*/
8567 static void
8568 genrshFour (operand * result, operand * left,
8569             int shCount, int sign)
8570 {
8571   D (emitcode (";", "genrshFour"););
8572
8573   /* if shifting more that 3 bytes */
8574   if (shCount >= 24)
8575     {
8576       shCount -= 24;
8577       _startLazyDPSEvaluation();
8578       if (shCount)
8579         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8580       else
8581         movLeft2Result (left, MSB32, result, LSB, sign);
8582       addSign (result, MSB16, sign);
8583       _endLazyDPSEvaluation();
8584     }
8585   else if (shCount >= 16)
8586     {
8587       shCount -= 16;
8588       _startLazyDPSEvaluation();
8589       if (shCount)
8590         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8591       else
8592         {
8593           movLeft2Result (left, MSB24, result, LSB, 0);
8594           movLeft2Result (left, MSB32, result, MSB16, sign);
8595         }
8596       addSign (result, MSB24, sign);
8597       _endLazyDPSEvaluation();
8598     }
8599   else if (shCount >= 8)
8600     {
8601       shCount -= 8;
8602       _startLazyDPSEvaluation();
8603       if (shCount == 1)
8604         {
8605             shiftRLong (left, MSB16, result, sign);
8606         }
8607       else if (shCount == 0)
8608         {
8609           movLeft2Result (left, MSB16, result, LSB, 0);
8610           movLeft2Result (left, MSB24, result, MSB16, 0);
8611           movLeft2Result (left, MSB32, result, MSB24, sign);
8612           addSign (result, MSB32, sign);
8613         }
8614       else
8615         {
8616           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8617           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8618           /* the last shift is signed */
8619           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8620           addSign (result, MSB32, sign);
8621         }
8622         _endLazyDPSEvaluation();
8623     }
8624   else
8625     {   
8626         /* 1 <= shCount <= 7 */
8627       if (shCount <= 2)
8628         {
8629           shiftRLong (left, LSB, result, sign);
8630           if (shCount == 2)
8631             shiftRLong (result, LSB, result, sign);
8632         }
8633       else
8634         {
8635           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8636           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8637           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8638         }
8639     }
8640 }
8641
8642 #ifdef BETTER_LITERAL_SHIFT
8643 /*-----------------------------------------------------------------*/
8644 /* genRightShiftLiteral - right shifting by known count            */
8645 /*-----------------------------------------------------------------*/
8646 static bool
8647 genRightShiftLiteral (operand * left,
8648                       operand * right,
8649                       operand * result,
8650                       iCode * ic,
8651                       int sign)
8652 {
8653   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8654   int size;
8655
8656   size = getSize (operandType (result));
8657
8658   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8659
8660   /* We only handle certain easy cases so far. */
8661   if ((shCount != 0)
8662    && (shCount < (size * 8))
8663    && (size != 1)
8664    && (size != 2)
8665    && (size != 4))
8666   {
8667       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8668       return FALSE;
8669   }
8670
8671   freeAsmop (right, NULL, ic, TRUE);
8672
8673   aopOp (left, ic, FALSE, FALSE);
8674   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8675
8676 #if VIEW_SIZE
8677   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8678             AOP_SIZE (left));
8679 #endif
8680
8681   /* test the LEFT size !!! */
8682
8683   /* I suppose that the left size >= result size */
8684   if (shCount == 0)
8685   {
8686       size = getDataSize (result);
8687       _startLazyDPSEvaluation();
8688       while (size--)
8689       {
8690         movLeft2Result (left, size, result, size, 0);
8691       }
8692       _endLazyDPSEvaluation();
8693   }
8694   else if (shCount >= (size * 8))
8695     {
8696       if (sign)
8697       {
8698         /* get sign in acc.7 */
8699         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8700       }
8701       addSign (result, LSB, sign);
8702     }
8703   else
8704     {
8705       switch (size)
8706         {
8707         case 1:
8708           genrshOne (result, left, shCount, sign);
8709           break;
8710
8711         case 2:
8712           genrshTwo (result, left, shCount, sign);
8713           break;
8714 #if 1
8715         case 4:
8716           genrshFour (result, left, shCount, sign);
8717           break;
8718 #endif    
8719         default:
8720           break;
8721         }
8722     }
8723   freeAsmop (left, NULL, ic, TRUE);
8724   freeAsmop (result, NULL, ic, TRUE);
8725   
8726   return TRUE;
8727 }
8728 #endif
8729
8730 /*-----------------------------------------------------------------*/
8731 /* genSignedRightShift - right shift of signed number              */
8732 /*-----------------------------------------------------------------*/
8733 static void
8734 genSignedRightShift (iCode * ic)
8735 {
8736   operand *right, *left, *result;
8737   int size, offset;
8738   char *l;
8739   symbol *tlbl, *tlbl1;
8740
8741   D (emitcode (";", "genSignedRightShift "););
8742
8743   /* we do it the hard way put the shift count in b
8744      and loop thru preserving the sign */
8745
8746   right = IC_RIGHT (ic);
8747   left = IC_LEFT (ic);
8748   result = IC_RESULT (ic);
8749
8750   aopOp (right, ic, FALSE, FALSE);
8751
8752 #ifdef BETTER_LITERAL_SHIFT
8753   if (AOP_TYPE (right) == AOP_LIT)
8754     {
8755       if (genRightShiftLiteral (left, right, result, ic, 1))
8756       {
8757         return;
8758       }
8759     }
8760 #endif
8761   /* shift count is unknown then we have to form
8762      a loop get the loop count in B : Note: we take
8763      only the lower order byte since shifting
8764      more that 32 bits make no sense anyway, ( the
8765      largest size of an object can be only 32 bits ) */
8766
8767   if (AOP_TYPE (right) == AOP_LIT)
8768   {
8769       /* Really should be handled by genRightShiftLiteral,
8770        * but since I'm too lazy to fix that today, at least we can make
8771        * some small improvement.
8772        */
8773        emitcode("mov", "b,#!constbyte",
8774                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8775   }
8776   else
8777   {
8778         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8779         emitcode ("inc", "b");
8780   }
8781   freeAsmop (right, NULL, ic, TRUE);
8782   aopOp (left, ic, FALSE, FALSE);
8783   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8784
8785   /* now move the left to the result if they are not the
8786      same */
8787   if (!sameRegs (AOP (left), AOP (result)) &&
8788       AOP_SIZE (result) > 1)
8789     {
8790
8791       size = AOP_SIZE (result);
8792       offset = 0;
8793       _startLazyDPSEvaluation ();
8794       while (size--)
8795         {
8796           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8797           if (*l == '@' && IS_AOP_PREG (result))
8798             {
8799
8800               emitcode ("mov", "a,%s", l);
8801               aopPut (AOP (result), "a", offset);
8802             }
8803           else
8804             aopPut (AOP (result), l, offset);
8805           offset++;
8806         }
8807       _endLazyDPSEvaluation ();
8808     }
8809
8810   /* mov the highest order bit to OVR */
8811   tlbl = newiTempLabel (NULL);
8812   tlbl1 = newiTempLabel (NULL);
8813
8814   size = AOP_SIZE (result);
8815   offset = size - 1;
8816   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8817   emitcode ("rlc", "a");
8818   emitcode ("mov", "ov,c");
8819   /* if it is only one byte then */
8820   if (size == 1)
8821     {
8822       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8823       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8824       emitcode ("", "!tlabeldef", tlbl->key + 100);
8825       emitcode ("mov", "c,ov");
8826       emitcode ("rrc", "a");
8827       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8828       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8829       aopPut (AOP (result), "a", 0);
8830       goto release;
8831     }
8832
8833   reAdjustPreg (AOP (result));
8834   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8835   emitcode ("", "!tlabeldef", tlbl->key + 100);
8836   emitcode ("mov", "c,ov");
8837   _startLazyDPSEvaluation ();
8838   while (size--)
8839     {
8840       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8841       emitcode ("rrc", "a");
8842       aopPut (AOP (result), "a", offset--);
8843     }
8844   _endLazyDPSEvaluation ();
8845   reAdjustPreg (AOP (result));
8846   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8847   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8848
8849 release:
8850   freeAsmop (left, NULL, ic, TRUE);
8851   freeAsmop (result, NULL, ic, TRUE);
8852 }
8853
8854 /*-----------------------------------------------------------------*/
8855 /* genRightShift - generate code for right shifting                */
8856 /*-----------------------------------------------------------------*/
8857 static void
8858 genRightShift (iCode * ic)
8859 {
8860   operand *right, *left, *result;
8861   sym_link *retype;
8862   int size, offset;
8863   char *l;
8864   symbol *tlbl, *tlbl1;
8865
8866   D (emitcode (";", "genRightShift "););
8867
8868   /* if signed then we do it the hard way preserve the
8869      sign bit moving it inwards */
8870   retype = getSpec (operandType (IC_RESULT (ic)));
8871
8872   if (!SPEC_USIGN (retype))
8873     {
8874       genSignedRightShift (ic);
8875       return;
8876     }
8877
8878   /* signed & unsigned types are treated the same : i.e. the
8879      signed is NOT propagated inwards : quoting from the
8880      ANSI - standard : "for E1 >> E2, is equivalent to division
8881      by 2**E2 if unsigned or if it has a non-negative value,
8882      otherwise the result is implementation defined ", MY definition
8883      is that the sign does not get propagated */
8884
8885   right = IC_RIGHT (ic);
8886   left = IC_LEFT (ic);
8887   result = IC_RESULT (ic);
8888
8889   aopOp (right, ic, FALSE, FALSE);
8890
8891 #ifdef BETTER_LITERAL_SHIFT
8892   /* if the shift count is known then do it
8893      as efficiently as possible */
8894   if (AOP_TYPE (right) == AOP_LIT)
8895     {
8896       if (genRightShiftLiteral (left, right, result, ic, 0))
8897       {
8898         return;
8899       }
8900     }
8901 #endif
8902
8903   /* shift count is unknown then we have to form
8904      a loop get the loop count in B : Note: we take
8905      only the lower order byte since shifting
8906      more that 32 bits make no sense anyway, ( the
8907      largest size of an object can be only 32 bits ) */
8908   
8909   if (AOP_TYPE (right) == AOP_LIT)
8910   {
8911       /* Really should be handled by genRightShiftLiteral,
8912        * but since I'm too lazy to fix that today, at least we can make
8913        * some small improvement.
8914        */
8915        emitcode("mov", "b,#!constbyte",
8916                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8917   }
8918   else
8919   {
8920       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8921       emitcode ("inc", "b");
8922   }
8923   freeAsmop (right, NULL, ic, TRUE);
8924   aopOp (left, ic, FALSE, FALSE);
8925   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8926
8927   /* now move the left to the result if they are not the
8928      same */
8929   if (!sameRegs (AOP (left), AOP (result)) &&
8930       AOP_SIZE (result) > 1)
8931     {
8932
8933       size = AOP_SIZE (result);
8934       offset = 0;
8935       _startLazyDPSEvaluation ();
8936       while (size--)
8937         {
8938           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8939           if (*l == '@' && IS_AOP_PREG (result))
8940             {
8941
8942               emitcode ("mov", "a,%s", l);
8943               aopPut (AOP (result), "a", offset);
8944             }
8945           else
8946             aopPut (AOP (result), l, offset);
8947           offset++;
8948         }
8949       _endLazyDPSEvaluation ();
8950     }
8951
8952   tlbl = newiTempLabel (NULL);
8953   tlbl1 = newiTempLabel (NULL);
8954   size = AOP_SIZE (result);
8955   offset = size - 1;
8956
8957   /* if it is only one byte then */
8958   if (size == 1)
8959     {
8960       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8961       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8962       emitcode ("", "!tlabeldef", tlbl->key + 100);
8963       CLRC;
8964       emitcode ("rrc", "a");
8965       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8966       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8967       aopPut (AOP (result), "a", 0);
8968       goto release;
8969     }
8970
8971   reAdjustPreg (AOP (result));
8972   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8973   emitcode ("", "!tlabeldef", tlbl->key + 100);
8974   CLRC;
8975   _startLazyDPSEvaluation ();
8976   while (size--)
8977     {
8978       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8979       emitcode ("rrc", "a");
8980       aopPut (AOP (result), "a", offset--);
8981     }
8982   _endLazyDPSEvaluation ();
8983   reAdjustPreg (AOP (result));
8984
8985   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8986   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8987
8988 release:
8989   freeAsmop (left, NULL, ic, TRUE);
8990   freeAsmop (result, NULL, ic, TRUE);
8991 }
8992
8993
8994 /*-----------------------------------------------------------------*/
8995 /* emitPtrByteGet - emits code to get a byte into A through a      */
8996 /*                  pointer register (R0, R1, or DPTR). The        */
8997 /*                  original value of A can be preserved in B.     */
8998 /*-----------------------------------------------------------------*/
8999 static void
9000 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9001 {
9002   switch (p_type)
9003     {
9004     case IPOINTER:
9005     case POINTER:
9006       if (preserveAinB)
9007         emitcode ("mov", "b,a");
9008       emitcode ("mov", "a,@%s", rname);
9009       break;
9010
9011     case PPOINTER:
9012       if (preserveAinB)
9013         emitcode ("mov", "b,a");
9014       emitcode ("movx", "a,@%s", rname);
9015       break;
9016       
9017     case FPOINTER:
9018       if (preserveAinB)
9019         emitcode ("mov", "b,a");
9020       emitcode ("movx", "a,@dptr");
9021       break;
9022
9023     case CPOINTER:
9024       if (preserveAinB)
9025         emitcode ("mov", "b,a");
9026       emitcode ("clr", "a");
9027       emitcode ("movc", "a,@a+dptr");
9028       break;
9029
9030     case GPOINTER:
9031       if (preserveAinB)
9032         {
9033           emitcode ("push", "b");
9034           emitcode ("push", "acc");
9035         }
9036       emitcode ("lcall", "__gptrget");
9037       if (preserveAinB)
9038         emitcode ("pop", "b");
9039       break;
9040     }
9041 }
9042
9043 /*-----------------------------------------------------------------*/
9044 /* emitPtrByteSet - emits code to set a byte from src through a    */
9045 /*                  pointer register (R0, R1, or DPTR).            */
9046 /*-----------------------------------------------------------------*/
9047 static void
9048 emitPtrByteSet (char *rname, int p_type, char *src)
9049 {
9050   switch (p_type)
9051     {
9052     case IPOINTER:
9053     case POINTER:
9054       if (*src=='@')
9055         {
9056           MOVA (src);
9057           emitcode ("mov", "@%s,a", rname);
9058         }
9059       else
9060         emitcode ("mov", "@%s,%s", rname, src);
9061       break;
9062
9063     case PPOINTER:
9064       MOVA (src);
9065       emitcode ("movx", "@%s,a", rname);
9066       break;
9067       
9068     case FPOINTER:
9069       MOVA (src);
9070       emitcode ("movx", "@dptr,a");
9071       break;
9072
9073     case GPOINTER:
9074       MOVA (src);
9075       emitcode ("lcall", "__gptrput");
9076       break;
9077     }
9078 }
9079
9080 /*-----------------------------------------------------------------*/
9081 /* genUnpackBits - generates code for unpacking bits               */
9082 /*-----------------------------------------------------------------*/
9083 static void
9084 genUnpackBits (operand * result, char *rname, int ptype)
9085 {
9086   int offset = 0;       /* result byte offset */
9087   int rsize;            /* result size */
9088   int rlen = 0;         /* remaining bitfield length */
9089   sym_link *etype;      /* bitfield type information */
9090   int blen;             /* bitfield length */
9091   int bstr;             /* bitfield starting bit within byte */
9092
9093   D(emitcode (";     genUnpackBits",""));
9094
9095   etype = getSpec (operandType (result));
9096   rsize = getSize (operandType (result));
9097   blen = SPEC_BLEN (etype);
9098   bstr = SPEC_BSTR (etype);
9099
9100   /* If the bitfield length is less than a byte */
9101   if (blen < 8)
9102     {
9103       emitPtrByteGet (rname, ptype, FALSE);
9104       AccRsh (bstr);
9105       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9106       aopPut (AOP (result), "a", offset++);
9107       goto finish;
9108     }
9109
9110   /* Bit field did not fit in a byte. Copy all
9111      but the partial byte at the end.  */
9112   for (rlen=blen;rlen>=8;rlen-=8)
9113     {
9114       emitPtrByteGet (rname, ptype, FALSE);
9115       aopPut (AOP (result), "a", offset++);
9116       if (rlen>8)
9117         emitcode ("inc", "%s", rname);
9118     }
9119
9120   /* Handle the partial byte at the end */
9121   if (rlen)
9122     {
9123       emitPtrByteGet (rname, ptype, FALSE);
9124       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9125       aopPut (AOP (result), "a", offset++);
9126     }
9127
9128 finish:
9129   if (offset < rsize)
9130     {
9131       rsize -= offset;
9132       while (rsize--)
9133         aopPut (AOP (result), zero, offset++);
9134     }
9135 }
9136
9137
9138 /*-----------------------------------------------------------------*/
9139 /* genDataPointerGet - generates code when ptr offset is known     */
9140 /*-----------------------------------------------------------------*/
9141 static void
9142 genDataPointerGet (operand * left,
9143                    operand * result,
9144                    iCode * ic)
9145 {
9146   char *l;
9147   char buff[256];
9148   int size, offset = 0;
9149   aopOp (result, ic, TRUE, FALSE);
9150
9151   /* get the string representation of the name */
9152   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9153   size = AOP_SIZE (result);
9154   _startLazyDPSEvaluation ();
9155   while (size--)
9156     {
9157         if (offset)
9158         {
9159             SNPRINTF (buff, sizeof(buff), 
9160                       "(%s + %d)", l + 1, offset);
9161         }
9162         else
9163         {
9164             SNPRINTF (buff, sizeof(buff), 
9165                       "%s", l + 1);
9166         }
9167       aopPut (AOP (result), buff, offset++);
9168     }
9169   _endLazyDPSEvaluation ();
9170
9171   freeAsmop (left, NULL, ic, TRUE);
9172   freeAsmop (result, NULL, ic, TRUE);
9173 }
9174
9175 /*-----------------------------------------------------------------*/
9176 /* genNearPointerGet - emitcode for near pointer fetch             */
9177 /*-----------------------------------------------------------------*/
9178 static void
9179 genNearPointerGet (operand * left,
9180                    operand * result,
9181                    iCode * ic,
9182                    iCode *pi)
9183 {
9184   asmop *aop = NULL;
9185   regs *preg;
9186   char *rname;
9187   sym_link *rtype, *retype, *letype;
9188   sym_link *ltype = operandType (left);
9189   char buff[80];
9190
9191   rtype = operandType (result);
9192   retype = getSpec (rtype);
9193   letype = getSpec (ltype);
9194
9195   aopOp (left, ic, FALSE, FALSE);
9196
9197   /* if left is rematerialisable and
9198      result is not bit variable type and
9199      the left is pointer to data space i.e
9200      lower 128 bytes of space */
9201   if (AOP_TYPE (left) == AOP_IMMD &&
9202       !IS_BITVAR (retype) &&
9203       !IS_BITVAR (letype) &&
9204       DCL_TYPE (ltype) == POINTER)
9205     {
9206       genDataPointerGet (left, result, ic);
9207       return;
9208     }
9209
9210   /* if the value is already in a pointer register
9211      then don't need anything more */
9212   if (!AOP_INPREG (AOP (left)))
9213     {
9214       /* otherwise get a free pointer register */
9215       aop = newAsmop (0);
9216       preg = getFreePtr (ic, &aop, FALSE);
9217       emitcode ("mov", "%s,%s",
9218                 preg->name,
9219                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9220       rname = preg->name;
9221     }
9222   else
9223     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9224
9225   freeAsmop (left, NULL, ic, TRUE);
9226   aopOp (result, ic, FALSE, FALSE);
9227
9228   /* if bitfield then unpack the bits */
9229   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9230     genUnpackBits (result, rname, POINTER);
9231   else
9232     {
9233       /* we have can just get the values */
9234       int size = AOP_SIZE (result);
9235       int offset = 0;
9236
9237       while (size--)
9238         {
9239           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9240             {
9241
9242               emitcode ("mov", "a,@%s", rname);
9243               aopPut (AOP (result), "a", offset);
9244             }
9245           else
9246             {
9247               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9248               aopPut (AOP (result), buff, offset);
9249             }
9250           offset++;
9251           if (size || pi)
9252             {
9253                 emitcode ("inc", "%s", rname);
9254             }
9255         }
9256     }
9257
9258   /* now some housekeeping stuff */
9259   if (aop)
9260     {
9261       /* we had to allocate for this iCode */
9262       if (pi) { /* post increment present */
9263         aopPut(AOP ( left ),rname,0);
9264       }
9265       freeAsmop (NULL, aop, ic, TRUE);
9266     }
9267   else
9268     {
9269       /* we did not allocate which means left
9270          already in a pointer register, then
9271          if size > 0 && this could be used again
9272          we have to point it back to where it
9273          belongs */
9274       if (AOP_SIZE (result) > 1 &&
9275           !OP_SYMBOL (left)->remat &&
9276           (OP_SYMBOL (left)->liveTo > ic->seq ||
9277            ic->depth) &&
9278           !pi)
9279         {
9280           int size = AOP_SIZE (result) - 1;
9281           while (size--)
9282             emitcode ("dec", "%s", rname);
9283         }
9284     }
9285
9286   /* done */
9287   freeAsmop (result, NULL, ic, TRUE);
9288   if (pi) pi->generated = 1;
9289 }
9290
9291 /*-----------------------------------------------------------------*/
9292 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9293 /*-----------------------------------------------------------------*/
9294 static void
9295 genPagedPointerGet (operand * left,
9296                     operand * result,
9297                     iCode * ic,
9298                     iCode * pi)
9299 {
9300   asmop *aop = NULL;
9301   regs *preg;
9302   char *rname;
9303   sym_link *rtype, *retype, *letype;
9304
9305   rtype = operandType (result);
9306   retype = getSpec (rtype);
9307   letype = getSpec (operandType (left));
9308   aopOp (left, ic, FALSE, FALSE);
9309
9310   /* if the value is already in a pointer register
9311      then don't need anything more */
9312   if (!AOP_INPREG (AOP (left)))
9313     {
9314       /* otherwise get a free pointer register */
9315       aop = newAsmop (0);
9316       preg = getFreePtr (ic, &aop, FALSE);
9317       emitcode ("mov", "%s,%s",
9318                 preg->name,
9319                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9320       rname = preg->name;
9321     }
9322   else
9323     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9324
9325   freeAsmop (left, NULL, ic, TRUE);
9326   aopOp (result, ic, FALSE, FALSE);
9327
9328   /* if bitfield then unpack the bits */
9329   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9330     genUnpackBits (result, rname, PPOINTER);
9331   else
9332     {
9333       /* we have can just get the values */
9334       int size = AOP_SIZE (result);
9335       int offset = 0;
9336
9337       while (size--)
9338         {
9339
9340           emitcode ("movx", "a,@%s", rname);
9341           aopPut (AOP (result), "a", offset);
9342
9343           offset++;
9344
9345           if (size || pi)
9346             emitcode ("inc", "%s", rname);
9347         }
9348     }
9349
9350   /* now some housekeeping stuff */
9351   if (aop)
9352     {
9353       /* we had to allocate for this iCode */
9354       if (pi) aopPut ( AOP (left), rname, 0);
9355       freeAsmop (NULL, aop, ic, TRUE);
9356     }
9357   else
9358     {
9359       /* we did not allocate which means left
9360          already in a pointer register, then
9361          if size > 0 && this could be used again
9362          we have to point it back to where it
9363          belongs */
9364       if (AOP_SIZE (result) > 1 &&
9365           !OP_SYMBOL (left)->remat &&
9366           (OP_SYMBOL (left)->liveTo > ic->seq ||
9367            ic->depth) &&
9368           !pi)
9369         {
9370           int size = AOP_SIZE (result) - 1;
9371           while (size--)
9372             emitcode ("dec", "%s", rname);
9373         }
9374     }
9375
9376   /* done */
9377   freeAsmop (result, NULL, ic, TRUE);
9378   if (pi) pi->generated = 1;
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* genFarPointerGet - gget value from far space                    */
9383 /*-----------------------------------------------------------------*/
9384 static void
9385 genFarPointerGet (operand * left,
9386                   operand * result, iCode * ic, iCode *pi)
9387 {
9388     int size, offset, dopi=1;
9389   sym_link *retype = getSpec (operandType (result));
9390   sym_link *letype = getSpec (operandType (left));
9391   D (emitcode (";", "genFarPointerGet"););
9392
9393   aopOp (left, ic, FALSE, FALSE);
9394
9395   /* if the operand is already in dptr
9396      then we do nothing else we move the value to dptr */
9397   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9398     {
9399       /* if this is remateriazable */
9400       if (AOP_TYPE (left) == AOP_IMMD)
9401         {
9402           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9403         }
9404       else
9405         {
9406           /* we need to get it byte by byte */
9407           _startLazyDPSEvaluation ();
9408           if (AOP_TYPE (left) != AOP_DPTR)
9409             {
9410               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9411               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9412               if (options.model == MODEL_FLAT24)
9413                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9414             }
9415           else
9416             {
9417               /* We need to generate a load to DPTR indirect through DPTR. */
9418               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9419               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9420               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9421               if (options.model == MODEL_FLAT24)
9422                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9423               emitcode ("pop", "dph");
9424               emitcode ("pop", "dpl");
9425               dopi =0;
9426             }
9427           _endLazyDPSEvaluation ();
9428         }
9429     }
9430   /* so dptr know contains the address */
9431   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9432
9433   /* if bit then unpack */
9434   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9435       if (AOP_INDPTRn(left)) {
9436           genSetDPTR(AOP(left)->aopu.dptr);
9437       }
9438       genUnpackBits (result, "dptr", FPOINTER);
9439       if (AOP_INDPTRn(left)) {
9440           genSetDPTR(0);
9441       }
9442   } else
9443     {
9444       size = AOP_SIZE (result);
9445       offset = 0;
9446
9447       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9448           while (size--) {
9449               genSetDPTR(AOP(left)->aopu.dptr);
9450               emitcode ("movx", "a,@dptr");
9451               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9452                   emitcode ("inc", "dptr");
9453               genSetDPTR (0);
9454               aopPut (AOP (result), "a", offset++);
9455           }
9456       } else {
9457           _startLazyDPSEvaluation ();
9458           while (size--) {
9459               if (AOP_INDPTRn(left)) {
9460                   genSetDPTR(AOP(left)->aopu.dptr);
9461               } else {
9462                   genSetDPTR (0);
9463               }
9464               _flushLazyDPS ();
9465               
9466               emitcode ("movx", "a,@dptr");
9467               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9468                   emitcode ("inc", "dptr");
9469               
9470               aopPut (AOP (result), "a", offset++);
9471           }
9472           _endLazyDPSEvaluation ();
9473       }
9474     }
9475   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9476       if (!AOP_INDPTRn(left)) {
9477           _startLazyDPSEvaluation ();
9478           aopPut ( AOP (left), "dpl", 0);
9479           aopPut ( AOP (left), "dph", 1);
9480           if (options.model == MODEL_FLAT24)
9481               aopPut ( AOP (left), "dpx", 2);
9482           _endLazyDPSEvaluation ();
9483       }
9484     pi->generated = 1;
9485   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9486              AOP_SIZE(result) > 1 &&
9487              IS_SYMOP(left) &&
9488              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9489       
9490       size = AOP_SIZE (result) - 1;
9491       if (AOP_INDPTRn(left)) {
9492           genSetDPTR(AOP(left)->aopu.dptr);
9493       }
9494       while (size--) emitcode ("lcall","__decdptr");
9495       if (AOP_INDPTRn(left)) {
9496           genSetDPTR(0);
9497       }
9498   }
9499
9500   freeAsmop (left, NULL, ic, TRUE);
9501   freeAsmop (result, NULL, ic, TRUE);
9502 }
9503
9504 /*-----------------------------------------------------------------*/
9505 /* genCodePointerGet - get value from code space                  */
9506 /*-----------------------------------------------------------------*/
9507 static void
9508 genCodePointerGet (operand * left,
9509                     operand * result, iCode * ic, iCode *pi)
9510 {
9511   int size, offset, dopi=1;
9512   sym_link *retype = getSpec (operandType (result));
9513
9514   aopOp (left, ic, FALSE, FALSE);
9515
9516   /* if the operand is already in dptr
9517      then we do nothing else we move the value to dptr */
9518   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9519     {
9520       /* if this is remateriazable */
9521       if (AOP_TYPE (left) == AOP_IMMD)
9522         {
9523           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9524         }
9525       else
9526         {                       /* we need to get it byte by byte */
9527           _startLazyDPSEvaluation ();
9528           if (AOP_TYPE (left) != AOP_DPTR)
9529             {
9530               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9531               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9532               if (options.model == MODEL_FLAT24)
9533                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9534             }
9535           else
9536             {
9537               /* We need to generate a load to DPTR indirect through DPTR. */
9538               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9539               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9540               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9541               if (options.model == MODEL_FLAT24)
9542                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9543               emitcode ("pop", "dph");
9544               emitcode ("pop", "dpl");
9545               dopi=0;
9546             }
9547           _endLazyDPSEvaluation ();
9548         }
9549     }
9550   /* so dptr know contains the address */
9551   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9552
9553   /* if bit then unpack */
9554   if (IS_BITVAR (retype)) {
9555       if (AOP_INDPTRn(left)) {
9556           genSetDPTR(AOP(left)->aopu.dptr);
9557       }
9558       genUnpackBits (result, "dptr", CPOINTER);
9559       if (AOP_INDPTRn(left)) {
9560           genSetDPTR(0);
9561       }
9562   } else
9563     {
9564       size = AOP_SIZE (result);
9565       offset = 0;
9566       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9567           while (size--) {
9568               genSetDPTR(AOP(left)->aopu.dptr);
9569               emitcode ("clr", "a");
9570               emitcode ("movc", "a,@a+dptr");
9571               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9572                   emitcode ("inc", "dptr");
9573               genSetDPTR (0);
9574               aopPut (AOP (result), "a", offset++);
9575           }
9576       } else {
9577           _startLazyDPSEvaluation ();
9578           while (size--)
9579               {
9580                   if (AOP_INDPTRn(left)) {
9581                       genSetDPTR(AOP(left)->aopu.dptr);
9582                   } else {
9583                       genSetDPTR (0);
9584                   }
9585                   _flushLazyDPS ();
9586                   
9587                   emitcode ("clr", "a");
9588                   emitcode ("movc", "a,@a+dptr");
9589                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9590                       emitcode ("inc", "dptr");
9591                   aopPut (AOP (result), "a", offset++);
9592               }
9593           _endLazyDPSEvaluation ();
9594       }
9595     }
9596   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9597       if (!AOP_INDPTRn(left)) {
9598           _startLazyDPSEvaluation ();
9599           
9600           aopPut ( AOP (left), "dpl", 0);
9601           aopPut ( AOP (left), "dph", 1);
9602           if (options.model == MODEL_FLAT24)
9603               aopPut ( AOP (left), "dpx", 2);
9604
9605           _endLazyDPSEvaluation ();
9606       }
9607       pi->generated = 1;
9608   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9609              AOP_SIZE(result) > 1 &&
9610              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9611       
9612       size = AOP_SIZE (result) - 1;
9613       if (AOP_INDPTRn(left)) {
9614           genSetDPTR(AOP(left)->aopu.dptr);
9615       }
9616       while (size--) emitcode ("lcall","__decdptr");
9617       if (AOP_INDPTRn(left)) {
9618           genSetDPTR(0);
9619       }
9620   }
9621   
9622   freeAsmop (left, NULL, ic, TRUE);
9623   freeAsmop (result, NULL, ic, TRUE);
9624 }
9625
9626 /*-----------------------------------------------------------------*/
9627 /* genGenPointerGet - gget value from generic pointer space        */
9628 /*-----------------------------------------------------------------*/
9629 static void
9630 genGenPointerGet (operand * left,
9631                   operand * result, iCode * ic, iCode * pi)
9632 {
9633   int size, offset;
9634   sym_link *retype = getSpec (operandType (result));
9635   sym_link *letype = getSpec (operandType (left));
9636
9637   D (emitcode (";", "genGenPointerGet "); );
9638
9639   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9640
9641   /* if the operand is already in dptr
9642      then we do nothing else we move the value to dptr */
9643   if (AOP_TYPE (left) != AOP_STR)
9644     {
9645       /* if this is remateriazable */
9646       if (AOP_TYPE (left) == AOP_IMMD)
9647         {
9648           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9649           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9650             {
9651                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9652             }
9653             else
9654             {
9655                 emitcode ("mov", "b,#%d", pointerCode (retype));
9656             }
9657         }
9658       else
9659         {                       /* we need to get it byte by byte */
9660             _startLazyDPSEvaluation ();
9661             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9662             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9663             if (options.model == MODEL_FLAT24) {
9664                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9665                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9666             } else {
9667                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9668             }
9669             _endLazyDPSEvaluation ();
9670         }
9671     }
9672
9673   /* so dptr-b now contains the address */
9674   _G.bInUse++;
9675   aopOp (result, ic, FALSE, TRUE);
9676   _G.bInUse--;
9677
9678   /* if bit then unpack */
9679   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9680   {
9681     genUnpackBits (result, "dptr", GPOINTER);
9682   }
9683   else
9684     {
9685         size = AOP_SIZE (result);
9686         offset = 0;
9687
9688         while (size--)
9689         {
9690             if (size)
9691             {
9692                 // Get two bytes at a time, results in _AP & A.
9693                 // dptr will be incremented ONCE by __gptrgetWord.
9694                 //
9695                 // Note: any change here must be coordinated
9696                 // with the implementation of __gptrgetWord
9697                 // in device/lib/_gptrget.c
9698                 emitcode ("lcall", "__gptrgetWord");
9699                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9700                 aopPut (AOP (result), "a", offset++);
9701                 size--;
9702             }
9703             else
9704             {
9705                 // Only one byte to get.
9706                 emitcode ("lcall", "__gptrget");
9707                 aopPut (AOP (result), "a", offset++);
9708             }
9709             
9710             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9711             {
9712                 emitcode ("inc", "dptr");
9713             }
9714         }
9715     }
9716
9717   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9718     _startLazyDPSEvaluation ();
9719       
9720     aopPut ( AOP (left), "dpl", 0);
9721     aopPut ( AOP (left), "dph", 1);
9722     if (options.model == MODEL_FLAT24) {
9723         aopPut ( AOP (left), "dpx", 2);
9724         aopPut ( AOP (left), "b", 3);   
9725     } else  aopPut ( AOP (left), "b", 2);       
9726     
9727     _endLazyDPSEvaluation ();
9728       
9729     pi->generated = 1;
9730   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9731              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9732       
9733       size = AOP_SIZE (result) - 1;
9734       while (size--) emitcode ("lcall","__decdptr");
9735   }
9736
9737   freeAsmop (left, NULL, ic, TRUE);
9738   freeAsmop (result, NULL, ic, TRUE);
9739 }
9740
9741 /*-----------------------------------------------------------------*/
9742 /* genPointerGet - generate code for pointer get                   */
9743 /*-----------------------------------------------------------------*/
9744 static void
9745 genPointerGet (iCode * ic, iCode *pi)
9746 {
9747   operand *left, *result;
9748   sym_link *type, *etype;
9749   int p_type;
9750
9751   D (emitcode (";", "genPointerGet ");
9752     );
9753
9754   left = IC_LEFT (ic);
9755   result = IC_RESULT (ic);
9756
9757   /* depending on the type of pointer we need to
9758      move it to the correct pointer register */
9759   type = operandType (left);
9760   etype = getSpec (type);
9761   /* if left is of type of pointer then it is simple */
9762   if (IS_PTR (type) && !IS_FUNC (type->next))
9763     p_type = DCL_TYPE (type);
9764   else
9765     {
9766       /* we have to go by the storage class */
9767       p_type = PTR_TYPE (SPEC_OCLS (etype));
9768     }
9769   /* special case when cast remat */
9770   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9771       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9772           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9773           type = operandType (left);
9774           p_type = DCL_TYPE (type);
9775   }
9776   /* now that we have the pointer type we assign
9777      the pointer values */
9778   switch (p_type)
9779     {
9780
9781     case POINTER:
9782     case IPOINTER:
9783       genNearPointerGet (left, result, ic, pi);
9784       break;
9785
9786     case PPOINTER:
9787       genPagedPointerGet (left, result, ic, pi);
9788       break;
9789
9790     case FPOINTER:
9791       genFarPointerGet (left, result, ic, pi);
9792       break;
9793
9794     case CPOINTER:
9795       genCodePointerGet (left, result, ic, pi);
9796       break;
9797
9798     case GPOINTER:
9799       genGenPointerGet (left, result, ic, pi);
9800       break;
9801     }
9802
9803 }
9804
9805 /*-----------------------------------------------------------------*/
9806 /* genPackBits - generates code for packed bit storage             */
9807 /*-----------------------------------------------------------------*/
9808 static void
9809 genPackBits (sym_link * etype,
9810              operand * right,
9811              char *rname, int p_type)
9812 {
9813   int offset = 0;       /* source byte offset */
9814   int rlen = 0;         /* remaining bitfield length */
9815   int blen;             /* bitfield length */
9816   int bstr;             /* bitfield starting bit within byte */
9817   int litval;           /* source literal value (if AOP_LIT) */
9818   unsigned char mask;   /* bitmask within current byte */
9819
9820   D(emitcode (";     genPackBits",""));
9821
9822   blen = SPEC_BLEN (etype);
9823   bstr = SPEC_BSTR (etype);
9824
9825   /* If the bitfield length is less than a byte */
9826   if (blen < 8)
9827     {
9828       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9829               (unsigned char) (0xFF >> (8 - bstr)));
9830
9831       if (AOP_TYPE (right) == AOP_LIT)
9832         {
9833           /* Case with a bitfield length <8 and literal source
9834           */
9835           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9836           litval <<= bstr;
9837           litval &= (~mask) & 0xff;
9838           emitPtrByteGet (rname, p_type, FALSE);
9839           if ((mask|litval)!=0xff)
9840             emitcode ("anl","a,#!constbyte", mask);
9841           if (litval)
9842             emitcode ("orl","a,#!constbyte", litval);
9843         }
9844       else
9845         {
9846           if ((blen==1) && (p_type!=GPOINTER))
9847             {
9848               /* Case with a bitfield length == 1 and no generic pointer
9849               */
9850               if (AOP_TYPE (right) == AOP_CRY)
9851                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9852               else
9853                 {
9854                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9855                   emitcode ("rrc","a");
9856                 }
9857               emitPtrByteGet (rname, p_type, FALSE);
9858               emitcode ("mov","acc.%d,c",bstr);
9859             }
9860           else
9861             {
9862               /* Case with a bitfield length < 8 and arbitrary source
9863               */
9864               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9865               /* shift and mask source value */
9866               AccLsh (bstr);
9867               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9868
9869               /* transfer A to B and get next byte */
9870               emitPtrByteGet (rname, p_type, TRUE);
9871
9872               emitcode ("anl", "a,#!constbyte", mask);
9873               emitcode ("orl", "a,b");
9874               if (p_type == GPOINTER)
9875                 emitcode ("pop", "b");
9876            }
9877         }
9878
9879       emitPtrByteSet (rname, p_type, "a");
9880       return;
9881     }
9882
9883   /* Bit length is greater than 7 bits. In this case, copy  */
9884   /* all except the partial byte at the end                 */
9885   for (rlen=blen;rlen>=8;rlen-=8)
9886     {
9887       emitPtrByteSet (rname, p_type, 
9888                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9889       if (rlen>8)
9890         emitcode ("inc", "%s", rname);
9891     }
9892
9893   /* If there was a partial byte at the end */
9894   if (rlen)
9895     {
9896       mask = (((unsigned char) -1 << rlen) & 0xff);
9897       
9898       if (AOP_TYPE (right) == AOP_LIT)
9899         {
9900           /* Case with partial byte and literal source
9901           */
9902           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9903           litval >>= (blen-rlen);
9904           litval &= (~mask) & 0xff;
9905           emitPtrByteGet (rname, p_type, FALSE);
9906           if ((mask|litval)!=0xff)
9907             emitcode ("anl","a,#!constbyte", mask);
9908           if (litval)
9909             emitcode ("orl","a,#!constbyte", litval);
9910         }
9911       else
9912         {
9913           /* Case with partial byte and arbitrary source
9914           */
9915           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9916           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9917
9918           /* transfer A to B and get next byte */
9919           emitPtrByteGet (rname, p_type, TRUE);
9920
9921           emitcode ("anl", "a,#!constbyte", mask);
9922           emitcode ("orl", "a,b");
9923           if (p_type == GPOINTER)
9924             emitcode ("pop", "b");
9925         }
9926       emitPtrByteSet (rname, p_type, "a");
9927     }
9928
9929 }
9930
9931
9932 /*-----------------------------------------------------------------*/
9933 /* genDataPointerSet - remat pointer to data space                 */
9934 /*-----------------------------------------------------------------*/
9935 static void
9936 genDataPointerSet (operand * right,
9937                    operand * result,
9938                    iCode * ic)
9939 {
9940   int size, offset = 0;
9941   char *l, buff[256];
9942
9943   aopOp (right, ic, FALSE, FALSE);
9944
9945   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9946   size = AOP_SIZE (right);
9947   while (size--)
9948     {
9949       if (offset)
9950         {
9951             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9952         }
9953       else
9954         {
9955             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9956         }
9957         
9958       emitcode ("mov", "%s,%s", buff,
9959                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9960     }
9961
9962   freeAsmop (right, NULL, ic, TRUE);
9963   freeAsmop (result, NULL, ic, TRUE);
9964 }
9965
9966 /*-----------------------------------------------------------------*/
9967 /* genNearPointerSet - emitcode for near pointer put                */
9968 /*-----------------------------------------------------------------*/
9969 static void
9970 genNearPointerSet (operand * right,
9971                    operand * result,
9972                    iCode * ic,
9973                    iCode * pi)
9974 {
9975   asmop *aop = NULL;
9976   char *rname, *l;
9977   sym_link *retype, *letype;
9978   sym_link *ptype = operandType (result);
9979
9980   retype = getSpec (operandType (right));
9981   letype = getSpec (ptype);
9982
9983   aopOp (result, ic, FALSE, FALSE);
9984
9985   /* if the result is rematerializable &
9986      in data space & not a bit variable */
9987   if (AOP_TYPE (result) == AOP_IMMD &&
9988       DCL_TYPE (ptype) == POINTER &&
9989       !IS_BITVAR (retype) &&
9990       !IS_BITVAR (letype))
9991     {
9992       genDataPointerSet (right, result, ic);
9993       return;
9994     }
9995
9996   /* if the value is already in a pointer register
9997      then don't need anything more */
9998   if (!AOP_INPREG (AOP (result)))
9999     {
10000       /* otherwise get a free pointer register */
10001       regs *preg;
10002         
10003       aop = newAsmop (0);
10004       preg = getFreePtr (ic, &aop, FALSE);
10005       emitcode ("mov", "%s,%s",
10006                 preg->name,
10007                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10008       rname = preg->name;
10009     }
10010   else
10011     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10012
10013   aopOp (right, ic, FALSE, FALSE);
10014
10015   /* if bitfield then unpack the bits */
10016   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10017     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10018   else
10019     {
10020       /* we have can just get the values */
10021       int size = AOP_SIZE (right);
10022       int offset = 0;
10023
10024       while (size--)
10025         {
10026           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10027           if (*l == '@')
10028             {
10029               MOVA (l);
10030               emitcode ("mov", "@%s,a", rname);
10031             }
10032           else
10033             emitcode ("mov", "@%s,%s", rname, l);
10034           if (size || pi)
10035             emitcode ("inc", "%s", rname);
10036           offset++;
10037         }
10038     }
10039
10040   /* now some housekeeping stuff */
10041   if (aop)
10042     {
10043       /* we had to allocate for this iCode */
10044       if (pi) aopPut (AOP (result),rname,0);
10045       freeAsmop (NULL, aop, ic, TRUE);
10046     }
10047   else
10048     {
10049       /* we did not allocate which means left
10050          already in a pointer register, then
10051          if size > 0 && this could be used again
10052          we have to point it back to where it
10053          belongs */
10054       if (AOP_SIZE (right) > 1 &&
10055           !OP_SYMBOL (result)->remat &&
10056           (OP_SYMBOL (result)->liveTo > ic->seq ||
10057            ic->depth) &&
10058           !pi)
10059         {
10060           int size = AOP_SIZE (right) - 1;
10061           while (size--)
10062             emitcode ("dec", "%s", rname);
10063         }
10064     }
10065
10066   /* done */
10067   if (pi) pi->generated = 1;
10068   freeAsmop (result, NULL, ic, TRUE);
10069   freeAsmop (right, NULL, ic, TRUE);
10070
10071
10072 }
10073
10074 /*-----------------------------------------------------------------*/
10075 /* genPagedPointerSet - emitcode for Paged pointer put             */
10076 /*-----------------------------------------------------------------*/
10077 static void
10078 genPagedPointerSet (operand * right,
10079                     operand * result,
10080                     iCode * ic,
10081                     iCode *pi)
10082 {
10083   asmop *aop = NULL;
10084   char *rname;
10085   sym_link *retype, *letype;
10086
10087   retype = getSpec (operandType (right));
10088   letype = getSpec (operandType (result));
10089
10090   aopOp (result, ic, FALSE, FALSE);
10091
10092   /* if the value is already in a pointer register
10093      then don't need anything more */
10094   if (!AOP_INPREG (AOP (result)))
10095     {
10096       /* otherwise get a free pointer register */
10097       regs *preg;
10098         
10099       aop = newAsmop (0);
10100       preg = getFreePtr (ic, &aop, FALSE);
10101       emitcode ("mov", "%s,%s",
10102                 preg->name,
10103                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10104       rname = preg->name;
10105     }
10106   else
10107     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10108
10109   aopOp (right, ic, FALSE, FALSE);
10110
10111   /* if bitfield then unpack the bits */
10112   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10113     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10114   else
10115     {
10116       /* we have can just get the values */
10117       int size = AOP_SIZE (right);
10118       int offset = 0;
10119
10120       while (size--)
10121         {
10122           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10123
10124           emitcode ("movx", "@%s,a", rname);
10125
10126           if (size || pi)
10127             emitcode ("inc", "%s", rname);
10128
10129           offset++;
10130         }
10131     }
10132
10133   /* now some housekeeping stuff */
10134   if (aop)
10135     {
10136       if (pi) aopPut (AOP (result),rname,0);
10137       /* we had to allocate for this iCode */
10138       freeAsmop (NULL, aop, ic, TRUE);
10139     }
10140   else
10141     {
10142       /* we did not allocate which means left
10143          already in a pointer register, then
10144          if size > 0 && this could be used again
10145          we have to point it back to where it
10146          belongs */
10147       if (AOP_SIZE (right) > 1 &&
10148           !OP_SYMBOL (result)->remat &&
10149           (OP_SYMBOL (result)->liveTo > ic->seq ||
10150            ic->depth) &&
10151           !pi)
10152         {
10153           int size = AOP_SIZE (right) - 1;
10154           while (size--)
10155             emitcode ("dec", "%s", rname);
10156         }
10157     }
10158
10159   /* done */
10160   if (pi) pi->generated = 1;
10161   freeAsmop (result, NULL, ic, TRUE);
10162   freeAsmop (right, NULL, ic, TRUE);
10163
10164
10165 }
10166
10167 /*-----------------------------------------------------------------*/
10168 /* genFarPointerSet - set value from far space                     */
10169 /*-----------------------------------------------------------------*/
10170 static void
10171 genFarPointerSet (operand * right,
10172                   operand * result, iCode * ic, iCode *pi)
10173 {
10174   int size, offset, dopi=1;
10175   sym_link *retype = getSpec (operandType (right));
10176   sym_link *letype = getSpec (operandType (result));
10177
10178   aopOp (result, ic, FALSE, FALSE);
10179
10180   /* if the operand is already in dptr
10181      then we do nothing else we move the value to dptr */
10182   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10183     {
10184       /* if this is remateriazable */
10185       if (AOP_TYPE (result) == AOP_IMMD)
10186         emitcode ("mov", "dptr,%s", 
10187                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10188       else
10189         {
10190           /* we need to get it byte by byte */
10191           _startLazyDPSEvaluation ();
10192           if (AOP_TYPE (result) != AOP_DPTR)
10193             {
10194               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10195               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10196               if (options.model == MODEL_FLAT24)
10197                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10198             }
10199           else
10200             {
10201               /* We need to generate a load to DPTR indirect through DPTR. */
10202               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10203                 
10204               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10205               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10206               if (options.model == MODEL_FLAT24)
10207                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10208               emitcode ("pop", "dph");
10209               emitcode ("pop", "dpl");
10210               dopi=0;
10211             }
10212           _endLazyDPSEvaluation ();
10213         }
10214     }
10215   /* so dptr know contains the address */
10216   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10217
10218   /* if bit then unpack */
10219   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10220       if (AOP_INDPTRn(result)) {
10221           genSetDPTR(AOP(result)->aopu.dptr);
10222       }
10223       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10224       if (AOP_INDPTRn(result)) {
10225           genSetDPTR(0);
10226       }
10227   } else {
10228       size = AOP_SIZE (right);
10229       offset = 0;
10230       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10231           while (size--) {
10232               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10233               
10234               genSetDPTR(AOP(result)->aopu.dptr);
10235               emitcode ("movx", "@dptr,a");
10236               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10237                   emitcode ("inc", "dptr");
10238               genSetDPTR (0);
10239           }
10240       } else {
10241           _startLazyDPSEvaluation ();
10242           while (size--) {
10243               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10244               
10245               if (AOP_INDPTRn(result)) {
10246                   genSetDPTR(AOP(result)->aopu.dptr);
10247               } else {
10248                   genSetDPTR (0);
10249               }
10250               _flushLazyDPS ();
10251               
10252               emitcode ("movx", "@dptr,a");
10253               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10254                   emitcode ("inc", "dptr");
10255           }
10256           _endLazyDPSEvaluation ();
10257       }
10258   }
10259   
10260   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10261       if (!AOP_INDPTRn(result)) {
10262           _startLazyDPSEvaluation ();
10263           
10264           aopPut (AOP(result),"dpl",0);
10265           aopPut (AOP(result),"dph",1);
10266           if (options.model == MODEL_FLAT24)
10267               aopPut (AOP(result),"dpx",2);
10268
10269           _endLazyDPSEvaluation ();
10270       }
10271       pi->generated=1;
10272   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10273              AOP_SIZE(right) > 1 &&
10274              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10275       
10276       size = AOP_SIZE (right) - 1;
10277       if (AOP_INDPTRn(result)) {
10278           genSetDPTR(AOP(result)->aopu.dptr);
10279       } 
10280       while (size--) emitcode ("lcall","__decdptr");
10281       if (AOP_INDPTRn(result)) {
10282           genSetDPTR(0);
10283       }
10284   }
10285   freeAsmop (result, NULL, ic, TRUE);
10286   freeAsmop (right, NULL, ic, TRUE);
10287 }
10288
10289 /*-----------------------------------------------------------------*/
10290 /* genGenPointerSet - set value from generic pointer space         */
10291 /*-----------------------------------------------------------------*/
10292 static void
10293 genGenPointerSet (operand * right,
10294                   operand * result, iCode * ic, iCode *pi)
10295 {
10296   int size, offset;
10297   sym_link *retype = getSpec (operandType (right));
10298   sym_link *letype = getSpec (operandType (result));
10299
10300   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10301
10302   /* if the operand is already in dptr
10303      then we do nothing else we move the value to dptr */
10304   if (AOP_TYPE (result) != AOP_STR)
10305     {
10306       _startLazyDPSEvaluation ();
10307       /* if this is remateriazable */
10308       if (AOP_TYPE (result) == AOP_IMMD)
10309         {
10310           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10311           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10312           {
10313               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10314           }
10315           else
10316           {
10317               emitcode ("mov", 
10318                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10319           }
10320         }
10321       else
10322         {                       /* we need to get it byte by byte */
10323           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10324           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10325           if (options.model == MODEL_FLAT24) {
10326             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10327             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10328           } else {
10329             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10330           }
10331         }
10332       _endLazyDPSEvaluation ();
10333     }
10334   /* so dptr + b now contains the address */
10335   _G.bInUse++;
10336   aopOp (right, ic, FALSE, TRUE);
10337   _G.bInUse--;
10338     
10339
10340   /* if bit then unpack */
10341   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10342     {
10343         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10344     }
10345   else
10346     {
10347         size = AOP_SIZE (right);
10348         offset = 0;
10349
10350         _startLazyDPSEvaluation ();
10351         while (size--)
10352         {
10353             if (size)
10354             {
10355                 // Set two bytes at a time, passed in _AP & A.
10356                 // dptr will be incremented ONCE by __gptrputWord.
10357                 //
10358                 // Note: any change here must be coordinated
10359                 // with the implementation of __gptrputWord
10360                 // in device/lib/_gptrput.c
10361                 emitcode("mov", "_ap, %s", 
10362                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10363                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10364                 
10365                 genSetDPTR (0);
10366                 _flushLazyDPS ();
10367                 emitcode ("lcall", "__gptrputWord");
10368                 size--;
10369             }
10370             else
10371             {
10372                 // Only one byte to put.
10373                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10374
10375                 genSetDPTR (0);
10376                 _flushLazyDPS ();               
10377                 emitcode ("lcall", "__gptrput");
10378             }
10379             
10380             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10381             {
10382                 emitcode ("inc", "dptr");
10383             }
10384         }
10385         _endLazyDPSEvaluation ();
10386     }
10387
10388   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10389       _startLazyDPSEvaluation ();
10390       
10391       aopPut (AOP(result),"dpl",0);
10392       aopPut (AOP(result),"dph",1);
10393       if (options.model == MODEL_FLAT24) {
10394           aopPut (AOP(result),"dpx",2);
10395           aopPut (AOP(result),"b",3);
10396       } else {
10397           aopPut (AOP(result),"b",2);
10398       }
10399       _endLazyDPSEvaluation ();
10400       
10401       pi->generated=1;
10402   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10403              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10404       
10405       size = AOP_SIZE (right) - 1;
10406       while (size--) emitcode ("lcall","__decdptr");
10407   }
10408   freeAsmop (result, NULL, ic, TRUE);
10409   freeAsmop (right, NULL, ic, TRUE);
10410 }
10411
10412 /*-----------------------------------------------------------------*/
10413 /* genPointerSet - stores the value into a pointer location        */
10414 /*-----------------------------------------------------------------*/
10415 static void
10416 genPointerSet (iCode * ic, iCode *pi)
10417 {
10418   operand *right, *result;
10419   sym_link *type, *etype;
10420   int p_type;
10421
10422   D (emitcode (";", "genPointerSet "););
10423
10424   right = IC_RIGHT (ic);
10425   result = IC_RESULT (ic);
10426
10427   /* depending on the type of pointer we need to
10428      move it to the correct pointer register */
10429   type = operandType (result);
10430   etype = getSpec (type);
10431   /* if left is of type of pointer then it is simple */
10432   if (IS_PTR (type) && !IS_FUNC (type->next))
10433     {
10434       p_type = DCL_TYPE (type);
10435     }
10436   else
10437     {
10438       /* we have to go by the storage class */
10439       p_type = PTR_TYPE (SPEC_OCLS (etype));
10440     }
10441   /* special case when cast remat */
10442   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10443       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10444           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10445           type = operandType (result);
10446           p_type = DCL_TYPE (type);
10447   }
10448
10449   /* now that we have the pointer type we assign
10450      the pointer values */
10451   switch (p_type)
10452     {
10453
10454     case POINTER:
10455     case IPOINTER:
10456       genNearPointerSet (right, result, ic, pi);
10457       break;
10458
10459     case PPOINTER:
10460       genPagedPointerSet (right, result, ic, pi);
10461       break;
10462
10463     case FPOINTER:
10464       genFarPointerSet (right, result, ic, pi);
10465       break;
10466
10467     case GPOINTER:
10468       genGenPointerSet (right, result, ic, pi);
10469       break;
10470
10471     default:
10472       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10473               "genPointerSet: illegal pointer type");
10474     }
10475
10476 }
10477
10478 /*-----------------------------------------------------------------*/
10479 /* genIfx - generate code for Ifx statement                        */
10480 /*-----------------------------------------------------------------*/
10481 static void
10482 genIfx (iCode * ic, iCode * popIc)
10483 {
10484   operand *cond = IC_COND (ic);
10485   int isbit = 0;
10486
10487   D (emitcode (";", "genIfx "););
10488
10489   aopOp (cond, ic, FALSE, FALSE);
10490
10491   /* get the value into acc */
10492   if (AOP_TYPE (cond) != AOP_CRY)
10493     {
10494         toBoolean (cond);
10495     }
10496   else
10497     {
10498         isbit = 1;
10499     }
10500     
10501   /* the result is now in the accumulator */
10502   freeAsmop (cond, NULL, ic, TRUE);
10503
10504   /* if there was something to be popped then do it */
10505   if (popIc)
10506     genIpop (popIc);
10507
10508   /* if the condition is  a bit variable */
10509   if (isbit && IS_ITEMP (cond) &&
10510       SPIL_LOC (cond))
10511     {
10512         genIfxJump (ic, SPIL_LOC (cond)->rname);
10513     }
10514   else if (isbit && !IS_ITEMP (cond))
10515     {
10516         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10517     }
10518   else
10519     {
10520         genIfxJump (ic, "a");
10521     }
10522
10523   ic->generated = 1;
10524 }
10525
10526 /*-----------------------------------------------------------------*/
10527 /* genAddrOf - generates code for address of                       */
10528 /*-----------------------------------------------------------------*/
10529 static void
10530 genAddrOf (iCode * ic)
10531 {
10532   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10533   int size, offset;
10534
10535   D (emitcode (";", "genAddrOf ");
10536     );
10537
10538   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10539
10540   /* if the operand is on the stack then we
10541      need to get the stack offset of this
10542      variable */
10543   if (sym->onStack) {
10544       
10545       /* if 10 bit stack */
10546       if (options.stack10bit) {
10547           char buff[10];
10548           int  offset;
10549           
10550           tsprintf(buff, sizeof(buff), 
10551                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10552           /* if it has an offset then we need to compute it */
10553 /*        emitcode ("subb", "a,#!constbyte", */
10554 /*                  -((sym->stack < 0) ? */
10555 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10556 /*                    ((short) sym->stack)) & 0xff); */
10557 /*        emitcode ("mov","b,a"); */
10558 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10559 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10560 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10561           if (sym->stack) {
10562               emitcode ("mov", "a,_bpx");
10563               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10564                                              ((char) (sym->stack - _G.nRegsSaved)) :
10565                                              ((char) sym->stack )) & 0xff);
10566               emitcode ("mov", "b,a");
10567               emitcode ("mov", "a,_bpx+1");
10568               
10569               offset = (((sym->stack < 0) ? 
10570                          ((short) (sym->stack - _G.nRegsSaved)) :
10571                          ((short) sym->stack )) >> 8) & 0xff;
10572           
10573               emitcode ("addc","a,#!constbyte", offset);
10574
10575               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10576               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10577               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10578           } else {
10579               /* we can just move _bp */
10580               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10581               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10582               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10583           }       
10584       } else {
10585           /* if it has an offset then we need to compute it */
10586           if (sym->stack) {
10587               emitcode ("mov", "a,_bp");
10588               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10589               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10590           } else {
10591               /* we can just move _bp */
10592               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10593           }
10594           /* fill the result with zero */
10595           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10596           
10597           
10598           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10599               fprintf (stderr,
10600                        "*** warning: pointer to stack var truncated.\n");
10601           }
10602
10603           offset = 1;
10604           while (size--) {
10605               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10606           }      
10607       }
10608       goto release;
10609   }
10610
10611   /* object not on stack then we need the name */
10612   size = AOP_SIZE (IC_RESULT (ic));
10613   offset = 0;
10614
10615   while (size--)
10616     {
10617       char s[SDCC_NAME_MAX];
10618       if (offset) {
10619           switch (offset) {
10620           case 1:
10621               tsprintf(s, sizeof(s), "#!his",sym->rname);
10622               break;
10623           case 2:
10624               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10625               break;
10626           case 3:
10627               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10628               break;
10629           default: /* should not need this (just in case) */
10630               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10631                        sym->rname,
10632                        offset * 8);
10633           }
10634       } 
10635       else
10636       {
10637           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10638       }
10639         
10640       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10641     }
10642
10643 release:
10644   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10645
10646 }
10647
10648 #if 0 // obsolete, and buggy for != xdata
10649 /*-----------------------------------------------------------------*/
10650 /* genArrayInit - generates code for address of                       */
10651 /*-----------------------------------------------------------------*/
10652 static void
10653 genArrayInit (iCode * ic)
10654 {
10655     literalList *iLoop;
10656     int         ix, count;
10657     int         elementSize = 0, eIndex;
10658     unsigned    val, lastVal;
10659     sym_link    *type;
10660     operand     *left=IC_LEFT(ic);
10661     
10662     D (emitcode (";", "genArrayInit "););
10663
10664     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10665     
10666     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10667     {
10668         // Load immediate value into DPTR.
10669         emitcode("mov", "dptr, %s",
10670              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10671     }
10672     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10673     {
10674 #if 0
10675       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10676               "Unexpected operand to genArrayInit.\n");
10677       exit(1);
10678 #else
10679       // a regression because of SDCCcse.c:1.52
10680       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10681       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10682       if (options.model == MODEL_FLAT24)
10683         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10684 #endif
10685     }
10686     
10687     type = operandType(IC_LEFT(ic));
10688     
10689     if (type && type->next)
10690     {
10691         elementSize = getSize(type->next);
10692     }
10693     else
10694     {
10695         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10696                                 "can't determine element size in genArrayInit.\n");
10697         exit(1);
10698     }
10699     
10700     iLoop = IC_ARRAYILIST(ic);
10701     lastVal = 0xffff;
10702     
10703     while (iLoop)
10704     {
10705         bool firstpass = TRUE;
10706         
10707         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10708                  iLoop->count, (int)iLoop->literalValue, elementSize);
10709         
10710         ix = iLoop->count;
10711         
10712         while (ix)
10713         {
10714             symbol *tlbl = NULL;
10715             
10716             count = ix > 256 ? 256 : ix;
10717             
10718             if (count > 1)
10719             {
10720                 tlbl = newiTempLabel (NULL);
10721                 if (firstpass || (count & 0xff))
10722                 {
10723                     emitcode("mov", "b, #!constbyte", count & 0xff);
10724                 }
10725                 
10726                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10727             }
10728             
10729             firstpass = FALSE;
10730                 
10731             for (eIndex = 0; eIndex < elementSize; eIndex++)
10732             {
10733                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10734                 if (val != lastVal)
10735                 {
10736                     emitcode("mov", "a, #!constbyte", val);
10737                     lastVal = val;
10738                 }
10739                 
10740                 emitcode("movx", "@dptr, a");
10741                 emitcode("inc", "dptr");
10742             }
10743             
10744             if (count > 1)
10745             {
10746                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10747             }
10748             
10749             ix -= count;
10750         }
10751         
10752         iLoop = iLoop->next;
10753     }
10754     
10755     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10756 }
10757 #endif
10758
10759 /*-----------------------------------------------------------------*/
10760 /* genFarFarAssign - assignment when both are in far space         */
10761 /*-----------------------------------------------------------------*/
10762 static void
10763 genFarFarAssign (operand * result, operand * right, iCode * ic)
10764 {
10765   int size = AOP_SIZE (right);
10766   int offset = 0;
10767   symbol *rSym = NULL;
10768
10769   if (size == 1)
10770   {
10771       /* quick & easy case. */
10772       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10773       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10774       freeAsmop (right, NULL, ic, FALSE);
10775       /* now assign DPTR to result */
10776       _G.accInUse++;
10777       aopOp(result, ic, FALSE, FALSE);
10778       _G.accInUse--;
10779       aopPut(AOP(result), "a", 0);
10780       freeAsmop(result, NULL, ic, FALSE);
10781       return;
10782   }
10783   
10784   /* See if we've got an underlying symbol to abuse. */
10785   if (IS_SYMOP(result) && OP_SYMBOL(result))
10786   {
10787       if (IS_TRUE_SYMOP(result))
10788       {
10789           rSym = OP_SYMBOL(result);
10790       }
10791       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10792       {
10793           rSym = OP_SYMBOL(result)->usl.spillLoc;
10794       }
10795   }
10796              
10797   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10798   {
10799       /* We can use the '390 auto-toggle feature to good effect here. */
10800       
10801       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10802       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10803       emitcode ("mov", "dptr,#%s", rSym->rname); 
10804       /* DP2 = result, DP1 = right, DP1 is current. */
10805       while (size)
10806       {
10807           emitcode("movx", "a,@dptr");
10808           emitcode("movx", "@dptr,a");
10809           if (--size)
10810           {
10811                emitcode("inc", "dptr");
10812                emitcode("inc", "dptr");
10813           }
10814       }
10815       emitcode("mov", "dps,#0");
10816       freeAsmop (right, NULL, ic, FALSE);
10817 #if 0
10818 some alternative code for processors without auto-toggle
10819 no time to test now, so later well put in...kpb
10820         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10821         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10822         emitcode ("mov", "dptr,#%s", rSym->rname); 
10823         /* DP2 = result, DP1 = right, DP1 is current. */
10824         while (size)
10825         {
10826           --size;
10827           emitcode("movx", "a,@dptr");
10828           if (size)
10829             emitcode("inc", "dptr");
10830           emitcode("inc", "dps");
10831           emitcode("movx", "@dptr,a");
10832           if (size)
10833             emitcode("inc", "dptr");
10834           emitcode("inc", "dps");
10835         }
10836         emitcode("mov", "dps,#0");
10837         freeAsmop (right, NULL, ic, FALSE);
10838 #endif
10839   }
10840   else
10841   {
10842       D (emitcode (";", "genFarFarAssign"););
10843       aopOp (result, ic, TRUE, TRUE);
10844
10845       _startLazyDPSEvaluation ();
10846       
10847       while (size--)
10848         {
10849           aopPut (AOP (result),
10850                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10851           offset++;
10852         }
10853       _endLazyDPSEvaluation ();
10854       freeAsmop (result, NULL, ic, FALSE);
10855       freeAsmop (right, NULL, ic, FALSE);
10856   }
10857 }
10858
10859 /*-----------------------------------------------------------------*/
10860 /* genAssign - generate code for assignment                        */
10861 /*-----------------------------------------------------------------*/
10862 static void
10863 genAssign (iCode * ic)
10864 {
10865   operand *result, *right;
10866   int size, offset;
10867   unsigned long lit = 0L;
10868
10869   D (emitcode (";", "genAssign ");
10870     );
10871
10872   result = IC_RESULT (ic);
10873   right = IC_RIGHT (ic);
10874
10875   /* if they are the same */
10876   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10877     return;
10878
10879   aopOp (right, ic, FALSE, FALSE);
10880
10881   emitcode (";", "genAssign: resultIsFar = %s",
10882             isOperandInFarSpace (result) ?
10883             "TRUE" : "FALSE");
10884
10885   /* special case both in far space */
10886   if ((AOP_TYPE (right) == AOP_DPTR ||
10887        AOP_TYPE (right) == AOP_DPTR2) &&
10888   /* IS_TRUE_SYMOP(result)       && */
10889       isOperandInFarSpace (result))
10890     {
10891       genFarFarAssign (result, right, ic);
10892       return;
10893     }
10894
10895   aopOp (result, ic, TRUE, FALSE);
10896
10897   /* if they are the same registers */
10898   if (sameRegs (AOP (right), AOP (result)))
10899     goto release;
10900
10901   /* if the result is a bit */
10902   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10903     {
10904       /* if the right size is a literal then
10905          we know what the value is */
10906       if (AOP_TYPE (right) == AOP_LIT)
10907         {
10908           if (((int) operandLitValue (right)))
10909             aopPut (AOP (result), one, 0);
10910           else
10911             aopPut (AOP (result), zero, 0);
10912           goto release;
10913         }
10914
10915       /* the right is also a bit variable */
10916       if (AOP_TYPE (right) == AOP_CRY)
10917         {
10918           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10919           aopPut (AOP (result), "c", 0);
10920           goto release;
10921         }
10922
10923       /* we need to or */
10924       toBoolean (right);
10925       aopPut (AOP (result), "a", 0);
10926       goto release;
10927     }
10928
10929   /* bit variables done */
10930   /* general case */
10931   size = AOP_SIZE (result);
10932   offset = 0;
10933   if (AOP_TYPE (right) == AOP_LIT)
10934     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10935
10936   if ((size > 1) &&
10937       (AOP_TYPE (result) != AOP_REG) &&
10938       (AOP_TYPE (right) == AOP_LIT) &&
10939       !IS_FLOAT (operandType (right)))
10940     {
10941       _startLazyDPSEvaluation ();
10942       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10943         {
10944           aopPut (AOP (result),
10945                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10946                   offset);
10947           offset++;
10948           size--;
10949         }
10950       /* And now fill the rest with zeros. */
10951       if (size)
10952         {
10953           emitcode ("clr", "a");
10954         }
10955       while (size--)
10956         {
10957           aopPut (AOP (result), "a", offset++);
10958         }
10959       _endLazyDPSEvaluation ();
10960     }
10961   else
10962     {
10963       _startLazyDPSEvaluation ();
10964       while (size--)
10965         {
10966           aopPut (AOP (result),
10967                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10968                   offset);
10969           offset++;
10970         }
10971       _endLazyDPSEvaluation ();
10972     }
10973
10974 release:
10975   freeAsmop (right, NULL, ic, FALSE);
10976   freeAsmop (result, NULL, ic, TRUE);
10977 }
10978
10979 /*-----------------------------------------------------------------*/
10980 /* genJumpTab - generates code for jump table                      */
10981 /*-----------------------------------------------------------------*/
10982 static void
10983 genJumpTab (iCode * ic)
10984 {
10985   symbol *jtab;
10986   char *l;
10987
10988   D (emitcode (";", "genJumpTab ");
10989     );
10990
10991   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10992   /* get the condition into accumulator */
10993   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10994   MOVA (l);
10995   /* multiply by four! */
10996   emitcode ("add", "a,acc");
10997   emitcode ("add", "a,acc");
10998   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10999
11000   jtab = newiTempLabel (NULL);
11001   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11002   emitcode ("jmp", "@a+dptr");
11003   emitcode ("", "!tlabeldef", jtab->key + 100);
11004   /* now generate the jump labels */
11005   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11006        jtab = setNextItem (IC_JTLABELS (ic)))
11007     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11008
11009 }
11010
11011 /*-----------------------------------------------------------------*/
11012 /* genCast - gen code for casting                                  */
11013 /*-----------------------------------------------------------------*/
11014 static void
11015 genCast (iCode * ic)
11016 {
11017   operand *result = IC_RESULT (ic);
11018   sym_link *ctype = operandType (IC_LEFT (ic));
11019   sym_link *rtype = operandType (IC_RIGHT (ic));
11020   operand *right = IC_RIGHT (ic);
11021   int size, offset;
11022
11023   D (emitcode (";", "genCast "););
11024
11025   /* if they are equivalent then do nothing */
11026   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11027     return;
11028
11029   aopOp (right, ic, FALSE, FALSE);
11030   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11031
11032   /* if the result is a bit */
11033   if (IS_BITVAR (OP_SYMBOL (result)->type)
11034       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11035     {
11036       /* if the right size is a literal then
11037          we know what the value is */
11038       if (AOP_TYPE (right) == AOP_LIT)
11039         {
11040           if (((int) operandLitValue (right)))
11041             aopPut (AOP (result), one, 0);
11042           else
11043             aopPut (AOP (result), zero, 0);
11044
11045           goto release;
11046         }
11047
11048       /* the right is also a bit variable */
11049       if (AOP_TYPE (right) == AOP_CRY)
11050         {
11051           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11052           aopPut (AOP (result), "c", 0);
11053           goto release;
11054         }
11055
11056       /* we need to or */
11057       toBoolean (right);
11058       aopPut (AOP (result), "a", 0);
11059       goto release;
11060     }
11061
11062   /* if they are the same size : or less */
11063   if (AOP_SIZE (result) <= AOP_SIZE (right))
11064     {
11065
11066       /* if they are in the same place */
11067       if (sameRegs (AOP (right), AOP (result)))
11068         goto release;
11069
11070       /* if they in different places then copy */
11071       size = AOP_SIZE (result);
11072       offset = 0;
11073       _startLazyDPSEvaluation ();
11074       while (size--)
11075         {
11076           aopPut (AOP (result),
11077                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11078                   offset);
11079           offset++;
11080         }
11081       _endLazyDPSEvaluation ();
11082       goto release;
11083     }
11084
11085
11086   /* if the result is of type pointer */
11087   if (IS_PTR (ctype))
11088     {
11089
11090       int p_type;
11091       sym_link *type = operandType (right);
11092
11093       /* pointer to generic pointer */
11094       if (IS_GENPTR (ctype))
11095         {
11096           if (IS_PTR (type))
11097             {
11098               p_type = DCL_TYPE (type);
11099             }
11100           else
11101             {
11102 #if OLD_CAST_BEHAVIOR
11103               /* KV: we are converting a non-pointer type to
11104                * a generic pointer. This (ifdef'd out) code
11105                * says that the resulting generic pointer
11106                * should have the same class as the storage
11107                * location of the non-pointer variable.
11108                *
11109                * For example, converting an int (which happens
11110                * to be stored in DATA space) to a pointer results
11111                * in a DATA generic pointer; if the original int
11112                * in XDATA space, so will be the resulting pointer.
11113                *
11114                * I don't like that behavior, and thus this change:
11115                * all such conversions will be forced to XDATA and
11116                * throw a warning. If you want some non-XDATA
11117                * type, or you want to suppress the warning, you
11118                * must go through an intermediate cast, like so:
11119                *
11120                * char _generic *gp = (char _xdata *)(intVar);
11121                */
11122               sym_link *etype = getSpec (type);
11123
11124               /* we have to go by the storage class */
11125               if (SPEC_OCLS (etype) != generic)
11126                 {
11127                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11128                 }
11129               else
11130 #endif
11131                 {
11132                   /* Converting unknown class (i.e. register variable)
11133                    * to generic pointer. This is not good, but
11134                    * we'll make a guess (and throw a warning).
11135                    */
11136                   p_type = FPOINTER;
11137                   werror (W_INT_TO_GEN_PTR_CAST);
11138                 }
11139             }
11140
11141           /* the first two bytes are known */
11142           size = GPTRSIZE - 1;
11143           offset = 0;
11144           _startLazyDPSEvaluation ();
11145           while (size--)
11146             {
11147               aopPut (AOP (result),
11148                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11149                       offset);
11150               offset++;
11151             }
11152           _endLazyDPSEvaluation ();
11153
11154           /* the last byte depending on type */
11155             {
11156                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11157                 char gpValStr[10];
11158             
11159                 if (gpVal == -1)
11160                 {
11161                     // pointerTypeToGPByte will have bitched.
11162                     exit(1);
11163                 }
11164             
11165                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11166                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11167             }
11168           goto release;
11169         }
11170
11171       /* just copy the pointers */
11172       size = AOP_SIZE (result);
11173       offset = 0;
11174       _startLazyDPSEvaluation ();
11175       while (size--)
11176         {
11177           aopPut (AOP (result),
11178                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11179                   offset);
11180           offset++;
11181         }
11182       _endLazyDPSEvaluation ();
11183       goto release;
11184     }
11185
11186   /* so we now know that the size of destination is greater
11187      than the size of the source */
11188   /* we move to result for the size of source */
11189   size = AOP_SIZE (right);
11190   offset = 0;
11191   _startLazyDPSEvaluation ();
11192   while (size--)
11193     {
11194       aopPut (AOP (result),
11195               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11196               offset);
11197       offset++;
11198     }
11199   _endLazyDPSEvaluation ();
11200
11201   /* now depending on the sign of the source && destination */
11202   size = AOP_SIZE (result) - AOP_SIZE (right);
11203   /* if unsigned or not an integral type */
11204   /* also, if the source is a bit, we don't need to sign extend, because
11205    * it can't possibly have set the sign bit.
11206    */
11207   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11208     {
11209       while (size--)
11210         {
11211           aopPut (AOP (result), zero, offset++);
11212         }
11213     }
11214   else
11215     {
11216       /* we need to extend the sign :{ */
11217       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11218                         FALSE, FALSE, NULL));
11219       emitcode ("rlc", "a");
11220       emitcode ("subb", "a,acc");
11221       while (size--)
11222         aopPut (AOP (result), "a", offset++);
11223     }
11224
11225   /* we are done hurray !!!! */
11226
11227 release:
11228   freeAsmop (right, NULL, ic, TRUE);
11229   freeAsmop (result, NULL, ic, TRUE);
11230
11231 }
11232
11233 /*-----------------------------------------------------------------*/
11234 /* genDjnz - generate decrement & jump if not zero instrucion      */
11235 /*-----------------------------------------------------------------*/
11236 static int
11237 genDjnz (iCode * ic, iCode * ifx)
11238 {
11239   symbol *lbl, *lbl1;
11240   if (!ifx)
11241     return 0;
11242
11243   /* if the if condition has a false label
11244      then we cannot save */
11245   if (IC_FALSE (ifx))
11246     return 0;
11247
11248   /* if the minus is not of the form
11249      a = a - 1 */
11250   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11251       !IS_OP_LITERAL (IC_RIGHT (ic)))
11252     return 0;
11253
11254   if (operandLitValue (IC_RIGHT (ic)) != 1)
11255     return 0;
11256
11257   /* if the size of this greater than one then no
11258      saving */
11259   if (getSize (operandType (IC_RESULT (ic))) > 1)
11260     return 0;
11261
11262   /* otherwise we can save BIG */
11263   D(emitcode(";", "genDjnz"););
11264
11265   lbl = newiTempLabel (NULL);
11266   lbl1 = newiTempLabel (NULL);
11267
11268   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11269
11270   if (AOP_NEEDSACC(IC_RESULT(ic)))
11271   {
11272       /* If the result is accessed indirectly via
11273        * the accumulator, we must explicitly write
11274        * it back after the decrement.
11275        */
11276       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11277       
11278       if (strcmp(rByte, "a"))
11279       {
11280            /* Something is hopelessly wrong */
11281            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11282                    __FILE__, __LINE__);
11283            /* We can just give up; the generated code will be inefficient,
11284             * but what the hey.
11285             */
11286            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11287            return 0;
11288       }
11289       emitcode ("dec", "%s", rByte);
11290       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11291       emitcode ("jnz", "!tlabel", lbl->key + 100);
11292   }
11293   else if (IS_AOP_PREG (IC_RESULT (ic)))
11294     {
11295       emitcode ("dec", "%s",
11296                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11297       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11298       emitcode ("jnz", "!tlabel", lbl->key + 100);
11299     }
11300   else
11301     {
11302       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11303                 lbl->key + 100);
11304     }
11305   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11306   emitcode ("", "!tlabeldef", lbl->key + 100);
11307   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11308   emitcode ("", "!tlabeldef", lbl1->key + 100);
11309
11310   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11311   ifx->generated = 1;
11312   return 1;
11313 }
11314
11315 /*-----------------------------------------------------------------*/
11316 /* genReceive - generate code for a receive iCode                  */
11317 /*-----------------------------------------------------------------*/
11318 static void
11319 genReceive (iCode * ic)
11320 {
11321     int size = getSize (operandType (IC_RESULT (ic)));
11322     int offset = 0;
11323     int rb1off ;
11324     
11325     D (emitcode (";", "genReceive "););
11326
11327     if (ic->argreg == 1) 
11328     {
11329         /* first parameter */
11330         if (AOP_IS_STR(IC_RESULT(ic)))
11331         {
11332             /* Nothing to do: it's already in the proper place. */
11333             return;
11334         }
11335         else
11336         {
11337             bool useDp2;
11338             
11339             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11340                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11341                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11342             
11343             _G.accInUse++;
11344             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11345             _G.accInUse--; 
11346             
11347             /* Sanity checking... */
11348             if (AOP_USESDPTR(IC_RESULT(ic)))
11349             {
11350                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11351                         "genReceive got unexpected DPTR.");
11352             }
11353             assignResultValue (IC_RESULT (ic));
11354         }
11355     } 
11356     else 
11357     { 
11358         /* second receive onwards */
11359         /* this gets a little tricky since unused recevies will be
11360          eliminated, we have saved the reg in the type field . and
11361          we use that to figure out which register to use */
11362         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11363         rb1off = ic->argreg;
11364         while (size--) 
11365         {
11366             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11367         }
11368     }
11369     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11370 }
11371
11372 /*-----------------------------------------------------------------*/
11373 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11374 /*-----------------------------------------------------------------*/
11375 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11376 {
11377     operand *from , *to , *count;
11378     symbol *lbl;
11379     bitVect *rsave;
11380     int i;
11381
11382     /* we know it has to be 3 parameters */
11383     assert (nparms == 3);
11384     
11385     rsave = newBitVect(16);
11386     /* save DPTR if it needs to be saved */
11387     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11388             if (bitVectBitValue(ic->rMask,i))
11389                     rsave = bitVectSetBit(rsave,i);
11390     }
11391     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11392                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11393     savermask(rsave);
11394     
11395     to = parms[0];
11396     from = parms[1];
11397     count = parms[2];
11398
11399     aopOp (from, ic->next, FALSE, FALSE);
11400
11401     /* get from into DPTR1 */
11402     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11403     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11404     if (options.model == MODEL_FLAT24) {
11405         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11406     }
11407
11408     freeAsmop (from, NULL, ic, FALSE);
11409     aopOp (to, ic, FALSE, FALSE);
11410     /* get "to" into DPTR */
11411     /* if the operand is already in dptr
11412        then we do nothing else we move the value to dptr */
11413     if (AOP_TYPE (to) != AOP_STR) {
11414         /* if already in DPTR then we need to push */
11415         if (AOP_TYPE(to) == AOP_DPTR) {
11416             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11417             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11418             if (options.model == MODEL_FLAT24)
11419                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11420             emitcode ("pop", "dph");
11421             emitcode ("pop", "dpl");        
11422         } else {
11423             _startLazyDPSEvaluation ();
11424             /* if this is remateriazable */
11425             if (AOP_TYPE (to) == AOP_IMMD) {
11426                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11427             } else {                    /* we need to get it byte by byte */
11428                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11429                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11430                 if (options.model == MODEL_FLAT24) {
11431                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11432                 }
11433             }
11434             _endLazyDPSEvaluation ();
11435         }
11436     }
11437     freeAsmop (to, NULL, ic, FALSE);
11438     _G.dptrInUse = _G.dptr1InUse = 1;
11439     aopOp (count, ic->next->next, FALSE,FALSE);
11440     lbl =newiTempLabel(NULL);
11441
11442     /* now for the actual copy */
11443     if (AOP_TYPE(count) == AOP_LIT && 
11444         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11445         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11446         if (fromc) {
11447             emitcode ("lcall","__bi_memcpyc2x_s");
11448         } else {
11449             emitcode ("lcall","__bi_memcpyx2x_s");
11450         }
11451         freeAsmop (count, NULL, ic, FALSE);
11452     } else {
11453         symbol *lbl1 = newiTempLabel(NULL);
11454         
11455         emitcode (";"," Auto increment but no djnz");
11456         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11457         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11458         freeAsmop (count, NULL, ic, FALSE);
11459         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11460         emitcode ("","!tlabeldef",lbl->key+100);
11461         if (fromc) {
11462             emitcode ("clr","a");
11463             emitcode ("movc", "a,@a+dptr");
11464         } else 
11465             emitcode ("movx", "a,@dptr");
11466         emitcode ("movx", "@dptr,a");
11467         emitcode ("inc", "dptr");
11468         emitcode ("inc", "dptr");
11469         emitcode ("mov","a,b");
11470         emitcode ("orl","a,_ap");
11471         emitcode ("jz","!tlabel",lbl1->key+100);
11472         emitcode ("mov","a,_ap");
11473         emitcode ("add","a,#!constbyte",0xFF);
11474         emitcode ("mov","_ap,a");
11475         emitcode ("mov","a,b");
11476         emitcode ("addc","a,#!constbyte",0xFF);
11477         emitcode ("mov","b,a");
11478         emitcode ("sjmp","!tlabel",lbl->key+100);
11479         emitcode ("","!tlabeldef",lbl1->key+100);
11480     }
11481     emitcode ("mov", "dps,#0"); 
11482     _G.dptrInUse = _G.dptr1InUse = 0;
11483     unsavermask(rsave);
11484
11485 }
11486
11487 /*-----------------------------------------------------------------*/
11488 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11489 /*-----------------------------------------------------------------*/
11490 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11491 {
11492     operand *from , *to , *count;
11493     symbol *lbl,*lbl2;
11494     bitVect *rsave;
11495     int i;
11496
11497     /* we know it has to be 3 parameters */
11498     assert (nparms == 3);
11499     
11500     rsave = newBitVect(16);
11501     /* save DPTR if it needs to be saved */
11502     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11503             if (bitVectBitValue(ic->rMask,i))
11504                     rsave = bitVectSetBit(rsave,i);
11505     }
11506     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11507                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11508     savermask(rsave);
11509     
11510     to = parms[0];
11511     from = parms[1];
11512     count = parms[2];
11513
11514     aopOp (from, ic->next, FALSE, FALSE);
11515
11516     /* get from into DPTR1 */
11517     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11518     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11519     if (options.model == MODEL_FLAT24) {
11520         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11521     }
11522
11523     freeAsmop (from, NULL, ic, FALSE);
11524     aopOp (to, ic, FALSE, FALSE);
11525     /* get "to" into DPTR */
11526     /* if the operand is already in dptr
11527        then we do nothing else we move the value to dptr */
11528     if (AOP_TYPE (to) != AOP_STR) {
11529         /* if already in DPTR then we need to push */
11530         if (AOP_TYPE(to) == AOP_DPTR) {
11531             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11532             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11533             if (options.model == MODEL_FLAT24)
11534                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11535             emitcode ("pop", "dph");
11536             emitcode ("pop", "dpl");        
11537         } else {
11538             _startLazyDPSEvaluation ();
11539             /* if this is remateriazable */
11540             if (AOP_TYPE (to) == AOP_IMMD) {
11541                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11542             } else {                    /* we need to get it byte by byte */
11543                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11544                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11545                 if (options.model == MODEL_FLAT24) {
11546                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11547                 }
11548             }
11549             _endLazyDPSEvaluation ();
11550         }
11551     }
11552     freeAsmop (to, NULL, ic, FALSE);
11553     _G.dptrInUse = _G.dptr1InUse = 1;
11554     aopOp (count, ic->next->next, FALSE,FALSE);
11555     lbl =newiTempLabel(NULL);
11556     lbl2 =newiTempLabel(NULL);
11557
11558     /* now for the actual compare */
11559     if (AOP_TYPE(count) == AOP_LIT && 
11560         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11561         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11562         if (fromc)
11563             emitcode("lcall","__bi_memcmpc2x_s");
11564         else
11565             emitcode("lcall","__bi_memcmpx2x_s");
11566         freeAsmop (count, NULL, ic, FALSE);
11567         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11568         aopPut(AOP(IC_RESULT(ic)),"a",0);
11569         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11570     } else {
11571         symbol *lbl1 = newiTempLabel(NULL);
11572
11573         emitcode("push","ar0");         
11574         emitcode (";"," Auto increment but no djnz");
11575         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11576         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11577         freeAsmop (count, NULL, ic, FALSE);
11578         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11579         emitcode ("","!tlabeldef",lbl->key+100);
11580         if (fromc) {
11581             emitcode ("clr","a");
11582             emitcode ("movc", "a,@a+dptr");
11583         } else 
11584             emitcode ("movx", "a,@dptr");
11585         emitcode ("mov","r0,a");
11586         emitcode ("movx", "a,@dptr");
11587         emitcode ("clr","c");
11588         emitcode ("subb","a,r0");
11589         emitcode ("jnz","!tlabel",lbl2->key+100);
11590         emitcode ("inc", "dptr");
11591         emitcode ("inc", "dptr");
11592         emitcode ("mov","a,b");
11593         emitcode ("orl","a,_ap");
11594         emitcode ("jz","!tlabel",lbl1->key+100);
11595         emitcode ("mov","a,_ap");
11596         emitcode ("add","a,#!constbyte",0xFF);
11597         emitcode ("mov","_ap,a");
11598         emitcode ("mov","a,b");
11599         emitcode ("addc","a,#!constbyte",0xFF);
11600         emitcode ("mov","b,a");
11601         emitcode ("sjmp","!tlabel",lbl->key+100);
11602         emitcode ("","!tlabeldef",lbl1->key+100);
11603         emitcode ("clr","a");
11604         emitcode ("","!tlabeldef",lbl2->key+100);
11605         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11606         aopPut(AOP(IC_RESULT(ic)),"a",0);
11607         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11608         emitcode("pop","ar0");
11609         emitcode ("mov", "dps,#0");      
11610     }
11611     _G.dptrInUse = _G.dptr1InUse = 0;
11612     unsavermask(rsave);
11613
11614 }
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11618 /* port, first parameter output area second parameter pointer to   */
11619 /* port third parameter count                                      */
11620 /*-----------------------------------------------------------------*/
11621 static void genInp( iCode *ic, int nparms, operand **parms)
11622 {
11623     operand *from , *to , *count;
11624     symbol *lbl;
11625     bitVect *rsave;
11626     int i;
11627
11628     /* we know it has to be 3 parameters */
11629     assert (nparms == 3);
11630     
11631     rsave = newBitVect(16);
11632     /* save DPTR if it needs to be saved */
11633     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11634             if (bitVectBitValue(ic->rMask,i))
11635                     rsave = bitVectSetBit(rsave,i);
11636     }
11637     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11638                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11639     savermask(rsave);
11640     
11641     to = parms[0];
11642     from = parms[1];
11643     count = parms[2];
11644
11645     aopOp (from, ic->next, FALSE, FALSE);
11646
11647     /* get from into DPTR1 */
11648     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11649     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11650     if (options.model == MODEL_FLAT24) {
11651         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11652     }
11653
11654     freeAsmop (from, NULL, ic, FALSE);
11655     aopOp (to, ic, FALSE, FALSE);
11656     /* get "to" into DPTR */
11657     /* if the operand is already in dptr
11658        then we do nothing else we move the value to dptr */
11659     if (AOP_TYPE (to) != AOP_STR) {
11660         /* if already in DPTR then we need to push */
11661         if (AOP_TYPE(to) == AOP_DPTR) {
11662             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11663             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11664             if (options.model == MODEL_FLAT24)
11665                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11666             emitcode ("pop", "dph");
11667             emitcode ("pop", "dpl");        
11668         } else {
11669             _startLazyDPSEvaluation ();
11670             /* if this is remateriazable */
11671             if (AOP_TYPE (to) == AOP_IMMD) {
11672                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11673             } else {                    /* we need to get it byte by byte */
11674                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11675                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11676                 if (options.model == MODEL_FLAT24) {
11677                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11678                 }
11679             }
11680             _endLazyDPSEvaluation ();
11681         }
11682     }
11683     freeAsmop (to, NULL, ic, FALSE);
11684
11685     _G.dptrInUse = _G.dptr1InUse = 1;
11686     aopOp (count, ic->next->next, FALSE,FALSE);
11687     lbl =newiTempLabel(NULL);
11688
11689     /* now for the actual copy */
11690     if (AOP_TYPE(count) == AOP_LIT && 
11691         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11692         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11693         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11694         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11695         freeAsmop (count, NULL, ic, FALSE);
11696         emitcode ("","!tlabeldef",lbl->key+100);
11697         emitcode ("movx", "a,@dptr");   /* read data from port */
11698         emitcode ("dec","dps");         /* switch to DPTR */
11699         emitcode ("movx", "@dptr,a");   /* save into location */
11700         emitcode ("inc", "dptr");       /* point to next area */
11701         emitcode ("inc","dps");         /* switch to DPTR2 */
11702         emitcode ("djnz","b,!tlabel",lbl->key+100);
11703     } else {
11704         symbol *lbl1 = newiTempLabel(NULL);
11705         
11706         emitcode (";"," Auto increment but no djnz");
11707         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11708         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11709         freeAsmop (count, NULL, ic, FALSE);
11710         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11711         emitcode ("","!tlabeldef",lbl->key+100);
11712         emitcode ("movx", "a,@dptr");
11713         emitcode ("dec","dps");         /* switch to DPTR */
11714         emitcode ("movx", "@dptr,a");
11715         emitcode ("inc", "dptr");
11716         emitcode ("inc","dps");         /* switch to DPTR2 */
11717 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11718 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11719         emitcode ("mov","a,b");
11720         emitcode ("orl","a,_ap");
11721         emitcode ("jz","!tlabel",lbl1->key+100);
11722         emitcode ("mov","a,_ap");
11723         emitcode ("add","a,#!constbyte",0xFF);
11724         emitcode ("mov","_ap,a");
11725         emitcode ("mov","a,b");
11726         emitcode ("addc","a,#!constbyte",0xFF);
11727         emitcode ("mov","b,a");
11728         emitcode ("sjmp","!tlabel",lbl->key+100);
11729         emitcode ("","!tlabeldef",lbl1->key+100);
11730     }
11731     emitcode ("mov", "dps,#0"); 
11732     _G.dptrInUse = _G.dptr1InUse = 0;
11733     unsavermask(rsave);
11734
11735 }
11736
11737 /*-----------------------------------------------------------------*/
11738 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11739 /* port, first parameter output area second parameter pointer to   */
11740 /* port third parameter count                                      */
11741 /*-----------------------------------------------------------------*/
11742 static void genOutp( iCode *ic, int nparms, operand **parms)
11743 {
11744     operand *from , *to , *count;
11745     symbol *lbl;
11746     bitVect *rsave;
11747     int i;
11748
11749     /* we know it has to be 3 parameters */
11750     assert (nparms == 3);
11751     
11752     rsave = newBitVect(16);
11753     /* save DPTR if it needs to be saved */
11754     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11755             if (bitVectBitValue(ic->rMask,i))
11756                     rsave = bitVectSetBit(rsave,i);
11757     }
11758     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11759                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11760     savermask(rsave);
11761     
11762     to = parms[0];
11763     from = parms[1];
11764     count = parms[2];
11765
11766     aopOp (from, ic->next, FALSE, FALSE);
11767
11768     /* get from into DPTR1 */
11769     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11770     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11771     if (options.model == MODEL_FLAT24) {
11772         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11773     }
11774
11775     freeAsmop (from, NULL, ic, FALSE);
11776     aopOp (to, ic, FALSE, FALSE);
11777     /* get "to" into DPTR */
11778     /* if the operand is already in dptr
11779        then we do nothing else we move the value to dptr */
11780     if (AOP_TYPE (to) != AOP_STR) {
11781         /* if already in DPTR then we need to push */
11782         if (AOP_TYPE(to) == AOP_DPTR) {
11783             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11784             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11785             if (options.model == MODEL_FLAT24)
11786                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11787             emitcode ("pop", "dph");
11788             emitcode ("pop", "dpl");        
11789         } else {
11790             _startLazyDPSEvaluation ();
11791             /* if this is remateriazable */
11792             if (AOP_TYPE (to) == AOP_IMMD) {
11793                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11794             } else {                    /* we need to get it byte by byte */
11795                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11796                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11797                 if (options.model == MODEL_FLAT24) {
11798                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11799                 }
11800             }
11801             _endLazyDPSEvaluation ();
11802         }
11803     }
11804     freeAsmop (to, NULL, ic, FALSE);
11805
11806     _G.dptrInUse = _G.dptr1InUse = 1;
11807     aopOp (count, ic->next->next, FALSE,FALSE);
11808     lbl =newiTempLabel(NULL);
11809
11810     /* now for the actual copy */
11811     if (AOP_TYPE(count) == AOP_LIT && 
11812         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11813         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11814         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11815         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11816         emitcode ("","!tlabeldef",lbl->key+100);
11817         emitcode ("movx", "a,@dptr");   /* read data from port */
11818         emitcode ("inc","dps");         /* switch to DPTR2 */
11819         emitcode ("movx", "@dptr,a");   /* save into location */
11820         emitcode ("inc", "dptr");       /* point to next area */
11821         emitcode ("dec","dps");         /* switch to DPTR */
11822         emitcode ("djnz","b,!tlabel",lbl->key+100);
11823         freeAsmop (count, NULL, ic, FALSE);
11824     } else {
11825         symbol *lbl1 = newiTempLabel(NULL);
11826         
11827         emitcode (";"," Auto increment but no djnz");
11828         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11829         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11830         freeAsmop (count, NULL, ic, FALSE);
11831         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11832         emitcode ("","!tlabeldef",lbl->key+100);
11833         emitcode ("movx", "a,@dptr");
11834         emitcode ("inc", "dptr");
11835         emitcode ("inc","dps");         /* switch to DPTR2 */
11836         emitcode ("movx", "@dptr,a");
11837         emitcode ("dec","dps");         /* switch to DPTR */
11838         emitcode ("mov","a,b");
11839         emitcode ("orl","a,_ap");
11840         emitcode ("jz","!tlabel",lbl1->key+100);
11841         emitcode ("mov","a,_ap");
11842         emitcode ("add","a,#!constbyte",0xFF);
11843         emitcode ("mov","_ap,a");
11844         emitcode ("mov","a,b");
11845         emitcode ("addc","a,#!constbyte",0xFF);
11846         emitcode ("mov","b,a");
11847         emitcode ("sjmp","!tlabel",lbl->key+100);
11848         emitcode ("","!tlabeldef",lbl1->key+100);
11849     }
11850     emitcode ("mov", "dps,#0"); 
11851     _G.dptrInUse = _G.dptr1InUse = 0;
11852     unsavermask(rsave);
11853
11854 }
11855
11856 /*-----------------------------------------------------------------*/
11857 /* genSwapW - swap lower & high order bytes                        */
11858 /*-----------------------------------------------------------------*/
11859 static void genSwapW(iCode *ic, int nparms, operand **parms)
11860 {
11861     operand *dest;
11862     operand *src;
11863     assert (nparms==1);
11864
11865     src = parms[0];
11866     dest=IC_RESULT(ic);
11867
11868     assert(getSize(operandType(src))==2);
11869
11870     aopOp (src, ic, FALSE, FALSE);
11871     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11872     _G.accInUse++;
11873     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11874     _G.accInUse--;
11875     freeAsmop (src, NULL, ic, FALSE);
11876     
11877     aopOp (dest,ic, FALSE, FALSE);
11878     aopPut(AOP(dest),"b",0);
11879     aopPut(AOP(dest),"a",1);
11880     freeAsmop (dest, NULL, ic, FALSE);    
11881 }
11882
11883 /*-----------------------------------------------------------------*/
11884 /* genMemsetX - gencode for memSetX data                           */
11885 /*-----------------------------------------------------------------*/
11886 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11887 {
11888     operand *to , *val , *count;
11889     symbol *lbl;
11890     char *l;
11891     int i;
11892     bitVect *rsave;
11893
11894     /* we know it has to be 3 parameters */
11895     assert (nparms == 3);
11896     
11897     to = parms[0];
11898     val = parms[1];
11899     count = parms[2];
11900         
11901     /* save DPTR if it needs to be saved */
11902     rsave = newBitVect(16);
11903     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11904             if (bitVectBitValue(ic->rMask,i))
11905                     rsave = bitVectSetBit(rsave,i);
11906     }
11907     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11908                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11909     savermask(rsave);
11910
11911     aopOp (to, ic, FALSE, FALSE);
11912     /* get "to" into DPTR */
11913     /* if the operand is already in dptr
11914        then we do nothing else we move the value to dptr */
11915     if (AOP_TYPE (to) != AOP_STR) {
11916         /* if already in DPTR then we need to push */
11917         if (AOP_TYPE(to) == AOP_DPTR) {
11918             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11919             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11920             if (options.model == MODEL_FLAT24)
11921                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11922             emitcode ("pop", "dph");
11923             emitcode ("pop", "dpl");        
11924         } else {
11925             _startLazyDPSEvaluation ();
11926             /* if this is remateriazable */
11927             if (AOP_TYPE (to) == AOP_IMMD) {
11928                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11929             } else {                    /* we need to get it byte by byte */
11930                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11931                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11932                 if (options.model == MODEL_FLAT24) {
11933                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11934                 }
11935             }
11936             _endLazyDPSEvaluation ();
11937         }
11938     }
11939     freeAsmop (to, NULL, ic, FALSE);
11940
11941     aopOp (val, ic->next->next, FALSE,FALSE);
11942     aopOp (count, ic->next->next, FALSE,FALSE);    
11943     lbl =newiTempLabel(NULL);
11944     /* now for the actual copy */
11945     if (AOP_TYPE(count) == AOP_LIT && 
11946         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11947         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11948         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11949         MOVA(l);
11950         emitcode ("","!tlabeldef",lbl->key+100);
11951         emitcode ("movx", "@dptr,a");
11952         emitcode ("inc", "dptr");
11953         emitcode ("djnz","b,!tlabel",lbl->key+100);
11954     } else {
11955         symbol *lbl1 = newiTempLabel(NULL);
11956         
11957         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11958         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11959         emitcode ("","!tlabeldef",lbl->key+100);
11960         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11961         emitcode ("movx", "@dptr,a");
11962         emitcode ("inc", "dptr");
11963         emitcode ("mov","a,b");
11964         emitcode ("orl","a,_ap");
11965         emitcode ("jz","!tlabel",lbl1->key+100);
11966         emitcode ("mov","a,_ap");
11967         emitcode ("add","a,#!constbyte",0xFF);
11968         emitcode ("mov","_ap,a");
11969         emitcode ("mov","a,b");
11970         emitcode ("addc","a,#!constbyte",0xFF);
11971         emitcode ("mov","b,a");
11972         emitcode ("sjmp","!tlabel",lbl->key+100);
11973         emitcode ("","!tlabeldef",lbl1->key+100);
11974     }
11975     freeAsmop (count, NULL, ic, FALSE);
11976     unsavermask(rsave);
11977 }
11978
11979 /*-----------------------------------------------------------------*/
11980 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11981 /*-----------------------------------------------------------------*/
11982 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11983 {
11984         bitVect *rsave ;
11985         operand *pnum, *result;
11986         int i;
11987     
11988         assert (nparms==1);
11989         /* save registers that need to be saved */
11990         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11991                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11992     
11993         pnum = parms[0]; 
11994         aopOp (pnum, ic, FALSE, FALSE);
11995         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11996         freeAsmop (pnum, NULL, ic, FALSE);
11997         emitcode ("lcall","NatLib_LoadPrimitive");
11998         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11999         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12000             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12001                 for (i = (size-1) ; i >= 0 ; i-- ) {
12002                         emitcode ("push","a%s",javaRet[i]);
12003                 }
12004                 for (i=0; i < size ; i++ ) {
12005                         emitcode ("pop","a%s",
12006                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12007                 }
12008         } else {
12009                 for (i = 0 ; i < size ; i++ ) {
12010                         aopPut(AOP(result),javaRet[i],i);
12011                 }
12012         }    
12013         freeAsmop (result, NULL, ic, FALSE);
12014         unsavermask(rsave);
12015 }
12016
12017 /*-----------------------------------------------------------------*/
12018 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12019 /*-----------------------------------------------------------------*/
12020 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12021 {
12022         bitVect *rsave ;
12023         operand *pnum, *result;
12024         int size = 3;
12025         int i;
12026     
12027         assert (nparms==1);
12028         /* save registers that need to be saved */
12029         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12030                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12031     
12032         pnum = parms[0]; 
12033         aopOp (pnum, ic, FALSE, FALSE);
12034         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12035         freeAsmop (pnum, NULL, ic, FALSE);
12036         emitcode ("lcall","NatLib_LoadPointer");
12037         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12038         if (AOP_TYPE(result)!=AOP_STR) {
12039                 for (i = 0 ; i < size ; i++ ) {
12040                         aopPut(AOP(result),fReturn[i],i);
12041                 }
12042         }    
12043         freeAsmop (result, NULL, ic, FALSE);
12044         unsavermask(rsave);
12045 }
12046
12047 /*-----------------------------------------------------------------*/
12048 /* genNatLibInstallStateBlock -                                    */
12049 /*-----------------------------------------------------------------*/
12050 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12051                                        operand **parms, const char *name)
12052 {
12053         bitVect *rsave ;
12054         operand *psb, *handle;
12055         assert (nparms==2);
12056
12057         /* save registers that need to be saved */
12058         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12059                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12060         psb = parms[0];
12061         handle = parms[1];
12062
12063         /* put pointer to state block into DPTR1 */
12064         aopOp (psb, ic, FALSE, FALSE);
12065         if (AOP_TYPE (psb) == AOP_IMMD) {
12066                 emitcode ("mov","dps,#1");
12067                 emitcode ("mov", "dptr,%s",
12068                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12069                 emitcode ("mov","dps,#0");
12070         } else {
12071                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12072                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12073                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12074         }
12075         freeAsmop (psb, NULL, ic, FALSE);
12076
12077         /* put libraryID into DPTR */
12078         emitcode ("mov","dptr,#LibraryID");
12079
12080         /* put handle into r3:r2 */
12081         aopOp (handle, ic, FALSE, FALSE);
12082         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12083                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12084                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12085                 emitcode ("pop","ar3");
12086                 emitcode ("pop","ar2");
12087         } else {        
12088                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12089                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12090         }
12091         freeAsmop (psb, NULL, ic, FALSE);
12092
12093         /* make the call */
12094         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12095
12096         /* put return value into place*/
12097         _G.accInUse++;
12098         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12099         _G.accInUse--;
12100         aopPut(AOP(IC_RESULT(ic)),"a",0);
12101         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12102         unsavermask(rsave);
12103 }
12104
12105 /*-----------------------------------------------------------------*/
12106 /* genNatLibRemoveStateBlock -                                     */
12107 /*-----------------------------------------------------------------*/
12108 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12109 {
12110         bitVect *rsave ;
12111
12112         assert(nparms==0);
12113
12114         /* save registers that need to be saved */
12115         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12116                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12117
12118         /* put libraryID into DPTR */
12119         emitcode ("mov","dptr,#LibraryID");
12120         /* make the call */
12121         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12122         unsavermask(rsave);
12123 }
12124
12125 /*-----------------------------------------------------------------*/
12126 /* genNatLibGetStateBlock -                                        */
12127 /*-----------------------------------------------------------------*/
12128 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12129                                    operand **parms,const char *name)
12130 {
12131         bitVect *rsave ;
12132         symbol *lbl = newiTempLabel(NULL);
12133         
12134         assert(nparms==0);
12135         /* save registers that need to be saved */
12136         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12137                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12138
12139         /* put libraryID into DPTR */
12140         emitcode ("mov","dptr,#LibraryID");
12141         /* make the call */
12142         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12143         emitcode ("jnz","!tlabel",lbl->key+100);
12144
12145         /* put return value into place */
12146         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12147         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12148                 emitcode ("push","ar3");
12149                 emitcode ("push","ar2");
12150                 emitcode ("pop","%s",
12151                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12152                 emitcode ("pop","%s",
12153                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12154         } else {
12155                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12156                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12157         }
12158         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12159         emitcode ("","!tlabeldef",lbl->key+100);
12160         unsavermask(rsave);
12161 }
12162
12163 /*-----------------------------------------------------------------*/
12164 /* genMMMalloc -                                                   */
12165 /*-----------------------------------------------------------------*/
12166 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12167                          int size, const char *name)
12168 {
12169         bitVect *rsave ;
12170         operand *bsize;
12171         symbol *rsym;
12172         symbol *lbl = newiTempLabel(NULL);
12173
12174         assert (nparms == 1);
12175         /* save registers that need to be saved */
12176         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12177                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12178         
12179         bsize=parms[0];
12180         aopOp (bsize,ic,FALSE,FALSE);
12181
12182         /* put the size in R4-R2 */
12183         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12184                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12185                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12186                 if (size==3) {
12187                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12188                         emitcode("pop","ar4");
12189                 }
12190                 emitcode("pop","ar3");
12191                 emitcode("pop","ar2");          
12192         } else {
12193                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12194                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12195                 if (size==3) {
12196                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12197                 }
12198         }
12199         freeAsmop (bsize, NULL, ic, FALSE);
12200
12201         /* make the call */
12202         emitcode ("lcall","MM_%s",name);
12203         emitcode ("jz","!tlabel",lbl->key+100);
12204         emitcode ("mov","r2,#!constbyte",0xff);
12205         emitcode ("mov","r3,#!constbyte",0xff);
12206         emitcode ("","!tlabeldef",lbl->key+100);
12207         /* we don't care about the pointer : we just save the handle */
12208         rsym = OP_SYMBOL(IC_RESULT(ic));
12209         if (rsym->liveFrom != rsym->liveTo) {
12210                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12211                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12212                         emitcode ("push","ar3");
12213                         emitcode ("push","ar2");
12214                         emitcode ("pop","%s",
12215                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12216                         emitcode ("pop","%s",
12217                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12218                 } else {
12219                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12220                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12221                 }
12222                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12223         }
12224         unsavermask(rsave);
12225 }
12226
12227 /*-----------------------------------------------------------------*/
12228 /* genMMDeref -                                                    */
12229 /*-----------------------------------------------------------------*/
12230 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12231 {
12232         bitVect *rsave ;
12233         operand *handle;
12234
12235         assert (nparms == 1);
12236         /* save registers that need to be saved */
12237         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12238                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12239         
12240         handle=parms[0];
12241         aopOp (handle,ic,FALSE,FALSE);
12242
12243         /* put the size in R4-R2 */
12244         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12245                 emitcode("push","%s",
12246                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12247                 emitcode("push","%s",
12248                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12249                 emitcode("pop","ar3");
12250                 emitcode("pop","ar2");          
12251         } else {
12252                 emitcode ("mov","r2,%s",
12253                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12254                 emitcode ("mov","r3,%s",
12255                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12256         }
12257         freeAsmop (handle, NULL, ic, FALSE);
12258
12259         /* make the call */
12260         emitcode ("lcall","MM_Deref");
12261         
12262         {
12263                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12264                 if (rsym->liveFrom != rsym->liveTo) {                   
12265                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12266                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12267                             _startLazyDPSEvaluation ();
12268                             
12269                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12270                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12271                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12272
12273                             _endLazyDPSEvaluation ();
12274                             
12275                         }
12276                 }
12277         }
12278         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12279         unsavermask(rsave);
12280 }
12281
12282 /*-----------------------------------------------------------------*/
12283 /* genMMUnrestrictedPersist -                                      */
12284 /*-----------------------------------------------------------------*/
12285 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12286 {
12287         bitVect *rsave ;
12288         operand *handle;
12289
12290         assert (nparms == 1);
12291         /* save registers that need to be saved */
12292         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12293                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12294         
12295         handle=parms[0];
12296         aopOp (handle,ic,FALSE,FALSE);
12297
12298         /* put the size in R3-R2 */
12299         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12300                 emitcode("push","%s",
12301                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12302                 emitcode("push","%s",
12303                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12304                 emitcode("pop","ar3");
12305                 emitcode("pop","ar2");          
12306         } else {
12307                 emitcode ("mov","r2,%s",
12308                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12309                 emitcode ("mov","r3,%s",
12310                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12311         }
12312         freeAsmop (handle, NULL, ic, FALSE);
12313
12314         /* make the call */
12315         emitcode ("lcall","MM_UnrestrictedPersist");
12316
12317         {
12318                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12319                 if (rsym->liveFrom != rsym->liveTo) {   
12320                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12321                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12322                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12323                 }
12324         }
12325         unsavermask(rsave);
12326 }
12327
12328 /*-----------------------------------------------------------------*/
12329 /* genSystemExecJavaProcess -                                      */
12330 /*-----------------------------------------------------------------*/
12331 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12332 {
12333         bitVect *rsave ;
12334         operand *handle, *pp;
12335
12336         assert (nparms==2);
12337         /* save registers that need to be saved */
12338         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12339                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12340         
12341         pp = parms[0];
12342         handle = parms[1];
12343         
12344         /* put the handle in R3-R2 */
12345         aopOp (handle,ic,FALSE,FALSE);
12346         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12347                 emitcode("push","%s",
12348                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12349                 emitcode("push","%s",
12350                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12351                 emitcode("pop","ar3");
12352                 emitcode("pop","ar2");          
12353         } else {
12354                 emitcode ("mov","r2,%s",
12355                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12356                 emitcode ("mov","r3,%s",
12357                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12358         }
12359         freeAsmop (handle, NULL, ic, FALSE);
12360         
12361         /* put pointer in DPTR */
12362         aopOp (pp,ic,FALSE,FALSE);
12363         if (AOP_TYPE(pp) == AOP_IMMD) {
12364                 emitcode ("mov", "dptr,%s",
12365                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12366         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12367                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12368                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12369                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12370         }
12371         freeAsmop (handle, NULL, ic, FALSE);
12372
12373         /* make the call */
12374         emitcode ("lcall","System_ExecJavaProcess");
12375         
12376         /* put result in place */
12377         {
12378                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12379                 if (rsym->liveFrom != rsym->liveTo) {   
12380                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12381                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12382                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12383                 }
12384         }
12385         
12386         unsavermask(rsave);
12387 }
12388
12389 /*-----------------------------------------------------------------*/
12390 /* genSystemRTCRegisters -                                         */
12391 /*-----------------------------------------------------------------*/
12392 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12393                                   char *name)
12394 {
12395         bitVect *rsave ;
12396         operand *pp;
12397
12398         assert (nparms==1);
12399         /* save registers that need to be saved */
12400         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12401                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12402         
12403         pp=parms[0];
12404         /* put pointer in DPTR */
12405         aopOp (pp,ic,FALSE,FALSE);
12406         if (AOP_TYPE (pp) == AOP_IMMD) {
12407                 emitcode ("mov","dps,#1");
12408                 emitcode ("mov", "dptr,%s", 
12409                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12410                 emitcode ("mov","dps,#0");
12411         } else {
12412                 emitcode ("mov","dpl1,%s",
12413                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12414                 emitcode ("mov","dph1,%s",
12415                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12416                 emitcode ("mov","dpx1,%s",
12417                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12418         }
12419         freeAsmop (pp, NULL, ic, FALSE);
12420
12421         /* make the call */
12422         emitcode ("lcall","System_%sRTCRegisters",name);
12423
12424         unsavermask(rsave);
12425 }
12426
12427 /*-----------------------------------------------------------------*/
12428 /* genSystemThreadSleep -                                          */
12429 /*-----------------------------------------------------------------*/
12430 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12431 {
12432         bitVect *rsave ;
12433         operand *to, *s;
12434
12435         assert (nparms==1);
12436         /* save registers that need to be saved */
12437         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12438                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12439
12440         to = parms[0];
12441         aopOp(to,ic,FALSE,FALSE);
12442         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12443             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12444                 emitcode ("push","%s",
12445                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12446                 emitcode ("push","%s",
12447                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12448                 emitcode ("push","%s",
12449                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12450                 emitcode ("push","%s",
12451                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12452                 emitcode ("pop","ar3");
12453                 emitcode ("pop","ar2");
12454                 emitcode ("pop","ar1");
12455                 emitcode ("pop","ar0");
12456         } else {
12457                 emitcode ("mov","r0,%s",
12458                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12459                 emitcode ("mov","r1,%s",
12460                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12461                 emitcode ("mov","r2,%s",
12462                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12463                 emitcode ("mov","r3,%s",
12464                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12465         }
12466         freeAsmop (to, NULL, ic, FALSE);
12467
12468         /* suspend in acc */
12469         s = parms[1];
12470         aopOp(s,ic,FALSE,FALSE);
12471         emitcode ("mov","a,%s",
12472                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12473         freeAsmop (s, NULL, ic, FALSE);
12474
12475         /* make the call */
12476         emitcode ("lcall","System_%s",name);
12477
12478         unsavermask(rsave);
12479 }
12480
12481 /*-----------------------------------------------------------------*/
12482 /* genSystemThreadResume -                                         */
12483 /*-----------------------------------------------------------------*/
12484 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12485 {
12486         bitVect *rsave ;
12487         operand *tid,*pid;
12488
12489         assert (nparms==2);
12490         /* save registers that need to be saved */
12491         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12492                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12493         
12494         tid = parms[0];
12495         pid = parms[1];
12496         
12497         /* PID in R0 */
12498         aopOp(pid,ic,FALSE,FALSE);
12499         emitcode ("mov","r0,%s",
12500                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12501         freeAsmop (pid, NULL, ic, FALSE);
12502         
12503         /* tid into ACC */
12504         aopOp(tid,ic,FALSE,FALSE);
12505         emitcode ("mov","a,%s",
12506                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12507         freeAsmop (tid, NULL, ic, FALSE);
12508         
12509         emitcode ("lcall","System_ThreadResume");
12510
12511         /* put result into place */
12512         {
12513                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12514                 if (rsym->liveFrom != rsym->liveTo) {   
12515                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12516                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12517                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12518                 }
12519         }
12520         unsavermask(rsave);
12521 }
12522
12523 /*-----------------------------------------------------------------*/
12524 /* genSystemProcessResume -                                        */
12525 /*-----------------------------------------------------------------*/
12526 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12527 {
12528         bitVect *rsave ;
12529         operand *pid;
12530
12531         assert (nparms==1);
12532         /* save registers that need to be saved */
12533         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12534                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12535         
12536         pid = parms[0];
12537         
12538         /* pid into ACC */
12539         aopOp(pid,ic,FALSE,FALSE);
12540         emitcode ("mov","a,%s",
12541                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12542         freeAsmop (pid, NULL, ic, FALSE);
12543         
12544         emitcode ("lcall","System_ProcessResume");
12545
12546         unsavermask(rsave);
12547 }
12548
12549 /*-----------------------------------------------------------------*/
12550 /* genSystem -                                                     */
12551 /*-----------------------------------------------------------------*/
12552 static void genSystem (iCode *ic,int nparms,char *name)
12553 {
12554         assert(nparms == 0);
12555
12556         emitcode ("lcall","System_%s",name);
12557 }
12558
12559 /*-----------------------------------------------------------------*/
12560 /* genSystemPoll -                                                  */
12561 /*-----------------------------------------------------------------*/
12562 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12563 {
12564         bitVect *rsave ;
12565         operand *fp;
12566
12567         assert (nparms==1);
12568         /* save registers that need to be saved */
12569         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12570                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12571
12572         fp = parms[0];
12573         aopOp (fp,ic,FALSE,FALSE);
12574         if (AOP_TYPE (fp) == AOP_IMMD) {
12575                 emitcode ("mov", "dptr,%s", 
12576                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12577         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12578                 emitcode ("mov","dpl,%s",
12579                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12580                 emitcode ("mov","dph,%s",
12581                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12582                 emitcode ("mov","dpx,%s",
12583                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12584         }
12585         freeAsmop (fp, NULL, ic, FALSE);
12586
12587         emitcode ("lcall","System_%sPoll",name);
12588
12589         /* put result into place */
12590         {
12591                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12592                 if (rsym->liveFrom != rsym->liveTo) {   
12593                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12594                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12595                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12596                 }
12597         }
12598         unsavermask(rsave);
12599 }
12600
12601 /*-----------------------------------------------------------------*/
12602 /* genSystemGetCurrentID -                                         */
12603 /*-----------------------------------------------------------------*/
12604 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12605 {
12606         assert (nparms==0);
12607
12608         emitcode ("lcall","System_GetCurrent%sId",name);
12609         /* put result into place */
12610         {
12611                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12612                 if (rsym->liveFrom != rsym->liveTo) {   
12613                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12614                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12615                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12616                 }
12617         }
12618 }
12619
12620 /*-----------------------------------------------------------------*/
12621 /* genDummyRead - generate code for dummy read of volatiles        */
12622 /*-----------------------------------------------------------------*/
12623 static void
12624 genDummyRead (iCode * ic)
12625 {
12626   operand *right;
12627   int size, offset;
12628
12629   D(emitcode(";     genDummyRead",""));
12630
12631   right = IC_RIGHT (ic);
12632
12633   aopOp (right, ic, FALSE, FALSE);
12634
12635   /* if the result is a bit */
12636   if (AOP_TYPE (right) == AOP_CRY)
12637     {
12638       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12639       goto release;
12640     }
12641
12642   /* bit variables done */
12643   /* general case */
12644   size = AOP_SIZE (right);
12645   offset = 0;
12646   while (size--)
12647     {
12648       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12649       offset++;
12650     }
12651
12652 release:
12653   freeAsmop (right, NULL, ic, TRUE);
12654 }
12655
12656 /*-----------------------------------------------------------------*/
12657 /* genBuiltIn - calls the appropriate function to  generating code */
12658 /* for a built in function                                         */
12659 /*-----------------------------------------------------------------*/
12660 static void genBuiltIn (iCode *ic)
12661 {
12662         operand *bi_parms[MAX_BUILTIN_ARGS];
12663         int nbi_parms;
12664         iCode *bi_iCode;
12665         symbol *bif;
12666
12667         /* get all the arguments for a built in function */
12668         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12669
12670         /* which function is it */
12671         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12672         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12673                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12674         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12675                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12676         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12677                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12678         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12679                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12680         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12681                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12682         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12683                 genInp(bi_iCode,nbi_parms,bi_parms);
12684         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12685                 genOutp(bi_iCode,nbi_parms,bi_parms);
12686         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12687                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12688                 /* JavaNative builtIns */               
12689         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12690                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12691         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12692                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12693         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12694                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12695         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12696                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12697         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12698                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12699         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12700                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12701         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12702                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12703         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12704                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12705         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12706                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12707         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12708                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12709         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12710                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12711         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12712                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12713         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12714                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12715         } else if (strcmp(bif->name,"MM_Free")==0) {
12716                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12717         } else if (strcmp(bif->name,"MM_Deref")==0) {
12718                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12719         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12720                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12721         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12722                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12723         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12724                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12725         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12726                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12727         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12728                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12729         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12730                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12731         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12732                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12733         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12734                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12735         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12736                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12737         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12738                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12739         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12740                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12741         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12742                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12743         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12744                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12745         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12746                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12747         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12748                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12749         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12750                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12751         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12752                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12753         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12754                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12755         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12756                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12757         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12758                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12759         } else {
12760                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12761                 return ;
12762         }
12763         return ;    
12764 }
12765
12766 /*-----------------------------------------------------------------*/
12767 /* gen390Code - generate code for Dallas 390 based controllers     */
12768 /*-----------------------------------------------------------------*/
12769 void
12770 gen390Code (iCode * lic)
12771 {
12772   iCode *ic;
12773   int cln = 0;
12774
12775   lineHead = lineCurr = NULL;
12776   dptrn[1][0] = "dpl1";
12777   dptrn[1][1] = "dph1";
12778   dptrn[1][2] = "dpx1";
12779   
12780   if (options.model == MODEL_FLAT24) {
12781     fReturnSizeDS390 = 5;
12782     fReturn = fReturn24;
12783   } else {
12784     fReturnSizeDS390 = 4;
12785     fReturn = fReturn16;
12786     options.stack10bit=0;
12787   }
12788 #if 1
12789   /* print the allocation information */
12790   if (allocInfo && currFunc)
12791     printAllocInfo (currFunc, codeOutFile);
12792 #endif
12793   /* if debug information required */
12794   if (options.debug && currFunc)
12795     {
12796       debugFile->writeFunction(currFunc);
12797       _G.debugLine = 1;
12798       if (IS_STATIC (currFunc->etype))
12799         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12800       else
12801         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12802       _G.debugLine = 0;
12803     }
12804   /* stack pointer name */
12805   if (options.useXstack)
12806     spname = "_spx";
12807   else
12808     spname = "sp";
12809
12810
12811   for (ic = lic; ic; ic = ic->next)
12812     {
12813
12814       if (ic->lineno && cln != ic->lineno)
12815         {
12816           if (options.debug)
12817             {
12818               _G.debugLine = 1;
12819               emitcode ("", "C$%s$%d$%d$%d ==.",
12820                         FileBaseName (ic->filename), ic->lineno,
12821                         ic->level, ic->block);
12822               _G.debugLine = 0;
12823             }
12824           if (!options.noCcodeInAsm) {
12825             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12826                       printCLine(ic->filename, ic->lineno));
12827           }
12828           cln = ic->lineno;
12829         }
12830       if (options.iCodeInAsm) {
12831         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12832       }
12833       /* if the result is marked as
12834          spilt and rematerializable or code for
12835          this has already been generated then
12836          do nothing */
12837       if (resultRemat (ic) || ic->generated)
12838         continue;
12839
12840       /* depending on the operation */
12841       switch (ic->op)
12842         {
12843         case '!':
12844           genNot (ic);
12845           break;
12846
12847         case '~':
12848           genCpl (ic);
12849           break;
12850
12851         case UNARYMINUS:
12852           genUminus (ic);
12853           break;
12854
12855         case IPUSH:
12856           genIpush (ic);
12857           break;
12858
12859         case IPOP:
12860           /* IPOP happens only when trying to restore a
12861              spilt live range, if there is an ifx statement
12862              following this pop then the if statement might
12863              be using some of the registers being popped which
12864              would destory the contents of the register so
12865              we need to check for this condition and handle it */
12866           if (ic->next &&
12867               ic->next->op == IFX &&
12868               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12869             genIfx (ic->next, ic);
12870           else
12871             genIpop (ic);
12872           break;
12873
12874         case CALL:
12875           genCall (ic);
12876           break;
12877
12878         case PCALL:
12879           genPcall (ic);
12880           break;
12881
12882         case FUNCTION:
12883           genFunction (ic);
12884           break;
12885
12886         case ENDFUNCTION:
12887           genEndFunction (ic);
12888           break;
12889
12890         case RETURN:
12891           genRet (ic);
12892           break;
12893
12894         case LABEL:
12895           genLabel (ic);
12896           break;
12897
12898         case GOTO:
12899           genGoto (ic);
12900           break;
12901
12902         case '+':
12903           genPlus (ic);
12904           break;
12905
12906         case '-':
12907           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12908             genMinus (ic);
12909           break;
12910
12911         case '*':
12912           genMult (ic);
12913           break;
12914
12915         case '/':
12916           genDiv (ic);
12917           break;
12918
12919         case '%':
12920           genMod (ic);
12921           break;
12922
12923         case '>':
12924           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12925           break;
12926
12927         case '<':
12928           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12929           break;
12930
12931         case LE_OP:
12932         case GE_OP:
12933         case NE_OP:
12934
12935           /* note these two are xlated by algebraic equivalence
12936              during parsing SDCC.y */
12937           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12938                   "got '>=' or '<=' shouldn't have come here");
12939           break;
12940
12941         case EQ_OP:
12942           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12943           break;
12944
12945         case AND_OP:
12946           genAndOp (ic);
12947           break;
12948
12949         case OR_OP:
12950           genOrOp (ic);
12951           break;
12952
12953         case '^':
12954           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12955           break;
12956
12957         case '|':
12958           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12959           break;
12960
12961         case BITWISEAND:
12962           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12963           break;
12964
12965         case INLINEASM:
12966           genInline (ic);
12967           break;
12968
12969         case RRC:
12970           genRRC (ic);
12971           break;
12972
12973         case RLC:
12974           genRLC (ic);
12975           break;
12976
12977         case GETHBIT:
12978           genGetHbit (ic);
12979           break;
12980
12981         case LEFT_OP:
12982           genLeftShift (ic);
12983           break;
12984
12985         case RIGHT_OP:
12986           genRightShift (ic);
12987           break;
12988
12989         case GET_VALUE_AT_ADDRESS:
12990           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12991           break;
12992
12993         case '=':
12994           if (POINTER_SET (ic))
12995             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12996           else
12997             genAssign (ic);
12998           break;
12999
13000         case IFX:
13001           genIfx (ic, NULL);
13002           break;
13003
13004         case ADDRESS_OF:
13005           genAddrOf (ic);
13006           break;
13007
13008         case JUMPTABLE:
13009           genJumpTab (ic);
13010           break;
13011
13012         case CAST:
13013           genCast (ic);
13014           break;
13015
13016         case RECEIVE:
13017           genReceive (ic);
13018           break;
13019
13020         case SEND:
13021           if (ic->builtinSEND) genBuiltIn(ic);
13022           else addSet (&_G.sendSet, ic);
13023           break;
13024
13025         case DUMMY_READ_VOLATILE:
13026           genDummyRead (ic);
13027           break;
13028
13029 #if 0 // obsolete, and buggy for != xdata
13030         case ARRAYINIT:
13031             genArrayInit(ic);
13032             break;
13033 #endif
13034             
13035         default:
13036           ic = ic;
13037         }
13038     }
13039
13040
13041   /* now we are ready to call the
13042      peep hole optimizer */
13043   if (!options.nopeep)
13044     peepHole (&lineHead);
13045
13046   /* now do the actual printing */
13047   printLine (lineHead, codeOutFile);
13048   return;
13049 }