* src/mcs51/gen.c (genFunction, genEndFunction),
[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
2901   /* here we need to generate the equates for the
2902      register bank if required */
2903   if (FUNC_REGBANK (ftype) != rbank)
2904     {
2905       int i;
2906
2907       rbank = FUNC_REGBANK (ftype);
2908       for (i = 0; i < ds390_nRegs; i++)
2909         {
2910           if (regs390[i].print) {
2911               if (strcmp (regs390[i].base, "0") == 0)
2912                   emitcode ("", "%s !equ !constbyte",
2913                             regs390[i].dname,
2914                             8 * rbank + regs390[i].offset);
2915               else
2916                   emitcode ("", "%s !equ %s + !constbyte",
2917                             regs390[i].dname,
2918                             regs390[i].base,
2919                             8 * rbank + regs390[i].offset);
2920           }
2921         }
2922     }
2923
2924   /* if this is an interrupt service routine then
2925      save acc, b, dpl, dph  */
2926   if (IFFUNC_ISISR (sym->type))
2927       { /* is ISR */
2928       if (!inExcludeList ("acc"))
2929         emitcode ("push", "acc");
2930       if (!inExcludeList ("b"))
2931         emitcode ("push", "b");
2932       if (!inExcludeList ("dpl"))
2933         emitcode ("push", "dpl");
2934       if (!inExcludeList ("dph"))
2935         emitcode ("push", "dph");
2936       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2937         {
2938           emitcode ("push", "dpx");
2939           /* Make sure we're using standard DPTR */
2940           emitcode ("push", "dps");
2941           emitcode ("mov", "dps,#0");
2942           if (options.stack10bit)
2943             {
2944               /* This ISR could conceivably use DPTR2. Better save it. */
2945               emitcode ("push", "dpl1");
2946               emitcode ("push", "dph1");
2947               emitcode ("push", "dpx1");
2948               emitcode ("push",  DP2_RESULT_REG);
2949             }
2950         }
2951       /* if this isr has no bank i.e. is going to
2952          run with bank 0 , then we need to save more
2953          registers :-) */
2954       if (!FUNC_REGBANK (sym->type))
2955         {
2956             int i;
2957
2958           /* if this function does not call any other
2959              function then we can be economical and
2960              save only those registers that are used */
2961           if (!IFFUNC_HASFCALL(sym->type))
2962             {
2963
2964               /* if any registers used */
2965               if (sym->regsUsed)
2966                 {
2967                   /* save the registers used */
2968                   for (i = 0; i < sym->regsUsed->size; i++)
2969                     {
2970                       if (bitVectBitValue (sym->regsUsed, i) ||
2971                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2972                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2973                     }
2974                 }
2975
2976             }
2977           else
2978             {
2979               /* this function has  a function call cannot
2980                  determines register usage so we will have to push the
2981                  entire bank */
2982               saveRBank (0, ic, FALSE);
2983               if (options.parms_in_bank1) {
2984                   for (i=0; i < 8 ; i++ ) {
2985                       emitcode ("push","%s",rb1regs[i]);
2986                   }
2987               }
2988             }
2989         }
2990         else
2991         {
2992             /* This ISR uses a non-zero bank.
2993              *
2994              * We assume that the bank is available for our
2995              * exclusive use.
2996              *
2997              * However, if this ISR calls a function which uses some
2998              * other bank, we must save that bank entirely.
2999              */
3000             unsigned long banksToSave = 0;
3001             
3002             if (IFFUNC_HASFCALL(sym->type))
3003             {
3004
3005 #define MAX_REGISTER_BANKS 4
3006
3007                 iCode *i;
3008                 int ix;
3009
3010                 for (i = ic; i; i = i->next)
3011                 {
3012                     if (i->op == ENDFUNCTION)
3013                     {
3014                         /* we got to the end OK. */
3015                         break;
3016                     }
3017                     
3018                     if (i->op == CALL)
3019                     {
3020                         sym_link *dtype;
3021                         
3022                         dtype = operandType (IC_LEFT(i));
3023                         if (dtype 
3024                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3025                         {
3026                              /* Mark this bank for saving. */
3027                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3028                              {
3029                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3030                              }
3031                              else
3032                              {
3033                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3034                              }
3035                              
3036                              /* And note that we don't need to do it in 
3037                               * genCall.
3038                               */
3039                              i->bankSaved = 1;
3040                         }
3041                     }
3042                     if (i->op == PCALL)
3043                     {
3044                         /* This is a mess; we have no idea what
3045                          * register bank the called function might
3046                          * use.
3047                          *
3048                          * The only thing I can think of to do is
3049                          * throw a warning and hope.
3050                          */
3051                         werror(W_FUNCPTR_IN_USING_ISR);   
3052                     }
3053                 }
3054
3055                 if (banksToSave && options.useXstack)
3056                 {
3057                     /* Since we aren't passing it an ic, 
3058                      * saveRBank will assume r0 is available to abuse.
3059                      *
3060                      * So switch to our (trashable) bank now, so
3061                      * the caller's R0 isn't trashed.
3062                      */
3063                     emitcode ("push", "psw");
3064                     emitcode ("mov", "psw,#!constbyte", 
3065                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3066                     switchedPSW = TRUE;
3067                 }
3068                 
3069                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3070                 {
3071                      if (banksToSave & (1 << ix))
3072                      {
3073                          saveRBank(ix, NULL, FALSE);
3074                      }
3075                 }
3076             }
3077             // TODO: this needs a closer look
3078             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3079         }
3080     }
3081   else
3082     {
3083       /* if callee-save to be used for this function
3084          then save the registers being used in this function */
3085       if (IFFUNC_CALLEESAVES(sym->type))
3086         {
3087           int i;
3088
3089           /* if any registers used */
3090           if (sym->regsUsed)
3091             {
3092               /* save the registers used */
3093               for (i = 0; i < sym->regsUsed->size; i++)
3094                 {
3095                   if (bitVectBitValue (sym->regsUsed, i) ||
3096                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3097                     {
3098                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3099                       _G.nRegsSaved++;
3100                     }
3101                 }
3102             }
3103         }
3104     }
3105
3106   /* set the register bank to the desired value */
3107   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3108    && !switchedPSW)
3109     {
3110       emitcode ("push", "psw");
3111       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3112     }
3113
3114   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3115        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3116       if (options.stack10bit) {
3117           emitcode ("push","_bpx");
3118           emitcode ("push","_bpx+1");
3119           emitcode ("mov","_bpx,%s",spname);
3120           emitcode ("mov","_bpx+1,esp");
3121           adjustEsp("_bpx+1");
3122       } else {
3123           if (options.useXstack) {
3124               emitcode ("mov", "r0,%s", spname);
3125               emitcode ("mov", "a,_bp");
3126               emitcode ("movx", "@r0,a");
3127               emitcode ("inc", "%s", spname);
3128           } else {
3129               /* set up the stack */
3130               emitcode ("push", "_bp"); /* save the callers stack  */
3131           }
3132           emitcode ("mov", "_bp,%s", spname);
3133       }
3134   }
3135
3136   /* adjust the stack for the function */
3137   if (sym->stack) {
3138       int i = sym->stack;
3139       if (options.stack10bit) {
3140           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3141           assert (sym->recvSize <= 4);
3142           if (sym->stack <= 8) {
3143               while (i--) emitcode ("push","acc");
3144           } else {
3145               PROTECT_SP;
3146               emitcode ("mov","a,sp");
3147               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3148               emitcode ("mov","sp,a");
3149               emitcode ("mov","a,esp");
3150               adjustEsp("a");
3151               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3152               emitcode ("mov","esp,a");
3153               UNPROTECT_SP;
3154           }
3155       } else {
3156           if (i > 256)
3157               werror (W_STACK_OVERFLOW, sym->name);
3158           
3159           if (i > 3 && sym->recvSize < 4) {
3160               
3161               emitcode ("mov", "a,sp");
3162               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3163               emitcode ("mov", "sp,a");
3164               
3165           } else
3166               while (i--)
3167                   emitcode ("inc", "sp");
3168       }
3169   }
3170
3171   if (sym->xstack)
3172     {
3173
3174       emitcode ("mov", "a,_spx");
3175       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3176       emitcode ("mov", "_spx,a");
3177     }
3178   
3179   /* if critical function then turn interrupts off */
3180   if (IFFUNC_ISCRITICAL (ftype))
3181     {
3182       emitcode ("mov", "c,ea");
3183       emitcode ("push", "psw"); /* save old ea via c in psw */
3184       emitcode ("clr", "ea");
3185     }
3186
3187 }
3188
3189 /*-----------------------------------------------------------------*/
3190 /* genEndFunction - generates epilogue for functions               */
3191 /*-----------------------------------------------------------------*/
3192 static void
3193 genEndFunction (iCode * ic)
3194 {
3195   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3196
3197   D (emitcode (";", "genEndFunction "););
3198
3199   if (IFFUNC_ISNAKED(sym->type))
3200   {
3201       emitcode(";", "naked function: no epilogue.");
3202       return;
3203   }
3204
3205   if (IFFUNC_ISCRITICAL (sym->type))
3206     {
3207       emitcode ("pop", "psw"); /* restore ea via c in psw */
3208       emitcode ("mov", "ea,c");
3209     }
3210   
3211   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3212        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3213
3214       if (options.stack10bit) {
3215           PROTECT_SP;     
3216           emitcode ("mov", "sp,_bpx", spname);
3217           emitcode ("mov", "esp,_bpx+1", spname);
3218           UNPROTECT_SP;
3219       } else {
3220           emitcode ("mov", "%s,_bp", spname);
3221       }
3222   }
3223
3224   /* if use external stack but some variables were
3225      added to the local stack then decrement the
3226      local stack */
3227   if (options.useXstack && sym->stack) {
3228       emitcode ("mov", "a,sp");
3229       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3230       emitcode ("mov", "sp,a");
3231   }
3232
3233
3234   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3235        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3236
3237       if (options.useXstack) {
3238           emitcode ("mov", "r0,%s", spname);
3239           emitcode ("movx", "a,@r0");
3240           emitcode ("mov", "_bp,a");
3241           emitcode ("dec", "%s", spname);
3242       } else {
3243           if (options.stack10bit) {
3244               emitcode ("pop", "_bpx+1");
3245               emitcode ("pop", "_bpx");
3246           } else {
3247               emitcode ("pop", "_bp");
3248           }
3249       }
3250   }
3251
3252   /* restore the register bank  */
3253   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3254   {
3255     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3256      || !options.useXstack)
3257     {
3258         /* Special case of ISR using non-zero bank with useXstack
3259          * is handled below.
3260          */
3261         emitcode ("pop", "psw");
3262     }
3263   } 
3264
3265   if (IFFUNC_ISISR (sym->type))
3266       { /* is ISR */  
3267
3268       /* now we need to restore the registers */
3269       /* if this isr has no bank i.e. is going to
3270          run with bank 0 , then we need to save more
3271          registers :-) */
3272       if (!FUNC_REGBANK (sym->type))
3273         {
3274             int i;
3275           /* if this function does not call any other
3276              function then we can be economical and
3277              save only those registers that are used */
3278           if (!IFFUNC_HASFCALL(sym->type))
3279             {
3280
3281               /* if any registers used */
3282               if (sym->regsUsed)
3283                 {
3284                   /* save the registers used */
3285                   for (i = sym->regsUsed->size; i >= 0; i--)
3286                     {
3287                       if (bitVectBitValue (sym->regsUsed, i) ||
3288                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3289                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3290                     }
3291                 }
3292
3293             }
3294           else
3295             {
3296               /* this function has  a function call cannot
3297                  determines register usage so we will have to pop the
3298                  entire bank */
3299               if (options.parms_in_bank1) {
3300                   for (i = 7 ; i >= 0 ; i-- ) {
3301                       emitcode ("pop","%s",rb1regs[i]);
3302                   }
3303               }
3304               unsaveRBank (0, ic, FALSE);
3305             }
3306         }
3307         else
3308         {
3309             /* This ISR uses a non-zero bank.
3310              *
3311              * Restore any register banks saved by genFunction
3312              * in reverse order.
3313              */
3314             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3315             int ix;
3316           
3317             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3318             {
3319                 if (savedBanks & (1 << ix))
3320                 {
3321                     unsaveRBank(ix, NULL, FALSE);
3322                 }
3323             }
3324             
3325             if (options.useXstack)
3326             {
3327                 /* Restore bank AFTER calling unsaveRBank,
3328                  * since it can trash r0.
3329                  */
3330                 emitcode ("pop", "psw");
3331             }
3332         }
3333
3334       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3335         {
3336           if (options.stack10bit)
3337             {
3338               emitcode ("pop", DP2_RESULT_REG);
3339               emitcode ("pop", "dpx1");
3340               emitcode ("pop", "dph1");
3341               emitcode ("pop", "dpl1");
3342             }
3343           emitcode ("pop", "dps");
3344           emitcode ("pop", "dpx");
3345         }
3346       if (!inExcludeList ("dph"))
3347         emitcode ("pop", "dph");
3348       if (!inExcludeList ("dpl"))
3349         emitcode ("pop", "dpl");
3350       if (!inExcludeList ("b"))
3351         emitcode ("pop", "b");
3352       if (!inExcludeList ("acc"))
3353         emitcode ("pop", "acc");
3354
3355       /* if debug then send end of function */
3356       if (options.debug && currFunc) {
3357           _G.debugLine = 1;
3358           emitcode ("", "C$%s$%d$%d$%d ==.",
3359                     FileBaseName (ic->filename), currFunc->lastLine,
3360                     ic->level, ic->block);
3361           if (IS_STATIC (currFunc->etype))
3362             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3363           else
3364             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3365           _G.debugLine = 0;
3366         }
3367
3368       emitcode ("reti", "");
3369     }
3370   else
3371     {
3372       if (IFFUNC_CALLEESAVES(sym->type))
3373         {
3374           int i;
3375
3376           /* if any registers used */
3377           if (sym->regsUsed)
3378             {
3379               /* save the registers used */
3380               for (i = sym->regsUsed->size; i >= 0; i--)
3381                 {
3382                   if (bitVectBitValue (sym->regsUsed, i) ||
3383                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3384                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3385                 }
3386             }
3387
3388         }
3389
3390       /* if debug then send end of function */
3391       if (options.debug && currFunc)
3392         {
3393           _G.debugLine = 1;
3394           emitcode ("", "C$%s$%d$%d$%d ==.",
3395                     FileBaseName (ic->filename), currFunc->lastLine,
3396                     ic->level, ic->block);
3397           if (IS_STATIC (currFunc->etype))
3398             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3399           else
3400             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3401           _G.debugLine = 0;
3402         }
3403
3404       emitcode ("ret", "");
3405     }
3406
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* genJavaNativeRet - generate code for return JavaNative          */
3411 /*-----------------------------------------------------------------*/
3412 static void genJavaNativeRet(iCode *ic)
3413 {
3414     int i, size;
3415
3416     aopOp (IC_LEFT (ic), ic, FALSE, 
3417            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3418     size = AOP_SIZE (IC_LEFT (ic));
3419
3420     assert (size <= 4);
3421
3422     /* it is assigned to GPR0-R3 then push them */
3423     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3424         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3425         for (i = 0 ; i < size ; i++ ) {
3426             emitcode ("push","%s",
3427                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3428         }
3429         for (i = (size-1) ; i >= 0 ; i--) {
3430             emitcode ("pop","a%s",javaRet[i]);
3431         }
3432     } else {
3433         for (i = 0 ; i < size ; i++) 
3434             emitcode ("mov","%s,%s",javaRet[i],
3435                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3436     }
3437     for (i = size ; i < 4 ; i++ )
3438             emitcode ("mov","%s,#0",javaRet[i]);
3439     return;
3440 }
3441
3442 /*-----------------------------------------------------------------*/
3443 /* genRet - generate code for return statement                     */
3444 /*-----------------------------------------------------------------*/
3445 static void
3446 genRet (iCode * ic)
3447 {
3448   int size, offset = 0, pushed = 0;
3449
3450   D (emitcode (";", "genRet "););
3451
3452   /* if we have no return value then
3453      just generate the "ret" */
3454   if (!IC_LEFT (ic))
3455     goto jumpret;
3456
3457   /* if this is a JavaNative function then return 
3458      value in different register */
3459   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3460       genJavaNativeRet(ic);
3461       goto jumpret;
3462   }
3463   /* we have something to return then
3464      move the return value into place */
3465   aopOp (IC_LEFT (ic), ic, FALSE, 
3466          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3467   size = AOP_SIZE (IC_LEFT (ic));
3468
3469   _startLazyDPSEvaluation ();
3470   while (size--)
3471     {
3472       char *l;
3473       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3474         {
3475           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3476                       FALSE, TRUE, NULL);
3477           emitcode ("push", "%s", l);
3478           pushed++;
3479         }
3480       else
3481         {
3482           /* Since A is the last element of fReturn,
3483            * is is OK to clobber it in the aopGet.
3484            */
3485           l = aopGet (AOP (IC_LEFT (ic)), offset,
3486                       FALSE, FALSE, NULL);
3487           if (strcmp (fReturn[offset], l))
3488             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3489         }
3490     }
3491   _endLazyDPSEvaluation ();
3492
3493   if (pushed)
3494     {
3495       while (pushed)
3496         {
3497           pushed--;
3498           if (strcmp (fReturn[pushed], "a"))
3499             emitcode ("pop", fReturn[pushed]);
3500           else
3501             emitcode ("pop", "acc");
3502         }
3503     }
3504   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3505
3506 jumpret:
3507   /* generate a jump to the return label
3508      if the next is not the return statement */
3509   if (!(ic->next && ic->next->op == LABEL &&
3510         IC_LABEL (ic->next) == returnLabel))
3511
3512     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3513
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* genLabel - generates a label                                    */
3518 /*-----------------------------------------------------------------*/
3519 static void
3520 genLabel (iCode * ic)
3521 {
3522   /* special case never generate */
3523   if (IC_LABEL (ic) == entryLabel)
3524     return;
3525
3526   D (emitcode (";", "genLabel ");
3527     );
3528
3529   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3530 }
3531
3532 /*-----------------------------------------------------------------*/
3533 /* genGoto - generates a ljmp                                      */
3534 /*-----------------------------------------------------------------*/
3535 static void
3536 genGoto (iCode * ic)
3537 {
3538   D (emitcode (";", "genGoto ");
3539     );
3540   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3541 }
3542
3543 /*-----------------------------------------------------------------*/
3544 /* findLabelBackwards: walks back through the iCode chain looking  */
3545 /* for the given label. Returns number of iCode instructions     */
3546 /* between that label and given ic.          */
3547 /* Returns zero if label not found.          */
3548 /*-----------------------------------------------------------------*/
3549 static int
3550 findLabelBackwards (iCode * ic, int key)
3551 {
3552   int count = 0;
3553
3554   while (ic->prev)
3555     {
3556       ic = ic->prev;
3557       count++;
3558
3559       /* If we have any pushes or pops, we cannot predict the distance.
3560          I don't like this at all, this should be dealt with in the 
3561          back-end */
3562       if (ic->op == IPUSH || ic->op == IPOP) {
3563         return 0;
3564       }
3565
3566       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3567         {
3568           /* printf("findLabelBackwards = %d\n", count); */
3569           return count;
3570         }
3571     }
3572
3573   return 0;
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* genPlusIncr :- does addition with increment if possible         */
3578 /*-----------------------------------------------------------------*/
3579 static bool
3580 genPlusIncr (iCode * ic)
3581 {
3582   unsigned int icount;
3583   unsigned int size = getDataSize (IC_RESULT (ic));
3584
3585   /* will try to generate an increment */
3586   /* if the right side is not a literal
3587      we cannot */
3588   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3589     return FALSE;
3590
3591   /* if the literal value of the right hand side
3592      is greater than 4 then it is not worth it */
3593   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3594     return FALSE;
3595
3596   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3597       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3598       while (icount--) {
3599           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3600       }
3601       return TRUE;
3602   }
3603   /* if increment 16 bits in register */
3604   if (
3605        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3606        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3607        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3608        (size > 1) &&
3609        (icount == 1))
3610     {
3611       symbol  *tlbl;
3612       int     emitTlbl;
3613       int     labelRange;
3614       char    *l;
3615
3616       /* If the next instruction is a goto and the goto target
3617        * is <= 5 instructions previous to this, we can generate
3618        * jumps straight to that target.
3619        */
3620       if (ic->next && ic->next->op == GOTO
3621           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3622           && labelRange <= 5)
3623         {
3624           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3625           tlbl = IC_LABEL (ic->next);
3626           emitTlbl = 0;
3627         }
3628       else
3629         {
3630           tlbl = newiTempLabel (NULL);
3631           emitTlbl = 1;
3632         }
3633         
3634       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3635       emitcode ("inc", "%s", l);
3636       
3637       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3638           IS_AOP_PREG (IC_RESULT (ic)))
3639       {   
3640         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3641       }
3642       else
3643       {
3644           emitcode ("clr", "a");
3645           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3646       }
3647
3648       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3649       emitcode ("inc", "%s", l);
3650       if (size > 2)
3651         {
3652             if (!strcmp(l, "acc"))
3653             {
3654                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3655             }
3656             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3657                      IS_AOP_PREG (IC_RESULT (ic)))
3658             {
3659                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3660             }
3661             else
3662             {
3663                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3664             }
3665
3666             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3667             emitcode ("inc", "%s", l);
3668         }
3669       if (size > 3)
3670         {
3671             if (!strcmp(l, "acc"))
3672             {
3673                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3674             }
3675             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3676                      IS_AOP_PREG (IC_RESULT (ic)))
3677             {
3678                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3679             }
3680             else
3681             {
3682                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3683             }
3684
3685             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3686             emitcode ("inc", "%s", l);  }
3687
3688       if (emitTlbl)
3689         {
3690           emitcode ("", "!tlabeldef", tlbl->key + 100);
3691         }
3692       return TRUE;
3693     }
3694
3695   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3696       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3697       options.model == MODEL_FLAT24 ) {
3698
3699       switch (size) {
3700       case 3:
3701           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3702       case 2:
3703           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3704       case 1:
3705           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3706           break;
3707       }
3708       while (icount--) emitcode ("inc","dptr");      
3709       return TRUE;
3710   }
3711
3712   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3713       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3714       icount <= 5 ) {
3715       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3716       while (icount--) emitcode ("inc","dptr");
3717       emitcode ("mov","dps,#0");
3718       return TRUE;
3719   }
3720
3721   /* if the sizes are greater than 1 then we cannot */
3722   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3723       AOP_SIZE (IC_LEFT (ic)) > 1)
3724     return FALSE;
3725
3726   /* we can if the aops of the left & result match or
3727      if they are in registers and the registers are the
3728      same */
3729   if (
3730        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3731        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3732        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3733     {
3734
3735       if (icount > 3)
3736         {
3737           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3738           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3739           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3740         }
3741       else
3742         {
3743
3744           _startLazyDPSEvaluation ();
3745           while (icount--)
3746             {
3747               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3748             }
3749           _endLazyDPSEvaluation ();
3750         }
3751
3752       return TRUE;
3753     }
3754
3755   return FALSE;
3756 }
3757
3758 /*-----------------------------------------------------------------*/
3759 /* outBitAcc - output a bit in acc                                 */
3760 /*-----------------------------------------------------------------*/
3761 static void
3762 outBitAcc (operand * result)
3763 {
3764   symbol *tlbl = newiTempLabel (NULL);
3765   /* if the result is a bit */
3766   if (AOP_TYPE (result) == AOP_CRY)
3767     {
3768       aopPut (AOP (result), "a", 0);
3769     }
3770   else
3771     {
3772       emitcode ("jz", "!tlabel", tlbl->key + 100);
3773       emitcode ("mov", "a,%s", one);
3774       emitcode ("", "!tlabeldef", tlbl->key + 100);
3775       outAcc (result);
3776     }
3777 }
3778
3779 /*-----------------------------------------------------------------*/
3780 /* genPlusBits - generates code for addition of two bits           */
3781 /*-----------------------------------------------------------------*/
3782 static void
3783 genPlusBits (iCode * ic)
3784 {
3785   D (emitcode (";", "genPlusBits "););
3786     
3787   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3788     {
3789       symbol *lbl = newiTempLabel (NULL);
3790       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3791       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3792       emitcode ("cpl", "c");
3793       emitcode ("", "!tlabeldef", (lbl->key + 100));
3794       outBitC (IC_RESULT (ic));
3795     }
3796   else
3797     {
3798       emitcode ("clr", "a");
3799       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3800       emitcode ("rlc", "a");
3801       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3802       emitcode ("addc", "a,#0");
3803       outAcc (IC_RESULT (ic));
3804     }
3805 }
3806
3807 static void
3808 adjustArithmeticResult (iCode * ic)
3809 {
3810   if (opIsGptr (IC_RESULT (ic)) &&
3811       opIsGptr (IC_LEFT (ic)) &&
3812       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3813     {
3814       aopPut (AOP (IC_RESULT (ic)),
3815               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3816               GPTRSIZE - 1);
3817     }
3818
3819   if (opIsGptr (IC_RESULT (ic)) &&
3820       opIsGptr (IC_RIGHT (ic)) &&
3821       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3822     {
3823       aopPut (AOP (IC_RESULT (ic)),
3824             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3825               GPTRSIZE - 1);
3826     }
3827
3828   if (opIsGptr (IC_RESULT (ic)) &&
3829       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3830       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3831       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3832       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3833     {
3834       char buff[5];
3835       SNPRINTF (buff, sizeof(buff), 
3836                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3837       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3838     }
3839 }
3840
3841 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3842 // generates the result if possible. If result is generated, returns TRUE; otherwise
3843 // returns false and caller must deal with fact that result isn't aopOp'd.
3844 bool aopOp3(iCode * ic)
3845 {
3846     bool dp1InUse, dp2InUse;
3847     bool useDp2;
3848     
3849     // First, generate the right opcode. DPTR may be used if neither left nor result are
3850     // of type AOP_STR.
3851     
3852 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3853 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3854 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3855 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3856 //      );
3857 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3858 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3859 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3860 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3861 //      );
3862     
3863     // Right uses DPTR unless left or result is an AOP_STR; however,
3864     // if right is an AOP_STR, it must use DPTR regardless.
3865     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3866      && !AOP_IS_STR(IC_RIGHT(ic)))
3867     {
3868         useDp2 = TRUE;
3869     }
3870     else
3871     {
3872         useDp2 = FALSE;
3873     }
3874         
3875     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3876     
3877     // if the right used DPTR, left MUST use DPTR2.
3878     // if the right used DPTR2, left MUST use DPTR.
3879     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3880     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3881     // enabling us to assign DPTR to result.
3882      
3883     if (AOP_USESDPTR(IC_RIGHT(ic)))
3884     {
3885         useDp2 = TRUE;
3886     }
3887     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3888     {
3889         useDp2 = FALSE;
3890     }
3891     else
3892     {
3893         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3894         {
3895             useDp2 = TRUE;
3896         }
3897         else
3898         {
3899             useDp2 = FALSE;
3900         }
3901     }
3902
3903     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3904     
3905     // We've op'd the left & right. So, if left or right are the same operand as result, 
3906     // we know aopOp will succeed, and we can just do it & bail.
3907     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3908         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3909     {
3910 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3911         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3912         return TRUE;
3913     }
3914     
3915     // Note which dptrs are currently in use.
3916     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3917     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3918     
3919     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3920     // generate it.
3921     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3922     {
3923         return FALSE;
3924     }
3925     
3926     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3927     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3928     {
3929         return FALSE;
3930     }
3931     
3932     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3933     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3934     {
3935         return FALSE;
3936     }
3937
3938     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3939
3940     // Some sanity checking...
3941     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3942     {
3943         fprintf(stderr,
3944                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3945                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3946         emitcode(";", ">>> unexpected DPTR here.");
3947     }
3948     
3949     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3950     {
3951         fprintf(stderr,
3952                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3953                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3954         emitcode(";", ">>> unexpected DPTR2 here.");
3955     }    
3956     
3957     return TRUE;
3958 }
3959
3960 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3961 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3962 // will be set TRUE. The caller must then handle the case specially, noting
3963 // that the IC_RESULT operand is not aopOp'd.
3964 // 
3965 #define AOP_OP_3_NOFATAL(ic, rc) \
3966             do { rc = !aopOp3(ic); } while (0)
3967
3968 // aopOp the left & right operands of an ic.
3969 #define AOP_OP_2(ic) \
3970     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3971     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3972
3973 // convienience macro.
3974 #define AOP_SET_LOCALS(ic) \
3975     left = IC_LEFT(ic); \
3976     right = IC_RIGHT(ic); \
3977     result = IC_RESULT(ic);
3978
3979
3980 // Given an integer value of pushedSize bytes on the stack,
3981 // adjust it to be resultSize bytes, either by discarding
3982 // the most significant bytes or by zero-padding.
3983 //
3984 // On exit from this macro, pushedSize will have been adjusted to
3985 // equal resultSize, and ACC may be trashed.
3986 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3987       /* If the pushed data is bigger than the result,          \
3988        * simply discard unused bytes. Icky, but works.          \
3989        */                                                       \
3990       while (pushedSize > resultSize)                           \
3991       {                                                         \
3992           D (emitcode (";", "discarding unused result byte."););\
3993           emitcode ("pop", "acc");                              \
3994           pushedSize--;                                         \
3995       }                                                         \
3996       if (pushedSize < resultSize)                              \
3997       {                                                         \
3998           emitcode ("clr", "a");                                \
3999           /* Conversly, we haven't pushed enough here.          \
4000            * just zero-pad, and all is well.                    \
4001            */                                                   \
4002           while (pushedSize < resultSize)                       \
4003           {                                                     \
4004               emitcode("push", "acc");                          \
4005               pushedSize++;                                     \
4006           }                                                     \
4007       }                                                         \
4008       assert(pushedSize == resultSize);
4009
4010 /*-----------------------------------------------------------------*/
4011 /* genPlus - generates code for addition                           */
4012 /*-----------------------------------------------------------------*/
4013 static void
4014 genPlus (iCode * ic)
4015 {
4016   int size, offset = 0;
4017   bool pushResult;
4018   int rSize;
4019
4020   D (emitcode (";", "genPlus "););
4021
4022   /* special cases :- */
4023   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4024       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4025       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4026       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4027       if (size <= 9) {
4028           while (size--) emitcode ("inc","dptr");
4029       } else {
4030           emitcode ("mov","a,dpl");
4031           emitcode ("add","a,#!constbyte",size & 0xff);
4032           emitcode ("mov","dpl,a");
4033           emitcode ("mov","a,dph");
4034           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4035           emitcode ("mov","dph,a");
4036           emitcode ("mov","a,dpx");
4037           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4038           emitcode ("mov","dpx,a");
4039       }
4040       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4041       return ;
4042   }
4043   if ( IS_SYMOP(IC_LEFT(ic)) && 
4044        OP_SYMBOL(IC_LEFT(ic))->remat &&
4045        isOperandInFarSpace(IC_RIGHT(ic))) {
4046       operand *op = IC_RIGHT(ic);
4047       IC_RIGHT(ic) = IC_LEFT(ic);
4048       IC_LEFT(ic) = op;
4049   }
4050                 
4051   AOP_OP_3_NOFATAL (ic, pushResult);
4052     
4053   if (pushResult)
4054     {
4055       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4056     }
4057
4058   if (!pushResult)
4059     {
4060       /* if literal, literal on the right or
4061          if left requires ACC or right is already
4062          in ACC */
4063       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4064        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4065           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4066         {
4067           operand *t = IC_RIGHT (ic);
4068           IC_RIGHT (ic) = IC_LEFT (ic);
4069           IC_LEFT (ic) = t;
4070           emitcode (";", "Swapped plus args.");
4071         }
4072
4073       /* if both left & right are in bit
4074          space */
4075       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4076           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4077         {
4078           genPlusBits (ic);
4079           goto release;
4080         }
4081
4082       /* if left in bit space & right literal */
4083       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4084           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4085         {
4086           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4087           /* if result in bit space */
4088           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4089             {
4090               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4091                 emitcode ("cpl", "c");
4092               outBitC (IC_RESULT (ic));
4093             }
4094           else
4095             {
4096               size = getDataSize (IC_RESULT (ic));
4097               _startLazyDPSEvaluation ();
4098               while (size--)
4099                 {
4100                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4101                   emitcode ("addc", "a,#0");
4102                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4103                 }
4104               _endLazyDPSEvaluation ();
4105             }
4106           goto release;
4107         }
4108
4109       /* if I can do an increment instead
4110          of add then GOOD for ME */
4111       if (genPlusIncr (ic) == TRUE)
4112         {
4113           emitcode (";", "did genPlusIncr");
4114           goto release;
4115         }
4116
4117     }
4118   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4119
4120   _startLazyDPSEvaluation ();
4121   while (size--)
4122     {
4123       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4124         {
4125           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4126           if (offset == 0)
4127             emitcode ("add", "a,%s",
4128                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4129           else
4130             emitcode ("addc", "a,%s",
4131                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4132         }
4133       else
4134         {
4135           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4136           {
4137               /* right is going to use ACC or we would have taken the
4138                * above branch.
4139                */
4140               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4141        TR_AP("#3");
4142               D(emitcode(";", "+ AOP_ACC special case."););
4143               emitcode("xch", "a, %s", DP2_RESULT_REG);
4144           }
4145           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4146           if (offset == 0)
4147           {
4148             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4149             {
4150          TR_AP("#4");
4151                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4152             }
4153             else
4154             {
4155                 emitcode ("add", "a,%s",
4156                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4157                                   DP2_RESULT_REG));
4158             }
4159           }
4160           else
4161           {
4162             emitcode ("addc", "a,%s",
4163                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4164                           DP2_RESULT_REG));
4165           }
4166         }
4167       if (!pushResult)
4168         {
4169           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4170         }
4171       else
4172         {
4173           emitcode ("push", "acc");
4174         }
4175       offset++;
4176     }
4177   _endLazyDPSEvaluation ();
4178
4179   if (pushResult)
4180     {
4181       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4182
4183       size = getDataSize (IC_LEFT (ic));
4184       rSize = getDataSize (IC_RESULT (ic));
4185
4186       ADJUST_PUSHED_RESULT(size, rSize);
4187
4188       _startLazyDPSEvaluation ();
4189       while (size--)
4190         {
4191           emitcode ("pop", "acc");
4192           aopPut (AOP (IC_RESULT (ic)), "a", size);
4193         }
4194       _endLazyDPSEvaluation ();
4195     }
4196
4197   adjustArithmeticResult (ic);
4198
4199 release:
4200   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4201   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4202   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4203 }
4204
4205 /*-----------------------------------------------------------------*/
4206 /* genMinusDec :- does subtraction with deccrement if possible     */
4207 /*-----------------------------------------------------------------*/
4208 static bool
4209 genMinusDec (iCode * ic)
4210 {
4211   unsigned int icount;
4212   unsigned int size = getDataSize (IC_RESULT (ic));
4213
4214   /* will try to generate an increment */
4215   /* if the right side is not a literal
4216      we cannot */
4217   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4218     return FALSE;
4219
4220   /* if the literal value of the right hand side
4221      is greater than 4 then it is not worth it */
4222   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4223     return FALSE;
4224
4225   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4226       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4227       while (icount--) {
4228           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4229       }
4230       return TRUE;
4231   }
4232   /* if decrement 16 bits in register */
4233   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4234       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4235       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4236       (size > 1) &&
4237       (icount == 1))
4238     {
4239       symbol *tlbl;
4240       int    emitTlbl;
4241       int    labelRange;
4242       char   *l;
4243
4244       /* If the next instruction is a goto and the goto target
4245          * is <= 5 instructions previous to this, we can generate
4246          * jumps straight to that target.
4247        */
4248       if (ic->next && ic->next->op == GOTO
4249           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4250           && labelRange <= 5)
4251         {
4252           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4253           tlbl = IC_LABEL (ic->next);
4254           emitTlbl = 0;
4255         }
4256       else
4257         {
4258           tlbl = newiTempLabel (NULL);
4259           emitTlbl = 1;
4260         }
4261
4262       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4263       emitcode ("dec", "%s", l);
4264  
4265       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4266           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4267           IS_AOP_PREG (IC_RESULT (ic)))
4268       {     
4269           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4270       }
4271       else
4272       {
4273           emitcode ("mov", "a,#!constbyte",0xff);
4274           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4275       }
4276       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4277       emitcode ("dec", "%s", l);
4278       if (size > 2)
4279         {
4280             if (!strcmp(l, "acc"))
4281             {
4282                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4283             }
4284             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4285                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4286                      IS_AOP_PREG (IC_RESULT (ic)))
4287             {       
4288                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4289             }
4290             else
4291             {
4292                 emitcode ("mov", "a,#!constbyte",0xff);
4293                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4294             }
4295             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4296             emitcode ("dec", "%s", l);
4297         }
4298       if (size > 3)
4299         {
4300             if (!strcmp(l, "acc"))
4301             {
4302                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4303             }
4304             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4305                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4306                      IS_AOP_PREG (IC_RESULT (ic)))
4307             {       
4308                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4309             }
4310             else
4311             {
4312                 emitcode ("mov", "a,#!constbyte",0xff);
4313                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4314             }       
4315             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4316             emitcode ("dec", "%s", l);
4317         }
4318       if (emitTlbl)
4319         {
4320           emitcode ("", "!tlabeldef", tlbl->key + 100);
4321         }
4322       return TRUE;
4323     }
4324
4325   /* if the sizes are greater than 1 then we cannot */
4326   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4327       AOP_SIZE (IC_LEFT (ic)) > 1)
4328     return FALSE;
4329
4330   /* we can if the aops of the left & result match or
4331      if they are in registers and the registers are the
4332      same */
4333   if (
4334        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4335        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4336        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4337     {
4338
4339       _startLazyDPSEvaluation ();
4340       while (icount--)
4341         {
4342           emitcode ("dec", "%s",
4343                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4344         }
4345       _endLazyDPSEvaluation ();
4346
4347       return TRUE;
4348     }
4349
4350   return FALSE;
4351 }
4352
4353 /*-----------------------------------------------------------------*/
4354 /* addSign - complete with sign                                    */
4355 /*-----------------------------------------------------------------*/
4356 static void
4357 addSign (operand * result, int offset, int sign)
4358 {
4359   int size = (getDataSize (result) - offset);
4360   if (size > 0)
4361     {
4362       _startLazyDPSEvaluation();
4363       if (sign)
4364         {
4365           emitcode ("rlc", "a");
4366           emitcode ("subb", "a,acc");
4367           while (size--)
4368           {
4369             aopPut (AOP (result), "a", offset++);
4370           }
4371         }
4372       else
4373       {
4374         while (size--)
4375         {
4376           aopPut (AOP (result), zero, offset++);
4377         }
4378       }
4379       _endLazyDPSEvaluation();
4380     }
4381 }
4382
4383 /*-----------------------------------------------------------------*/
4384 /* genMinusBits - generates code for subtraction  of two bits      */
4385 /*-----------------------------------------------------------------*/
4386 static void
4387 genMinusBits (iCode * ic)
4388 {
4389   symbol *lbl = newiTempLabel (NULL);
4390
4391   D (emitcode (";", "genMinusBits "););
4392
4393   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4394     {
4395       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4397       emitcode ("cpl", "c");
4398       emitcode ("", "!tlabeldef", (lbl->key + 100));
4399       outBitC (IC_RESULT (ic));
4400     }
4401   else
4402     {
4403       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4404       emitcode ("subb", "a,acc");
4405       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4406       emitcode ("inc", "a");
4407       emitcode ("", "!tlabeldef", (lbl->key + 100));
4408       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4409       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4410     }
4411 }
4412
4413 /*-----------------------------------------------------------------*/
4414 /* genMinus - generates code for subtraction                       */
4415 /*-----------------------------------------------------------------*/
4416 static void
4417 genMinus (iCode * ic)
4418 {
4419     int size, offset = 0;
4420     int rSize;
4421     long lit = 0L;
4422     bool pushResult;
4423
4424     D (emitcode (";", "genMinus "););
4425
4426     AOP_OP_3_NOFATAL(ic, pushResult);   
4427
4428     if (!pushResult)
4429     {
4430       /* special cases :- */
4431       /* if both left & right are in bit space */
4432       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4433           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4434         {
4435           genMinusBits (ic);
4436           goto release;
4437         }
4438
4439       /* if I can do an decrement instead
4440          of subtract then GOOD for ME */
4441       if (genMinusDec (ic) == TRUE)
4442         goto release;
4443
4444     }
4445
4446   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4447
4448   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4449     {
4450       CLRC;
4451     }
4452   else
4453     {
4454       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4455       lit = -lit;
4456     }
4457
4458
4459   /* if literal, add a,#-lit, else normal subb */
4460   _startLazyDPSEvaluation ();
4461   while (size--) {
4462       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4463           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4464               emitcode ("mov","b,%s",
4465                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4466               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4467               emitcode ("subb","a,b");
4468           } else {
4469               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4470               emitcode ("subb", "a,%s",
4471                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4472                                 DP2_RESULT_REG));
4473           }
4474       } else {
4475           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4476           /* first add without previous c */
4477           if (!offset) {
4478               if (!size && lit==-1) {
4479                   emitcode ("dec", "a");
4480               } else {
4481                   emitcode ("add", "a,#!constbyte",
4482                             (unsigned int) (lit & 0x0FFL));
4483               }
4484           } else {
4485               emitcode ("addc", "a,#!constbyte",
4486                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4487           }
4488       }
4489       
4490       if (pushResult) {
4491           emitcode ("push", "acc");
4492       } else {
4493           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4494       }
4495       offset++;
4496   }
4497   _endLazyDPSEvaluation ();
4498   
4499   if (pushResult)
4500     {
4501       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4502
4503       size = getDataSize (IC_LEFT (ic));
4504       rSize = getDataSize (IC_RESULT (ic));
4505
4506       ADJUST_PUSHED_RESULT(size, rSize);
4507
4508       _startLazyDPSEvaluation ();
4509       while (size--)
4510         {
4511           emitcode ("pop", "acc");
4512           aopPut (AOP (IC_RESULT (ic)), "a", size);
4513         }
4514       _endLazyDPSEvaluation ();
4515     }
4516
4517   adjustArithmeticResult (ic);
4518
4519 release:
4520   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4523 }
4524
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genMultbits :- multiplication of bits                           */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 genMultbits (operand * left,
4531              operand * right,
4532              operand * result,
4533              iCode   * ic)
4534 {
4535   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4536   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4537   aopOp(result, ic, TRUE, FALSE);
4538   outBitC (result);
4539 }
4540
4541
4542 /*-----------------------------------------------------------------*/
4543 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4544 /*-----------------------------------------------------------------*/
4545 static void
4546 genMultOneByte (operand * left,
4547                 operand * right,
4548                 operand * result,
4549                 iCode   * ic)
4550 {
4551   sym_link *opetype = operandType (result);
4552   symbol *lbl;
4553
4554
4555   /* (if two literals: the value is computed before) */
4556   /* if one literal, literal on the right */
4557   if (AOP_TYPE (left) == AOP_LIT)
4558     {
4559       operand *t = right;
4560       right = left;
4561       left = t;
4562       emitcode (";", "swapped left and right");
4563     }
4564
4565   if (SPEC_USIGN(opetype)
4566       // ignore the sign of left and right, what else can we do?
4567       || (SPEC_USIGN(operandType(left)) && 
4568           SPEC_USIGN(operandType(right)))) {
4569     // just an unsigned 8*8=8/16 multiply
4570     //emitcode (";","unsigned");
4571     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4572     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4573     emitcode ("mul", "ab");
4574    
4575     _G.accInUse++; _G.bInUse++;
4576     aopOp(result, ic, TRUE, FALSE);
4577       
4578       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4579       {
4580           // this should never happen
4581           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4582                    AOP_SIZE(result), __FILE__, lineno);
4583           exit (1);
4584       }      
4585       
4586     aopPut (AOP (result), "a", 0);
4587     _G.accInUse--; _G.bInUse--;
4588     if (AOP_SIZE(result)==2) 
4589     {
4590       aopPut (AOP (result), "b", 1);
4591     }
4592     return;
4593   }
4594
4595   // we have to do a signed multiply
4596
4597   emitcode (";", "signed");
4598   emitcode ("clr", "F0"); // reset sign flag
4599   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4600
4601   lbl=newiTempLabel(NULL);
4602   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4603   // left side is negative, 8-bit two's complement, this fails for -128
4604   emitcode ("setb", "F0"); // set sign flag
4605   emitcode ("cpl", "a");
4606   emitcode ("inc", "a");
4607
4608   emitcode ("", "!tlabeldef", lbl->key+100);
4609
4610   /* if literal */
4611   if (AOP_TYPE(right)==AOP_LIT) {
4612     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4613     /* AND literal negative */
4614     if ((int) val < 0) {
4615       emitcode ("cpl", "F0"); // complement sign flag
4616       emitcode ("mov", "b,#!constbyte", -val);
4617     } else {
4618       emitcode ("mov", "b,#!constbyte", val);
4619     }
4620   } else {
4621     lbl=newiTempLabel(NULL);
4622     emitcode ("mov", "b,a");
4623     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4624     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4625     // right side is negative, 8-bit two's complement
4626     emitcode ("cpl", "F0"); // complement sign flag
4627     emitcode ("cpl", "a");
4628     emitcode ("inc", "a");
4629     emitcode ("", "!tlabeldef", lbl->key+100);
4630   }
4631   emitcode ("mul", "ab");
4632     
4633   _G.accInUse++;_G.bInUse++;
4634   aopOp(result, ic, TRUE, FALSE);
4635     
4636   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4637   {
4638     // this should never happen
4639       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4640                AOP_SIZE(result), __FILE__, lineno);
4641       exit (1);
4642   }    
4643     
4644   lbl=newiTempLabel(NULL);
4645   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4646   // only ONE op was negative, we have to do a 8/16-bit two's complement
4647   emitcode ("cpl", "a"); // lsb
4648   if (AOP_SIZE(result)==1) {
4649     emitcode ("inc", "a");
4650   } else {
4651     emitcode ("add", "a,#1");
4652     emitcode ("xch", "a,b");
4653     emitcode ("cpl", "a"); // msb
4654     emitcode ("addc", "a,#0");
4655     emitcode ("xch", "a,b");
4656   }
4657
4658   emitcode ("", "!tlabeldef", lbl->key+100);
4659   aopPut (AOP (result), "a", 0);
4660   _G.accInUse--;_G.bInUse--;
4661   if (AOP_SIZE(result)==2) {
4662     aopPut (AOP (result), "b", 1);
4663   }
4664 }
4665
4666 /*-----------------------------------------------------------------*/
4667 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4668 /*-----------------------------------------------------------------*/
4669 static void genMultTwoByte (operand *left, operand *right, 
4670                             operand *result, iCode *ic)
4671 {
4672         sym_link *retype = getSpec(operandType(right));
4673         sym_link *letype = getSpec(operandType(left));
4674         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4675         symbol *lbl;
4676
4677         if (AOP_TYPE (left) == AOP_LIT) {
4678                 operand *t = right;
4679                 right = left;
4680                 left = t;
4681         }
4682         /* save EA bit in F1 */
4683         lbl = newiTempLabel(NULL);
4684         emitcode ("setb","F1");
4685         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4686         emitcode ("clr","F1");
4687         emitcode("","!tlabeldef",lbl->key+100);
4688
4689         /* load up MB with right */
4690         if (!umult) {
4691                 emitcode("clr","F0");
4692                 if (AOP_TYPE(right) == AOP_LIT) {
4693                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4694                         if (val < 0) {
4695                                 emitcode("setb","F0");
4696                                 val = -val;
4697                         }
4698                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4699                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4700                 } else {
4701                         lbl = newiTempLabel(NULL);
4702                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4703                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4704                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4705                         emitcode ("xch", "a,b");
4706                         emitcode ("cpl","a");
4707                         emitcode ("add", "a,#1");
4708                         emitcode ("xch", "a,b");
4709                         emitcode ("cpl", "a"); // msb
4710                         emitcode ("addc", "a,#0");
4711                         emitcode ("setb","F0");
4712                         emitcode ("","!tlabeldef",lbl->key+100);
4713                         emitcode ("mov","mb,b");
4714                         emitcode ("mov","mb,a");
4715                 }
4716         } else {
4717                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4718                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4719         }
4720         /* load up MA with left */
4721         if (!umult) {
4722                 lbl = newiTempLabel(NULL);
4723                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4724                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4725                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4726                 emitcode ("xch", "a,b");
4727                 emitcode ("cpl","a");
4728                 emitcode ("add", "a,#1");
4729                 emitcode ("xch", "a,b");
4730                 emitcode ("cpl", "a"); // msb
4731                 emitcode ("addc","a,#0");
4732                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4733                 emitcode ("setb","F0");
4734                 emitcode ("","!tlabeldef",lbl->key+100);
4735                 emitcode ("mov","ma,b");
4736                 emitcode ("mov","ma,a");
4737         } else {
4738                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4739                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4740         }
4741         /* wait for multiplication to finish */
4742         lbl = newiTempLabel(NULL);
4743         emitcode("","!tlabeldef", lbl->key+100);
4744         emitcode("mov","a,mcnt1");
4745         emitcode("anl","a,#!constbyte",0x80);
4746         emitcode("jnz","!tlabel",lbl->key+100);
4747         
4748         freeAsmop (left, NULL, ic, TRUE);
4749         freeAsmop (right, NULL, ic,TRUE);
4750         aopOp(result, ic, TRUE, FALSE);
4751
4752         /* if unsigned then simple */   
4753         if (umult) {
4754                 emitcode ("mov","a,ma");
4755                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4756                 emitcode ("mov","a,ma");
4757                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4758                 aopPut(AOP(result),"ma",1);
4759                 aopPut(AOP(result),"ma",0);
4760         } else {
4761                 emitcode("push","ma");
4762                 emitcode("push","ma");
4763                 emitcode("push","ma");
4764                 MOVA("ma");
4765                 /* negate result if needed */
4766                 lbl = newiTempLabel(NULL);      
4767                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4768                 emitcode("cpl","a");
4769                 emitcode("add","a,#1");
4770                 emitcode("","!tlabeldef", lbl->key+100);
4771                 if (AOP_TYPE(result) == AOP_ACC)
4772                 {
4773                     D(emitcode(";", "ACC special case."););
4774                     /* We know result is the only live aop, and 
4775                      * it's obviously not a DPTR2, so AP is available.
4776                      */
4777                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4778                 }
4779                 else
4780                 {
4781                     aopPut(AOP(result),"a",0);
4782                 }
4783             
4784                 emitcode("pop","acc");
4785                 lbl = newiTempLabel(NULL);      
4786                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4787                 emitcode("cpl","a");
4788                 emitcode("addc","a,#0");
4789                 emitcode("","!tlabeldef", lbl->key+100);
4790                 aopPut(AOP(result),"a",1);
4791                 emitcode("pop","acc");
4792                 if (AOP_SIZE(result) >= 3) {
4793                         lbl = newiTempLabel(NULL);      
4794                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4795                         emitcode("cpl","a");
4796                         emitcode("addc","a,#0");                        
4797                         emitcode("","!tlabeldef", lbl->key+100);
4798                         aopPut(AOP(result),"a",2);
4799                 }
4800                 emitcode("pop","acc");
4801                 if (AOP_SIZE(result) >= 4) {
4802                         lbl = newiTempLabel(NULL);      
4803                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4804                         emitcode("cpl","a");
4805                         emitcode("addc","a,#0");                        
4806                         emitcode("","!tlabeldef", lbl->key+100);
4807                         aopPut(AOP(result),"a",3);
4808                 }
4809                 if (AOP_TYPE(result) == AOP_ACC)
4810                 {
4811                     /* We stashed the result away above. */
4812                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4813                 }           
4814                 
4815         }
4816         freeAsmop (result, NULL, ic, TRUE);
4817
4818         /* restore EA bit in F1 */
4819         lbl = newiTempLabel(NULL);
4820         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4821         emitcode ("setb","EA");
4822         emitcode("","!tlabeldef",lbl->key+100);
4823         return ;
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* genMult - generates code for multiplication                     */
4828 /*-----------------------------------------------------------------*/
4829 static void
4830 genMult (iCode * ic)
4831 {
4832   operand *left = IC_LEFT (ic);
4833   operand *right = IC_RIGHT (ic);
4834   operand *result = IC_RESULT (ic);
4835
4836   D (emitcode (";", "genMult "););
4837
4838   /* assign the amsops */
4839   AOP_OP_2 (ic);
4840
4841   /* special cases first */
4842   /* both are bits */
4843   if (AOP_TYPE (left) == AOP_CRY &&
4844       AOP_TYPE (right) == AOP_CRY)
4845     {
4846       genMultbits (left, right, result, ic);
4847       goto release;
4848     }
4849
4850   /* if both are of size == 1 */
4851   if (AOP_SIZE (left) == 1 &&
4852       AOP_SIZE (right) == 1)
4853     {
4854       genMultOneByte (left, right, result, ic);
4855       goto release;
4856     }
4857
4858   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4859           /* use the ds390 ARITHMETIC accel UNIT */
4860           genMultTwoByte (left, right, result, ic);
4861           return ;
4862   }
4863   /* should have been converted to function call */
4864   assert (0);
4865
4866 release:
4867   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4868   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869   freeAsmop (result, NULL, ic, TRUE);
4870 }
4871
4872 /*-----------------------------------------------------------------*/
4873 /* genDivbits :- division of bits                                  */
4874 /*-----------------------------------------------------------------*/
4875 static void
4876 genDivbits (operand * left,
4877             operand * right,
4878             operand * result,
4879             iCode   * ic)
4880 {
4881
4882   char *l;
4883
4884   /* the result must be bit */
4885   LOAD_AB_FOR_DIV (left, right, l);
4886   emitcode ("div", "ab");
4887   emitcode ("rrc", "a");
4888   aopOp(result, ic, TRUE, FALSE);
4889     
4890   aopPut (AOP (result), "c", 0);
4891 }
4892
4893 /*-----------------------------------------------------------------*/
4894 /* genDivOneByte : 8 bit division                                  */
4895 /*-----------------------------------------------------------------*/
4896 static void
4897 genDivOneByte (operand * left,
4898                operand * right,
4899                operand * result,
4900                iCode   * ic)
4901 {
4902   sym_link *opetype = operandType (result);
4903   char *l;
4904   symbol *lbl;
4905   int size, offset;
4906
4907   offset = 1;
4908   /* signed or unsigned */
4909   if (SPEC_USIGN (opetype))
4910     {
4911         /* unsigned is easy */
4912         LOAD_AB_FOR_DIV (left, right, l);
4913         emitcode ("div", "ab");
4914
4915         _G.accInUse++;
4916         aopOp(result, ic, TRUE, FALSE);
4917         aopPut (AOP (result), "a", 0);
4918         _G.accInUse--;
4919
4920         size = AOP_SIZE (result) - 1;
4921         
4922         while (size--)
4923         {
4924             aopPut (AOP (result), zero, offset++);
4925         }
4926       return;
4927     }
4928
4929   /* signed is a little bit more difficult */
4930
4931   /* save the signs of the operands */
4932   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4933   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4934   emitcode ("push", "acc");     /* save it on the stack */
4935
4936   /* now sign adjust for both left & right */
4937   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4938   lbl = newiTempLabel (NULL);
4939   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4940   emitcode ("cpl", "a");
4941   emitcode ("inc", "a");
4942   emitcode ("", "!tlabeldef", (lbl->key + 100));
4943   emitcode ("mov", "b,a");
4944
4945   /* sign adjust left side */
4946   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4947
4948   lbl = newiTempLabel (NULL);
4949   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4950   emitcode ("cpl", "a");
4951   emitcode ("inc", "a");
4952   emitcode ("", "!tlabeldef", (lbl->key + 100));
4953
4954   /* now the division */
4955   emitcode ("nop", "; workaround for DS80C390 div bug.");
4956   emitcode ("div", "ab");
4957   /* we are interested in the lower order
4958      only */
4959   emitcode ("mov", "b,a");
4960   lbl = newiTempLabel (NULL);
4961   emitcode ("pop", "acc");
4962   /* if there was an over flow we don't
4963      adjust the sign of the result */
4964   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4965   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4966   CLRC;
4967   emitcode ("clr", "a");
4968   emitcode ("subb", "a,b");
4969   emitcode ("mov", "b,a");
4970   emitcode ("", "!tlabeldef", (lbl->key + 100));
4971
4972   /* now we are done */
4973   _G.accInUse++;     _G.bInUse++;
4974     aopOp(result, ic, TRUE, FALSE);
4975     
4976     aopPut (AOP (result), "b", 0);
4977     
4978     size = AOP_SIZE (result) - 1;
4979     
4980     if (size > 0)
4981     {
4982       emitcode ("mov", "c,b.7");
4983       emitcode ("subb", "a,acc");
4984     }
4985     while (size--)
4986     {
4987         aopPut (AOP (result), "a", offset++);
4988     }
4989     _G.accInUse--;     _G.bInUse--;
4990
4991 }
4992
4993 /*-----------------------------------------------------------------*/
4994 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4995 /*-----------------------------------------------------------------*/
4996 static void genDivTwoByte (operand *left, operand *right, 
4997                             operand *result, iCode *ic)
4998 {
4999         sym_link *retype = getSpec(operandType(right));
5000         sym_link *letype = getSpec(operandType(left));
5001         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5002         symbol *lbl;
5003
5004         /* save EA bit in F1 */
5005         lbl = newiTempLabel(NULL);
5006         emitcode ("setb","F1");
5007         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5008         emitcode ("clr","F1");
5009         emitcode("","!tlabeldef",lbl->key+100);
5010
5011         /* load up MA with left */
5012         if (!umult) {
5013                 emitcode("clr","F0");
5014                 lbl = newiTempLabel(NULL);
5015                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5016                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5017                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5018                 emitcode ("xch", "a,b");
5019                 emitcode ("cpl","a");
5020                 emitcode ("add", "a,#1");
5021                 emitcode ("xch", "a,b");
5022                 emitcode ("cpl", "a"); // msb
5023                 emitcode ("addc","a,#0");
5024                 emitcode ("setb","F0");
5025                 emitcode ("","!tlabeldef",lbl->key+100);
5026                 emitcode ("mov","ma,b");
5027                 emitcode ("mov","ma,a");
5028         } else {
5029                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5030                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5031         }
5032
5033         /* load up MB with right */
5034         if (!umult) {
5035                 if (AOP_TYPE(right) == AOP_LIT) {
5036                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5037                         if (val < 0) {
5038                                 lbl = newiTempLabel(NULL);
5039                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5040                                 emitcode("setb","F0");
5041                                 emitcode ("","!tlabeldef",lbl->key+100);
5042                                 val = -val;
5043                         } 
5044                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5045                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5046                 } else {
5047                         lbl = newiTempLabel(NULL);
5048                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5049                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5050                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5051                         emitcode ("xch", "a,b");
5052                         emitcode ("cpl","a");
5053                         emitcode ("add", "a,#1");
5054                         emitcode ("xch", "a,b");
5055                         emitcode ("cpl", "a"); // msb
5056                         emitcode ("addc", "a,#0");
5057                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058                         emitcode ("setb","F0");
5059                         emitcode ("","!tlabeldef",lbl->key+100);
5060                         emitcode ("mov","mb,b");
5061                         emitcode ("mov","mb,a");
5062                 }
5063         } else {
5064                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5065                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5066         }
5067
5068         /* wait for multiplication to finish */
5069         lbl = newiTempLabel(NULL);
5070         emitcode("","!tlabeldef", lbl->key+100);
5071         emitcode("mov","a,mcnt1");
5072         emitcode("anl","a,#!constbyte",0x80);
5073         emitcode("jnz","!tlabel",lbl->key+100);
5074         
5075         freeAsmop (left, NULL, ic, TRUE);
5076         freeAsmop (right, NULL, ic,TRUE);
5077         aopOp(result, ic, TRUE, FALSE);
5078
5079         /* if unsigned then simple */   
5080         if (umult) {
5081                 aopPut(AOP(result),"ma",1);
5082                 aopPut(AOP(result),"ma",0);
5083         } else {
5084                 emitcode("push","ma");
5085                 MOVA("ma");
5086                 /* negate result if needed */
5087                 lbl = newiTempLabel(NULL);      
5088                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5089                 emitcode("cpl","a");
5090                 emitcode("add","a,#1");
5091                 emitcode("","!tlabeldef", lbl->key+100);
5092                 aopPut(AOP(result),"a",0);
5093                 emitcode("pop","acc");
5094                 lbl = newiTempLabel(NULL);      
5095                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5096                 emitcode("cpl","a");
5097                 emitcode("addc","a,#0");
5098                 emitcode("","!tlabeldef", lbl->key+100);
5099                 aopPut(AOP(result),"a",1);
5100         }
5101         freeAsmop (result, NULL, ic, TRUE);
5102         /* restore EA bit in F1 */
5103         lbl = newiTempLabel(NULL);
5104         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5105         emitcode ("setb","EA");
5106         emitcode("","!tlabeldef",lbl->key+100);
5107         return ;
5108 }
5109
5110 /*-----------------------------------------------------------------*/
5111 /* genDiv - generates code for division                            */
5112 /*-----------------------------------------------------------------*/
5113 static void
5114 genDiv (iCode * ic)
5115 {
5116   operand *left = IC_LEFT (ic);
5117   operand *right = IC_RIGHT (ic);
5118   operand *result = IC_RESULT (ic);
5119
5120   D (emitcode (";", "genDiv "););
5121
5122   /* assign the amsops */
5123   AOP_OP_2 (ic);
5124
5125   /* special cases first */
5126   /* both are bits */
5127   if (AOP_TYPE (left) == AOP_CRY &&
5128       AOP_TYPE (right) == AOP_CRY)
5129     {
5130       genDivbits (left, right, result, ic);
5131       goto release;
5132     }
5133
5134   /* if both are of size == 1 */
5135   if (AOP_SIZE (left) == 1 &&
5136       AOP_SIZE (right) == 1)
5137     {
5138       genDivOneByte (left, right, result, ic);
5139       goto release;
5140     }
5141
5142   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5143           /* use the ds390 ARITHMETIC accel UNIT */
5144           genDivTwoByte (left, right, result, ic);
5145           return ;
5146   }
5147   /* should have been converted to function call */
5148   assert (0);
5149 release:
5150   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152   freeAsmop (result, NULL, ic, TRUE);
5153 }
5154
5155 /*-----------------------------------------------------------------*/
5156 /* genModbits :- modulus of bits                                   */
5157 /*-----------------------------------------------------------------*/
5158 static void
5159 genModbits (operand * left,
5160             operand * right,
5161             operand * result,
5162             iCode   * ic)
5163 {
5164
5165   char *l;
5166
5167   /* the result must be bit */
5168   LOAD_AB_FOR_DIV (left, right, l);
5169   emitcode ("div", "ab");
5170   emitcode ("mov", "a,b");
5171   emitcode ("rrc", "a");
5172   aopOp(result, ic, TRUE, FALSE);
5173   aopPut (AOP (result), "c", 0);
5174 }
5175
5176 /*-----------------------------------------------------------------*/
5177 /* genModOneByte : 8 bit modulus                                   */
5178 /*-----------------------------------------------------------------*/
5179 static void
5180 genModOneByte (operand * left,
5181                operand * right,
5182                operand * result,
5183                iCode   * ic)
5184 {
5185   sym_link *opetype = operandType (result);
5186   char *l;
5187   symbol *lbl;
5188
5189   /* signed or unsigned */
5190   if (SPEC_USIGN (opetype))
5191     {
5192       /* unsigned is easy */
5193       LOAD_AB_FOR_DIV (left, right, l);
5194       emitcode ("div", "ab");
5195       aopOp(result, ic, TRUE, FALSE);   
5196       aopPut (AOP (result), "b", 0);
5197       return;
5198     }
5199
5200   /* signed is a little bit more difficult */
5201
5202   /* save the signs of the operands */
5203   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5204
5205   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5206   emitcode ("push", "acc");     /* save it on the stack */
5207
5208   /* now sign adjust for both left & right */
5209   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5210
5211   lbl = newiTempLabel (NULL);
5212   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5213   emitcode ("cpl", "a");
5214   emitcode ("inc", "a");
5215   emitcode ("", "!tlabeldef", (lbl->key + 100));
5216   emitcode ("mov", "b,a");
5217
5218   /* sign adjust left side */
5219   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5220
5221   lbl = newiTempLabel (NULL);
5222   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5223   emitcode ("cpl", "a");
5224   emitcode ("inc", "a");
5225   emitcode ("", "!tlabeldef", (lbl->key + 100));
5226
5227   /* now the multiplication */
5228   emitcode ("nop", "; workaround for DS80C390 div bug.");
5229   emitcode ("div", "ab");
5230   /* we are interested in the lower order
5231      only */
5232   lbl = newiTempLabel (NULL);
5233   emitcode ("pop", "acc");
5234   /* if there was an over flow we don't
5235      adjust the sign of the result */
5236   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5237   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5238   CLRC;
5239   emitcode ("clr", "a");
5240   emitcode ("subb", "a,b");
5241   emitcode ("mov", "b,a");
5242   emitcode ("", "!tlabeldef", (lbl->key + 100));
5243   
5244   _G.bInUse++;
5245   /* now we are done */
5246   aopOp(result, ic, TRUE, FALSE);    
5247   aopPut (AOP (result), "b", 0);
5248   _G.bInUse--;
5249
5250 }
5251
5252 /*-----------------------------------------------------------------*/
5253 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5254 /*-----------------------------------------------------------------*/
5255 static void genModTwoByte (operand *left, operand *right, 
5256                             operand *result, iCode *ic)
5257 {
5258         sym_link *retype = getSpec(operandType(right));
5259         sym_link *letype = getSpec(operandType(left));
5260         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5261         symbol *lbl;
5262
5263         /* load up MA with left */
5264         /* save EA bit in F1 */
5265         lbl = newiTempLabel(NULL);
5266         emitcode ("setb","F1");
5267         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5268         emitcode ("clr","F1");
5269         emitcode("","!tlabeldef",lbl->key+100);
5270
5271         if (!umult) {
5272                 lbl = newiTempLabel(NULL);
5273                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5274                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5275                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5276                 emitcode ("xch", "a,b");
5277                 emitcode ("cpl","a");
5278                 emitcode ("add", "a,#1");
5279                 emitcode ("xch", "a,b");
5280                 emitcode ("cpl", "a"); // msb
5281                 emitcode ("addc","a,#0");
5282                 emitcode ("","!tlabeldef",lbl->key+100);
5283                 emitcode ("mov","ma,b");
5284                 emitcode ("mov","ma,a");
5285         } else {
5286                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5287                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5288         }
5289
5290         /* load up MB with right */
5291         if (!umult) {
5292                 if (AOP_TYPE(right) == AOP_LIT) {
5293                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5294                         if (val < 0) {
5295                                 val = -val;
5296                         } 
5297                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5298                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5299                 } else {
5300                         lbl = newiTempLabel(NULL);
5301                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5302                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5303                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5304                         emitcode ("xch", "a,b");
5305                         emitcode ("cpl","a");
5306                         emitcode ("add", "a,#1");
5307                         emitcode ("xch", "a,b");
5308                         emitcode ("cpl", "a"); // msb
5309                         emitcode ("addc", "a,#0");
5310                         emitcode ("","!tlabeldef",lbl->key+100);
5311                         emitcode ("mov","mb,b");
5312                         emitcode ("mov","mb,a");
5313                 }
5314         } else {
5315                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5316                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5317         }
5318
5319         /* wait for multiplication to finish */
5320         lbl = newiTempLabel(NULL);
5321         emitcode("","!tlabeldef", lbl->key+100);
5322         emitcode("mov","a,mcnt1");
5323         emitcode("anl","a,#!constbyte",0x80);
5324         emitcode("jnz","!tlabel",lbl->key+100);
5325         
5326         freeAsmop (left, NULL, ic, TRUE);
5327         freeAsmop (right, NULL, ic,TRUE);
5328         aopOp(result, ic, TRUE, FALSE);
5329
5330         aopPut(AOP(result),"mb",1);
5331         aopPut(AOP(result),"mb",0);
5332         freeAsmop (result, NULL, ic, TRUE);
5333
5334         /* restore EA bit in F1 */
5335         lbl = newiTempLabel(NULL);
5336         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5337         emitcode ("setb","EA");
5338         emitcode("","!tlabeldef",lbl->key+100);
5339         return ;
5340 }
5341
5342 /*-----------------------------------------------------------------*/
5343 /* genMod - generates code for division                            */
5344 /*-----------------------------------------------------------------*/
5345 static void
5346 genMod (iCode * ic)
5347 {
5348   operand *left = IC_LEFT (ic);
5349   operand *right = IC_RIGHT (ic);
5350   operand *result = IC_RESULT (ic);
5351
5352   D (emitcode (";", "genMod "); );
5353
5354   /* assign the amsops */
5355   AOP_OP_2 (ic);
5356
5357   /* special cases first */
5358   /* both are bits */
5359   if (AOP_TYPE (left) == AOP_CRY &&
5360       AOP_TYPE (right) == AOP_CRY)
5361     {
5362       genModbits (left, right, result, ic);
5363       goto release;
5364     }
5365
5366   /* if both are of size == 1 */
5367   if (AOP_SIZE (left) == 1 &&
5368       AOP_SIZE (right) == 1)
5369     {
5370       genModOneByte (left, right, result, ic);
5371       goto release;
5372     }
5373
5374   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5375           /* use the ds390 ARITHMETIC accel UNIT */
5376           genModTwoByte (left, right, result, ic);
5377           return ;
5378   }
5379
5380   /* should have been converted to function call */
5381   assert (0);
5382
5383 release:
5384   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5385   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5386   freeAsmop (result, NULL, ic, TRUE);
5387 }
5388
5389 /*-----------------------------------------------------------------*/
5390 /* genIfxJump :- will create a jump depending on the ifx           */
5391 /*-----------------------------------------------------------------*/
5392 static void
5393 genIfxJump (iCode * ic, char *jval)
5394 {
5395   symbol *jlbl;
5396   symbol *tlbl = newiTempLabel (NULL);
5397   char *inst;
5398
5399   D (emitcode (";", "genIfxJump"););
5400
5401   /* if true label then we jump if condition
5402      supplied is true */
5403   if (IC_TRUE (ic))
5404     {
5405       jlbl = IC_TRUE (ic);
5406       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5407                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5408     }
5409   else
5410     {
5411       /* false label is present */
5412       jlbl = IC_FALSE (ic);
5413       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5414                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5415     }
5416   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5417     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5418   else
5419     emitcode (inst, "!tlabel", tlbl->key + 100);
5420   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5421   emitcode ("", "!tlabeldef", tlbl->key + 100);
5422
5423   /* mark the icode as generated */
5424   ic->generated = 1;
5425 }
5426
5427 /*-----------------------------------------------------------------*/
5428 /* genCmp :- greater or less than comparison                       */
5429 /*-----------------------------------------------------------------*/
5430 static void
5431 genCmp (operand * left, operand * right,
5432         iCode * ic, iCode * ifx, int sign)
5433 {
5434   int size, offset = 0;
5435   unsigned long lit = 0L;
5436   operand *result;
5437
5438   D (emitcode (";", "genCmp"););
5439
5440   result = IC_RESULT (ic);
5441
5442   /* if left & right are bit variables */
5443   if (AOP_TYPE (left) == AOP_CRY &&
5444       AOP_TYPE (right) == AOP_CRY)
5445     {
5446       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5447       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5448     }
5449   else
5450     {
5451       /* subtract right from left if at the
5452          end the carry flag is set then we know that
5453          left is greater than right */
5454       size = max (AOP_SIZE (left), AOP_SIZE (right));
5455
5456       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5457       if ((size == 1) && !sign 
5458           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5459         {
5460           symbol *lbl = newiTempLabel (NULL);
5461           emitcode ("cjne", "%s,%s,!tlabel",
5462                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5463                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5464                     lbl->key + 100);
5465           emitcode ("", "!tlabeldef", lbl->key + 100);
5466         }
5467       else
5468         {
5469           if (AOP_TYPE (right) == AOP_LIT)
5470             {
5471               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5472               /* optimize if(x < 0) or if(x >= 0) */
5473               if (lit == 0L)
5474                 {
5475                   if (!sign)
5476                     {
5477                       CLRC;
5478                     }
5479                   else
5480                     {
5481                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5482
5483                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5484                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5485
5486                       aopOp (result, ic, FALSE, FALSE);
5487
5488                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5489                         {
5490                           freeAsmop (result, NULL, ic, TRUE);
5491                           genIfxJump (ifx, "acc.7");
5492                           return;
5493                         }
5494                       else
5495                         {
5496                           emitcode ("rlc", "a");
5497                         }
5498                       goto release_freedLR;
5499                     }
5500                   goto release;
5501                 }
5502             }
5503           CLRC;
5504           while (size--)
5505             {
5506               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5507               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5508               // emitcode (";", "genCmp #2");
5509               if (sign && (size == 0))
5510                 {
5511                   // emitcode (";", "genCmp #3");
5512                   emitcode ("xrl", "a,#!constbyte",0x80);
5513                   if (AOP_TYPE (right) == AOP_LIT)
5514                     {
5515                       unsigned long lit = (unsigned long)
5516                       floatFromVal (AOP (right)->aopu.aop_lit);
5517                       // emitcode (";", "genCmp #3.1");
5518                       emitcode ("subb", "a,#!constbyte",
5519                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5520                     }
5521                   else
5522                     {
5523                       // emitcode (";", "genCmp #3.2");
5524                       saveAccWarn = 0;  
5525                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5526                       saveAccWarn = DEFAULT_ACC_WARNING;
5527                       emitcode ("xrl", "b,#!constbyte",0x80);
5528                       emitcode ("subb", "a,b");
5529                     }
5530                 }
5531               else
5532                 {
5533                   const char *s;
5534
5535                   // emitcode (";", "genCmp #4");
5536                   saveAccWarn = 0;
5537                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5538                   saveAccWarn = DEFAULT_ACC_WARNING;
5539
5540                   emitcode ("subb", "a,%s", s);
5541                 }
5542             }
5543         }
5544     }
5545
5546 release:
5547 /* Don't need the left & right operands any more; do need the result. */
5548   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5550
5551   aopOp (result, ic, FALSE, FALSE);
5552
5553 release_freedLR:
5554
5555   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5556     {
5557       outBitC (result);
5558     }
5559   else
5560     {
5561       /* if the result is used in the next
5562          ifx conditional branch then generate
5563          code a little differently */
5564       if (ifx)
5565         {
5566           genIfxJump (ifx, "c");
5567         }
5568       else
5569         {
5570           outBitC (result);
5571         }
5572       /* leave the result in acc */
5573     }
5574   freeAsmop (result, NULL, ic, TRUE);
5575 }
5576
5577 /*-----------------------------------------------------------------*/
5578 /* genCmpGt :- greater than comparison                             */
5579 /*-----------------------------------------------------------------*/
5580 static void
5581 genCmpGt (iCode * ic, iCode * ifx)
5582 {
5583   operand *left, *right;
5584   sym_link *letype, *retype;
5585   int sign;
5586
5587   D (emitcode (";", "genCmpGt ");
5588     );
5589
5590   left = IC_LEFT (ic);
5591   right = IC_RIGHT (ic);
5592
5593   letype = getSpec (operandType (left));
5594   retype = getSpec (operandType (right));
5595   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5596
5597   /* assign the left & right amsops */
5598   AOP_OP_2 (ic);
5599
5600   genCmp (right, left, ic, ifx, sign);
5601 }
5602
5603 /*-----------------------------------------------------------------*/
5604 /* genCmpLt - less than comparisons                                */
5605 /*-----------------------------------------------------------------*/
5606 static void
5607 genCmpLt (iCode * ic, iCode * ifx)
5608 {
5609   operand *left, *right;
5610   sym_link *letype, *retype;
5611   int sign;
5612
5613   D (emitcode (";", "genCmpLt "););
5614
5615   left = IC_LEFT (ic);
5616   right = IC_RIGHT (ic);
5617
5618   letype = getSpec (operandType (left));
5619   retype = getSpec (operandType (right));
5620   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5621
5622   /* assign the left & right amsops */
5623   AOP_OP_2 (ic);
5624
5625   genCmp (left, right, ic, ifx, sign);
5626 }
5627
5628 /*-----------------------------------------------------------------*/
5629 /* gencjneshort - compare and jump if not equal                    */
5630 /*-----------------------------------------------------------------*/
5631 static void
5632 gencjneshort (operand * left, operand * right, symbol * lbl)
5633 {
5634   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5635   int offset = 0;
5636   unsigned long lit = 0L;
5637
5638   D (emitcode (";", "gencjneshort");
5639     );
5640
5641   /* if the left side is a literal or
5642      if the right is in a pointer register and left
5643      is not */
5644   if ((AOP_TYPE (left) == AOP_LIT) ||
5645       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5646     {
5647       operand *t = right;
5648       right = left;
5649       left = t;
5650     }
5651
5652   if (AOP_TYPE (right) == AOP_LIT)
5653     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5654
5655   if (opIsGptr (left) || opIsGptr (right))
5656     {
5657       /* We are comparing a generic pointer to something.
5658        * Exclude the generic type byte from the comparison.
5659        */
5660       size--;
5661       D (emitcode (";", "cjneshort: generic ptr special case."););
5662     }
5663
5664
5665   /* if the right side is a literal then anything goes */
5666   if (AOP_TYPE (right) == AOP_LIT &&
5667       AOP_TYPE (left) != AOP_DIR)
5668     {
5669       while (size--)
5670         {
5671           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5672           emitcode ("cjne", "a,%s,!tlabel",
5673                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5674                     lbl->key + 100);
5675           offset++;
5676         }
5677     }
5678
5679   /* if the right side is in a register or in direct space or
5680      if the left is a pointer register & right is not */
5681   else if (AOP_TYPE (right) == AOP_REG ||
5682            AOP_TYPE (right) == AOP_DIR ||
5683            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5684            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5685     {
5686       while (size--)
5687         {
5688           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5689           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5690               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5691             emitcode ("jnz", "!tlabel", lbl->key + 100);
5692           else
5693             emitcode ("cjne", "a,%s,!tlabel",
5694                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5695                       lbl->key + 100);
5696           offset++;
5697         }
5698     }
5699   else
5700     {
5701       /* right is a pointer reg need both a & b */
5702       while (size--)
5703         {
5704           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5705           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5706           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5707           offset++;
5708         }
5709     }
5710 }
5711
5712 /*-----------------------------------------------------------------*/
5713 /* gencjne - compare and jump if not equal                         */
5714 /*-----------------------------------------------------------------*/
5715 static void
5716 gencjne (operand * left, operand * right, symbol * lbl)
5717 {
5718   symbol *tlbl = newiTempLabel (NULL);
5719
5720   D (emitcode (";", "gencjne");
5721     );
5722
5723   gencjneshort (left, right, lbl);
5724
5725   emitcode ("mov", "a,%s", one);
5726   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5727   emitcode ("", "!tlabeldef", lbl->key + 100);
5728   emitcode ("clr", "a");
5729   emitcode ("", "!tlabeldef", tlbl->key + 100);
5730 }
5731
5732 /*-----------------------------------------------------------------*/
5733 /* genCmpEq - generates code for equal to                          */
5734 /*-----------------------------------------------------------------*/
5735 static void
5736 genCmpEq (iCode * ic, iCode * ifx)
5737 {
5738   operand *left, *right, *result;
5739
5740   D (emitcode (";", "genCmpEq ");
5741     );
5742
5743   AOP_OP_2 (ic);
5744   AOP_SET_LOCALS (ic);
5745
5746   /* if literal, literal on the right or
5747      if the right is in a pointer register and left
5748      is not */
5749   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5750       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5751     {
5752       operand *t = IC_RIGHT (ic);
5753       IC_RIGHT (ic) = IC_LEFT (ic);
5754       IC_LEFT (ic) = t;
5755     }
5756
5757   if (ifx &&                    /* !AOP_SIZE(result) */
5758       OP_SYMBOL (result) &&
5759       OP_SYMBOL (result)->regType == REG_CND)
5760     {
5761       symbol *tlbl;
5762       /* if they are both bit variables */
5763       if (AOP_TYPE (left) == AOP_CRY &&
5764           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5765         {
5766           if (AOP_TYPE (right) == AOP_LIT)
5767             {
5768               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5769               if (lit == 0L)
5770                 {
5771                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5772                   emitcode ("cpl", "c");
5773                 }
5774               else if (lit == 1L)
5775                 {
5776                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5777                 }
5778               else
5779                 {
5780                   emitcode ("clr", "c");
5781                 }
5782               /* AOP_TYPE(right) == AOP_CRY */
5783             }
5784           else
5785             {
5786               symbol *lbl = newiTempLabel (NULL);
5787               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5788               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5789               emitcode ("cpl", "c");
5790               emitcode ("", "!tlabeldef", (lbl->key + 100));
5791             }
5792           /* if true label then we jump if condition
5793              supplied is true */
5794           tlbl = newiTempLabel (NULL);
5795           if (IC_TRUE (ifx))
5796             {
5797               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5798               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5799             }
5800           else
5801             {
5802               emitcode ("jc", "!tlabel", tlbl->key + 100);
5803               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5804             }
5805           emitcode ("", "!tlabeldef", tlbl->key + 100);
5806         }
5807       else
5808         {
5809           tlbl = newiTempLabel (NULL);
5810           gencjneshort (left, right, tlbl);
5811           if (IC_TRUE (ifx))
5812             {
5813               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5814               emitcode ("", "!tlabeldef", tlbl->key + 100);
5815             }
5816           else
5817             {
5818               symbol *lbl = newiTempLabel (NULL);
5819               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5820               emitcode ("", "!tlabeldef", tlbl->key + 100);
5821               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5822               emitcode ("", "!tlabeldef", lbl->key + 100);
5823             }
5824         }
5825       /* mark the icode as generated */
5826       ifx->generated = 1;
5827
5828       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5829       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5830       return;
5831     }
5832
5833   /* if they are both bit variables */
5834   if (AOP_TYPE (left) == AOP_CRY &&
5835       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5836     {
5837       if (AOP_TYPE (right) == AOP_LIT)
5838         {
5839           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5840           if (lit == 0L)
5841             {
5842               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5843               emitcode ("cpl", "c");
5844             }
5845           else if (lit == 1L)
5846             {
5847               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5848             }
5849           else
5850             {
5851               emitcode ("clr", "c");
5852             }
5853           /* AOP_TYPE(right) == AOP_CRY */
5854         }
5855       else
5856         {
5857           symbol *lbl = newiTempLabel (NULL);
5858           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5859           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5860           emitcode ("cpl", "c");
5861           emitcode ("", "!tlabeldef", (lbl->key + 100));
5862         }
5863
5864       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5865       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866
5867       aopOp (result, ic, TRUE, FALSE);
5868
5869       /* c = 1 if egal */
5870       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5871         {
5872           outBitC (result);
5873           goto release;
5874         }
5875       if (ifx)
5876         {
5877           genIfxJump (ifx, "c");
5878           goto release;
5879         }
5880       /* if the result is used in an arithmetic operation
5881          then put the result in place */
5882       outBitC (result);
5883     }
5884   else
5885     {
5886       gencjne (left, right, newiTempLabel (NULL));
5887
5888       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5889       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5890
5891       aopOp (result, ic, TRUE, FALSE);
5892
5893       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5894         {
5895           aopPut (AOP (result), "a", 0);
5896           goto release;
5897         }
5898       if (ifx)
5899         {
5900           genIfxJump (ifx, "a");
5901           goto release;
5902         }
5903       /* if the result is used in an arithmetic operation
5904          then put the result in place */
5905       if (AOP_TYPE (result) != AOP_CRY)
5906         outAcc (result);
5907       /* leave the result in acc */
5908     }
5909
5910 release:
5911   freeAsmop (result, NULL, ic, TRUE);
5912 }
5913
5914 /*-----------------------------------------------------------------*/
5915 /* ifxForOp - returns the icode containing the ifx for operand     */
5916 /*-----------------------------------------------------------------*/
5917 static iCode *
5918 ifxForOp (operand * op, iCode * ic)
5919 {
5920   /* if true symbol then needs to be assigned */
5921   if (IS_TRUE_SYMOP (op))
5922     return NULL;
5923
5924   /* if this has register type condition and
5925      the next instruction is ifx with the same operand
5926      and live to of the operand is upto the ifx only then */
5927   if (ic->next &&
5928       ic->next->op == IFX &&
5929       IC_COND (ic->next)->key == op->key &&
5930       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5931     return ic->next;
5932
5933   return NULL;
5934 }
5935 /*-----------------------------------------------------------------*/
5936 /* hasInc - operand is incremented before any other use            */
5937 /*-----------------------------------------------------------------*/
5938 static iCode *
5939 hasInc (operand *op, iCode *ic, int osize)
5940 {
5941   sym_link *type = operandType(op);
5942   sym_link *retype = getSpec (type);
5943   iCode *lic = ic->next;
5944   int isize ;
5945   
5946   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5947   if (!IS_SYMOP(op)) return NULL;
5948
5949   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5950   if (IS_AGGREGATE(type->next)) return NULL;
5951   if (osize != (isize = getSize(type->next))) return NULL;
5952
5953   while (lic) {
5954       /* if operand of the form op = op + <sizeof *op> */
5955       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5956           isOperandEqual(IC_RESULT(lic),op) && 
5957           isOperandLiteral(IC_RIGHT(lic)) &&
5958           operandLitValue(IC_RIGHT(lic)) == isize) {
5959           return lic;
5960       }
5961       /* if the operand used or deffed */
5962       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5963           return NULL;
5964       }
5965       /* if GOTO or IFX */
5966       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5967       lic = lic->next;
5968   }
5969   return NULL;
5970 }
5971
5972 /*-----------------------------------------------------------------*/
5973 /* genAndOp - for && operation                                     */
5974 /*-----------------------------------------------------------------*/
5975 static void
5976 genAndOp (iCode * ic)
5977 {
5978   operand *left, *right, *result;
5979   symbol *tlbl;
5980
5981   D (emitcode (";", "genAndOp "););
5982
5983   /* note here that && operations that are in an
5984      if statement are taken away by backPatchLabels
5985      only those used in arthmetic operations remain */
5986   AOP_OP_2 (ic);
5987   AOP_SET_LOCALS (ic);
5988
5989   /* if both are bit variables */
5990   if (AOP_TYPE (left) == AOP_CRY &&
5991       AOP_TYPE (right) == AOP_CRY)
5992     {
5993       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5994       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5995       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5997   
5998       aopOp (result,ic,FALSE, FALSE);
5999       outBitC (result);
6000     }
6001   else
6002     {
6003       tlbl = newiTempLabel (NULL);
6004       toBoolean (left);
6005       emitcode ("jz", "!tlabel", tlbl->key + 100);
6006       toBoolean (right);
6007       emitcode ("", "!tlabeldef", tlbl->key + 100);
6008       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6009       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6010   
6011       aopOp (result,ic,FALSE, FALSE);
6012       outBitAcc (result);
6013     }
6014     freeAsmop (result, NULL, ic, TRUE);
6015 }
6016
6017
6018 /*-----------------------------------------------------------------*/
6019 /* genOrOp - for || operation                                      */
6020 /*-----------------------------------------------------------------*/
6021 static void
6022 genOrOp (iCode * ic)
6023 {
6024   operand *left, *right, *result;
6025   symbol *tlbl;
6026
6027   D (emitcode (";", "genOrOp "););
6028
6029   /* note here that || operations that are in an
6030      if statement are taken away by backPatchLabels
6031      only those used in arthmetic operations remain */
6032   AOP_OP_2 (ic);
6033   AOP_SET_LOCALS (ic);
6034
6035   /* if both are bit variables */
6036   if (AOP_TYPE (left) == AOP_CRY &&
6037       AOP_TYPE (right) == AOP_CRY)
6038     {
6039       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6040       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6041       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6042       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6043   
6044       aopOp (result,ic,FALSE, FALSE);
6045       
6046       outBitC (result);
6047     }
6048   else
6049     {
6050       tlbl = newiTempLabel (NULL);
6051       toBoolean (left);
6052       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6053       toBoolean (right);
6054       emitcode ("", "!tlabeldef", tlbl->key + 100);
6055       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6056       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6057   
6058       aopOp (result,ic,FALSE, FALSE);
6059       
6060       outBitAcc (result);
6061     }
6062
6063   freeAsmop (result, NULL, ic, TRUE);
6064 }
6065
6066 /*-----------------------------------------------------------------*/
6067 /* isLiteralBit - test if lit == 2^n                               */
6068 /*-----------------------------------------------------------------*/
6069 static int
6070 isLiteralBit (unsigned long lit)
6071 {
6072   unsigned long pw[32] =
6073   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6074    0x100L, 0x200L, 0x400L, 0x800L,
6075    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6076    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6077    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6078    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6079    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6080   int idx;
6081
6082   for (idx = 0; idx < 32; idx++)
6083     if (lit == pw[idx])
6084       return idx + 1;
6085   return 0;
6086 }
6087
6088 /*-----------------------------------------------------------------*/
6089 /* continueIfTrue -                                                */
6090 /*-----------------------------------------------------------------*/
6091 static void
6092 continueIfTrue (iCode * ic)
6093 {
6094   if (IC_TRUE (ic))
6095     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6096   ic->generated = 1;
6097 }
6098
6099 /*-----------------------------------------------------------------*/
6100 /* jmpIfTrue -                                                     */
6101 /*-----------------------------------------------------------------*/
6102 static void
6103 jumpIfTrue (iCode * ic)
6104 {
6105   if (!IC_TRUE (ic))
6106     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6107   ic->generated = 1;
6108 }
6109
6110 /*-----------------------------------------------------------------*/
6111 /* jmpTrueOrFalse -                                                */
6112 /*-----------------------------------------------------------------*/
6113 static void
6114 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6115 {
6116   // ugly but optimized by peephole
6117   if (IC_TRUE (ic))
6118     {
6119       symbol *nlbl = newiTempLabel (NULL);
6120       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6121       emitcode ("", "!tlabeldef", tlbl->key + 100);
6122       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6123       emitcode ("", "!tlabeldef", nlbl->key + 100);
6124     }
6125   else
6126     {
6127       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6128       emitcode ("", "!tlabeldef", tlbl->key + 100);
6129     }
6130   ic->generated = 1;
6131 }
6132
6133 // Generate code to perform a bit-wise logic operation
6134 // on two operands in far space (assumed to already have been 
6135 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6136 // in far space. This requires pushing the result on the stack
6137 // then popping it into the result.
6138 static void
6139 genFarFarLogicOp(iCode *ic, char *logicOp)
6140 {
6141       int size, resultSize, compSize;
6142       int offset = 0;
6143       
6144       TR_AP("#5");
6145       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6146       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6147                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6148       
6149       _startLazyDPSEvaluation();
6150       for (size = compSize; (size--); offset++)
6151       {
6152           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6153           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6154           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6155           
6156           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6157           emitcode ("push", "acc");
6158       }
6159       _endLazyDPSEvaluation();
6160      
6161       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6162       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6163       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6164      
6165       resultSize = AOP_SIZE(IC_RESULT(ic));
6166
6167       ADJUST_PUSHED_RESULT(compSize, resultSize);
6168
6169       _startLazyDPSEvaluation();
6170       while (compSize--)
6171       {
6172           emitcode ("pop", "acc");
6173           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6174       }
6175       _endLazyDPSEvaluation();
6176       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6177 }
6178
6179
6180 /*-----------------------------------------------------------------*/
6181 /* genAnd  - code for and                                          */
6182 /*-----------------------------------------------------------------*/
6183 static void
6184 genAnd (iCode * ic, iCode * ifx)
6185 {
6186   operand *left, *right, *result;
6187   int size, offset = 0;
6188   unsigned long lit = 0L;
6189   int bytelit;
6190   char buff[10];
6191   bool pushResult;
6192
6193   D (emitcode (";", "genAnd "););
6194
6195   AOP_OP_3_NOFATAL (ic, pushResult);
6196   AOP_SET_LOCALS (ic);
6197
6198   if (pushResult)
6199   {
6200       genFarFarLogicOp(ic, "anl");
6201       return;
6202   }  
6203
6204 #ifdef DEBUG_TYPE
6205   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6206             AOP_TYPE (result),
6207             AOP_TYPE (left), AOP_TYPE (right));
6208   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6209             AOP_SIZE (result),
6210             AOP_SIZE (left), AOP_SIZE (right));
6211 #endif
6212
6213   /* if left is a literal & right is not then exchange them */
6214   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6215 #ifdef LOGIC_OPS_BROKEN      
6216     ||  AOP_NEEDSACC (left)
6217 #endif
6218     )
6219     {
6220       operand *tmp = right;
6221       right = left;
6222       left = tmp;
6223     }
6224
6225   /* if result = right then exchange them */
6226   if (sameRegs (AOP (result), AOP (right)))
6227     {
6228       operand *tmp = right;
6229       right = left;
6230       left = tmp;
6231     }
6232
6233   /* if right is bit then exchange them */
6234   if (AOP_TYPE (right) == AOP_CRY &&
6235       AOP_TYPE (left) != AOP_CRY)
6236     {
6237       operand *tmp = right;
6238       right = left;
6239       left = tmp;
6240     }
6241   if (AOP_TYPE (right) == AOP_LIT)
6242     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6243
6244   size = AOP_SIZE (result);
6245
6246   // if(bit & yy)
6247   // result = bit & yy;
6248   if (AOP_TYPE (left) == AOP_CRY)
6249     {
6250       // c = bit & literal;
6251       if (AOP_TYPE (right) == AOP_LIT)
6252         {
6253           if (lit & 1)
6254             {
6255               if (size && sameRegs (AOP (result), AOP (left)))
6256                 // no change
6257                 goto release;
6258               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6259             }
6260           else
6261             {
6262               // bit(result) = 0;
6263               if (size && (AOP_TYPE (result) == AOP_CRY))
6264                 {
6265                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6266                   goto release;
6267                 }
6268               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6269                 {
6270                   jumpIfTrue (ifx);
6271                   goto release;
6272                 }
6273               emitcode ("clr", "c");
6274             }
6275         }
6276       else
6277         {
6278           if (AOP_TYPE (right) == AOP_CRY)
6279             {
6280               // c = bit & bit;
6281               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6282               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6283             }
6284           else
6285             {
6286               // c = bit & val;
6287               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6288               // c = lsb
6289               emitcode ("rrc", "a");
6290               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6291             }
6292         }
6293       // bit = c
6294       // val = c
6295       if (size)
6296         outBitC (result);
6297       // if(bit & ...)
6298       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6299         genIfxJump (ifx, "c");
6300       goto release;
6301     }
6302
6303   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6304   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6305   if ((AOP_TYPE (right) == AOP_LIT) &&
6306       (AOP_TYPE (result) == AOP_CRY) &&
6307       (AOP_TYPE (left) != AOP_CRY))
6308     {
6309       int posbit = isLiteralBit (lit);
6310       /* left &  2^n */
6311       if (posbit)
6312         {
6313           posbit--;
6314           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6315           // bit = left & 2^n
6316           if (size)
6317             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6318           // if(left &  2^n)
6319           else
6320             {
6321               if (ifx)
6322                 {
6323                   SNPRINTF (buff, sizeof(buff), 
6324                             "acc.%d", posbit & 0x07);
6325                   genIfxJump (ifx, buff);
6326                 }
6327               else 
6328                   {
6329                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6330                   }
6331               goto release;
6332             }
6333         }
6334       else
6335         {
6336           symbol *tlbl = newiTempLabel (NULL);
6337           int sizel = AOP_SIZE (left);
6338           if (size)
6339             emitcode ("setb", "c");
6340           while (sizel--)
6341             {
6342               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6343                 {
6344                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6345                   // byte ==  2^n ?
6346                   if ((posbit = isLiteralBit (bytelit)) != 0)
6347                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6348                   else
6349                     {
6350                       if (bytelit != 0x0FFL)
6351                         emitcode ("anl", "a,%s",
6352                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6353                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6354                     }
6355                 }
6356               offset++;
6357             }
6358           // bit = left & literal
6359           if (size)
6360             {
6361               emitcode ("clr", "c");
6362               emitcode ("", "!tlabeldef", tlbl->key + 100);
6363             }
6364           // if(left & literal)
6365           else
6366             {
6367               if (ifx)
6368                 jmpTrueOrFalse (ifx, tlbl);
6369               goto release;
6370             }
6371         }
6372       outBitC (result);
6373       goto release;
6374     }
6375
6376   /* if left is same as result */
6377   if (sameRegs (AOP (result), AOP (left)))
6378     {
6379       for (; size--; offset++)
6380         {
6381           if (AOP_TYPE (right) == AOP_LIT)
6382             {
6383               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6384                 continue;
6385               else if (bytelit == 0)
6386                 aopPut (AOP (result), zero, offset);
6387               else if (IS_AOP_PREG (result))
6388                 {
6389                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6390                   emitcode ("anl", "a,%s",
6391                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6392                   aopPut (AOP (result), "a", offset);
6393                 }
6394               else
6395                 emitcode ("anl", "%s,%s",
6396                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6397                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6398             }
6399           else
6400             {
6401               if (AOP_TYPE (left) == AOP_ACC)
6402                 emitcode ("anl", "a,%s",
6403                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6404               else
6405                 {
6406                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6407                   if (IS_AOP_PREG (result))
6408                     {
6409                       emitcode ("anl", "a,%s",
6410                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6411                       aopPut (AOP (result), "a", offset);
6412                     }
6413                   else
6414                     emitcode ("anl", "%s,a",
6415                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6416                 }
6417             }
6418         }
6419     }
6420   else
6421     {
6422       // left & result in different registers
6423       if (AOP_TYPE (result) == AOP_CRY)
6424         {
6425           // result = bit
6426           // if(size), result in bit
6427           // if(!size && ifx), conditional oper: if(left & right)
6428           symbol *tlbl = newiTempLabel (NULL);
6429           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6430           if (size)
6431             emitcode ("setb", "c");
6432           while (sizer--)
6433             {
6434               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6435                 emitcode ("anl", "a,%s",
6436                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6437               } else {
6438                 if (AOP_TYPE(left)==AOP_ACC) {
6439                   emitcode("mov", "b,a");
6440                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6441                   emitcode("anl", "a,b");
6442                 }else {
6443                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6444                   emitcode ("anl", "a,%s",
6445                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6446                 }
6447               }
6448               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6449               offset++;
6450             }
6451           if (size)
6452             {
6453               CLRC;
6454               emitcode ("", "!tlabeldef", tlbl->key + 100);
6455               outBitC (result);
6456             }
6457           else if (ifx)
6458             jmpTrueOrFalse (ifx, tlbl);
6459         }
6460       else
6461         {
6462           for (; (size--); offset++)
6463             {
6464               // normal case
6465               // result = left & right
6466               if (AOP_TYPE (right) == AOP_LIT)
6467                 {
6468                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6469                     {
6470                       aopPut (AOP (result),
6471                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6472                               offset);
6473                       continue;
6474                     }
6475                   else if (bytelit == 0)
6476                     {
6477                       aopPut (AOP (result), zero, offset);
6478                       continue;
6479                     }
6480                   D (emitcode (";", "better literal AND."););
6481                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6483                                                     FALSE, FALSE, DP2_RESULT_REG));
6484
6485                 }
6486               else
6487                 {
6488                   // faster than result <- left, anl result,right
6489                   // and better if result is SFR
6490                   if (AOP_TYPE (left) == AOP_ACC)
6491                     {
6492                       emitcode ("anl", "a,%s", 
6493                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6494                     }
6495                   else
6496                     {
6497                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6498                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6499                       {
6500                           emitcode("mov", "b,a");
6501                           rOp = "b";
6502                       }
6503                         
6504                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6505                       emitcode ("anl", "a,%s", rOp);
6506                     }                   
6507                 }
6508               aopPut (AOP (result), "a", offset);
6509             }
6510         }
6511     }
6512
6513 release:
6514   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6515   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6516   freeAsmop (result, NULL, ic, TRUE);
6517 }
6518
6519
6520 /*-----------------------------------------------------------------*/
6521 /* genOr  - code for or                                            */
6522 /*-----------------------------------------------------------------*/
6523 static void
6524 genOr (iCode * ic, iCode * ifx)
6525 {
6526   operand *left, *right, *result;
6527   int size, offset = 0;
6528   unsigned long lit = 0L;
6529   bool     pushResult;
6530
6531   D (emitcode (";", "genOr "););
6532
6533   AOP_OP_3_NOFATAL (ic, pushResult);
6534   AOP_SET_LOCALS (ic);
6535
6536   if (pushResult)
6537   {
6538       genFarFarLogicOp(ic, "orl");
6539       return;
6540   }
6541
6542
6543 #ifdef DEBUG_TYPE
6544   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6545             AOP_TYPE (result),
6546             AOP_TYPE (left), AOP_TYPE (right));
6547   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6548             AOP_SIZE (result),
6549             AOP_SIZE (left), AOP_SIZE (right));
6550 #endif
6551
6552   /* if left is a literal & right is not then exchange them */
6553   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6554 #ifdef LOGIC_OPS_BROKEN
6555    || AOP_NEEDSACC (left) // I think this is a net loss now.
6556 #endif      
6557       )
6558     {
6559       operand *tmp = right;
6560       right = left;
6561       left = tmp;
6562     }
6563
6564   /* if result = right then exchange them */
6565   if (sameRegs (AOP (result), AOP (right)))
6566     {
6567       operand *tmp = right;
6568       right = left;
6569       left = tmp;
6570     }
6571
6572   /* if right is bit then exchange them */
6573   if (AOP_TYPE (right) == AOP_CRY &&
6574       AOP_TYPE (left) != AOP_CRY)
6575     {
6576       operand *tmp = right;
6577       right = left;
6578       left = tmp;
6579     }
6580   if (AOP_TYPE (right) == AOP_LIT)
6581     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6582
6583   size = AOP_SIZE (result);
6584
6585   // if(bit | yy)
6586   // xx = bit | yy;
6587   if (AOP_TYPE (left) == AOP_CRY)
6588     {
6589       if (AOP_TYPE (right) == AOP_LIT)
6590         {
6591           // c = bit & literal;
6592           if (lit)
6593             {
6594               // lit != 0 => result = 1
6595               if (AOP_TYPE (result) == AOP_CRY)
6596                 {
6597                   if (size)
6598                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6599                   else if (ifx)
6600                     continueIfTrue (ifx);
6601                   goto release;
6602                 }
6603               emitcode ("setb", "c");
6604             }
6605           else
6606             {
6607               // lit == 0 => result = left
6608               if (size && sameRegs (AOP (result), AOP (left)))
6609                 goto release;
6610               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6611             }
6612         }
6613       else
6614         {
6615           if (AOP_TYPE (right) == AOP_CRY)
6616             {
6617               // c = bit | bit;
6618               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6619               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6620             }
6621           else
6622             {
6623               // c = bit | val;
6624               symbol *tlbl = newiTempLabel (NULL);
6625               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6626                 emitcode ("setb", "c");
6627               emitcode ("jb", "%s,!tlabel",
6628                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6629               toBoolean (right);
6630               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6631               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6632                 {
6633                   jmpTrueOrFalse (ifx, tlbl);
6634                   goto release;
6635                 }
6636               else
6637                 {
6638                   CLRC;
6639                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6640                 }
6641             }
6642         }
6643       // bit = c
6644       // val = c
6645       if (size)
6646         outBitC (result);
6647       // if(bit | ...)
6648       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6649            genIfxJump (ifx, "c");
6650       goto release;
6651     }
6652
6653   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6654   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6655   if ((AOP_TYPE (right) == AOP_LIT) &&
6656       (AOP_TYPE (result) == AOP_CRY) &&
6657       (AOP_TYPE (left) != AOP_CRY))
6658     {
6659       if (lit)
6660         {
6661           // result = 1
6662           if (size)
6663             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6664           else
6665             continueIfTrue (ifx);
6666           goto release;
6667         }
6668       else
6669         {
6670           // lit = 0, result = boolean(left)
6671           if (size)
6672             emitcode ("setb", "c");
6673           toBoolean (right);
6674           if (size)
6675             {
6676               symbol *tlbl = newiTempLabel (NULL);
6677               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6678               CLRC;
6679               emitcode ("", "!tlabeldef", tlbl->key + 100);
6680             }
6681           else
6682             {
6683               genIfxJump (ifx, "a");
6684               goto release;
6685             }
6686         }
6687       outBitC (result);
6688       goto release;
6689     }
6690
6691   /* if left is same as result */
6692   if (sameRegs (AOP (result), AOP (left)))
6693     {
6694       for (; size--; offset++)
6695         {
6696           if (AOP_TYPE (right) == AOP_LIT)
6697             {
6698               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6699                 {
6700                   continue;
6701                 }
6702               else
6703                 {
6704                   if (IS_AOP_PREG (left))
6705                     {
6706                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6707                       emitcode ("orl", "a,%s",
6708                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6709                       aopPut (AOP (result), "a", offset);
6710                     }
6711                   else
6712                     {
6713                       emitcode ("orl", "%s,%s",
6714                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6715                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6716                     }
6717                 }
6718             }
6719           else
6720             {
6721               if (AOP_TYPE (left) == AOP_ACC)
6722                 {
6723                   emitcode ("orl", "a,%s",
6724                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6725                 }
6726               else
6727                 {
6728                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6729                   if (IS_AOP_PREG (left))
6730                     {
6731                       emitcode ("orl", "a,%s", 
6732                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6733                       aopPut (AOP (result), "a", offset);
6734                     }
6735                   else
6736                     {
6737                       emitcode ("orl", "%s,a",
6738                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6739                     }
6740                 }
6741             }
6742         }
6743     }
6744   else
6745     {
6746       // left & result in different registers
6747       if (AOP_TYPE (result) == AOP_CRY)
6748         {
6749           // result = bit
6750           // if(size), result in bit
6751           // if(!size && ifx), conditional oper: if(left | right)
6752           symbol *tlbl = newiTempLabel (NULL);
6753           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6754           if (size)
6755             emitcode ("setb", "c");
6756           while (sizer--)
6757             {
6758               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6759                 emitcode ("orl", "a,%s",
6760                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6761               } else {
6762                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6763                 emitcode ("orl", "a,%s",
6764                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6765               }
6766               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6767               offset++;
6768             }
6769           if (size)
6770             {
6771               CLRC;
6772               emitcode ("", "!tlabeldef", tlbl->key + 100);
6773               outBitC (result);
6774             }
6775           else if (ifx)
6776             jmpTrueOrFalse (ifx, tlbl);
6777         }
6778       else
6779         {
6780             _startLazyDPSEvaluation();
6781           for (; (size--); offset++)
6782             {
6783               // normal case
6784               // result = left & right
6785               if (AOP_TYPE (right) == AOP_LIT)
6786                 {
6787                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6788                     {
6789                       aopPut (AOP (result),
6790                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6791                               offset);
6792                       continue;
6793                     }
6794                   D (emitcode (";", "better literal OR."););
6795                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6796                   emitcode ("orl", "a, %s",
6797                             aopGet (AOP (right), offset,
6798                                     FALSE, FALSE, DP2_RESULT_REG));
6799
6800                 }
6801               else
6802                 {
6803                   // faster than result <- left, anl result,right
6804                   // and better if result is SFR
6805                   if (AOP_TYPE (left) == AOP_ACC)
6806                     {
6807                       emitcode ("orl", "a,%s",
6808                                 aopGet (AOP (right), offset,
6809                                         FALSE, FALSE, DP2_RESULT_REG));
6810                     }
6811                   else
6812                     {
6813                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6814                         
6815                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6816                       {
6817                           emitcode("mov", "b,a");
6818                           rOp = "b";
6819                       }
6820                         
6821                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6822                       emitcode ("orl", "a,%s", rOp);
6823                     }
6824                 }
6825               aopPut (AOP (result), "a", offset);
6826             }
6827             _endLazyDPSEvaluation();
6828         }
6829     }
6830
6831 release:
6832   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6833   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6834   freeAsmop (result, NULL, ic, TRUE);
6835 }
6836
6837 /*-----------------------------------------------------------------*/
6838 /* genXor - code for xclusive or                                   */
6839 /*-----------------------------------------------------------------*/
6840 static void
6841 genXor (iCode * ic, iCode * ifx)
6842 {
6843   operand *left, *right, *result;
6844   int size, offset = 0;
6845   unsigned long lit = 0L;
6846   bool pushResult;
6847
6848   D (emitcode (";", "genXor "););
6849
6850   AOP_OP_3_NOFATAL (ic, pushResult);
6851   AOP_SET_LOCALS (ic);
6852
6853   if (pushResult)
6854   {
6855       genFarFarLogicOp(ic, "xrl");
6856       return;
6857   }  
6858
6859 #ifdef DEBUG_TYPE
6860   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6861             AOP_TYPE (result),
6862             AOP_TYPE (left), AOP_TYPE (right));
6863   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6864             AOP_SIZE (result),
6865             AOP_SIZE (left), AOP_SIZE (right));
6866 #endif
6867
6868   /* if left is a literal & right is not ||
6869      if left needs acc & right does not */
6870   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6871 #ifdef LOGIC_OPS_BROKEN      
6872       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6873 #endif
6874      )
6875     {
6876       operand *tmp = right;
6877       right = left;
6878       left = tmp;
6879     }
6880
6881   /* if result = right then exchange them */
6882   if (sameRegs (AOP (result), AOP (right)))
6883     {
6884       operand *tmp = right;
6885       right = left;
6886       left = tmp;
6887     }
6888
6889   /* if right is bit then exchange them */
6890   if (AOP_TYPE (right) == AOP_CRY &&
6891       AOP_TYPE (left) != AOP_CRY)
6892     {
6893       operand *tmp = right;
6894       right = left;
6895       left = tmp;
6896     }
6897   if (AOP_TYPE (right) == AOP_LIT)
6898     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6899
6900   size = AOP_SIZE (result);
6901
6902   // if(bit ^ yy)
6903   // xx = bit ^ yy;
6904   if (AOP_TYPE (left) == AOP_CRY)
6905     {
6906       if (AOP_TYPE (right) == AOP_LIT)
6907         {
6908           // c = bit & literal;
6909           if (lit >> 1)
6910             {
6911               // lit>>1  != 0 => result = 1
6912               if (AOP_TYPE (result) == AOP_CRY)
6913                 {
6914                   if (size)
6915                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6916                   else if (ifx)
6917                     continueIfTrue (ifx);
6918                   goto release;
6919                 }
6920               emitcode ("setb", "c");
6921             }
6922           else
6923             {
6924               // lit == (0 or 1)
6925               if (lit == 0)
6926                 {
6927                   // lit == 0, result = left
6928                   if (size && sameRegs (AOP (result), AOP (left)))
6929                     goto release;
6930                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6931                 }
6932               else
6933                 {
6934                   // lit == 1, result = not(left)
6935                   if (size && sameRegs (AOP (result), AOP (left)))
6936                     {
6937                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6938                       goto release;
6939                     }
6940                   else
6941                     {
6942                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6943                       emitcode ("cpl", "c");
6944                     }
6945                 }
6946             }
6947
6948         }
6949       else
6950         {
6951           // right != literal
6952           symbol *tlbl = newiTempLabel (NULL);
6953           if (AOP_TYPE (right) == AOP_CRY)
6954             {
6955               // c = bit ^ bit;
6956               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6957             }
6958           else
6959             {
6960               int sizer = AOP_SIZE (right);
6961               // c = bit ^ val
6962               // if val>>1 != 0, result = 1
6963               emitcode ("setb", "c");
6964               while (sizer)
6965                 {
6966                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6967                   if (sizer == 1)
6968                     // test the msb of the lsb
6969                     emitcode ("anl", "a,#!constbyte",0xfe);
6970                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6971                   sizer--;
6972                 }
6973               // val = (0,1)
6974               emitcode ("rrc", "a");
6975             }
6976           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6977           emitcode ("cpl", "c");
6978           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6979         }
6980       // bit = c
6981       // val = c
6982       if (size)
6983         outBitC (result);
6984       // if(bit | ...)
6985       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6986         genIfxJump (ifx, "c");
6987       goto release;
6988     }
6989
6990   if (sameRegs (AOP (result), AOP (left)))
6991     {
6992       /* if left is same as result */
6993       for (; size--; offset++)
6994         {
6995           if (AOP_TYPE (right) == AOP_LIT)
6996             {
6997               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6998                 continue;
6999               else if (IS_AOP_PREG (left))
7000                 {
7001                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7002                   emitcode ("xrl", "a,%s",
7003                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7004                   aopPut (AOP (result), "a", offset);
7005                 }
7006               else
7007                 emitcode ("xrl", "%s,%s",
7008                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7009                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7010             }
7011           else
7012             {
7013               if (AOP_TYPE (left) == AOP_ACC)
7014                 emitcode ("xrl", "a,%s",
7015                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7016               else
7017                 {
7018                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7019                   if (IS_AOP_PREG (left))
7020                     {
7021                       emitcode ("xrl", "a,%s",
7022                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7023                       aopPut (AOP (result), "a", offset);
7024                     }
7025                   else
7026                     emitcode ("xrl", "%s,a",
7027                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7028                 }
7029             }
7030         }
7031     }
7032   else
7033     {
7034       // left & result in different registers
7035       if (AOP_TYPE (result) == AOP_CRY)
7036         {
7037           // result = bit
7038           // if(size), result in bit
7039           // if(!size && ifx), conditional oper: if(left ^ right)
7040           symbol *tlbl = newiTempLabel (NULL);
7041           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7042                   
7043           if (size)
7044             emitcode ("setb", "c");
7045           while (sizer--)
7046             {
7047               if ((AOP_TYPE (right) == AOP_LIT) &&
7048                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7049                 {
7050                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7051                 }
7052               else
7053                 {
7054                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7055                     emitcode ("xrl", "a,%s",
7056                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7057                   } else {
7058                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7059                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7060                       {
7061                           emitcode("mov", "b,a");
7062                           rOp = "b";
7063                       }
7064                         
7065                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7066                       emitcode ("xrl", "a,%s", rOp);                  
7067                   }
7068                 }
7069               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7070               offset++;
7071             }
7072           if (size)
7073             {
7074               CLRC;
7075               emitcode ("", "!tlabeldef", tlbl->key + 100);
7076               outBitC (result);
7077             }
7078           else if (ifx)
7079             jmpTrueOrFalse (ifx, tlbl);
7080         }
7081       else
7082         {
7083         for (; (size--); offset++)
7084           {
7085             // normal case
7086             // result = left & right
7087             if (AOP_TYPE (right) == AOP_LIT)
7088               {
7089                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7090                   {
7091                     aopPut (AOP (result),
7092                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7093                             offset);
7094                     continue;
7095                   }
7096                 D (emitcode (";", "better literal XOR."););
7097                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098                 emitcode ("xrl", "a, %s",
7099                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7100               }
7101             else
7102               {
7103                 // faster than result <- left, anl result,right
7104                 // and better if result is SFR
7105                 if (AOP_TYPE (left) == AOP_ACC)
7106                   {
7107                     emitcode ("xrl", "a,%s",
7108                               aopGet (AOP (right), offset,
7109                                       FALSE, FALSE, DP2_RESULT_REG));
7110                   }
7111                 else
7112                   {
7113                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7114                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7115                       {
7116                           emitcode("mov", "b,a");
7117                           rOp = "b";
7118                       }
7119                         
7120                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7121                       emitcode ("xrl", "a,%s", rOp);
7122                   }
7123               }
7124             aopPut (AOP (result), "a", offset);
7125           }
7126         }
7127         
7128     }
7129
7130 release:
7131   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7132   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7133   freeAsmop (result, NULL, ic, TRUE);
7134 }
7135
7136 /*-----------------------------------------------------------------*/
7137 /* genInline - write the inline code out                           */
7138 /*-----------------------------------------------------------------*/
7139 static void
7140 genInline (iCode * ic)
7141 {
7142   char *buffer, *bp, *bp1;
7143
7144   D (emitcode (";", "genInline "); );
7145
7146   _G.inLine += (!options.asmpeep);
7147
7148   buffer = Safe_strdup(IC_INLINE(ic));
7149   bp = buffer;
7150   bp1 = buffer;
7151
7152   /* emit each line as a code */
7153   while (*bp)
7154     {
7155       if (*bp == '\n')
7156         {
7157           *bp++ = '\0';
7158           emitcode (bp1, "");
7159           bp1 = bp;
7160         }
7161       else
7162         {
7163           if (*bp == ':')
7164             {
7165               bp++;
7166               *bp = '\0';
7167               bp++;
7168               emitcode (bp1, "");
7169               bp1 = bp;
7170             }
7171           else
7172             bp++;
7173         }
7174     }
7175   if (bp1 != bp)
7176     emitcode (bp1, "");
7177   /*     emitcode("",buffer); */
7178   _G.inLine -= (!options.asmpeep);
7179 }
7180
7181 /*-----------------------------------------------------------------*/
7182 /* genRRC - rotate right with carry                                */
7183 /*-----------------------------------------------------------------*/
7184 static void
7185 genRRC (iCode * ic)
7186 {
7187   operand *left, *result;
7188   int     size, offset;
7189
7190   D (emitcode (";", "genRRC "););
7191
7192   /* rotate right with carry */
7193   left = IC_LEFT (ic);
7194   result = IC_RESULT (ic);
7195   aopOp (left, ic, FALSE, FALSE);
7196   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7197
7198   /* move it to the result */
7199   size = AOP_SIZE (result);
7200   offset = size - 1;
7201   CLRC;
7202
7203   _startLazyDPSEvaluation ();
7204   while (size--)
7205     {
7206       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7207       emitcode ("rrc", "a");
7208       if (AOP_SIZE (result) > 1)
7209         aopPut (AOP (result), "a", offset--);
7210     }
7211   _endLazyDPSEvaluation ();
7212
7213   /* now we need to put the carry into the
7214      highest order byte of the result */
7215   if (AOP_SIZE (result) > 1)
7216     {
7217       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7218     }
7219   emitcode ("mov", "acc.7,c");
7220   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7221   freeAsmop (left, NULL, ic, TRUE);
7222   freeAsmop (result, NULL, ic, TRUE);
7223 }
7224
7225 /*-----------------------------------------------------------------*/
7226 /* genRLC - generate code for rotate left with carry               */
7227 /*-----------------------------------------------------------------*/
7228 static void
7229 genRLC (iCode * ic)
7230 {
7231   operand *left, *result;
7232   int size, offset;
7233   char *l;
7234
7235   D (emitcode (";", "genRLC "););
7236
7237   /* rotate right with carry */
7238   left = IC_LEFT (ic);
7239   result = IC_RESULT (ic);
7240   aopOp (left, ic, FALSE, FALSE);
7241   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7242
7243   /* move it to the result */
7244   size = AOP_SIZE (result);
7245   offset = 0;
7246   if (size--)
7247     {
7248       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7249       MOVA (l);
7250       emitcode ("add", "a,acc");
7251       if (AOP_SIZE (result) > 1)
7252         {
7253           aopPut (AOP (result), "a", offset++);
7254         }
7255
7256       _startLazyDPSEvaluation ();
7257       while (size--)
7258         {
7259           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7260           MOVA (l);
7261           emitcode ("rlc", "a");
7262           if (AOP_SIZE (result) > 1)
7263             aopPut (AOP (result), "a", offset++);
7264         }
7265       _endLazyDPSEvaluation ();
7266     }
7267   /* now we need to put the carry into the
7268      highest order byte of the result */
7269   if (AOP_SIZE (result) > 1)
7270     {
7271       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7272       MOVA (l);
7273     }
7274   emitcode ("mov", "acc.0,c");
7275   aopPut (AOP (result), "a", 0);
7276   freeAsmop (left, NULL, ic, TRUE);
7277   freeAsmop (result, NULL, ic, TRUE);
7278 }
7279
7280 /*-----------------------------------------------------------------*/
7281 /* genGetHbit - generates code get highest order bit               */
7282 /*-----------------------------------------------------------------*/
7283 static void
7284 genGetHbit (iCode * ic)
7285 {
7286   operand *left, *result;
7287   left = IC_LEFT (ic);
7288   result = IC_RESULT (ic);
7289   aopOp (left, ic, FALSE, FALSE);
7290   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7291
7292   D (emitcode (";", "genGetHbit "););
7293
7294   /* get the highest order byte into a */
7295   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7296   if (AOP_TYPE (result) == AOP_CRY)
7297     {
7298       emitcode ("rlc", "a");
7299       outBitC (result);
7300     }
7301   else
7302     {
7303       emitcode ("rl", "a");
7304       emitcode ("anl", "a,#1");
7305       outAcc (result);
7306     }
7307
7308
7309   freeAsmop (left, NULL, ic, TRUE);
7310   freeAsmop (result, NULL, ic, TRUE);
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* AccRol - rotate left accumulator by known count                 */
7315 /*-----------------------------------------------------------------*/
7316 static void
7317 AccRol (int shCount)
7318 {
7319   shCount &= 0x0007;            // shCount : 0..7
7320
7321   switch (shCount)
7322     {
7323     case 0:
7324       break;
7325     case 1:
7326       emitcode ("rl", "a");
7327       break;
7328     case 2:
7329       emitcode ("rl", "a");
7330       emitcode ("rl", "a");
7331       break;
7332     case 3:
7333       emitcode ("swap", "a");
7334       emitcode ("rr", "a");
7335       break;
7336     case 4:
7337       emitcode ("swap", "a");
7338       break;
7339     case 5:
7340       emitcode ("swap", "a");
7341       emitcode ("rl", "a");
7342       break;
7343     case 6:
7344       emitcode ("rr", "a");
7345       emitcode ("rr", "a");
7346       break;
7347     case 7:
7348       emitcode ("rr", "a");
7349       break;
7350     }
7351 }
7352
7353 /*-----------------------------------------------------------------*/
7354 /* AccLsh - left shift accumulator by known count                  */
7355 /*-----------------------------------------------------------------*/
7356 static void
7357 AccLsh (int shCount)
7358 {
7359   if (shCount != 0)
7360     {
7361       if (shCount == 1)
7362         emitcode ("add", "a,acc");
7363       else if (shCount == 2)
7364         {
7365           emitcode ("add", "a,acc");
7366           emitcode ("add", "a,acc");
7367         }
7368       else
7369         {
7370           /* rotate left accumulator */
7371           AccRol (shCount);
7372           /* and kill the lower order bits */
7373           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7374         }
7375     }
7376 }
7377
7378 /*-----------------------------------------------------------------*/
7379 /* AccRsh - right shift accumulator by known count                 */
7380 /*-----------------------------------------------------------------*/
7381 static void
7382 AccRsh (int shCount)
7383 {
7384   if (shCount != 0)
7385     {
7386       if (shCount == 1)
7387         {
7388           CLRC;
7389           emitcode ("rrc", "a");
7390         }
7391       else
7392         {
7393           /* rotate right accumulator */
7394           AccRol (8 - shCount);
7395           /* and kill the higher order bits */
7396           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7397         }
7398     }
7399 }
7400
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* AccSRsh - signed right shift accumulator by known count                 */
7404 /*-----------------------------------------------------------------*/
7405 static void
7406 AccSRsh (int shCount)
7407 {
7408   symbol *tlbl;
7409   if (shCount != 0)
7410     {
7411       if (shCount == 1)
7412         {
7413           emitcode ("mov", "c,acc.7");
7414           emitcode ("rrc", "a");
7415         }
7416       else if (shCount == 2)
7417         {
7418           emitcode ("mov", "c,acc.7");
7419           emitcode ("rrc", "a");
7420           emitcode ("mov", "c,acc.7");
7421           emitcode ("rrc", "a");
7422         }
7423       else
7424         {
7425           tlbl = newiTempLabel (NULL);
7426           /* rotate right accumulator */
7427           AccRol (8 - shCount);
7428           /* and kill the higher order bits */
7429           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7430           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7431           emitcode ("orl", "a,#!constbyte",
7432                     (unsigned char) ~SRMask[shCount]);
7433           emitcode ("", "!tlabeldef", tlbl->key + 100);
7434         }
7435     }
7436 }
7437 #endif
7438
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* shiftR1Left2Result - shift right one byte from left to result   */
7442 /*-----------------------------------------------------------------*/
7443 static void
7444 shiftR1Left2Result (operand * left, int offl,
7445                     operand * result, int offr,
7446                     int shCount, int sign)
7447 {
7448   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7449   /* shift right accumulator */
7450   if (sign)
7451     AccSRsh (shCount);
7452   else
7453     AccRsh (shCount);
7454   aopPut (AOP (result), "a", offr);
7455 }
7456 #endif
7457
7458 #ifdef BETTER_LITERAL_SHIFT
7459 /*-----------------------------------------------------------------*/
7460 /* shiftL1Left2Result - shift left one byte from left to result    */
7461 /*-----------------------------------------------------------------*/
7462 static void
7463 shiftL1Left2Result (operand * left, int offl,
7464                     operand * result, int offr, int shCount)
7465 {
7466   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7467   /* shift left accumulator */
7468   AccLsh (shCount);
7469   aopPut (AOP (result), "a", offr);
7470 }
7471 #endif
7472
7473 #ifdef BETTER_LITERAL_SHIFT
7474 /*-----------------------------------------------------------------*/
7475 /* movLeft2Result - move byte from left to result                  */
7476 /*-----------------------------------------------------------------*/
7477 static void
7478 movLeft2Result (operand * left, int offl,
7479                 operand * result, int offr, int sign)
7480 {
7481   char *l;
7482   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7483   {
7484       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7485
7486       if (*l == '@' && (IS_AOP_PREG (result)))
7487       {
7488           emitcode ("mov", "a,%s", l);
7489           aopPut (AOP (result), "a", offr);
7490       }
7491       else
7492       {
7493           if (!sign)
7494           {
7495             aopPut (AOP (result), l, offr);
7496           }
7497           else
7498             {
7499               /* MSB sign in acc.7 ! */
7500               if (getDataSize (left) == offl + 1)
7501                 {
7502                   emitcode ("mov", "a,%s", l);
7503                   aopPut (AOP (result), "a", offr);
7504                 }
7505             }
7506       }
7507   }
7508 }
7509 #endif
7510
7511 #ifdef BETTER_LITERAL_SHIFT
7512 /*-----------------------------------------------------------------*/
7513 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7514 /*-----------------------------------------------------------------*/
7515 static void
7516 AccAXRrl1 (char *x)
7517 {
7518   emitcode ("rrc", "a");
7519   emitcode ("xch", "a,%s", x);
7520   emitcode ("rrc", "a");
7521   emitcode ("xch", "a,%s", x);
7522 }
7523 #endif
7524
7525 #ifdef BETTER_LITERAL_SHIFT
7526 //REMOVE ME!!!
7527 /*-----------------------------------------------------------------*/
7528 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7529 /*-----------------------------------------------------------------*/
7530 static void
7531 AccAXLrl1 (char *x)
7532 {
7533   emitcode ("xch", "a,%s", x);
7534   emitcode ("rlc", "a");
7535   emitcode ("xch", "a,%s", x);
7536   emitcode ("rlc", "a");
7537 }
7538 #endif
7539
7540 #ifdef BETTER_LITERAL_SHIFT
7541 /*-----------------------------------------------------------------*/
7542 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7543 /*-----------------------------------------------------------------*/
7544 static void
7545 AccAXLsh1 (char *x)
7546 {
7547   emitcode ("xch", "a,%s", x);
7548   emitcode ("add", "a,acc");
7549   emitcode ("xch", "a,%s", x);
7550   emitcode ("rlc", "a");
7551 }
7552 #endif
7553
7554 #ifdef BETTER_LITERAL_SHIFT
7555 /*-----------------------------------------------------------------*/
7556 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7557 /*-----------------------------------------------------------------*/
7558 static void
7559 AccAXLsh (char *x, int shCount)
7560 {
7561   switch (shCount)
7562     {
7563     case 0:
7564       break;
7565     case 1:
7566       AccAXLsh1 (x);
7567       break;
7568     case 2:
7569       AccAXLsh1 (x);
7570       AccAXLsh1 (x);
7571       break;
7572     case 3:
7573     case 4:
7574     case 5:                     // AAAAABBB:CCCCCDDD
7575
7576       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7577
7578       emitcode ("anl", "a,#!constbyte",
7579                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7580
7581       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7582
7583       AccRol (shCount);         // DDDCCCCC:BBB00000
7584
7585       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7586
7587       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7588
7589       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7590
7591       emitcode ("anl", "a,#!constbyte",
7592                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7593
7594       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7595
7596       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7597
7598       break;
7599     case 6:                     // AAAAAABB:CCCCCCDD
7600       emitcode ("anl", "a,#!constbyte",
7601                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7602       emitcode ("mov", "c,acc.0");      // c = B
7603       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7604 #if 0
7605       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7606       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7607 #else
7608       emitcode("rrc","a"); 
7609       emitcode("xch","a,%s", x); 
7610       emitcode("rrc","a"); 
7611       emitcode("mov","c,acc.0"); //<< get correct bit 
7612       emitcode("xch","a,%s", x); 
7613
7614       emitcode("rrc","a"); 
7615       emitcode("xch","a,%s", x); 
7616       emitcode("rrc","a"); 
7617       emitcode("xch","a,%s", x); 
7618 #endif
7619       break;
7620     case 7:                     // a:x <<= 7
7621
7622       emitcode ("anl", "a,#!constbyte",
7623                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7624
7625       emitcode ("mov", "c,acc.0");      // c = B
7626
7627       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7628
7629       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7630
7631       break;
7632     default:
7633       break;
7634     }
7635 }
7636 #endif
7637
7638 #ifdef BETTER_LITERAL_SHIFT
7639 //REMOVE ME!!!
7640 /*-----------------------------------------------------------------*/
7641 /* AccAXRsh - right shift a:x known count (0..7)                   */
7642 /*-----------------------------------------------------------------*/
7643 static void
7644 AccAXRsh (char *x, int shCount)
7645 {
7646   switch (shCount)
7647     {
7648     case 0:
7649       break;
7650     case 1:
7651       CLRC;
7652       AccAXRrl1 (x);            // 0->a:x
7653
7654       break;
7655     case 2:
7656       CLRC;
7657       AccAXRrl1 (x);            // 0->a:x
7658
7659       CLRC;
7660       AccAXRrl1 (x);            // 0->a:x
7661
7662       break;
7663     case 3:
7664     case 4:
7665     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7666
7667       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7668
7669       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7670
7671       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7672
7673       emitcode ("anl", "a,#!constbyte",
7674                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7675
7676       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7677
7678       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7679
7680       emitcode ("anl", "a,#!constbyte",
7681                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7682
7683       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7684
7685       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7686
7687       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7688
7689       break;
7690     case 6:                     // AABBBBBB:CCDDDDDD
7691
7692       emitcode ("mov", "c,acc.7");
7693       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7694
7695       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7696
7697       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7698
7699       emitcode ("anl", "a,#!constbyte",
7700                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7701
7702       break;
7703     case 7:                     // ABBBBBBB:CDDDDDDD
7704
7705       emitcode ("mov", "c,acc.7");      // c = A
7706
7707       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7708
7709       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7710
7711       emitcode ("anl", "a,#!constbyte",
7712                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7713
7714       break;
7715     default:
7716       break;
7717     }
7718 }
7719 #endif
7720
7721 #ifdef BETTER_LITERAL_SHIFT
7722 /*-----------------------------------------------------------------*/
7723 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7724 /*-----------------------------------------------------------------*/
7725 static void
7726 AccAXRshS (char *x, int shCount)
7727 {
7728   symbol *tlbl;
7729   switch (shCount)
7730     {
7731     case 0:
7732       break;
7733     case 1:
7734       emitcode ("mov", "c,acc.7");
7735       AccAXRrl1 (x);            // s->a:x
7736
7737       break;
7738     case 2:
7739       emitcode ("mov", "c,acc.7");
7740       AccAXRrl1 (x);            // s->a:x
7741
7742       emitcode ("mov", "c,acc.7");
7743       AccAXRrl1 (x);            // s->a:x
7744
7745       break;
7746     case 3:
7747     case 4:
7748     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7749
7750       tlbl = newiTempLabel (NULL);
7751       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7752
7753       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7754
7755       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7756
7757       emitcode ("anl", "a,#!constbyte",
7758                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7759
7760       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7761
7762       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7763
7764       emitcode ("anl", "a,#!constbyte",
7765                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7766
7767       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7768
7769       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7770
7771       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7772
7773       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7774       emitcode ("orl", "a,#!constbyte",
7775                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7776
7777       emitcode ("", "!tlabeldef", tlbl->key + 100);
7778       break;                    // SSSSAAAA:BBBCCCCC
7779
7780     case 6:                     // AABBBBBB:CCDDDDDD
7781
7782       tlbl = newiTempLabel (NULL);
7783       emitcode ("mov", "c,acc.7");
7784       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7785
7786       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7787
7788       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7789
7790       emitcode ("anl", "a,#!constbyte",
7791                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7792
7793       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7794       emitcode ("orl", "a,#!constbyte",
7795                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7796
7797       emitcode ("", "!tlabeldef", tlbl->key + 100);
7798       break;
7799     case 7:                     // ABBBBBBB:CDDDDDDD
7800
7801       tlbl = newiTempLabel (NULL);
7802       emitcode ("mov", "c,acc.7");      // c = A
7803
7804       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7805
7806       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7807
7808       emitcode ("anl", "a,#!constbyte",
7809                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7810
7811       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7812       emitcode ("orl", "a,#!constbyte",
7813                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7814
7815       emitcode ("", "!tlabeldef", tlbl->key + 100);
7816       break;
7817     default:
7818       break;
7819     }
7820 }
7821 #endif
7822
7823 #ifdef BETTER_LITERAL_SHIFT
7824 static void
7825 _loadLeftIntoAx(char    **lsb, 
7826                 operand *left, 
7827                 operand *result,
7828                 int     offl,
7829                 int     offr)
7830 {
7831   // Get the initial value from left into a pair of registers.
7832   // MSB must be in A, LSB can be any register.
7833   //
7834   // If the result is held in registers, it is an optimization
7835   // if the LSB can be held in the register which will hold the,
7836   // result LSB since this saves us from having to copy it into
7837   // the result following AccAXLsh.
7838   //
7839   // If the result is addressed indirectly, this is not a gain.
7840   if (AOP_NEEDSACC(result))
7841   {
7842        char *leftByte;
7843        
7844        _startLazyDPSEvaluation();
7845       if (AOP_TYPE(left) == AOP_DPTR2)
7846        {
7847            // Get MSB in A.
7848            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7849            // get LSB in DP2_RESULT_REG.
7850            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7851            assert(!strcmp(leftByte, DP2_RESULT_REG));
7852        }
7853        else
7854        {
7855            // get LSB into DP2_RESULT_REG
7856            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7857            if (strcmp(leftByte, DP2_RESULT_REG))
7858            {
7859                TR_AP("#7");
7860                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7861            }
7862            // And MSB in A.
7863            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7864            assert(strcmp(leftByte, DP2_RESULT_REG));
7865            MOVA(leftByte);
7866        }
7867        _endLazyDPSEvaluation();
7868        *lsb = DP2_RESULT_REG;
7869   }
7870   else
7871   {
7872       if (sameRegs (AOP (result), AOP (left)) &&
7873         ((offl + MSB16) == offr))
7874       {
7875           /* don't crash result[offr] */
7876           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7877           emitcode ("xch", "a,%s", 
7878                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7879       }
7880       else
7881       {
7882           movLeft2Result (left, offl, result, offr, 0);
7883           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7884       }
7885       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7886       assert(strcmp(*lsb,"a"));      
7887   }
7888 }
7889
7890 static void
7891 _storeAxResults(char    *lsb,
7892                 operand *result,
7893                 int     offr)
7894 {
7895   _startLazyDPSEvaluation();
7896   if (AOP_NEEDSACC(result))
7897   {
7898       /* We have to explicitly update the result LSB.
7899        */
7900       emitcode("xch","a,%s", lsb);
7901       aopPut(AOP(result), "a", offr);
7902       emitcode("mov","a,%s", lsb);
7903   }
7904   if (getDataSize (result) > 1)
7905   {
7906       aopPut (AOP (result), "a", offr + MSB16);
7907   }
7908   _endLazyDPSEvaluation();
7909 }
7910
7911 /*-----------------------------------------------------------------*/
7912 /* shiftL2Left2Result - shift left two bytes from left to result   */
7913 /*-----------------------------------------------------------------*/
7914 static void
7915 shiftL2Left2Result (operand * left, int offl,
7916                     operand * result, int offr, int shCount)
7917 {
7918   char *lsb;
7919
7920   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7921   
7922   AccAXLsh (lsb, shCount);
7923   
7924   _storeAxResults(lsb, result, offr);
7925 }
7926 #endif
7927
7928 #ifdef BETTER_LITERAL_SHIFT
7929 /*-----------------------------------------------------------------*/
7930 /* shiftR2Left2Result - shift right two bytes from left to result  */
7931 /*-----------------------------------------------------------------*/
7932 static void
7933 shiftR2Left2Result (operand * left, int offl,
7934                     operand * result, int offr,
7935                     int shCount, int sign)
7936 {
7937   char *lsb;
7938   
7939   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7940   
7941   /* a:x >> shCount (x = lsb(result)) */
7942   if (sign)
7943   {
7944      AccAXRshS(lsb, shCount);
7945   }
7946   else
7947   {
7948     AccAXRsh(lsb, shCount);
7949   }
7950   
7951   _storeAxResults(lsb, result, offr);
7952 }
7953 #endif
7954
7955 /*-----------------------------------------------------------------*/
7956 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 shiftLLeftOrResult (operand * left, int offl,
7960                     operand * result, int offr, int shCount)
7961 {
7962   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7963   /* shift left accumulator */
7964   AccLsh (shCount);
7965   /* or with result */
7966   emitcode ("orl", "a,%s",
7967             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7968   /* back to result */
7969   aopPut (AOP (result), "a", offr);
7970 }
7971
7972 #if 0
7973 //REMOVE ME!!!
7974 /*-----------------------------------------------------------------*/
7975 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7976 /*-----------------------------------------------------------------*/
7977 static void
7978 shiftRLeftOrResult (operand * left, int offl,
7979                     operand * result, int offr, int shCount)
7980 {
7981   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7982   /* shift right accumulator */
7983   AccRsh (shCount);
7984   /* or with result */
7985   emitcode ("orl", "a,%s",
7986             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7987   /* back to result */
7988   aopPut (AOP (result), "a", offr);
7989 }
7990 #endif
7991
7992 #ifdef BETTER_LITERAL_SHIFT
7993 /*-----------------------------------------------------------------*/
7994 /* genlshOne - left shift a one byte quantity by known count       */
7995 /*-----------------------------------------------------------------*/
7996 static void
7997 genlshOne (operand * result, operand * left, int shCount)
7998 {
7999   D (emitcode (";", "genlshOne "););
8000   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8001 }
8002 #endif
8003
8004 #ifdef BETTER_LITERAL_SHIFT
8005 /*-----------------------------------------------------------------*/
8006 /* genlshTwo - left shift two bytes by known amount != 0           */
8007 /*-----------------------------------------------------------------*/
8008 static void
8009 genlshTwo (operand * result, operand * left, int shCount)
8010 {
8011   int size;
8012
8013   D (emitcode (";", "genlshTwo "););
8014
8015   size = getDataSize (result);
8016
8017   /* if shCount >= 8 */
8018   if (shCount >= 8)
8019   {
8020       shCount -= 8;
8021
8022       _startLazyDPSEvaluation();
8023
8024       if (size > 1)
8025         {
8026           if (shCount)
8027           {
8028             _endLazyDPSEvaluation();
8029             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8030             aopPut (AOP (result), zero, LSB);       
8031           }
8032           else
8033           {
8034             movLeft2Result (left, LSB, result, MSB16, 0);
8035             aopPut (AOP (result), zero, LSB);
8036             _endLazyDPSEvaluation();
8037           }
8038         }
8039         else
8040         {
8041           aopPut (AOP (result), zero, LSB);
8042           _endLazyDPSEvaluation();
8043         }
8044   }
8045
8046   /*  1 <= shCount <= 7 */
8047   else
8048     {
8049       if (size == 1)
8050       {
8051         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8052       }
8053       else
8054       {
8055         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8056       }
8057     }
8058 }
8059 #endif
8060
8061 #if 0
8062 //REMOVE ME!!!
8063 /*-----------------------------------------------------------------*/
8064 /* shiftLLong - shift left one long from left to result            */
8065 /* offl = LSB or MSB16                                             */
8066 /*-----------------------------------------------------------------*/
8067 static void
8068 shiftLLong (operand * left, operand * result, int offr)
8069 {
8070   char *l;
8071   int size = AOP_SIZE (result);
8072
8073   if (size >= LSB + offr)
8074     {
8075       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8076       MOVA (l);
8077       emitcode ("add", "a,acc");
8078       if (sameRegs (AOP (left), AOP (result)) &&
8079           size >= MSB16 + offr && offr != LSB)
8080         emitcode ("xch", "a,%s",
8081                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8082       else
8083         aopPut (AOP (result), "a", LSB + offr);
8084     }
8085
8086   if (size >= MSB16 + offr)
8087     {
8088       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8089         {
8090           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8091         }
8092       emitcode ("rlc", "a");
8093       if (sameRegs (AOP (left), AOP (result)) &&
8094           size >= MSB24 + offr && offr != LSB)
8095         emitcode ("xch", "a,%s",
8096                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8097       else
8098         aopPut (AOP (result), "a", MSB16 + offr);
8099     }
8100
8101   if (size >= MSB24 + offr)
8102     {
8103       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8104         {
8105           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8106         }
8107       emitcode ("rlc", "a");
8108       if (sameRegs (AOP (left), AOP (result)) &&
8109           size >= MSB32 + offr && offr != LSB)
8110         emitcode ("xch", "a,%s",
8111                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8112       else
8113         aopPut (AOP (result), "a", MSB24 + offr);
8114     }
8115
8116   if (size > MSB32 + offr)
8117     {
8118       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8119         {
8120           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8121         }
8122       emitcode ("rlc", "a");
8123       aopPut (AOP (result), "a", MSB32 + offr);
8124     }
8125   if (offr != LSB)
8126     aopPut (AOP (result), zero, LSB);
8127 }
8128 #endif
8129
8130 #if 0
8131 //REMOVE ME!!!
8132 /*-----------------------------------------------------------------*/
8133 /* genlshFour - shift four byte by a known amount != 0             */
8134 /*-----------------------------------------------------------------*/
8135 static void
8136 genlshFour (operand * result, operand * left, int shCount)
8137 {
8138   int size;
8139
8140   D (emitcode (";", "genlshFour ");
8141     );
8142
8143   size = AOP_SIZE (result);
8144
8145   /* if shifting more that 3 bytes */
8146   if (shCount >= 24)
8147     {
8148       shCount -= 24;
8149       if (shCount)
8150         /* lowest order of left goes to the highest
8151            order of the destination */
8152         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8153       else
8154         movLeft2Result (left, LSB, result, MSB32, 0);
8155       aopPut (AOP (result), zero, LSB);
8156       aopPut (AOP (result), zero, MSB16);
8157       aopPut (AOP (result), zero, MSB24);
8158       return;
8159     }
8160
8161   /* more than two bytes */
8162   else if (shCount >= 16)
8163     {
8164       /* lower order two bytes goes to higher order two bytes */
8165       shCount -= 16;
8166       /* if some more remaining */
8167       if (shCount)
8168         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8169       else
8170         {
8171           movLeft2Result (left, MSB16, result, MSB32, 0);
8172           movLeft2Result (left, LSB, result, MSB24, 0);
8173         }
8174       aopPut (AOP (result), zero, MSB16);
8175       aopPut (AOP (result), zero, LSB);
8176       return;
8177     }
8178
8179   /* if more than 1 byte */
8180   else if (shCount >= 8)
8181     {
8182       /* lower order three bytes goes to higher order  three bytes */
8183       shCount -= 8;
8184       if (size == 2)
8185         {
8186           if (shCount)
8187             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8188           else
8189             movLeft2Result (left, LSB, result, MSB16, 0);
8190         }
8191       else
8192         {                       /* size = 4 */
8193           if (shCount == 0)
8194             {
8195               movLeft2Result (left, MSB24, result, MSB32, 0);
8196               movLeft2Result (left, MSB16, result, MSB24, 0);
8197               movLeft2Result (left, LSB, result, MSB16, 0);
8198               aopPut (AOP (result), zero, LSB);
8199             }
8200           else if (shCount == 1)
8201             shiftLLong (left, result, MSB16);
8202           else
8203             {
8204               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8205               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8206               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8207               aopPut (AOP (result), zero, LSB);
8208             }
8209         }
8210     }
8211
8212   /* 1 <= shCount <= 7 */
8213   else if (shCount <= 2)
8214     {
8215       shiftLLong (left, result, LSB);
8216       if (shCount == 2)
8217         shiftLLong (result, result, LSB);
8218     }
8219   /* 3 <= shCount <= 7, optimize */
8220   else
8221     {
8222       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8223       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8224       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8225     }
8226 }
8227 #endif
8228
8229 #ifdef BETTER_LITERAL_SHIFT
8230 /*-----------------------------------------------------------------*/
8231 /* genLeftShiftLiteral - left shifting by known count              */
8232 /*-----------------------------------------------------------------*/
8233 static bool
8234 genLeftShiftLiteral (operand * left,
8235                      operand * right,
8236                      operand * result,
8237                      iCode * ic)
8238 {
8239   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8240   int size;
8241
8242   size = getSize (operandType (result));
8243
8244   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8245
8246   /* We only handle certain easy cases so far. */
8247   if ((shCount != 0)
8248    && (shCount < (size * 8))
8249    && (size != 1)
8250    && (size != 2))
8251   {
8252       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8253       return FALSE;
8254   }
8255
8256   freeAsmop (right, NULL, ic, TRUE);
8257
8258   aopOp(left, ic, FALSE, FALSE);
8259   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8260
8261 #if 0 // debug spew
8262   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8263   {
8264         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8265         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8266         {
8267            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8268         }
8269   }
8270   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8271   {
8272         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8273         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8274         {
8275            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8276         }       
8277   }  
8278 #endif
8279   
8280 #if VIEW_SIZE
8281   emitcode ("; shift left ", "result %d, left %d", size,
8282             AOP_SIZE (left));
8283 #endif
8284
8285   /* I suppose that the left size >= result size */
8286   if (shCount == 0)
8287   {
8288         _startLazyDPSEvaluation();
8289         while (size--)
8290         {
8291           movLeft2Result (left, size, result, size, 0);
8292         }
8293         _endLazyDPSEvaluation();
8294   }
8295   else if (shCount >= (size * 8))
8296   {
8297     _startLazyDPSEvaluation();
8298     while (size--)
8299     {
8300       aopPut (AOP (result), zero, size);
8301     }
8302     _endLazyDPSEvaluation();
8303   }
8304   else
8305   {
8306       switch (size)
8307         {
8308         case 1:
8309           genlshOne (result, left, shCount);
8310           break;
8311
8312         case 2:
8313           genlshTwo (result, left, shCount);
8314           break;
8315 #if 0
8316         case 4:
8317           genlshFour (result, left, shCount);
8318           break;
8319 #endif
8320         default:
8321           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8322           break;
8323         }
8324     }
8325   freeAsmop (left, NULL, ic, TRUE);
8326   freeAsmop (result, NULL, ic, TRUE);
8327   return TRUE;
8328 }
8329 #endif
8330
8331 /*-----------------------------------------------------------------*/
8332 /* genLeftShift - generates code for left shifting                 */
8333 /*-----------------------------------------------------------------*/
8334 static void
8335 genLeftShift (iCode * ic)
8336 {
8337   operand *left, *right, *result;
8338   int size, offset;
8339   char *l;
8340   symbol *tlbl, *tlbl1;
8341
8342   D (emitcode (";", "genLeftShift "););
8343
8344   right = IC_RIGHT (ic);
8345   left = IC_LEFT (ic);
8346   result = IC_RESULT (ic);
8347
8348   aopOp (right, ic, FALSE, FALSE);
8349
8350
8351 #ifdef BETTER_LITERAL_SHIFT
8352   /* if the shift count is known then do it
8353      as efficiently as possible */
8354   if (AOP_TYPE (right) == AOP_LIT)
8355     {
8356       if (genLeftShiftLiteral (left, right, result, ic))
8357       {
8358         return;
8359       }
8360     }
8361 #endif
8362
8363   /* shift count is unknown then we have to form
8364      a loop get the loop count in B : Note: we take
8365      only the lower order byte since shifting
8366      more that 32 bits make no sense anyway, ( the
8367      largest size of an object can be only 32 bits ) */
8368
8369   if (AOP_TYPE (right) == AOP_LIT)
8370   {
8371       /* Really should be handled by genLeftShiftLiteral,
8372        * but since I'm too lazy to fix that today, at least we can make
8373        * some small improvement.
8374        */
8375        emitcode("mov", "b,#!constbyte",
8376                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8377   }
8378   else
8379   {
8380       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8381       emitcode ("inc", "b");
8382   }
8383   freeAsmop (right, NULL, ic, TRUE);
8384   aopOp (left, ic, FALSE, FALSE);
8385   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8386
8387   /* now move the left to the result if they are not the
8388      same */
8389   if (!sameRegs (AOP (left), AOP (result)) &&
8390       AOP_SIZE (result) > 1)
8391     {
8392
8393       size = AOP_SIZE (result);
8394       offset = 0;
8395       _startLazyDPSEvaluation ();
8396       while (size--)
8397         {
8398           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8399           if (*l == '@' && (IS_AOP_PREG (result)))
8400             {
8401
8402               emitcode ("mov", "a,%s", l);
8403               aopPut (AOP (result), "a", offset);
8404             }
8405           else
8406             aopPut (AOP (result), l, offset);
8407           offset++;
8408         }
8409       _endLazyDPSEvaluation ();
8410     }
8411
8412   tlbl = newiTempLabel (NULL);
8413   size = AOP_SIZE (result);
8414   offset = 0;
8415   tlbl1 = newiTempLabel (NULL);
8416
8417   /* if it is only one byte then */
8418   if (size == 1)
8419     {
8420       symbol *tlbl1 = newiTempLabel (NULL);
8421
8422       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8423       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8424       emitcode ("", "!tlabeldef", tlbl->key + 100);
8425       emitcode ("add", "a,acc");
8426       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8428       aopPut (AOP (result), "a", 0);
8429       goto release;
8430     }
8431
8432   reAdjustPreg (AOP (result));
8433
8434   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8435   emitcode ("", "!tlabeldef", tlbl->key + 100);
8436   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8437   emitcode ("add", "a,acc");
8438   aopPut (AOP (result), "a", offset++);
8439   _startLazyDPSEvaluation ();
8440   while (--size)
8441     {
8442       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8443       emitcode ("rlc", "a");
8444       aopPut (AOP (result), "a", offset++);
8445     }
8446   _endLazyDPSEvaluation ();
8447   reAdjustPreg (AOP (result));
8448
8449   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8450   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8451 release:
8452   freeAsmop (left, NULL, ic, TRUE);
8453   freeAsmop (result, NULL, ic, TRUE);
8454 }
8455
8456 #ifdef BETTER_LITERAL_SHIFT
8457 /*-----------------------------------------------------------------*/
8458 /* genrshOne - right shift a one byte quantity by known count      */
8459 /*-----------------------------------------------------------------*/
8460 static void
8461 genrshOne (operand * result, operand * left,
8462            int shCount, int sign)
8463 {
8464   D (emitcode (";", "genrshOne"););
8465   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8466 }
8467 #endif
8468
8469 #ifdef BETTER_LITERAL_SHIFT
8470 /*-----------------------------------------------------------------*/
8471 /* genrshTwo - right shift two bytes by known amount != 0          */
8472 /*-----------------------------------------------------------------*/
8473 static void
8474 genrshTwo (operand * result, operand * left,
8475            int shCount, int sign)
8476 {
8477   D (emitcode (";", "genrshTwo"););
8478
8479   /* if shCount >= 8 */
8480   if (shCount >= 8)
8481     {
8482       shCount -= 8;
8483       _startLazyDPSEvaluation();
8484       if (shCount)
8485       {
8486         shiftR1Left2Result (left, MSB16, result, LSB,
8487                             shCount, sign);
8488       }                     
8489       else
8490       {
8491         movLeft2Result (left, MSB16, result, LSB, sign);
8492       }
8493       addSign (result, MSB16, sign);
8494       _endLazyDPSEvaluation();
8495     }
8496
8497   /*  1 <= shCount <= 7 */
8498   else
8499   {
8500     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8501   }
8502 }
8503 #endif
8504
8505 /*-----------------------------------------------------------------*/
8506 /* shiftRLong - shift right one long from left to result           */
8507 /* offl = LSB or MSB16                                             */
8508 /*-----------------------------------------------------------------*/
8509 static void
8510 shiftRLong (operand * left, int offl,
8511             operand * result, int sign)
8512 {
8513   int isSameRegs=sameRegs(AOP(left),AOP(result));
8514
8515   if (isSameRegs && offl>1) {
8516     // we are in big trouble, but this shouldn't happen
8517     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8518   }
8519
8520   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8521   
8522   if (offl==MSB16) {
8523     // shift is > 8
8524     if (sign) {
8525       emitcode ("rlc", "a");
8526       emitcode ("subb", "a,acc");
8527       emitcode ("xch", "a,%s",
8528                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8529     } else {
8530       aopPut (AOP(result), zero, MSB32);
8531     }
8532   }
8533
8534   if (!sign) {
8535     emitcode ("clr", "c");
8536   } else {
8537     emitcode ("mov", "c,acc.7");
8538   }
8539
8540   emitcode ("rrc", "a");
8541
8542   if (isSameRegs && offl==MSB16) {
8543     emitcode ("xch",
8544               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8545   } else {
8546     aopPut (AOP (result), "a", MSB32);
8547     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8548   }
8549
8550   emitcode ("rrc", "a");
8551   if (isSameRegs && offl==1) {
8552     emitcode ("xch", "a,%s",
8553               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8554   } else {
8555     aopPut (AOP (result), "a", MSB24);
8556     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8557   }
8558   emitcode ("rrc", "a");
8559   aopPut (AOP (result), "a", MSB16 - offl);
8560
8561   if (offl == LSB)
8562     {
8563       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8564       emitcode ("rrc", "a");
8565       aopPut (AOP (result), "a", LSB);
8566     }
8567 }
8568
8569 /*-----------------------------------------------------------------*/
8570 /* genrshFour - shift four byte by a known amount != 0             */
8571 /*-----------------------------------------------------------------*/
8572 static void
8573 genrshFour (operand * result, operand * left,
8574             int shCount, int sign)
8575 {
8576   D (emitcode (";", "genrshFour"););
8577
8578   /* if shifting more that 3 bytes */
8579   if (shCount >= 24)
8580     {
8581       shCount -= 24;
8582       _startLazyDPSEvaluation();
8583       if (shCount)
8584         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8585       else
8586         movLeft2Result (left, MSB32, result, LSB, sign);
8587       addSign (result, MSB16, sign);
8588       _endLazyDPSEvaluation();
8589     }
8590   else if (shCount >= 16)
8591     {
8592       shCount -= 16;
8593       _startLazyDPSEvaluation();
8594       if (shCount)
8595         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8596       else
8597         {
8598           movLeft2Result (left, MSB24, result, LSB, 0);
8599           movLeft2Result (left, MSB32, result, MSB16, sign);
8600         }
8601       addSign (result, MSB24, sign);
8602       _endLazyDPSEvaluation();
8603     }
8604   else if (shCount >= 8)
8605     {
8606       shCount -= 8;
8607       _startLazyDPSEvaluation();
8608       if (shCount == 1)
8609         {
8610             shiftRLong (left, MSB16, result, sign);
8611         }
8612       else if (shCount == 0)
8613         {
8614           movLeft2Result (left, MSB16, result, LSB, 0);
8615           movLeft2Result (left, MSB24, result, MSB16, 0);
8616           movLeft2Result (left, MSB32, result, MSB24, sign);
8617           addSign (result, MSB32, sign);
8618         }
8619       else
8620         {
8621           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8622           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8623           /* the last shift is signed */
8624           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8625           addSign (result, MSB32, sign);
8626         }
8627         _endLazyDPSEvaluation();
8628     }
8629   else
8630     {   
8631         /* 1 <= shCount <= 7 */
8632       if (shCount <= 2)
8633         {
8634           shiftRLong (left, LSB, result, sign);
8635           if (shCount == 2)
8636             shiftRLong (result, LSB, result, sign);
8637         }
8638       else
8639         {
8640           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8641           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8642           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8643         }
8644     }
8645 }
8646
8647 #ifdef BETTER_LITERAL_SHIFT
8648 /*-----------------------------------------------------------------*/
8649 /* genRightShiftLiteral - right shifting by known count            */
8650 /*-----------------------------------------------------------------*/
8651 static bool
8652 genRightShiftLiteral (operand * left,
8653                       operand * right,
8654                       operand * result,
8655                       iCode * ic,
8656                       int sign)
8657 {
8658   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8659   int size;
8660
8661   size = getSize (operandType (result));
8662
8663   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8664
8665   /* We only handle certain easy cases so far. */
8666   if ((shCount != 0)
8667    && (shCount < (size * 8))
8668    && (size != 1)
8669    && (size != 2)
8670    && (size != 4))
8671   {
8672       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8673       return FALSE;
8674   }
8675
8676   freeAsmop (right, NULL, ic, TRUE);
8677
8678   aopOp (left, ic, FALSE, FALSE);
8679   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8680
8681 #if VIEW_SIZE
8682   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8683             AOP_SIZE (left));
8684 #endif
8685
8686   /* test the LEFT size !!! */
8687
8688   /* I suppose that the left size >= result size */
8689   if (shCount == 0)
8690   {
8691       size = getDataSize (result);
8692       _startLazyDPSEvaluation();
8693       while (size--)
8694       {
8695         movLeft2Result (left, size, result, size, 0);
8696       }
8697       _endLazyDPSEvaluation();
8698   }
8699   else if (shCount >= (size * 8))
8700     {
8701       if (sign)
8702       {
8703         /* get sign in acc.7 */
8704         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8705       }
8706       addSign (result, LSB, sign);
8707     }
8708   else
8709     {
8710       switch (size)
8711         {
8712         case 1:
8713           genrshOne (result, left, shCount, sign);
8714           break;
8715
8716         case 2:
8717           genrshTwo (result, left, shCount, sign);
8718           break;
8719 #if 1
8720         case 4:
8721           genrshFour (result, left, shCount, sign);
8722           break;
8723 #endif    
8724         default:
8725           break;
8726         }
8727     }
8728   freeAsmop (left, NULL, ic, TRUE);
8729   freeAsmop (result, NULL, ic, TRUE);
8730   
8731   return TRUE;
8732 }
8733 #endif
8734
8735 /*-----------------------------------------------------------------*/
8736 /* genSignedRightShift - right shift of signed number              */
8737 /*-----------------------------------------------------------------*/
8738 static void
8739 genSignedRightShift (iCode * ic)
8740 {
8741   operand *right, *left, *result;
8742   int size, offset;
8743   char *l;
8744   symbol *tlbl, *tlbl1;
8745
8746   D (emitcode (";", "genSignedRightShift "););
8747
8748   /* we do it the hard way put the shift count in b
8749      and loop thru preserving the sign */
8750
8751   right = IC_RIGHT (ic);
8752   left = IC_LEFT (ic);
8753   result = IC_RESULT (ic);
8754
8755   aopOp (right, ic, FALSE, FALSE);
8756
8757 #ifdef BETTER_LITERAL_SHIFT
8758   if (AOP_TYPE (right) == AOP_LIT)
8759     {
8760       if (genRightShiftLiteral (left, right, result, ic, 1))
8761       {
8762         return;
8763       }
8764     }
8765 #endif
8766   /* shift count is unknown then we have to form
8767      a loop get the loop count in B : Note: we take
8768      only the lower order byte since shifting
8769      more that 32 bits make no sense anyway, ( the
8770      largest size of an object can be only 32 bits ) */
8771
8772   if (AOP_TYPE (right) == AOP_LIT)
8773   {
8774       /* Really should be handled by genRightShiftLiteral,
8775        * but since I'm too lazy to fix that today, at least we can make
8776        * some small improvement.
8777        */
8778        emitcode("mov", "b,#!constbyte",
8779                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8780   }
8781   else
8782   {
8783         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8784         emitcode ("inc", "b");
8785   }
8786   freeAsmop (right, NULL, ic, TRUE);
8787   aopOp (left, ic, FALSE, FALSE);
8788   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8789
8790   /* now move the left to the result if they are not the
8791      same */
8792   if (!sameRegs (AOP (left), AOP (result)) &&
8793       AOP_SIZE (result) > 1)
8794     {
8795
8796       size = AOP_SIZE (result);
8797       offset = 0;
8798       _startLazyDPSEvaluation ();
8799       while (size--)
8800         {
8801           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8802           if (*l == '@' && IS_AOP_PREG (result))
8803             {
8804
8805               emitcode ("mov", "a,%s", l);
8806               aopPut (AOP (result), "a", offset);
8807             }
8808           else
8809             aopPut (AOP (result), l, offset);
8810           offset++;
8811         }
8812       _endLazyDPSEvaluation ();
8813     }
8814
8815   /* mov the highest order bit to OVR */
8816   tlbl = newiTempLabel (NULL);
8817   tlbl1 = newiTempLabel (NULL);
8818
8819   size = AOP_SIZE (result);
8820   offset = size - 1;
8821   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8822   emitcode ("rlc", "a");
8823   emitcode ("mov", "ov,c");
8824   /* if it is only one byte then */
8825   if (size == 1)
8826     {
8827       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8828       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8829       emitcode ("", "!tlabeldef", tlbl->key + 100);
8830       emitcode ("mov", "c,ov");
8831       emitcode ("rrc", "a");
8832       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8833       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8834       aopPut (AOP (result), "a", 0);
8835       goto release;
8836     }
8837
8838   reAdjustPreg (AOP (result));
8839   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8840   emitcode ("", "!tlabeldef", tlbl->key + 100);
8841   emitcode ("mov", "c,ov");
8842   _startLazyDPSEvaluation ();
8843   while (size--)
8844     {
8845       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8846       emitcode ("rrc", "a");
8847       aopPut (AOP (result), "a", offset--);
8848     }
8849   _endLazyDPSEvaluation ();
8850   reAdjustPreg (AOP (result));
8851   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8852   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8853
8854 release:
8855   freeAsmop (left, NULL, ic, TRUE);
8856   freeAsmop (result, NULL, ic, TRUE);
8857 }
8858
8859 /*-----------------------------------------------------------------*/
8860 /* genRightShift - generate code for right shifting                */
8861 /*-----------------------------------------------------------------*/
8862 static void
8863 genRightShift (iCode * ic)
8864 {
8865   operand *right, *left, *result;
8866   sym_link *retype;
8867   int size, offset;
8868   char *l;
8869   symbol *tlbl, *tlbl1;
8870
8871   D (emitcode (";", "genRightShift "););
8872
8873   /* if signed then we do it the hard way preserve the
8874      sign bit moving it inwards */
8875   retype = getSpec (operandType (IC_RESULT (ic)));
8876
8877   if (!SPEC_USIGN (retype))
8878     {
8879       genSignedRightShift (ic);
8880       return;
8881     }
8882
8883   /* signed & unsigned types are treated the same : i.e. the
8884      signed is NOT propagated inwards : quoting from the
8885      ANSI - standard : "for E1 >> E2, is equivalent to division
8886      by 2**E2 if unsigned or if it has a non-negative value,
8887      otherwise the result is implementation defined ", MY definition
8888      is that the sign does not get propagated */
8889
8890   right = IC_RIGHT (ic);
8891   left = IC_LEFT (ic);
8892   result = IC_RESULT (ic);
8893
8894   aopOp (right, ic, FALSE, FALSE);
8895
8896 #ifdef BETTER_LITERAL_SHIFT
8897   /* if the shift count is known then do it
8898      as efficiently as possible */
8899   if (AOP_TYPE (right) == AOP_LIT)
8900     {
8901       if (genRightShiftLiteral (left, right, result, ic, 0))
8902       {
8903         return;
8904       }
8905     }
8906 #endif
8907
8908   /* shift count is unknown then we have to form
8909      a loop get the loop count in B : Note: we take
8910      only the lower order byte since shifting
8911      more that 32 bits make no sense anyway, ( the
8912      largest size of an object can be only 32 bits ) */
8913   
8914   if (AOP_TYPE (right) == AOP_LIT)
8915   {
8916       /* Really should be handled by genRightShiftLiteral,
8917        * but since I'm too lazy to fix that today, at least we can make
8918        * some small improvement.
8919        */
8920        emitcode("mov", "b,#!constbyte",
8921                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8922   }
8923   else
8924   {
8925       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8926       emitcode ("inc", "b");
8927   }
8928   freeAsmop (right, NULL, ic, TRUE);
8929   aopOp (left, ic, FALSE, FALSE);
8930   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8931
8932   /* now move the left to the result if they are not the
8933      same */
8934   if (!sameRegs (AOP (left), AOP (result)) &&
8935       AOP_SIZE (result) > 1)
8936     {
8937
8938       size = AOP_SIZE (result);
8939       offset = 0;
8940       _startLazyDPSEvaluation ();
8941       while (size--)
8942         {
8943           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8944           if (*l == '@' && IS_AOP_PREG (result))
8945             {
8946
8947               emitcode ("mov", "a,%s", l);
8948               aopPut (AOP (result), "a", offset);
8949             }
8950           else
8951             aopPut (AOP (result), l, offset);
8952           offset++;
8953         }
8954       _endLazyDPSEvaluation ();
8955     }
8956
8957   tlbl = newiTempLabel (NULL);
8958   tlbl1 = newiTempLabel (NULL);
8959   size = AOP_SIZE (result);
8960   offset = size - 1;
8961
8962   /* if it is only one byte then */
8963   if (size == 1)
8964     {
8965       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8966       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8967       emitcode ("", "!tlabeldef", tlbl->key + 100);
8968       CLRC;
8969       emitcode ("rrc", "a");
8970       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8971       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8972       aopPut (AOP (result), "a", 0);
8973       goto release;
8974     }
8975
8976   reAdjustPreg (AOP (result));
8977   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8978   emitcode ("", "!tlabeldef", tlbl->key + 100);
8979   CLRC;
8980   _startLazyDPSEvaluation ();
8981   while (size--)
8982     {
8983       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8984       emitcode ("rrc", "a");
8985       aopPut (AOP (result), "a", offset--);
8986     }
8987   _endLazyDPSEvaluation ();
8988   reAdjustPreg (AOP (result));
8989
8990   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8991   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8992
8993 release:
8994   freeAsmop (left, NULL, ic, TRUE);
8995   freeAsmop (result, NULL, ic, TRUE);
8996 }
8997
8998
8999 /*-----------------------------------------------------------------*/
9000 /* emitPtrByteGet - emits code to get a byte into A through a      */
9001 /*                  pointer register (R0, R1, or DPTR). The        */
9002 /*                  original value of A can be preserved in B.     */
9003 /*-----------------------------------------------------------------*/
9004 static void
9005 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9006 {
9007   switch (p_type)
9008     {
9009     case IPOINTER:
9010     case POINTER:
9011       if (preserveAinB)
9012         emitcode ("mov", "b,a");
9013       emitcode ("mov", "a,@%s", rname);
9014       break;
9015
9016     case PPOINTER:
9017       if (preserveAinB)
9018         emitcode ("mov", "b,a");
9019       emitcode ("movx", "a,@%s", rname);
9020       break;
9021       
9022     case FPOINTER:
9023       if (preserveAinB)
9024         emitcode ("mov", "b,a");
9025       emitcode ("movx", "a,@dptr");
9026       break;
9027
9028     case CPOINTER:
9029       if (preserveAinB)
9030         emitcode ("mov", "b,a");
9031       emitcode ("clr", "a");
9032       emitcode ("movc", "a,@a+dptr");
9033       break;
9034
9035     case GPOINTER:
9036       if (preserveAinB)
9037         {
9038           emitcode ("push", "b");
9039           emitcode ("push", "acc");
9040         }
9041       emitcode ("lcall", "__gptrget");
9042       if (preserveAinB)
9043         emitcode ("pop", "b");
9044       break;
9045     }
9046 }
9047
9048 /*-----------------------------------------------------------------*/
9049 /* emitPtrByteSet - emits code to set a byte from src through a    */
9050 /*                  pointer register (R0, R1, or DPTR).            */
9051 /*-----------------------------------------------------------------*/
9052 static void
9053 emitPtrByteSet (char *rname, int p_type, char *src)
9054 {
9055   switch (p_type)
9056     {
9057     case IPOINTER:
9058     case POINTER:
9059       if (*src=='@')
9060         {
9061           MOVA (src);
9062           emitcode ("mov", "@%s,a", rname);
9063         }
9064       else
9065         emitcode ("mov", "@%s,%s", rname, src);
9066       break;
9067
9068     case PPOINTER:
9069       MOVA (src);
9070       emitcode ("movx", "@%s,a", rname);
9071       break;
9072       
9073     case FPOINTER:
9074       MOVA (src);
9075       emitcode ("movx", "@dptr,a");
9076       break;
9077
9078     case GPOINTER:
9079       MOVA (src);
9080       emitcode ("lcall", "__gptrput");
9081       break;
9082     }
9083 }
9084
9085 /*-----------------------------------------------------------------*/
9086 /* genUnpackBits - generates code for unpacking bits               */
9087 /*-----------------------------------------------------------------*/
9088 static void
9089 genUnpackBits (operand * result, char *rname, int ptype)
9090 {
9091   int offset = 0;       /* result byte offset */
9092   int rsize;            /* result size */
9093   int rlen = 0;         /* remaining bitfield length */
9094   sym_link *etype;      /* bitfield type information */
9095   int blen;             /* bitfield length */
9096   int bstr;             /* bitfield starting bit within byte */
9097
9098   D(emitcode (";     genUnpackBits",""));
9099
9100   etype = getSpec (operandType (result));
9101   rsize = getSize (operandType (result));
9102   blen = SPEC_BLEN (etype);
9103   bstr = SPEC_BSTR (etype);
9104
9105   /* If the bitfield length is less than a byte */
9106   if (blen < 8)
9107     {
9108       emitPtrByteGet (rname, ptype, FALSE);
9109       AccRsh (bstr);
9110       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9111       aopPut (AOP (result), "a", offset++);
9112       goto finish;
9113     }
9114
9115   /* Bit field did not fit in a byte. Copy all
9116      but the partial byte at the end.  */
9117   for (rlen=blen;rlen>=8;rlen-=8)
9118     {
9119       emitPtrByteGet (rname, ptype, FALSE);
9120       aopPut (AOP (result), "a", offset++);
9121       if (rlen>8)
9122         emitcode ("inc", "%s", rname);
9123     }
9124
9125   /* Handle the partial byte at the end */
9126   if (rlen)
9127     {
9128       emitPtrByteGet (rname, ptype, FALSE);
9129       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9130       aopPut (AOP (result), "a", offset++);
9131     }
9132
9133 finish:
9134   if (offset < rsize)
9135     {
9136       rsize -= offset;
9137       while (rsize--)
9138         aopPut (AOP (result), zero, offset++);
9139     }
9140 }
9141
9142
9143 /*-----------------------------------------------------------------*/
9144 /* genDataPointerGet - generates code when ptr offset is known     */
9145 /*-----------------------------------------------------------------*/
9146 static void
9147 genDataPointerGet (operand * left,
9148                    operand * result,
9149                    iCode * ic)
9150 {
9151   char *l;
9152   char buff[256];
9153   int size, offset = 0;
9154   aopOp (result, ic, TRUE, FALSE);
9155
9156   /* get the string representation of the name */
9157   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9158   size = AOP_SIZE (result);
9159   _startLazyDPSEvaluation ();
9160   while (size--)
9161     {
9162         if (offset)
9163         {
9164             SNPRINTF (buff, sizeof(buff), 
9165                       "(%s + %d)", l + 1, offset);
9166         }
9167         else
9168         {
9169             SNPRINTF (buff, sizeof(buff), 
9170                       "%s", l + 1);
9171         }
9172       aopPut (AOP (result), buff, offset++);
9173     }
9174   _endLazyDPSEvaluation ();
9175
9176   freeAsmop (left, NULL, ic, TRUE);
9177   freeAsmop (result, NULL, ic, TRUE);
9178 }
9179
9180 /*-----------------------------------------------------------------*/
9181 /* genNearPointerGet - emitcode for near pointer fetch             */
9182 /*-----------------------------------------------------------------*/
9183 static void
9184 genNearPointerGet (operand * left,
9185                    operand * result,
9186                    iCode * ic,
9187                    iCode *pi)
9188 {
9189   asmop *aop = NULL;
9190   regs *preg;
9191   char *rname;
9192   sym_link *rtype, *retype, *letype;
9193   sym_link *ltype = operandType (left);
9194   char buff[80];
9195
9196   rtype = operandType (result);
9197   retype = getSpec (rtype);
9198   letype = getSpec (ltype);
9199
9200   aopOp (left, ic, FALSE, FALSE);
9201
9202   /* if left is rematerialisable and
9203      result is not bit variable type and
9204      the left is pointer to data space i.e
9205      lower 128 bytes of space */
9206   if (AOP_TYPE (left) == AOP_IMMD &&
9207       !IS_BITVAR (retype) &&
9208       !IS_BITVAR (letype) &&
9209       DCL_TYPE (ltype) == POINTER)
9210     {
9211       genDataPointerGet (left, result, ic);
9212       return;
9213     }
9214
9215   /* if the value is already in a pointer register
9216      then don't need anything more */
9217   if (!AOP_INPREG (AOP (left)))
9218     {
9219       /* otherwise get a free pointer register */
9220       aop = newAsmop (0);
9221       preg = getFreePtr (ic, &aop, FALSE);
9222       emitcode ("mov", "%s,%s",
9223                 preg->name,
9224                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9225       rname = preg->name;
9226     }
9227   else
9228     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9229
9230   freeAsmop (left, NULL, ic, TRUE);
9231   aopOp (result, ic, FALSE, FALSE);
9232
9233   /* if bitfield then unpack the bits */
9234   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9235     genUnpackBits (result, rname, POINTER);
9236   else
9237     {
9238       /* we have can just get the values */
9239       int size = AOP_SIZE (result);
9240       int offset = 0;
9241
9242       while (size--)
9243         {
9244           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9245             {
9246
9247               emitcode ("mov", "a,@%s", rname);
9248               aopPut (AOP (result), "a", offset);
9249             }
9250           else
9251             {
9252               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9253               aopPut (AOP (result), buff, offset);
9254             }
9255           offset++;
9256           if (size || pi)
9257             {
9258                 emitcode ("inc", "%s", rname);
9259             }
9260         }
9261     }
9262
9263   /* now some housekeeping stuff */
9264   if (aop)
9265     {
9266       /* we had to allocate for this iCode */
9267       if (pi) { /* post increment present */
9268         aopPut(AOP ( left ),rname,0);
9269       }
9270       freeAsmop (NULL, aop, ic, TRUE);
9271     }
9272   else
9273     {
9274       /* we did not allocate which means left
9275          already in a pointer register, then
9276          if size > 0 && this could be used again
9277          we have to point it back to where it
9278          belongs */
9279       if (AOP_SIZE (result) > 1 &&
9280           !OP_SYMBOL (left)->remat &&
9281           (OP_SYMBOL (left)->liveTo > ic->seq ||
9282            ic->depth) &&
9283           !pi)
9284         {
9285           int size = AOP_SIZE (result) - 1;
9286           while (size--)
9287             emitcode ("dec", "%s", rname);
9288         }
9289     }
9290
9291   /* done */
9292   freeAsmop (result, NULL, ic, TRUE);
9293   if (pi) pi->generated = 1;
9294 }
9295
9296 /*-----------------------------------------------------------------*/
9297 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9298 /*-----------------------------------------------------------------*/
9299 static void
9300 genPagedPointerGet (operand * left,
9301                     operand * result,
9302                     iCode * ic,
9303                     iCode * pi)
9304 {
9305   asmop *aop = NULL;
9306   regs *preg;
9307   char *rname;
9308   sym_link *rtype, *retype, *letype;
9309
9310   rtype = operandType (result);
9311   retype = getSpec (rtype);
9312   letype = getSpec (operandType (left));
9313   aopOp (left, ic, FALSE, FALSE);
9314
9315   /* if the value is already in a pointer register
9316      then don't need anything more */
9317   if (!AOP_INPREG (AOP (left)))
9318     {
9319       /* otherwise get a free pointer register */
9320       aop = newAsmop (0);
9321       preg = getFreePtr (ic, &aop, FALSE);
9322       emitcode ("mov", "%s,%s",
9323                 preg->name,
9324                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9325       rname = preg->name;
9326     }
9327   else
9328     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9329
9330   freeAsmop (left, NULL, ic, TRUE);
9331   aopOp (result, ic, FALSE, FALSE);
9332
9333   /* if bitfield then unpack the bits */
9334   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9335     genUnpackBits (result, rname, PPOINTER);
9336   else
9337     {
9338       /* we have can just get the values */
9339       int size = AOP_SIZE (result);
9340       int offset = 0;
9341
9342       while (size--)
9343         {
9344
9345           emitcode ("movx", "a,@%s", rname);
9346           aopPut (AOP (result), "a", offset);
9347
9348           offset++;
9349
9350           if (size || pi)
9351             emitcode ("inc", "%s", rname);
9352         }
9353     }
9354
9355   /* now some housekeeping stuff */
9356   if (aop)
9357     {
9358       /* we had to allocate for this iCode */
9359       if (pi) aopPut ( AOP (left), rname, 0);
9360       freeAsmop (NULL, aop, ic, TRUE);
9361     }
9362   else
9363     {
9364       /* we did not allocate which means left
9365          already in a pointer register, then
9366          if size > 0 && this could be used again
9367          we have to point it back to where it
9368          belongs */
9369       if (AOP_SIZE (result) > 1 &&
9370           !OP_SYMBOL (left)->remat &&
9371           (OP_SYMBOL (left)->liveTo > ic->seq ||
9372            ic->depth) &&
9373           !pi)
9374         {
9375           int size = AOP_SIZE (result) - 1;
9376           while (size--)
9377             emitcode ("dec", "%s", rname);
9378         }
9379     }
9380
9381   /* done */
9382   freeAsmop (result, NULL, ic, TRUE);
9383   if (pi) pi->generated = 1;
9384 }
9385
9386 /*-----------------------------------------------------------------*/
9387 /* genFarPointerGet - gget value from far space                    */
9388 /*-----------------------------------------------------------------*/
9389 static void
9390 genFarPointerGet (operand * left,
9391                   operand * result, iCode * ic, iCode *pi)
9392 {
9393     int size, offset, dopi=1;
9394   sym_link *retype = getSpec (operandType (result));
9395   sym_link *letype = getSpec (operandType (left));
9396   D (emitcode (";", "genFarPointerGet"););
9397
9398   aopOp (left, ic, FALSE, FALSE);
9399
9400   /* if the operand is already in dptr
9401      then we do nothing else we move the value to dptr */
9402   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9403     {
9404       /* if this is remateriazable */
9405       if (AOP_TYPE (left) == AOP_IMMD)
9406         {
9407           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9408         }
9409       else
9410         {
9411           /* we need to get it byte by byte */
9412           _startLazyDPSEvaluation ();
9413           if (AOP_TYPE (left) != AOP_DPTR)
9414             {
9415               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9416               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9417               if (options.model == MODEL_FLAT24)
9418                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9419             }
9420           else
9421             {
9422               /* We need to generate a load to DPTR indirect through DPTR. */
9423               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9424               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9425               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9426               if (options.model == MODEL_FLAT24)
9427                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9428               emitcode ("pop", "dph");
9429               emitcode ("pop", "dpl");
9430               dopi =0;
9431             }
9432           _endLazyDPSEvaluation ();
9433         }
9434     }
9435   /* so dptr know contains the address */
9436   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9437
9438   /* if bit then unpack */
9439   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9440       if (AOP_INDPTRn(left)) {
9441           genSetDPTR(AOP(left)->aopu.dptr);
9442       }
9443       genUnpackBits (result, "dptr", FPOINTER);
9444       if (AOP_INDPTRn(left)) {
9445           genSetDPTR(0);
9446       }
9447   } else
9448     {
9449       size = AOP_SIZE (result);
9450       offset = 0;
9451
9452       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9453           while (size--) {
9454               genSetDPTR(AOP(left)->aopu.dptr);
9455               emitcode ("movx", "a,@dptr");
9456               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9457                   emitcode ("inc", "dptr");
9458               genSetDPTR (0);
9459               aopPut (AOP (result), "a", offset++);
9460           }
9461       } else {
9462           _startLazyDPSEvaluation ();
9463           while (size--) {
9464               if (AOP_INDPTRn(left)) {
9465                   genSetDPTR(AOP(left)->aopu.dptr);
9466               } else {
9467                   genSetDPTR (0);
9468               }
9469               _flushLazyDPS ();
9470               
9471               emitcode ("movx", "a,@dptr");
9472               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9473                   emitcode ("inc", "dptr");
9474               
9475               aopPut (AOP (result), "a", offset++);
9476           }
9477           _endLazyDPSEvaluation ();
9478       }
9479     }
9480   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9481       if (!AOP_INDPTRn(left)) {
9482           _startLazyDPSEvaluation ();
9483           aopPut ( AOP (left), "dpl", 0);
9484           aopPut ( AOP (left), "dph", 1);
9485           if (options.model == MODEL_FLAT24)
9486               aopPut ( AOP (left), "dpx", 2);
9487           _endLazyDPSEvaluation ();
9488       }
9489     pi->generated = 1;
9490   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9491              AOP_SIZE(result) > 1 &&
9492              IS_SYMOP(left) &&
9493              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9494       
9495       size = AOP_SIZE (result) - 1;
9496       if (AOP_INDPTRn(left)) {
9497           genSetDPTR(AOP(left)->aopu.dptr);
9498       }
9499       while (size--) emitcode ("lcall","__decdptr");
9500       if (AOP_INDPTRn(left)) {
9501           genSetDPTR(0);
9502       }
9503   }
9504
9505   freeAsmop (left, NULL, ic, TRUE);
9506   freeAsmop (result, NULL, ic, TRUE);
9507 }
9508
9509 /*-----------------------------------------------------------------*/
9510 /* genCodePointerGet - get value from code space                  */
9511 /*-----------------------------------------------------------------*/
9512 static void
9513 genCodePointerGet (operand * left,
9514                     operand * result, iCode * ic, iCode *pi)
9515 {
9516   int size, offset, dopi=1;
9517   sym_link *retype = getSpec (operandType (result));
9518
9519   aopOp (left, ic, FALSE, FALSE);
9520
9521   /* if the operand is already in dptr
9522      then we do nothing else we move the value to dptr */
9523   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9524     {
9525       /* if this is remateriazable */
9526       if (AOP_TYPE (left) == AOP_IMMD)
9527         {
9528           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9529         }
9530       else
9531         {                       /* we need to get it byte by byte */
9532           _startLazyDPSEvaluation ();
9533           if (AOP_TYPE (left) != AOP_DPTR)
9534             {
9535               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9536               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9537               if (options.model == MODEL_FLAT24)
9538                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9539             }
9540           else
9541             {
9542               /* We need to generate a load to DPTR indirect through DPTR. */
9543               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9544               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9545               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9546               if (options.model == MODEL_FLAT24)
9547                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9548               emitcode ("pop", "dph");
9549               emitcode ("pop", "dpl");
9550               dopi=0;
9551             }
9552           _endLazyDPSEvaluation ();
9553         }
9554     }
9555   /* so dptr know contains the address */
9556   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9557
9558   /* if bit then unpack */
9559   if (IS_BITVAR (retype)) {
9560       if (AOP_INDPTRn(left)) {
9561           genSetDPTR(AOP(left)->aopu.dptr);
9562       }
9563       genUnpackBits (result, "dptr", CPOINTER);
9564       if (AOP_INDPTRn(left)) {
9565           genSetDPTR(0);
9566       }
9567   } else
9568     {
9569       size = AOP_SIZE (result);
9570       offset = 0;
9571       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9572           while (size--) {
9573               genSetDPTR(AOP(left)->aopu.dptr);
9574               emitcode ("clr", "a");
9575               emitcode ("movc", "a,@a+dptr");
9576               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9577                   emitcode ("inc", "dptr");
9578               genSetDPTR (0);
9579               aopPut (AOP (result), "a", offset++);
9580           }
9581       } else {
9582           _startLazyDPSEvaluation ();
9583           while (size--)
9584               {
9585                   if (AOP_INDPTRn(left)) {
9586                       genSetDPTR(AOP(left)->aopu.dptr);
9587                   } else {
9588                       genSetDPTR (0);
9589                   }
9590                   _flushLazyDPS ();
9591                   
9592                   emitcode ("clr", "a");
9593                   emitcode ("movc", "a,@a+dptr");
9594                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9595                       emitcode ("inc", "dptr");
9596                   aopPut (AOP (result), "a", offset++);
9597               }
9598           _endLazyDPSEvaluation ();
9599       }
9600     }
9601   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9602       if (!AOP_INDPTRn(left)) {
9603           _startLazyDPSEvaluation ();
9604           
9605           aopPut ( AOP (left), "dpl", 0);
9606           aopPut ( AOP (left), "dph", 1);
9607           if (options.model == MODEL_FLAT24)
9608               aopPut ( AOP (left), "dpx", 2);
9609
9610           _endLazyDPSEvaluation ();
9611       }
9612       pi->generated = 1;
9613   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9614              AOP_SIZE(result) > 1 &&
9615              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9616       
9617       size = AOP_SIZE (result) - 1;
9618       if (AOP_INDPTRn(left)) {
9619           genSetDPTR(AOP(left)->aopu.dptr);
9620       }
9621       while (size--) emitcode ("lcall","__decdptr");
9622       if (AOP_INDPTRn(left)) {
9623           genSetDPTR(0);
9624       }
9625   }
9626   
9627   freeAsmop (left, NULL, ic, TRUE);
9628   freeAsmop (result, NULL, ic, TRUE);
9629 }
9630
9631 /*-----------------------------------------------------------------*/
9632 /* genGenPointerGet - gget value from generic pointer space        */
9633 /*-----------------------------------------------------------------*/
9634 static void
9635 genGenPointerGet (operand * left,
9636                   operand * result, iCode * ic, iCode * pi)
9637 {
9638   int size, offset;
9639   sym_link *retype = getSpec (operandType (result));
9640   sym_link *letype = getSpec (operandType (left));
9641
9642   D (emitcode (";", "genGenPointerGet "); );
9643
9644   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9645
9646   /* if the operand is already in dptr
9647      then we do nothing else we move the value to dptr */
9648   if (AOP_TYPE (left) != AOP_STR)
9649     {
9650       /* if this is remateriazable */
9651       if (AOP_TYPE (left) == AOP_IMMD)
9652         {
9653           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9654           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9655             {
9656                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9657             }
9658             else
9659             {
9660                 emitcode ("mov", "b,#%d", pointerCode (retype));
9661             }
9662         }
9663       else
9664         {                       /* we need to get it byte by byte */
9665             _startLazyDPSEvaluation ();
9666             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9667             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9668             if (options.model == MODEL_FLAT24) {
9669                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9670                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9671             } else {
9672                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9673             }
9674             _endLazyDPSEvaluation ();
9675         }
9676     }
9677
9678   /* so dptr-b now contains the address */
9679   _G.bInUse++;
9680   aopOp (result, ic, FALSE, TRUE);
9681   _G.bInUse--;
9682
9683   /* if bit then unpack */
9684   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9685   {
9686     genUnpackBits (result, "dptr", GPOINTER);
9687   }
9688   else
9689     {
9690         size = AOP_SIZE (result);
9691         offset = 0;
9692
9693         while (size--)
9694         {
9695             if (size)
9696             {
9697                 // Get two bytes at a time, results in _AP & A.
9698                 // dptr will be incremented ONCE by __gptrgetWord.
9699                 //
9700                 // Note: any change here must be coordinated
9701                 // with the implementation of __gptrgetWord
9702                 // in device/lib/_gptrget.c
9703                 emitcode ("lcall", "__gptrgetWord");
9704                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9705                 aopPut (AOP (result), "a", offset++);
9706                 size--;
9707             }
9708             else
9709             {
9710                 // Only one byte to get.
9711                 emitcode ("lcall", "__gptrget");
9712                 aopPut (AOP (result), "a", offset++);
9713             }
9714             
9715             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9716             {
9717                 emitcode ("inc", "dptr");
9718             }
9719         }
9720     }
9721
9722   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9723     _startLazyDPSEvaluation ();
9724       
9725     aopPut ( AOP (left), "dpl", 0);
9726     aopPut ( AOP (left), "dph", 1);
9727     if (options.model == MODEL_FLAT24) {
9728         aopPut ( AOP (left), "dpx", 2);
9729         aopPut ( AOP (left), "b", 3);   
9730     } else  aopPut ( AOP (left), "b", 2);       
9731     
9732     _endLazyDPSEvaluation ();
9733       
9734     pi->generated = 1;
9735   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9736              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9737       
9738       size = AOP_SIZE (result) - 1;
9739       while (size--) emitcode ("lcall","__decdptr");
9740   }
9741
9742   freeAsmop (left, NULL, ic, TRUE);
9743   freeAsmop (result, NULL, ic, TRUE);
9744 }
9745
9746 /*-----------------------------------------------------------------*/
9747 /* genPointerGet - generate code for pointer get                   */
9748 /*-----------------------------------------------------------------*/
9749 static void
9750 genPointerGet (iCode * ic, iCode *pi)
9751 {
9752   operand *left, *result;
9753   sym_link *type, *etype;
9754   int p_type;
9755
9756   D (emitcode (";", "genPointerGet ");
9757     );
9758
9759   left = IC_LEFT (ic);
9760   result = IC_RESULT (ic);
9761
9762   /* depending on the type of pointer we need to
9763      move it to the correct pointer register */
9764   type = operandType (left);
9765   etype = getSpec (type);
9766   /* if left is of type of pointer then it is simple */
9767   if (IS_PTR (type) && !IS_FUNC (type->next))
9768     p_type = DCL_TYPE (type);
9769   else
9770     {
9771       /* we have to go by the storage class */
9772       p_type = PTR_TYPE (SPEC_OCLS (etype));
9773     }
9774   /* special case when cast remat */
9775   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9776       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9777           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9778           type = operandType (left);
9779           p_type = DCL_TYPE (type);
9780   }
9781   /* now that we have the pointer type we assign
9782      the pointer values */
9783   switch (p_type)
9784     {
9785
9786     case POINTER:
9787     case IPOINTER:
9788       genNearPointerGet (left, result, ic, pi);
9789       break;
9790
9791     case PPOINTER:
9792       genPagedPointerGet (left, result, ic, pi);
9793       break;
9794
9795     case FPOINTER:
9796       genFarPointerGet (left, result, ic, pi);
9797       break;
9798
9799     case CPOINTER:
9800       genCodePointerGet (left, result, ic, pi);
9801       break;
9802
9803     case GPOINTER:
9804       genGenPointerGet (left, result, ic, pi);
9805       break;
9806     }
9807
9808 }
9809
9810 /*-----------------------------------------------------------------*/
9811 /* genPackBits - generates code for packed bit storage             */
9812 /*-----------------------------------------------------------------*/
9813 static void
9814 genPackBits (sym_link * etype,
9815              operand * right,
9816              char *rname, int p_type)
9817 {
9818   int offset = 0;       /* source byte offset */
9819   int rlen = 0;         /* remaining bitfield length */
9820   int blen;             /* bitfield length */
9821   int bstr;             /* bitfield starting bit within byte */
9822   int litval;           /* source literal value (if AOP_LIT) */
9823   unsigned char mask;   /* bitmask within current byte */
9824
9825   D(emitcode (";     genPackBits",""));
9826
9827   blen = SPEC_BLEN (etype);
9828   bstr = SPEC_BSTR (etype);
9829
9830   /* If the bitfield length is less than a byte */
9831   if (blen < 8)
9832     {
9833       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9834               (unsigned char) (0xFF >> (8 - bstr)));
9835
9836       if (AOP_TYPE (right) == AOP_LIT)
9837         {
9838           /* Case with a bitfield length <8 and literal source
9839           */
9840           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9841           litval <<= bstr;
9842           litval &= (~mask) & 0xff;
9843           emitPtrByteGet (rname, p_type, FALSE);
9844           if ((mask|litval)!=0xff)
9845             emitcode ("anl","a,#!constbyte", mask);
9846           if (litval)
9847             emitcode ("orl","a,#!constbyte", litval);
9848         }
9849       else
9850         {
9851           if ((blen==1) && (p_type!=GPOINTER))
9852             {
9853               /* Case with a bitfield length == 1 and no generic pointer
9854               */
9855               if (AOP_TYPE (right) == AOP_CRY)
9856                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9857               else
9858                 {
9859                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9860                   emitcode ("rrc","a");
9861                 }
9862               emitPtrByteGet (rname, p_type, FALSE);
9863               emitcode ("mov","acc.%d,c",bstr);
9864             }
9865           else
9866             {
9867               /* Case with a bitfield length < 8 and arbitrary source
9868               */
9869               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9870               /* shift and mask source value */
9871               AccLsh (bstr);
9872               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9873
9874               /* transfer A to B and get next byte */
9875               emitPtrByteGet (rname, p_type, TRUE);
9876
9877               emitcode ("anl", "a,#!constbyte", mask);
9878               emitcode ("orl", "a,b");
9879               if (p_type == GPOINTER)
9880                 emitcode ("pop", "b");
9881            }
9882         }
9883
9884       emitPtrByteSet (rname, p_type, "a");
9885       return;
9886     }
9887
9888   /* Bit length is greater than 7 bits. In this case, copy  */
9889   /* all except the partial byte at the end                 */
9890   for (rlen=blen;rlen>=8;rlen-=8)
9891     {
9892       emitPtrByteSet (rname, p_type, 
9893                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9894       if (rlen>8)
9895         emitcode ("inc", "%s", rname);
9896     }
9897
9898   /* If there was a partial byte at the end */
9899   if (rlen)
9900     {
9901       mask = (((unsigned char) -1 << rlen) & 0xff);
9902       
9903       if (AOP_TYPE (right) == AOP_LIT)
9904         {
9905           /* Case with partial byte and literal source
9906           */
9907           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9908           litval >>= (blen-rlen);
9909           litval &= (~mask) & 0xff;
9910           emitPtrByteGet (rname, p_type, FALSE);
9911           if ((mask|litval)!=0xff)
9912             emitcode ("anl","a,#!constbyte", mask);
9913           if (litval)
9914             emitcode ("orl","a,#!constbyte", litval);
9915         }
9916       else
9917         {
9918           /* Case with partial byte and arbitrary source
9919           */
9920           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9921           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9922
9923           /* transfer A to B and get next byte */
9924           emitPtrByteGet (rname, p_type, TRUE);
9925
9926           emitcode ("anl", "a,#!constbyte", mask);
9927           emitcode ("orl", "a,b");
9928           if (p_type == GPOINTER)
9929             emitcode ("pop", "b");
9930         }
9931       emitPtrByteSet (rname, p_type, "a");
9932     }
9933
9934 }
9935
9936
9937 /*-----------------------------------------------------------------*/
9938 /* genDataPointerSet - remat pointer to data space                 */
9939 /*-----------------------------------------------------------------*/
9940 static void
9941 genDataPointerSet (operand * right,
9942                    operand * result,
9943                    iCode * ic)
9944 {
9945   int size, offset = 0;
9946   char *l, buff[256];
9947
9948   aopOp (right, ic, FALSE, FALSE);
9949
9950   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9951   size = AOP_SIZE (right);
9952   while (size--)
9953     {
9954       if (offset)
9955         {
9956             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9957         }
9958       else
9959         {
9960             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9961         }
9962         
9963       emitcode ("mov", "%s,%s", buff,
9964                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9965     }
9966
9967   freeAsmop (right, NULL, ic, TRUE);
9968   freeAsmop (result, NULL, ic, TRUE);
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerSet - emitcode for near pointer put                */
9973 /*-----------------------------------------------------------------*/
9974 static void
9975 genNearPointerSet (operand * right,
9976                    operand * result,
9977                    iCode * ic,
9978                    iCode * pi)
9979 {
9980   asmop *aop = NULL;
9981   char *rname, *l;
9982   sym_link *retype, *letype;
9983   sym_link *ptype = operandType (result);
9984
9985   retype = getSpec (operandType (right));
9986   letype = getSpec (ptype);
9987
9988   aopOp (result, ic, FALSE, FALSE);
9989
9990   /* if the result is rematerializable &
9991      in data space & not a bit variable */
9992   if (AOP_TYPE (result) == AOP_IMMD &&
9993       DCL_TYPE (ptype) == POINTER &&
9994       !IS_BITVAR (retype) &&
9995       !IS_BITVAR (letype))
9996     {
9997       genDataPointerSet (right, result, ic);
9998       return;
9999     }
10000
10001   /* if the value is already in a pointer register
10002      then don't need anything more */
10003   if (!AOP_INPREG (AOP (result)))
10004     {
10005       /* otherwise get a free pointer register */
10006       regs *preg;
10007         
10008       aop = newAsmop (0);
10009       preg = getFreePtr (ic, &aop, FALSE);
10010       emitcode ("mov", "%s,%s",
10011                 preg->name,
10012                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10013       rname = preg->name;
10014     }
10015   else
10016     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10017
10018   aopOp (right, ic, FALSE, FALSE);
10019
10020   /* if bitfield then unpack the bits */
10021   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10022     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10023   else
10024     {
10025       /* we have can just get the values */
10026       int size = AOP_SIZE (right);
10027       int offset = 0;
10028
10029       while (size--)
10030         {
10031           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10032           if (*l == '@')
10033             {
10034               MOVA (l);
10035               emitcode ("mov", "@%s,a", rname);
10036             }
10037           else
10038             emitcode ("mov", "@%s,%s", rname, l);
10039           if (size || pi)
10040             emitcode ("inc", "%s", rname);
10041           offset++;
10042         }
10043     }
10044
10045   /* now some housekeeping stuff */
10046   if (aop)
10047     {
10048       /* we had to allocate for this iCode */
10049       if (pi) aopPut (AOP (result),rname,0);
10050       freeAsmop (NULL, aop, ic, TRUE);
10051     }
10052   else
10053     {
10054       /* we did not allocate which means left
10055          already in a pointer register, then
10056          if size > 0 && this could be used again
10057          we have to point it back to where it
10058          belongs */
10059       if (AOP_SIZE (right) > 1 &&
10060           !OP_SYMBOL (result)->remat &&
10061           (OP_SYMBOL (result)->liveTo > ic->seq ||
10062            ic->depth) &&
10063           !pi)
10064         {
10065           int size = AOP_SIZE (right) - 1;
10066           while (size--)
10067             emitcode ("dec", "%s", rname);
10068         }
10069     }
10070
10071   /* done */
10072   if (pi) pi->generated = 1;
10073   freeAsmop (result, NULL, ic, TRUE);
10074   freeAsmop (right, NULL, ic, TRUE);
10075
10076
10077 }
10078
10079 /*-----------------------------------------------------------------*/
10080 /* genPagedPointerSet - emitcode for Paged pointer put             */
10081 /*-----------------------------------------------------------------*/
10082 static void
10083 genPagedPointerSet (operand * right,
10084                     operand * result,
10085                     iCode * ic,
10086                     iCode *pi)
10087 {
10088   asmop *aop = NULL;
10089   char *rname;
10090   sym_link *retype, *letype;
10091
10092   retype = getSpec (operandType (right));
10093   letype = getSpec (operandType (result));
10094
10095   aopOp (result, ic, FALSE, FALSE);
10096
10097   /* if the value is already in a pointer register
10098      then don't need anything more */
10099   if (!AOP_INPREG (AOP (result)))
10100     {
10101       /* otherwise get a free pointer register */
10102       regs *preg;
10103         
10104       aop = newAsmop (0);
10105       preg = getFreePtr (ic, &aop, FALSE);
10106       emitcode ("mov", "%s,%s",
10107                 preg->name,
10108                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10109       rname = preg->name;
10110     }
10111   else
10112     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10113
10114   aopOp (right, ic, FALSE, FALSE);
10115
10116   /* if bitfield then unpack the bits */
10117   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10118     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10119   else
10120     {
10121       /* we have can just get the values */
10122       int size = AOP_SIZE (right);
10123       int offset = 0;
10124
10125       while (size--)
10126         {
10127           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10128
10129           emitcode ("movx", "@%s,a", rname);
10130
10131           if (size || pi)
10132             emitcode ("inc", "%s", rname);
10133
10134           offset++;
10135         }
10136     }
10137
10138   /* now some housekeeping stuff */
10139   if (aop)
10140     {
10141       if (pi) aopPut (AOP (result),rname,0);
10142       /* we had to allocate for this iCode */
10143       freeAsmop (NULL, aop, ic, TRUE);
10144     }
10145   else
10146     {
10147       /* we did not allocate which means left
10148          already in a pointer register, then
10149          if size > 0 && this could be used again
10150          we have to point it back to where it
10151          belongs */
10152       if (AOP_SIZE (right) > 1 &&
10153           !OP_SYMBOL (result)->remat &&
10154           (OP_SYMBOL (result)->liveTo > ic->seq ||
10155            ic->depth) &&
10156           !pi)
10157         {
10158           int size = AOP_SIZE (right) - 1;
10159           while (size--)
10160             emitcode ("dec", "%s", rname);
10161         }
10162     }
10163
10164   /* done */
10165   if (pi) pi->generated = 1;
10166   freeAsmop (result, NULL, ic, TRUE);
10167   freeAsmop (right, NULL, ic, TRUE);
10168
10169
10170 }
10171
10172 /*-----------------------------------------------------------------*/
10173 /* genFarPointerSet - set value from far space                     */
10174 /*-----------------------------------------------------------------*/
10175 static void
10176 genFarPointerSet (operand * right,
10177                   operand * result, iCode * ic, iCode *pi)
10178 {
10179   int size, offset, dopi=1;
10180   sym_link *retype = getSpec (operandType (right));
10181   sym_link *letype = getSpec (operandType (result));
10182
10183   aopOp (result, ic, FALSE, FALSE);
10184
10185   /* if the operand is already in dptr
10186      then we do nothing else we move the value to dptr */
10187   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10188     {
10189       /* if this is remateriazable */
10190       if (AOP_TYPE (result) == AOP_IMMD)
10191         emitcode ("mov", "dptr,%s", 
10192                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10193       else
10194         {
10195           /* we need to get it byte by byte */
10196           _startLazyDPSEvaluation ();
10197           if (AOP_TYPE (result) != AOP_DPTR)
10198             {
10199               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10200               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10201               if (options.model == MODEL_FLAT24)
10202                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10203             }
10204           else
10205             {
10206               /* We need to generate a load to DPTR indirect through DPTR. */
10207               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10208                 
10209               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10210               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10211               if (options.model == MODEL_FLAT24)
10212                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10213               emitcode ("pop", "dph");
10214               emitcode ("pop", "dpl");
10215               dopi=0;
10216             }
10217           _endLazyDPSEvaluation ();
10218         }
10219     }
10220   /* so dptr know contains the address */
10221   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10222
10223   /* if bit then unpack */
10224   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10225       if (AOP_INDPTRn(result)) {
10226           genSetDPTR(AOP(result)->aopu.dptr);
10227       }
10228       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10229       if (AOP_INDPTRn(result)) {
10230           genSetDPTR(0);
10231       }
10232   } else {
10233       size = AOP_SIZE (right);
10234       offset = 0;
10235       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10236           while (size--) {
10237               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10238               
10239               genSetDPTR(AOP(result)->aopu.dptr);
10240               emitcode ("movx", "@dptr,a");
10241               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10242                   emitcode ("inc", "dptr");
10243               genSetDPTR (0);
10244           }
10245       } else {
10246           _startLazyDPSEvaluation ();
10247           while (size--) {
10248               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10249               
10250               if (AOP_INDPTRn(result)) {
10251                   genSetDPTR(AOP(result)->aopu.dptr);
10252               } else {
10253                   genSetDPTR (0);
10254               }
10255               _flushLazyDPS ();
10256               
10257               emitcode ("movx", "@dptr,a");
10258               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10259                   emitcode ("inc", "dptr");
10260           }
10261           _endLazyDPSEvaluation ();
10262       }
10263   }
10264   
10265   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10266       if (!AOP_INDPTRn(result)) {
10267           _startLazyDPSEvaluation ();
10268           
10269           aopPut (AOP(result),"dpl",0);
10270           aopPut (AOP(result),"dph",1);
10271           if (options.model == MODEL_FLAT24)
10272               aopPut (AOP(result),"dpx",2);
10273
10274           _endLazyDPSEvaluation ();
10275       }
10276       pi->generated=1;
10277   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10278              AOP_SIZE(right) > 1 &&
10279              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10280       
10281       size = AOP_SIZE (right) - 1;
10282       if (AOP_INDPTRn(result)) {
10283           genSetDPTR(AOP(result)->aopu.dptr);
10284       } 
10285       while (size--) emitcode ("lcall","__decdptr");
10286       if (AOP_INDPTRn(result)) {
10287           genSetDPTR(0);
10288       }
10289   }
10290   freeAsmop (result, NULL, ic, TRUE);
10291   freeAsmop (right, NULL, ic, TRUE);
10292 }
10293
10294 /*-----------------------------------------------------------------*/
10295 /* genGenPointerSet - set value from generic pointer space         */
10296 /*-----------------------------------------------------------------*/
10297 static void
10298 genGenPointerSet (operand * right,
10299                   operand * result, iCode * ic, iCode *pi)
10300 {
10301   int size, offset;
10302   sym_link *retype = getSpec (operandType (right));
10303   sym_link *letype = getSpec (operandType (result));
10304
10305   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10306
10307   /* if the operand is already in dptr
10308      then we do nothing else we move the value to dptr */
10309   if (AOP_TYPE (result) != AOP_STR)
10310     {
10311       _startLazyDPSEvaluation ();
10312       /* if this is remateriazable */
10313       if (AOP_TYPE (result) == AOP_IMMD)
10314         {
10315           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10316           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10317           {
10318               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10319           }
10320           else
10321           {
10322               emitcode ("mov", 
10323                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10324           }
10325         }
10326       else
10327         {                       /* we need to get it byte by byte */
10328           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10329           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10330           if (options.model == MODEL_FLAT24) {
10331             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10332             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10333           } else {
10334             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10335           }
10336         }
10337       _endLazyDPSEvaluation ();
10338     }
10339   /* so dptr + b now contains the address */
10340   _G.bInUse++;
10341   aopOp (right, ic, FALSE, TRUE);
10342   _G.bInUse--;
10343     
10344
10345   /* if bit then unpack */
10346   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10347     {
10348         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10349     }
10350   else
10351     {
10352         size = AOP_SIZE (right);
10353         offset = 0;
10354
10355         _startLazyDPSEvaluation ();
10356         while (size--)
10357         {
10358             if (size)
10359             {
10360                 // Set two bytes at a time, passed in _AP & A.
10361                 // dptr will be incremented ONCE by __gptrputWord.
10362                 //
10363                 // Note: any change here must be coordinated
10364                 // with the implementation of __gptrputWord
10365                 // in device/lib/_gptrput.c
10366                 emitcode("mov", "_ap, %s", 
10367                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10368                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10369                 
10370                 genSetDPTR (0);
10371                 _flushLazyDPS ();
10372                 emitcode ("lcall", "__gptrputWord");
10373                 size--;
10374             }
10375             else
10376             {
10377                 // Only one byte to put.
10378                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10379
10380                 genSetDPTR (0);
10381                 _flushLazyDPS ();               
10382                 emitcode ("lcall", "__gptrput");
10383             }
10384             
10385             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10386             {
10387                 emitcode ("inc", "dptr");
10388             }
10389         }
10390         _endLazyDPSEvaluation ();
10391     }
10392
10393   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10394       _startLazyDPSEvaluation ();
10395       
10396       aopPut (AOP(result),"dpl",0);
10397       aopPut (AOP(result),"dph",1);
10398       if (options.model == MODEL_FLAT24) {
10399           aopPut (AOP(result),"dpx",2);
10400           aopPut (AOP(result),"b",3);
10401       } else {
10402           aopPut (AOP(result),"b",2);
10403       }
10404       _endLazyDPSEvaluation ();
10405       
10406       pi->generated=1;
10407   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10408              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10409       
10410       size = AOP_SIZE (right) - 1;
10411       while (size--) emitcode ("lcall","__decdptr");
10412   }
10413   freeAsmop (result, NULL, ic, TRUE);
10414   freeAsmop (right, NULL, ic, TRUE);
10415 }
10416
10417 /*-----------------------------------------------------------------*/
10418 /* genPointerSet - stores the value into a pointer location        */
10419 /*-----------------------------------------------------------------*/
10420 static void
10421 genPointerSet (iCode * ic, iCode *pi)
10422 {
10423   operand *right, *result;
10424   sym_link *type, *etype;
10425   int p_type;
10426
10427   D (emitcode (";", "genPointerSet "););
10428
10429   right = IC_RIGHT (ic);
10430   result = IC_RESULT (ic);
10431
10432   /* depending on the type of pointer we need to
10433      move it to the correct pointer register */
10434   type = operandType (result);
10435   etype = getSpec (type);
10436   /* if left is of type of pointer then it is simple */
10437   if (IS_PTR (type) && !IS_FUNC (type->next))
10438     {
10439       p_type = DCL_TYPE (type);
10440     }
10441   else
10442     {
10443       /* we have to go by the storage class */
10444       p_type = PTR_TYPE (SPEC_OCLS (etype));
10445     }
10446   /* special case when cast remat */
10447   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10448       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10449           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10450           type = operandType (result);
10451           p_type = DCL_TYPE (type);
10452   }
10453
10454   /* now that we have the pointer type we assign
10455      the pointer values */
10456   switch (p_type)
10457     {
10458
10459     case POINTER:
10460     case IPOINTER:
10461       genNearPointerSet (right, result, ic, pi);
10462       break;
10463
10464     case PPOINTER:
10465       genPagedPointerSet (right, result, ic, pi);
10466       break;
10467
10468     case FPOINTER:
10469       genFarPointerSet (right, result, ic, pi);
10470       break;
10471
10472     case GPOINTER:
10473       genGenPointerSet (right, result, ic, pi);
10474       break;
10475
10476     default:
10477       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10478               "genPointerSet: illegal pointer type");
10479     }
10480
10481 }
10482
10483 /*-----------------------------------------------------------------*/
10484 /* genIfx - generate code for Ifx statement                        */
10485 /*-----------------------------------------------------------------*/
10486 static void
10487 genIfx (iCode * ic, iCode * popIc)
10488 {
10489   operand *cond = IC_COND (ic);
10490   int isbit = 0;
10491
10492   D (emitcode (";", "genIfx "););
10493
10494   aopOp (cond, ic, FALSE, FALSE);
10495
10496   /* get the value into acc */
10497   if (AOP_TYPE (cond) != AOP_CRY)
10498     {
10499         toBoolean (cond);
10500     }
10501   else
10502     {
10503         isbit = 1;
10504     }
10505     
10506   /* the result is now in the accumulator */
10507   freeAsmop (cond, NULL, ic, TRUE);
10508
10509   /* if there was something to be popped then do it */
10510   if (popIc)
10511     genIpop (popIc);
10512
10513   /* if the condition is  a bit variable */
10514   if (isbit && IS_ITEMP (cond) &&
10515       SPIL_LOC (cond))
10516     {
10517         genIfxJump (ic, SPIL_LOC (cond)->rname);
10518     }
10519   else if (isbit && !IS_ITEMP (cond))
10520     {
10521         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10522     }
10523   else
10524     {
10525         genIfxJump (ic, "a");
10526     }
10527
10528   ic->generated = 1;
10529 }
10530
10531 /*-----------------------------------------------------------------*/
10532 /* genAddrOf - generates code for address of                       */
10533 /*-----------------------------------------------------------------*/
10534 static void
10535 genAddrOf (iCode * ic)
10536 {
10537   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10538   int size, offset;
10539
10540   D (emitcode (";", "genAddrOf ");
10541     );
10542
10543   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10544
10545   /* if the operand is on the stack then we
10546      need to get the stack offset of this
10547      variable */
10548   if (sym->onStack) {
10549       
10550       /* if 10 bit stack */
10551       if (options.stack10bit) {
10552           char buff[10];
10553           int  offset;
10554           
10555           tsprintf(buff, sizeof(buff), 
10556                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10557           /* if it has an offset then we need to compute it */
10558 /*        emitcode ("subb", "a,#!constbyte", */
10559 /*                  -((sym->stack < 0) ? */
10560 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10561 /*                    ((short) sym->stack)) & 0xff); */
10562 /*        emitcode ("mov","b,a"); */
10563 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10564 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10565 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10566           if (sym->stack) {
10567               emitcode ("mov", "a,_bpx");
10568               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10569                                              ((char) (sym->stack - _G.nRegsSaved)) :
10570                                              ((char) sym->stack )) & 0xff);
10571               emitcode ("mov", "b,a");
10572               emitcode ("mov", "a,_bpx+1");
10573               
10574               offset = (((sym->stack < 0) ? 
10575                          ((short) (sym->stack - _G.nRegsSaved)) :
10576                          ((short) sym->stack )) >> 8) & 0xff;
10577           
10578               emitcode ("addc","a,#!constbyte", offset);
10579
10580               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10581               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10582               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10583           } else {
10584               /* we can just move _bp */
10585               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10586               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10587               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10588           }       
10589       } else {
10590           /* if it has an offset then we need to compute it */
10591           if (sym->stack) {
10592               emitcode ("mov", "a,_bp");
10593               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10594               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10595           } else {
10596               /* we can just move _bp */
10597               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10598           }
10599           /* fill the result with zero */
10600           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10601           
10602           
10603           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10604               fprintf (stderr,
10605                        "*** warning: pointer to stack var truncated.\n");
10606           }
10607
10608           offset = 1;
10609           while (size--) {
10610               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10611           }      
10612       }
10613       goto release;
10614   }
10615
10616   /* object not on stack then we need the name */
10617   size = AOP_SIZE (IC_RESULT (ic));
10618   offset = 0;
10619
10620   while (size--)
10621     {
10622       char s[SDCC_NAME_MAX];
10623       if (offset) {
10624           switch (offset) {
10625           case 1:
10626               tsprintf(s, sizeof(s), "#!his",sym->rname);
10627               break;
10628           case 2:
10629               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10630               break;
10631           case 3:
10632               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10633               break;
10634           default: /* should not need this (just in case) */
10635               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10636                        sym->rname,
10637                        offset * 8);
10638           }
10639       } 
10640       else
10641       {
10642           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10643       }
10644         
10645       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10646     }
10647
10648 release:
10649   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10650
10651 }
10652
10653 #if 0 // obsolete, and buggy for != xdata
10654 /*-----------------------------------------------------------------*/
10655 /* genArrayInit - generates code for address of                       */
10656 /*-----------------------------------------------------------------*/
10657 static void
10658 genArrayInit (iCode * ic)
10659 {
10660     literalList *iLoop;
10661     int         ix, count;
10662     int         elementSize = 0, eIndex;
10663     unsigned    val, lastVal;
10664     sym_link    *type;
10665     operand     *left=IC_LEFT(ic);
10666     
10667     D (emitcode (";", "genArrayInit "););
10668
10669     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10670     
10671     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10672     {
10673         // Load immediate value into DPTR.
10674         emitcode("mov", "dptr, %s",
10675              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10676     }
10677     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10678     {
10679 #if 0
10680       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10681               "Unexpected operand to genArrayInit.\n");
10682       exit(1);
10683 #else
10684       // a regression because of SDCCcse.c:1.52
10685       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10686       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10687       if (options.model == MODEL_FLAT24)
10688         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10689 #endif
10690     }
10691     
10692     type = operandType(IC_LEFT(ic));
10693     
10694     if (type && type->next)
10695     {
10696         elementSize = getSize(type->next);
10697     }
10698     else
10699     {
10700         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10701                                 "can't determine element size in genArrayInit.\n");
10702         exit(1);
10703     }
10704     
10705     iLoop = IC_ARRAYILIST(ic);
10706     lastVal = 0xffff;
10707     
10708     while (iLoop)
10709     {
10710         bool firstpass = TRUE;
10711         
10712         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10713                  iLoop->count, (int)iLoop->literalValue, elementSize);
10714         
10715         ix = iLoop->count;
10716         
10717         while (ix)
10718         {
10719             symbol *tlbl = NULL;
10720             
10721             count = ix > 256 ? 256 : ix;
10722             
10723             if (count > 1)
10724             {
10725                 tlbl = newiTempLabel (NULL);
10726                 if (firstpass || (count & 0xff))
10727                 {
10728                     emitcode("mov", "b, #!constbyte", count & 0xff);
10729                 }
10730                 
10731                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10732             }
10733             
10734             firstpass = FALSE;
10735                 
10736             for (eIndex = 0; eIndex < elementSize; eIndex++)
10737             {
10738                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10739                 if (val != lastVal)
10740                 {
10741                     emitcode("mov", "a, #!constbyte", val);
10742                     lastVal = val;
10743                 }
10744                 
10745                 emitcode("movx", "@dptr, a");
10746                 emitcode("inc", "dptr");
10747             }
10748             
10749             if (count > 1)
10750             {
10751                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10752             }
10753             
10754             ix -= count;
10755         }
10756         
10757         iLoop = iLoop->next;
10758     }
10759     
10760     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10761 }
10762 #endif
10763
10764 /*-----------------------------------------------------------------*/
10765 /* genFarFarAssign - assignment when both are in far space         */
10766 /*-----------------------------------------------------------------*/
10767 static void
10768 genFarFarAssign (operand * result, operand * right, iCode * ic)
10769 {
10770   int size = AOP_SIZE (right);
10771   int offset = 0;
10772   symbol *rSym = NULL;
10773
10774   if (size == 1)
10775   {
10776       /* quick & easy case. */
10777       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10778       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10779       freeAsmop (right, NULL, ic, FALSE);
10780       /* now assign DPTR to result */
10781       _G.accInUse++;
10782       aopOp(result, ic, FALSE, FALSE);
10783       _G.accInUse--;
10784       aopPut(AOP(result), "a", 0);
10785       freeAsmop(result, NULL, ic, FALSE);
10786       return;
10787   }
10788   
10789   /* See if we've got an underlying symbol to abuse. */
10790   if (IS_SYMOP(result) && OP_SYMBOL(result))
10791   {
10792       if (IS_TRUE_SYMOP(result))
10793       {
10794           rSym = OP_SYMBOL(result);
10795       }
10796       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10797       {
10798           rSym = OP_SYMBOL(result)->usl.spillLoc;
10799       }
10800   }
10801              
10802   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10803   {
10804       /* We can use the '390 auto-toggle feature to good effect here. */
10805       
10806       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10807       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10808       emitcode ("mov", "dptr,#%s", rSym->rname); 
10809       /* DP2 = result, DP1 = right, DP1 is current. */
10810       while (size)
10811       {
10812           emitcode("movx", "a,@dptr");
10813           emitcode("movx", "@dptr,a");
10814           if (--size)
10815           {
10816                emitcode("inc", "dptr");
10817                emitcode("inc", "dptr");
10818           }
10819       }
10820       emitcode("mov", "dps,#0");
10821       freeAsmop (right, NULL, ic, FALSE);
10822 #if 0
10823 some alternative code for processors without auto-toggle
10824 no time to test now, so later well put in...kpb
10825         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10826         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10827         emitcode ("mov", "dptr,#%s", rSym->rname); 
10828         /* DP2 = result, DP1 = right, DP1 is current. */
10829         while (size)
10830         {
10831           --size;
10832           emitcode("movx", "a,@dptr");
10833           if (size)
10834             emitcode("inc", "dptr");
10835           emitcode("inc", "dps");
10836           emitcode("movx", "@dptr,a");
10837           if (size)
10838             emitcode("inc", "dptr");
10839           emitcode("inc", "dps");
10840         }
10841         emitcode("mov", "dps,#0");
10842         freeAsmop (right, NULL, ic, FALSE);
10843 #endif
10844   }
10845   else
10846   {
10847       D (emitcode (";", "genFarFarAssign"););
10848       aopOp (result, ic, TRUE, TRUE);
10849
10850       _startLazyDPSEvaluation ();
10851       
10852       while (size--)
10853         {
10854           aopPut (AOP (result),
10855                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10856           offset++;
10857         }
10858       _endLazyDPSEvaluation ();
10859       freeAsmop (result, NULL, ic, FALSE);
10860       freeAsmop (right, NULL, ic, FALSE);
10861   }
10862 }
10863
10864 /*-----------------------------------------------------------------*/
10865 /* genAssign - generate code for assignment                        */
10866 /*-----------------------------------------------------------------*/
10867 static void
10868 genAssign (iCode * ic)
10869 {
10870   operand *result, *right;
10871   int size, offset;
10872   unsigned long lit = 0L;
10873
10874   D (emitcode (";", "genAssign ");
10875     );
10876
10877   result = IC_RESULT (ic);
10878   right = IC_RIGHT (ic);
10879
10880   /* if they are the same */
10881   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10882     return;
10883
10884   aopOp (right, ic, FALSE, FALSE);
10885
10886   emitcode (";", "genAssign: resultIsFar = %s",
10887             isOperandInFarSpace (result) ?
10888             "TRUE" : "FALSE");
10889
10890   /* special case both in far space */
10891   if ((AOP_TYPE (right) == AOP_DPTR ||
10892        AOP_TYPE (right) == AOP_DPTR2) &&
10893   /* IS_TRUE_SYMOP(result)       && */
10894       isOperandInFarSpace (result))
10895     {
10896       genFarFarAssign (result, right, ic);
10897       return;
10898     }
10899
10900   aopOp (result, ic, TRUE, FALSE);
10901
10902   /* if they are the same registers */
10903   if (sameRegs (AOP (right), AOP (result)))
10904     goto release;
10905
10906   /* if the result is a bit */
10907   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10908     {
10909       /* if the right size is a literal then
10910          we know what the value is */
10911       if (AOP_TYPE (right) == AOP_LIT)
10912         {
10913           if (((int) operandLitValue (right)))
10914             aopPut (AOP (result), one, 0);
10915           else
10916             aopPut (AOP (result), zero, 0);
10917           goto release;
10918         }
10919
10920       /* the right is also a bit variable */
10921       if (AOP_TYPE (right) == AOP_CRY)
10922         {
10923           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10924           aopPut (AOP (result), "c", 0);
10925           goto release;
10926         }
10927
10928       /* we need to or */
10929       toBoolean (right);
10930       aopPut (AOP (result), "a", 0);
10931       goto release;
10932     }
10933
10934   /* bit variables done */
10935   /* general case */
10936   size = AOP_SIZE (result);
10937   offset = 0;
10938   if (AOP_TYPE (right) == AOP_LIT)
10939     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10940
10941   if ((size > 1) &&
10942       (AOP_TYPE (result) != AOP_REG) &&
10943       (AOP_TYPE (right) == AOP_LIT) &&
10944       !IS_FLOAT (operandType (right)))
10945     {
10946       _startLazyDPSEvaluation ();
10947       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10948         {
10949           aopPut (AOP (result),
10950                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10951                   offset);
10952           offset++;
10953           size--;
10954         }
10955       /* And now fill the rest with zeros. */
10956       if (size)
10957         {
10958           emitcode ("clr", "a");
10959         }
10960       while (size--)
10961         {
10962           aopPut (AOP (result), "a", offset++);
10963         }
10964       _endLazyDPSEvaluation ();
10965     }
10966   else
10967     {
10968       _startLazyDPSEvaluation ();
10969       while (size--)
10970         {
10971           aopPut (AOP (result),
10972                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10973                   offset);
10974           offset++;
10975         }
10976       _endLazyDPSEvaluation ();
10977     }
10978
10979 release:
10980   freeAsmop (right, NULL, ic, FALSE);
10981   freeAsmop (result, NULL, ic, TRUE);
10982 }
10983
10984 /*-----------------------------------------------------------------*/
10985 /* genJumpTab - generates code for jump table                      */
10986 /*-----------------------------------------------------------------*/
10987 static void
10988 genJumpTab (iCode * ic)
10989 {
10990   symbol *jtab;
10991   char *l;
10992
10993   D (emitcode (";", "genJumpTab ");
10994     );
10995
10996   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10997   /* get the condition into accumulator */
10998   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10999   MOVA (l);
11000   /* multiply by four! */
11001   emitcode ("add", "a,acc");
11002   emitcode ("add", "a,acc");
11003   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11004
11005   jtab = newiTempLabel (NULL);
11006   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11007   emitcode ("jmp", "@a+dptr");
11008   emitcode ("", "!tlabeldef", jtab->key + 100);
11009   /* now generate the jump labels */
11010   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11011        jtab = setNextItem (IC_JTLABELS (ic)))
11012     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11013
11014 }
11015
11016 /*-----------------------------------------------------------------*/
11017 /* genCast - gen code for casting                                  */
11018 /*-----------------------------------------------------------------*/
11019 static void
11020 genCast (iCode * ic)
11021 {
11022   operand *result = IC_RESULT (ic);
11023   sym_link *ctype = operandType (IC_LEFT (ic));
11024   sym_link *rtype = operandType (IC_RIGHT (ic));
11025   operand *right = IC_RIGHT (ic);
11026   int size, offset;
11027
11028   D (emitcode (";", "genCast "););
11029
11030   /* if they are equivalent then do nothing */
11031   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11032     return;
11033
11034   aopOp (right, ic, FALSE, FALSE);
11035   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11036
11037   /* if the result is a bit */
11038   if (IS_BITVAR (OP_SYMBOL (result)->type)
11039       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11040     {
11041       /* if the right size is a literal then
11042          we know what the value is */
11043       if (AOP_TYPE (right) == AOP_LIT)
11044         {
11045           if (((int) operandLitValue (right)))
11046             aopPut (AOP (result), one, 0);
11047           else
11048             aopPut (AOP (result), zero, 0);
11049
11050           goto release;
11051         }
11052
11053       /* the right is also a bit variable */
11054       if (AOP_TYPE (right) == AOP_CRY)
11055         {
11056           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11057           aopPut (AOP (result), "c", 0);
11058           goto release;
11059         }
11060
11061       /* we need to or */
11062       toBoolean (right);
11063       aopPut (AOP (result), "a", 0);
11064       goto release;
11065     }
11066
11067   /* if they are the same size : or less */
11068   if (AOP_SIZE (result) <= AOP_SIZE (right))
11069     {
11070
11071       /* if they are in the same place */
11072       if (sameRegs (AOP (right), AOP (result)))
11073         goto release;
11074
11075       /* if they in different places then copy */
11076       size = AOP_SIZE (result);
11077       offset = 0;
11078       _startLazyDPSEvaluation ();
11079       while (size--)
11080         {
11081           aopPut (AOP (result),
11082                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11083                   offset);
11084           offset++;
11085         }
11086       _endLazyDPSEvaluation ();
11087       goto release;
11088     }
11089
11090
11091   /* if the result is of type pointer */
11092   if (IS_PTR (ctype))
11093     {
11094
11095       int p_type;
11096       sym_link *type = operandType (right);
11097
11098       /* pointer to generic pointer */
11099       if (IS_GENPTR (ctype))
11100         {
11101           if (IS_PTR (type))
11102             {
11103               p_type = DCL_TYPE (type);
11104             }
11105           else
11106             {
11107 #if OLD_CAST_BEHAVIOR
11108               /* KV: we are converting a non-pointer type to
11109                * a generic pointer. This (ifdef'd out) code
11110                * says that the resulting generic pointer
11111                * should have the same class as the storage
11112                * location of the non-pointer variable.
11113                *
11114                * For example, converting an int (which happens
11115                * to be stored in DATA space) to a pointer results
11116                * in a DATA generic pointer; if the original int
11117                * in XDATA space, so will be the resulting pointer.
11118                *
11119                * I don't like that behavior, and thus this change:
11120                * all such conversions will be forced to XDATA and
11121                * throw a warning. If you want some non-XDATA
11122                * type, or you want to suppress the warning, you
11123                * must go through an intermediate cast, like so:
11124                *
11125                * char _generic *gp = (char _xdata *)(intVar);
11126                */
11127               sym_link *etype = getSpec (type);
11128
11129               /* we have to go by the storage class */
11130               if (SPEC_OCLS (etype) != generic)
11131                 {
11132                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11133                 }
11134               else
11135 #endif
11136                 {
11137                   /* Converting unknown class (i.e. register variable)
11138                    * to generic pointer. This is not good, but
11139                    * we'll make a guess (and throw a warning).
11140                    */
11141                   p_type = FPOINTER;
11142                   werror (W_INT_TO_GEN_PTR_CAST);
11143                 }
11144             }
11145
11146           /* the first two bytes are known */
11147           size = GPTRSIZE - 1;
11148           offset = 0;
11149           _startLazyDPSEvaluation ();
11150           while (size--)
11151             {
11152               aopPut (AOP (result),
11153                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11154                       offset);
11155               offset++;
11156             }
11157           _endLazyDPSEvaluation ();
11158
11159           /* the last byte depending on type */
11160             {
11161                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11162                 char gpValStr[10];
11163             
11164                 if (gpVal == -1)
11165                 {
11166                     // pointerTypeToGPByte will have bitched.
11167                     exit(1);
11168                 }
11169             
11170                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11171                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11172             }
11173           goto release;
11174         }
11175
11176       /* just copy the pointers */
11177       size = AOP_SIZE (result);
11178       offset = 0;
11179       _startLazyDPSEvaluation ();
11180       while (size--)
11181         {
11182           aopPut (AOP (result),
11183                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11184                   offset);
11185           offset++;
11186         }
11187       _endLazyDPSEvaluation ();
11188       goto release;
11189     }
11190
11191   /* so we now know that the size of destination is greater
11192      than the size of the source */
11193   /* we move to result for the size of source */
11194   size = AOP_SIZE (right);
11195   offset = 0;
11196   _startLazyDPSEvaluation ();
11197   while (size--)
11198     {
11199       aopPut (AOP (result),
11200               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11201               offset);
11202       offset++;
11203     }
11204   _endLazyDPSEvaluation ();
11205
11206   /* now depending on the sign of the source && destination */
11207   size = AOP_SIZE (result) - AOP_SIZE (right);
11208   /* if unsigned or not an integral type */
11209   /* also, if the source is a bit, we don't need to sign extend, because
11210    * it can't possibly have set the sign bit.
11211    */
11212   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11213     {
11214       while (size--)
11215         {
11216           aopPut (AOP (result), zero, offset++);
11217         }
11218     }
11219   else
11220     {
11221       /* we need to extend the sign :{ */
11222       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11223                         FALSE, FALSE, NULL));
11224       emitcode ("rlc", "a");
11225       emitcode ("subb", "a,acc");
11226       while (size--)
11227         aopPut (AOP (result), "a", offset++);
11228     }
11229
11230   /* we are done hurray !!!! */
11231
11232 release:
11233   freeAsmop (right, NULL, ic, TRUE);
11234   freeAsmop (result, NULL, ic, TRUE);
11235
11236 }
11237
11238 /*-----------------------------------------------------------------*/
11239 /* genDjnz - generate decrement & jump if not zero instrucion      */
11240 /*-----------------------------------------------------------------*/
11241 static int
11242 genDjnz (iCode * ic, iCode * ifx)
11243 {
11244   symbol *lbl, *lbl1;
11245   if (!ifx)
11246     return 0;
11247
11248   /* if the if condition has a false label
11249      then we cannot save */
11250   if (IC_FALSE (ifx))
11251     return 0;
11252
11253   /* if the minus is not of the form
11254      a = a - 1 */
11255   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11256       !IS_OP_LITERAL (IC_RIGHT (ic)))
11257     return 0;
11258
11259   if (operandLitValue (IC_RIGHT (ic)) != 1)
11260     return 0;
11261
11262   /* if the size of this greater than one then no
11263      saving */
11264   if (getSize (operandType (IC_RESULT (ic))) > 1)
11265     return 0;
11266
11267   /* otherwise we can save BIG */
11268   D(emitcode(";", "genDjnz"););
11269
11270   lbl = newiTempLabel (NULL);
11271   lbl1 = newiTempLabel (NULL);
11272
11273   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11274
11275   if (AOP_NEEDSACC(IC_RESULT(ic)))
11276   {
11277       /* If the result is accessed indirectly via
11278        * the accumulator, we must explicitly write
11279        * it back after the decrement.
11280        */
11281       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11282       
11283       if (strcmp(rByte, "a"))
11284       {
11285            /* Something is hopelessly wrong */
11286            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11287                    __FILE__, __LINE__);
11288            /* We can just give up; the generated code will be inefficient,
11289             * but what the hey.
11290             */
11291            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11292            return 0;
11293       }
11294       emitcode ("dec", "%s", rByte);
11295       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11296       emitcode ("jnz", "!tlabel", lbl->key + 100);
11297   }
11298   else if (IS_AOP_PREG (IC_RESULT (ic)))
11299     {
11300       emitcode ("dec", "%s",
11301                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11302       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11303       emitcode ("jnz", "!tlabel", lbl->key + 100);
11304     }
11305   else
11306     {
11307       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11308                 lbl->key + 100);
11309     }
11310   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11311   emitcode ("", "!tlabeldef", lbl->key + 100);
11312   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11313   emitcode ("", "!tlabeldef", lbl1->key + 100);
11314
11315   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11316   ifx->generated = 1;
11317   return 1;
11318 }
11319
11320 /*-----------------------------------------------------------------*/
11321 /* genReceive - generate code for a receive iCode                  */
11322 /*-----------------------------------------------------------------*/
11323 static void
11324 genReceive (iCode * ic)
11325 {
11326     int size = getSize (operandType (IC_RESULT (ic)));
11327     int offset = 0;
11328     int rb1off ;
11329     
11330     D (emitcode (";", "genReceive "););
11331
11332     if (ic->argreg == 1) 
11333     {
11334         /* first parameter */
11335         if (AOP_IS_STR(IC_RESULT(ic)))
11336         {
11337             /* Nothing to do: it's already in the proper place. */
11338             return;
11339         }
11340         else
11341         {
11342             bool useDp2;
11343             
11344             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11345                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11346                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11347             
11348             _G.accInUse++;
11349             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11350             _G.accInUse--; 
11351             
11352             /* Sanity checking... */
11353             if (AOP_USESDPTR(IC_RESULT(ic)))
11354             {
11355                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11356                         "genReceive got unexpected DPTR.");
11357             }
11358             assignResultValue (IC_RESULT (ic));
11359         }
11360     } 
11361     else 
11362     { 
11363         /* second receive onwards */
11364         /* this gets a little tricky since unused recevies will be
11365          eliminated, we have saved the reg in the type field . and
11366          we use that to figure out which register to use */
11367         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11368         rb1off = ic->argreg;
11369         while (size--) 
11370         {
11371             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11372         }
11373     }
11374     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11375 }
11376
11377 /*-----------------------------------------------------------------*/
11378 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11379 /*-----------------------------------------------------------------*/
11380 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11381 {
11382     operand *from , *to , *count;
11383     symbol *lbl;
11384     bitVect *rsave;
11385     int i;
11386
11387     /* we know it has to be 3 parameters */
11388     assert (nparms == 3);
11389     
11390     rsave = newBitVect(16);
11391     /* save DPTR if it needs to be saved */
11392     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11393             if (bitVectBitValue(ic->rMask,i))
11394                     rsave = bitVectSetBit(rsave,i);
11395     }
11396     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11397                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11398     savermask(rsave);
11399     
11400     to = parms[0];
11401     from = parms[1];
11402     count = parms[2];
11403
11404     aopOp (from, ic->next, FALSE, FALSE);
11405
11406     /* get from into DPTR1 */
11407     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11408     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11409     if (options.model == MODEL_FLAT24) {
11410         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11411     }
11412
11413     freeAsmop (from, NULL, ic, FALSE);
11414     aopOp (to, ic, FALSE, FALSE);
11415     /* get "to" into DPTR */
11416     /* if the operand is already in dptr
11417        then we do nothing else we move the value to dptr */
11418     if (AOP_TYPE (to) != AOP_STR) {
11419         /* if already in DPTR then we need to push */
11420         if (AOP_TYPE(to) == AOP_DPTR) {
11421             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11422             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11423             if (options.model == MODEL_FLAT24)
11424                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11425             emitcode ("pop", "dph");
11426             emitcode ("pop", "dpl");        
11427         } else {
11428             _startLazyDPSEvaluation ();
11429             /* if this is remateriazable */
11430             if (AOP_TYPE (to) == AOP_IMMD) {
11431                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11432             } else {                    /* we need to get it byte by byte */
11433                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11434                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11435                 if (options.model == MODEL_FLAT24) {
11436                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11437                 }
11438             }
11439             _endLazyDPSEvaluation ();
11440         }
11441     }
11442     freeAsmop (to, NULL, ic, FALSE);
11443     _G.dptrInUse = _G.dptr1InUse = 1;
11444     aopOp (count, ic->next->next, FALSE,FALSE);
11445     lbl =newiTempLabel(NULL);
11446
11447     /* now for the actual copy */
11448     if (AOP_TYPE(count) == AOP_LIT && 
11449         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11450         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11451         if (fromc) {
11452             emitcode ("lcall","__bi_memcpyc2x_s");
11453         } else {
11454             emitcode ("lcall","__bi_memcpyx2x_s");
11455         }
11456         freeAsmop (count, NULL, ic, FALSE);
11457     } else {
11458         symbol *lbl1 = newiTempLabel(NULL);
11459         
11460         emitcode (";"," Auto increment but no djnz");
11461         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11462         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11463         freeAsmop (count, NULL, ic, FALSE);
11464         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11465         emitcode ("","!tlabeldef",lbl->key+100);
11466         if (fromc) {
11467             emitcode ("clr","a");
11468             emitcode ("movc", "a,@a+dptr");
11469         } else 
11470             emitcode ("movx", "a,@dptr");
11471         emitcode ("movx", "@dptr,a");
11472         emitcode ("inc", "dptr");
11473         emitcode ("inc", "dptr");
11474         emitcode ("mov","a,b");
11475         emitcode ("orl","a,_ap");
11476         emitcode ("jz","!tlabel",lbl1->key+100);
11477         emitcode ("mov","a,_ap");
11478         emitcode ("add","a,#!constbyte",0xFF);
11479         emitcode ("mov","_ap,a");
11480         emitcode ("mov","a,b");
11481         emitcode ("addc","a,#!constbyte",0xFF);
11482         emitcode ("mov","b,a");
11483         emitcode ("sjmp","!tlabel",lbl->key+100);
11484         emitcode ("","!tlabeldef",lbl1->key+100);
11485     }
11486     emitcode ("mov", "dps,#0"); 
11487     _G.dptrInUse = _G.dptr1InUse = 0;
11488     unsavermask(rsave);
11489
11490 }
11491
11492 /*-----------------------------------------------------------------*/
11493 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11494 /*-----------------------------------------------------------------*/
11495 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11496 {
11497     operand *from , *to , *count;
11498     symbol *lbl,*lbl2;
11499     bitVect *rsave;
11500     int i;
11501
11502     /* we know it has to be 3 parameters */
11503     assert (nparms == 3);
11504     
11505     rsave = newBitVect(16);
11506     /* save DPTR if it needs to be saved */
11507     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11508             if (bitVectBitValue(ic->rMask,i))
11509                     rsave = bitVectSetBit(rsave,i);
11510     }
11511     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11512                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11513     savermask(rsave);
11514     
11515     to = parms[0];
11516     from = parms[1];
11517     count = parms[2];
11518
11519     aopOp (from, ic->next, FALSE, FALSE);
11520
11521     /* get from into DPTR1 */
11522     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11523     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11524     if (options.model == MODEL_FLAT24) {
11525         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11526     }
11527
11528     freeAsmop (from, NULL, ic, FALSE);
11529     aopOp (to, ic, FALSE, FALSE);
11530     /* get "to" into DPTR */
11531     /* if the operand is already in dptr
11532        then we do nothing else we move the value to dptr */
11533     if (AOP_TYPE (to) != AOP_STR) {
11534         /* if already in DPTR then we need to push */
11535         if (AOP_TYPE(to) == AOP_DPTR) {
11536             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11537             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11538             if (options.model == MODEL_FLAT24)
11539                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11540             emitcode ("pop", "dph");
11541             emitcode ("pop", "dpl");        
11542         } else {
11543             _startLazyDPSEvaluation ();
11544             /* if this is remateriazable */
11545             if (AOP_TYPE (to) == AOP_IMMD) {
11546                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11547             } else {                    /* we need to get it byte by byte */
11548                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11549                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11550                 if (options.model == MODEL_FLAT24) {
11551                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11552                 }
11553             }
11554             _endLazyDPSEvaluation ();
11555         }
11556     }
11557     freeAsmop (to, NULL, ic, FALSE);
11558     _G.dptrInUse = _G.dptr1InUse = 1;
11559     aopOp (count, ic->next->next, FALSE,FALSE);
11560     lbl =newiTempLabel(NULL);
11561     lbl2 =newiTempLabel(NULL);
11562
11563     /* now for the actual compare */
11564     if (AOP_TYPE(count) == AOP_LIT && 
11565         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11566         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11567         if (fromc)
11568             emitcode("lcall","__bi_memcmpc2x_s");
11569         else
11570             emitcode("lcall","__bi_memcmpx2x_s");
11571         freeAsmop (count, NULL, ic, FALSE);
11572         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11573         aopPut(AOP(IC_RESULT(ic)),"a",0);
11574         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11575     } else {
11576         symbol *lbl1 = newiTempLabel(NULL);
11577
11578         emitcode("push","ar0");         
11579         emitcode (";"," Auto increment but no djnz");
11580         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11581         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11582         freeAsmop (count, NULL, ic, FALSE);
11583         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11584         emitcode ("","!tlabeldef",lbl->key+100);
11585         if (fromc) {
11586             emitcode ("clr","a");
11587             emitcode ("movc", "a,@a+dptr");
11588         } else 
11589             emitcode ("movx", "a,@dptr");
11590         emitcode ("mov","r0,a");
11591         emitcode ("movx", "a,@dptr");
11592         emitcode ("clr","c");
11593         emitcode ("subb","a,r0");
11594         emitcode ("jnz","!tlabel",lbl2->key+100);
11595         emitcode ("inc", "dptr");
11596         emitcode ("inc", "dptr");
11597         emitcode ("mov","a,b");
11598         emitcode ("orl","a,_ap");
11599         emitcode ("jz","!tlabel",lbl1->key+100);
11600         emitcode ("mov","a,_ap");
11601         emitcode ("add","a,#!constbyte",0xFF);
11602         emitcode ("mov","_ap,a");
11603         emitcode ("mov","a,b");
11604         emitcode ("addc","a,#!constbyte",0xFF);
11605         emitcode ("mov","b,a");
11606         emitcode ("sjmp","!tlabel",lbl->key+100);
11607         emitcode ("","!tlabeldef",lbl1->key+100);
11608         emitcode ("clr","a");
11609         emitcode ("","!tlabeldef",lbl2->key+100);
11610         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11611         aopPut(AOP(IC_RESULT(ic)),"a",0);
11612         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11613         emitcode("pop","ar0");
11614         emitcode ("mov", "dps,#0");      
11615     }
11616     _G.dptrInUse = _G.dptr1InUse = 0;
11617     unsavermask(rsave);
11618
11619 }
11620
11621 /*-----------------------------------------------------------------*/
11622 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11623 /* port, first parameter output area second parameter pointer to   */
11624 /* port third parameter count                                      */
11625 /*-----------------------------------------------------------------*/
11626 static void genInp( iCode *ic, int nparms, operand **parms)
11627 {
11628     operand *from , *to , *count;
11629     symbol *lbl;
11630     bitVect *rsave;
11631     int i;
11632
11633     /* we know it has to be 3 parameters */
11634     assert (nparms == 3);
11635     
11636     rsave = newBitVect(16);
11637     /* save DPTR if it needs to be saved */
11638     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11639             if (bitVectBitValue(ic->rMask,i))
11640                     rsave = bitVectSetBit(rsave,i);
11641     }
11642     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11643                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11644     savermask(rsave);
11645     
11646     to = parms[0];
11647     from = parms[1];
11648     count = parms[2];
11649
11650     aopOp (from, ic->next, FALSE, FALSE);
11651
11652     /* get from into DPTR1 */
11653     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11654     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11655     if (options.model == MODEL_FLAT24) {
11656         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11657     }
11658
11659     freeAsmop (from, NULL, ic, FALSE);
11660     aopOp (to, ic, FALSE, FALSE);
11661     /* get "to" into DPTR */
11662     /* if the operand is already in dptr
11663        then we do nothing else we move the value to dptr */
11664     if (AOP_TYPE (to) != AOP_STR) {
11665         /* if already in DPTR then we need to push */
11666         if (AOP_TYPE(to) == AOP_DPTR) {
11667             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11668             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11669             if (options.model == MODEL_FLAT24)
11670                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11671             emitcode ("pop", "dph");
11672             emitcode ("pop", "dpl");        
11673         } else {
11674             _startLazyDPSEvaluation ();
11675             /* if this is remateriazable */
11676             if (AOP_TYPE (to) == AOP_IMMD) {
11677                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11678             } else {                    /* we need to get it byte by byte */
11679                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11680                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11681                 if (options.model == MODEL_FLAT24) {
11682                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11683                 }
11684             }
11685             _endLazyDPSEvaluation ();
11686         }
11687     }
11688     freeAsmop (to, NULL, ic, FALSE);
11689
11690     _G.dptrInUse = _G.dptr1InUse = 1;
11691     aopOp (count, ic->next->next, FALSE,FALSE);
11692     lbl =newiTempLabel(NULL);
11693
11694     /* now for the actual copy */
11695     if (AOP_TYPE(count) == AOP_LIT && 
11696         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11697         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11698         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11699         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11700         freeAsmop (count, NULL, ic, FALSE);
11701         emitcode ("","!tlabeldef",lbl->key+100);
11702         emitcode ("movx", "a,@dptr");   /* read data from port */
11703         emitcode ("dec","dps");         /* switch to DPTR */
11704         emitcode ("movx", "@dptr,a");   /* save into location */
11705         emitcode ("inc", "dptr");       /* point to next area */
11706         emitcode ("inc","dps");         /* switch to DPTR2 */
11707         emitcode ("djnz","b,!tlabel",lbl->key+100);
11708     } else {
11709         symbol *lbl1 = newiTempLabel(NULL);
11710         
11711         emitcode (";"," Auto increment but no djnz");
11712         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11713         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11714         freeAsmop (count, NULL, ic, FALSE);
11715         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11716         emitcode ("","!tlabeldef",lbl->key+100);
11717         emitcode ("movx", "a,@dptr");
11718         emitcode ("dec","dps");         /* switch to DPTR */
11719         emitcode ("movx", "@dptr,a");
11720         emitcode ("inc", "dptr");
11721         emitcode ("inc","dps");         /* switch to DPTR2 */
11722 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11723 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11724         emitcode ("mov","a,b");
11725         emitcode ("orl","a,_ap");
11726         emitcode ("jz","!tlabel",lbl1->key+100);
11727         emitcode ("mov","a,_ap");
11728         emitcode ("add","a,#!constbyte",0xFF);
11729         emitcode ("mov","_ap,a");
11730         emitcode ("mov","a,b");
11731         emitcode ("addc","a,#!constbyte",0xFF);
11732         emitcode ("mov","b,a");
11733         emitcode ("sjmp","!tlabel",lbl->key+100);
11734         emitcode ("","!tlabeldef",lbl1->key+100);
11735     }
11736     emitcode ("mov", "dps,#0"); 
11737     _G.dptrInUse = _G.dptr1InUse = 0;
11738     unsavermask(rsave);
11739
11740 }
11741
11742 /*-----------------------------------------------------------------*/
11743 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11744 /* port, first parameter output area second parameter pointer to   */
11745 /* port third parameter count                                      */
11746 /*-----------------------------------------------------------------*/
11747 static void genOutp( iCode *ic, int nparms, operand **parms)
11748 {
11749     operand *from , *to , *count;
11750     symbol *lbl;
11751     bitVect *rsave;
11752     int i;
11753
11754     /* we know it has to be 3 parameters */
11755     assert (nparms == 3);
11756     
11757     rsave = newBitVect(16);
11758     /* save DPTR if it needs to be saved */
11759     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11760             if (bitVectBitValue(ic->rMask,i))
11761                     rsave = bitVectSetBit(rsave,i);
11762     }
11763     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11764                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11765     savermask(rsave);
11766     
11767     to = parms[0];
11768     from = parms[1];
11769     count = parms[2];
11770
11771     aopOp (from, ic->next, FALSE, FALSE);
11772
11773     /* get from into DPTR1 */
11774     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11775     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11776     if (options.model == MODEL_FLAT24) {
11777         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11778     }
11779
11780     freeAsmop (from, NULL, ic, FALSE);
11781     aopOp (to, ic, FALSE, FALSE);
11782     /* get "to" into DPTR */
11783     /* if the operand is already in dptr
11784        then we do nothing else we move the value to dptr */
11785     if (AOP_TYPE (to) != AOP_STR) {
11786         /* if already in DPTR then we need to push */
11787         if (AOP_TYPE(to) == AOP_DPTR) {
11788             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11789             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11790             if (options.model == MODEL_FLAT24)
11791                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11792             emitcode ("pop", "dph");
11793             emitcode ("pop", "dpl");        
11794         } else {
11795             _startLazyDPSEvaluation ();
11796             /* if this is remateriazable */
11797             if (AOP_TYPE (to) == AOP_IMMD) {
11798                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11799             } else {                    /* we need to get it byte by byte */
11800                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11801                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11802                 if (options.model == MODEL_FLAT24) {
11803                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11804                 }
11805             }
11806             _endLazyDPSEvaluation ();
11807         }
11808     }
11809     freeAsmop (to, NULL, ic, FALSE);
11810
11811     _G.dptrInUse = _G.dptr1InUse = 1;
11812     aopOp (count, ic->next->next, FALSE,FALSE);
11813     lbl =newiTempLabel(NULL);
11814
11815     /* now for the actual copy */
11816     if (AOP_TYPE(count) == AOP_LIT && 
11817         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11818         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11819         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11820         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11821         emitcode ("","!tlabeldef",lbl->key+100);
11822         emitcode ("movx", "a,@dptr");   /* read data from port */
11823         emitcode ("inc","dps");         /* switch to DPTR2 */
11824         emitcode ("movx", "@dptr,a");   /* save into location */
11825         emitcode ("inc", "dptr");       /* point to next area */
11826         emitcode ("dec","dps");         /* switch to DPTR */
11827         emitcode ("djnz","b,!tlabel",lbl->key+100);
11828         freeAsmop (count, NULL, ic, FALSE);
11829     } else {
11830         symbol *lbl1 = newiTempLabel(NULL);
11831         
11832         emitcode (";"," Auto increment but no djnz");
11833         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11834         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11835         freeAsmop (count, NULL, ic, FALSE);
11836         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11837         emitcode ("","!tlabeldef",lbl->key+100);
11838         emitcode ("movx", "a,@dptr");
11839         emitcode ("inc", "dptr");
11840         emitcode ("inc","dps");         /* switch to DPTR2 */
11841         emitcode ("movx", "@dptr,a");
11842         emitcode ("dec","dps");         /* switch to DPTR */
11843         emitcode ("mov","a,b");
11844         emitcode ("orl","a,_ap");
11845         emitcode ("jz","!tlabel",lbl1->key+100);
11846         emitcode ("mov","a,_ap");
11847         emitcode ("add","a,#!constbyte",0xFF);
11848         emitcode ("mov","_ap,a");
11849         emitcode ("mov","a,b");
11850         emitcode ("addc","a,#!constbyte",0xFF);
11851         emitcode ("mov","b,a");
11852         emitcode ("sjmp","!tlabel",lbl->key+100);
11853         emitcode ("","!tlabeldef",lbl1->key+100);
11854     }
11855     emitcode ("mov", "dps,#0"); 
11856     _G.dptrInUse = _G.dptr1InUse = 0;
11857     unsavermask(rsave);
11858
11859 }
11860
11861 /*-----------------------------------------------------------------*/
11862 /* genSwapW - swap lower & high order bytes                        */
11863 /*-----------------------------------------------------------------*/
11864 static void genSwapW(iCode *ic, int nparms, operand **parms)
11865 {
11866     operand *dest;
11867     operand *src;
11868     assert (nparms==1);
11869
11870     src = parms[0];
11871     dest=IC_RESULT(ic);
11872
11873     assert(getSize(operandType(src))==2);
11874
11875     aopOp (src, ic, FALSE, FALSE);
11876     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11877     _G.accInUse++;
11878     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11879     _G.accInUse--;
11880     freeAsmop (src, NULL, ic, FALSE);
11881     
11882     aopOp (dest,ic, FALSE, FALSE);
11883     aopPut(AOP(dest),"b",0);
11884     aopPut(AOP(dest),"a",1);
11885     freeAsmop (dest, NULL, ic, FALSE);    
11886 }
11887
11888 /*-----------------------------------------------------------------*/
11889 /* genMemsetX - gencode for memSetX data                           */
11890 /*-----------------------------------------------------------------*/
11891 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11892 {
11893     operand *to , *val , *count;
11894     symbol *lbl;
11895     char *l;
11896     int i;
11897     bitVect *rsave;
11898
11899     /* we know it has to be 3 parameters */
11900     assert (nparms == 3);
11901     
11902     to = parms[0];
11903     val = parms[1];
11904     count = parms[2];
11905         
11906     /* save DPTR if it needs to be saved */
11907     rsave = newBitVect(16);
11908     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11909             if (bitVectBitValue(ic->rMask,i))
11910                     rsave = bitVectSetBit(rsave,i);
11911     }
11912     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11913                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11914     savermask(rsave);
11915
11916     aopOp (to, ic, FALSE, FALSE);
11917     /* get "to" into DPTR */
11918     /* if the operand is already in dptr
11919        then we do nothing else we move the value to dptr */
11920     if (AOP_TYPE (to) != AOP_STR) {
11921         /* if already in DPTR then we need to push */
11922         if (AOP_TYPE(to) == AOP_DPTR) {
11923             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11924             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11925             if (options.model == MODEL_FLAT24)
11926                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11927             emitcode ("pop", "dph");
11928             emitcode ("pop", "dpl");        
11929         } else {
11930             _startLazyDPSEvaluation ();
11931             /* if this is remateriazable */
11932             if (AOP_TYPE (to) == AOP_IMMD) {
11933                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11934             } else {                    /* we need to get it byte by byte */
11935                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11936                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11937                 if (options.model == MODEL_FLAT24) {
11938                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11939                 }
11940             }
11941             _endLazyDPSEvaluation ();
11942         }
11943     }
11944     freeAsmop (to, NULL, ic, FALSE);
11945
11946     aopOp (val, ic->next->next, FALSE,FALSE);
11947     aopOp (count, ic->next->next, FALSE,FALSE);    
11948     lbl =newiTempLabel(NULL);
11949     /* now for the actual copy */
11950     if (AOP_TYPE(count) == AOP_LIT && 
11951         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11952         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11953         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11954         MOVA(l);
11955         emitcode ("","!tlabeldef",lbl->key+100);
11956         emitcode ("movx", "@dptr,a");
11957         emitcode ("inc", "dptr");
11958         emitcode ("djnz","b,!tlabel",lbl->key+100);
11959     } else {
11960         symbol *lbl1 = newiTempLabel(NULL);
11961         
11962         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11963         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11964         emitcode ("","!tlabeldef",lbl->key+100);
11965         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11966         emitcode ("movx", "@dptr,a");
11967         emitcode ("inc", "dptr");
11968         emitcode ("mov","a,b");
11969         emitcode ("orl","a,_ap");
11970         emitcode ("jz","!tlabel",lbl1->key+100);
11971         emitcode ("mov","a,_ap");
11972         emitcode ("add","a,#!constbyte",0xFF);
11973         emitcode ("mov","_ap,a");
11974         emitcode ("mov","a,b");
11975         emitcode ("addc","a,#!constbyte",0xFF);
11976         emitcode ("mov","b,a");
11977         emitcode ("sjmp","!tlabel",lbl->key+100);
11978         emitcode ("","!tlabeldef",lbl1->key+100);
11979     }
11980     freeAsmop (count, NULL, ic, FALSE);
11981     unsavermask(rsave);
11982 }
11983
11984 /*-----------------------------------------------------------------*/
11985 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11986 /*-----------------------------------------------------------------*/
11987 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11988 {
11989         bitVect *rsave ;
11990         operand *pnum, *result;
11991         int i;
11992     
11993         assert (nparms==1);
11994         /* save registers that need to be saved */
11995         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11996                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11997     
11998         pnum = parms[0]; 
11999         aopOp (pnum, ic, FALSE, FALSE);
12000         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12001         freeAsmop (pnum, NULL, ic, FALSE);
12002         emitcode ("lcall","NatLib_LoadPrimitive");
12003         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12004         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12005             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12006                 for (i = (size-1) ; i >= 0 ; i-- ) {
12007                         emitcode ("push","a%s",javaRet[i]);
12008                 }
12009                 for (i=0; i < size ; i++ ) {
12010                         emitcode ("pop","a%s",
12011                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12012                 }
12013         } else {
12014                 for (i = 0 ; i < size ; i++ ) {
12015                         aopPut(AOP(result),javaRet[i],i);
12016                 }
12017         }    
12018         freeAsmop (result, NULL, ic, FALSE);
12019         unsavermask(rsave);
12020 }
12021
12022 /*-----------------------------------------------------------------*/
12023 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12024 /*-----------------------------------------------------------------*/
12025 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12026 {
12027         bitVect *rsave ;
12028         operand *pnum, *result;
12029         int size = 3;
12030         int i;
12031     
12032         assert (nparms==1);
12033         /* save registers that need to be saved */
12034         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12035                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12036     
12037         pnum = parms[0]; 
12038         aopOp (pnum, ic, FALSE, FALSE);
12039         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12040         freeAsmop (pnum, NULL, ic, FALSE);
12041         emitcode ("lcall","NatLib_LoadPointer");
12042         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12043         if (AOP_TYPE(result)!=AOP_STR) {
12044                 for (i = 0 ; i < size ; i++ ) {
12045                         aopPut(AOP(result),fReturn[i],i);
12046                 }
12047         }    
12048         freeAsmop (result, NULL, ic, FALSE);
12049         unsavermask(rsave);
12050 }
12051
12052 /*-----------------------------------------------------------------*/
12053 /* genNatLibInstallStateBlock -                                    */
12054 /*-----------------------------------------------------------------*/
12055 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12056                                        operand **parms, const char *name)
12057 {
12058         bitVect *rsave ;
12059         operand *psb, *handle;
12060         assert (nparms==2);
12061
12062         /* save registers that need to be saved */
12063         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12064                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12065         psb = parms[0];
12066         handle = parms[1];
12067
12068         /* put pointer to state block into DPTR1 */
12069         aopOp (psb, ic, FALSE, FALSE);
12070         if (AOP_TYPE (psb) == AOP_IMMD) {
12071                 emitcode ("mov","dps,#1");
12072                 emitcode ("mov", "dptr,%s",
12073                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12074                 emitcode ("mov","dps,#0");
12075         } else {
12076                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12077                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12078                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12079         }
12080         freeAsmop (psb, NULL, ic, FALSE);
12081
12082         /* put libraryID into DPTR */
12083         emitcode ("mov","dptr,#LibraryID");
12084
12085         /* put handle into r3:r2 */
12086         aopOp (handle, ic, FALSE, FALSE);
12087         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12088                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12089                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12090                 emitcode ("pop","ar3");
12091                 emitcode ("pop","ar2");
12092         } else {        
12093                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12094                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12095         }
12096         freeAsmop (psb, NULL, ic, FALSE);
12097
12098         /* make the call */
12099         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12100
12101         /* put return value into place*/
12102         _G.accInUse++;
12103         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12104         _G.accInUse--;
12105         aopPut(AOP(IC_RESULT(ic)),"a",0);
12106         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12107         unsavermask(rsave);
12108 }
12109
12110 /*-----------------------------------------------------------------*/
12111 /* genNatLibRemoveStateBlock -                                     */
12112 /*-----------------------------------------------------------------*/
12113 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12114 {
12115         bitVect *rsave ;
12116
12117         assert(nparms==0);
12118
12119         /* save registers that need to be saved */
12120         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12122
12123         /* put libraryID into DPTR */
12124         emitcode ("mov","dptr,#LibraryID");
12125         /* make the call */
12126         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12127         unsavermask(rsave);
12128 }
12129
12130 /*-----------------------------------------------------------------*/
12131 /* genNatLibGetStateBlock -                                        */
12132 /*-----------------------------------------------------------------*/
12133 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12134                                    operand **parms,const char *name)
12135 {
12136         bitVect *rsave ;
12137         symbol *lbl = newiTempLabel(NULL);
12138         
12139         assert(nparms==0);
12140         /* save registers that need to be saved */
12141         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12142                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12143
12144         /* put libraryID into DPTR */
12145         emitcode ("mov","dptr,#LibraryID");
12146         /* make the call */
12147         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12148         emitcode ("jnz","!tlabel",lbl->key+100);
12149
12150         /* put return value into place */
12151         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12152         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12153                 emitcode ("push","ar3");
12154                 emitcode ("push","ar2");
12155                 emitcode ("pop","%s",
12156                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12157                 emitcode ("pop","%s",
12158                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12159         } else {
12160                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12161                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12162         }
12163         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12164         emitcode ("","!tlabeldef",lbl->key+100);
12165         unsavermask(rsave);
12166 }
12167
12168 /*-----------------------------------------------------------------*/
12169 /* genMMMalloc -                                                   */
12170 /*-----------------------------------------------------------------*/
12171 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12172                          int size, const char *name)
12173 {
12174         bitVect *rsave ;
12175         operand *bsize;
12176         symbol *rsym;
12177         symbol *lbl = newiTempLabel(NULL);
12178
12179         assert (nparms == 1);
12180         /* save registers that need to be saved */
12181         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12182                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12183         
12184         bsize=parms[0];
12185         aopOp (bsize,ic,FALSE,FALSE);
12186
12187         /* put the size in R4-R2 */
12188         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12189                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12190                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12191                 if (size==3) {
12192                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12193                         emitcode("pop","ar4");
12194                 }
12195                 emitcode("pop","ar3");
12196                 emitcode("pop","ar2");          
12197         } else {
12198                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12199                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12200                 if (size==3) {
12201                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12202                 }
12203         }
12204         freeAsmop (bsize, NULL, ic, FALSE);
12205
12206         /* make the call */
12207         emitcode ("lcall","MM_%s",name);
12208         emitcode ("jz","!tlabel",lbl->key+100);
12209         emitcode ("mov","r2,#!constbyte",0xff);
12210         emitcode ("mov","r3,#!constbyte",0xff);
12211         emitcode ("","!tlabeldef",lbl->key+100);
12212         /* we don't care about the pointer : we just save the handle */
12213         rsym = OP_SYMBOL(IC_RESULT(ic));
12214         if (rsym->liveFrom != rsym->liveTo) {
12215                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12216                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12217                         emitcode ("push","ar3");
12218                         emitcode ("push","ar2");
12219                         emitcode ("pop","%s",
12220                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12221                         emitcode ("pop","%s",
12222                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12223                 } else {
12224                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12225                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12226                 }
12227                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12228         }
12229         unsavermask(rsave);
12230 }
12231
12232 /*-----------------------------------------------------------------*/
12233 /* genMMDeref -                                                    */
12234 /*-----------------------------------------------------------------*/
12235 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12236 {
12237         bitVect *rsave ;
12238         operand *handle;
12239
12240         assert (nparms == 1);
12241         /* save registers that need to be saved */
12242         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12243                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12244         
12245         handle=parms[0];
12246         aopOp (handle,ic,FALSE,FALSE);
12247
12248         /* put the size in R4-R2 */
12249         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12250                 emitcode("push","%s",
12251                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12252                 emitcode("push","%s",
12253                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12254                 emitcode("pop","ar3");
12255                 emitcode("pop","ar2");          
12256         } else {
12257                 emitcode ("mov","r2,%s",
12258                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12259                 emitcode ("mov","r3,%s",
12260                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12261         }
12262         freeAsmop (handle, NULL, ic, FALSE);
12263
12264         /* make the call */
12265         emitcode ("lcall","MM_Deref");
12266         
12267         {
12268                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12269                 if (rsym->liveFrom != rsym->liveTo) {                   
12270                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12271                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12272                             _startLazyDPSEvaluation ();
12273                             
12274                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12275                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12276                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12277
12278                             _endLazyDPSEvaluation ();
12279                             
12280                         }
12281                 }
12282         }
12283         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12284         unsavermask(rsave);
12285 }
12286
12287 /*-----------------------------------------------------------------*/
12288 /* genMMUnrestrictedPersist -                                      */
12289 /*-----------------------------------------------------------------*/
12290 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12291 {
12292         bitVect *rsave ;
12293         operand *handle;
12294
12295         assert (nparms == 1);
12296         /* save registers that need to be saved */
12297         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12298                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12299         
12300         handle=parms[0];
12301         aopOp (handle,ic,FALSE,FALSE);
12302
12303         /* put the size in R3-R2 */
12304         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12305                 emitcode("push","%s",
12306                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12307                 emitcode("push","%s",
12308                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12309                 emitcode("pop","ar3");
12310                 emitcode("pop","ar2");          
12311         } else {
12312                 emitcode ("mov","r2,%s",
12313                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12314                 emitcode ("mov","r3,%s",
12315                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12316         }
12317         freeAsmop (handle, NULL, ic, FALSE);
12318
12319         /* make the call */
12320         emitcode ("lcall","MM_UnrestrictedPersist");
12321
12322         {
12323                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12324                 if (rsym->liveFrom != rsym->liveTo) {   
12325                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12326                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12327                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12328                 }
12329         }
12330         unsavermask(rsave);
12331 }
12332
12333 /*-----------------------------------------------------------------*/
12334 /* genSystemExecJavaProcess -                                      */
12335 /*-----------------------------------------------------------------*/
12336 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12337 {
12338         bitVect *rsave ;
12339         operand *handle, *pp;
12340
12341         assert (nparms==2);
12342         /* save registers that need to be saved */
12343         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12344                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12345         
12346         pp = parms[0];
12347         handle = parms[1];
12348         
12349         /* put the handle in R3-R2 */
12350         aopOp (handle,ic,FALSE,FALSE);
12351         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12352                 emitcode("push","%s",
12353                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12354                 emitcode("push","%s",
12355                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12356                 emitcode("pop","ar3");
12357                 emitcode("pop","ar2");          
12358         } else {
12359                 emitcode ("mov","r2,%s",
12360                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12361                 emitcode ("mov","r3,%s",
12362                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12363         }
12364         freeAsmop (handle, NULL, ic, FALSE);
12365         
12366         /* put pointer in DPTR */
12367         aopOp (pp,ic,FALSE,FALSE);
12368         if (AOP_TYPE(pp) == AOP_IMMD) {
12369                 emitcode ("mov", "dptr,%s",
12370                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12371         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12372                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12373                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12374                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12375         }
12376         freeAsmop (handle, NULL, ic, FALSE);
12377
12378         /* make the call */
12379         emitcode ("lcall","System_ExecJavaProcess");
12380         
12381         /* put result in place */
12382         {
12383                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12384                 if (rsym->liveFrom != rsym->liveTo) {   
12385                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12386                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12387                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12388                 }
12389         }
12390         
12391         unsavermask(rsave);
12392 }
12393
12394 /*-----------------------------------------------------------------*/
12395 /* genSystemRTCRegisters -                                         */
12396 /*-----------------------------------------------------------------*/
12397 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12398                                   char *name)
12399 {
12400         bitVect *rsave ;
12401         operand *pp;
12402
12403         assert (nparms==1);
12404         /* save registers that need to be saved */
12405         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12406                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12407         
12408         pp=parms[0];
12409         /* put pointer in DPTR */
12410         aopOp (pp,ic,FALSE,FALSE);
12411         if (AOP_TYPE (pp) == AOP_IMMD) {
12412                 emitcode ("mov","dps,#1");
12413                 emitcode ("mov", "dptr,%s", 
12414                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12415                 emitcode ("mov","dps,#0");
12416         } else {
12417                 emitcode ("mov","dpl1,%s",
12418                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12419                 emitcode ("mov","dph1,%s",
12420                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12421                 emitcode ("mov","dpx1,%s",
12422                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12423         }
12424         freeAsmop (pp, NULL, ic, FALSE);
12425
12426         /* make the call */
12427         emitcode ("lcall","System_%sRTCRegisters",name);
12428
12429         unsavermask(rsave);
12430 }
12431
12432 /*-----------------------------------------------------------------*/
12433 /* genSystemThreadSleep -                                          */
12434 /*-----------------------------------------------------------------*/
12435 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12436 {
12437         bitVect *rsave ;
12438         operand *to, *s;
12439
12440         assert (nparms==1);
12441         /* save registers that need to be saved */
12442         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12443                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12444
12445         to = parms[0];
12446         aopOp(to,ic,FALSE,FALSE);
12447         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12448             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12449                 emitcode ("push","%s",
12450                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12451                 emitcode ("push","%s",
12452                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12453                 emitcode ("push","%s",
12454                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12455                 emitcode ("push","%s",
12456                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12457                 emitcode ("pop","ar3");
12458                 emitcode ("pop","ar2");
12459                 emitcode ("pop","ar1");
12460                 emitcode ("pop","ar0");
12461         } else {
12462                 emitcode ("mov","r0,%s",
12463                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12464                 emitcode ("mov","r1,%s",
12465                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12466                 emitcode ("mov","r2,%s",
12467                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12468                 emitcode ("mov","r3,%s",
12469                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12470         }
12471         freeAsmop (to, NULL, ic, FALSE);
12472
12473         /* suspend in acc */
12474         s = parms[1];
12475         aopOp(s,ic,FALSE,FALSE);
12476         emitcode ("mov","a,%s",
12477                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12478         freeAsmop (s, NULL, ic, FALSE);
12479
12480         /* make the call */
12481         emitcode ("lcall","System_%s",name);
12482
12483         unsavermask(rsave);
12484 }
12485
12486 /*-----------------------------------------------------------------*/
12487 /* genSystemThreadResume -                                         */
12488 /*-----------------------------------------------------------------*/
12489 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12490 {
12491         bitVect *rsave ;
12492         operand *tid,*pid;
12493
12494         assert (nparms==2);
12495         /* save registers that need to be saved */
12496         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12497                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12498         
12499         tid = parms[0];
12500         pid = parms[1];
12501         
12502         /* PID in R0 */
12503         aopOp(pid,ic,FALSE,FALSE);
12504         emitcode ("mov","r0,%s",
12505                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12506         freeAsmop (pid, NULL, ic, FALSE);
12507         
12508         /* tid into ACC */
12509         aopOp(tid,ic,FALSE,FALSE);
12510         emitcode ("mov","a,%s",
12511                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12512         freeAsmop (tid, NULL, ic, FALSE);
12513         
12514         emitcode ("lcall","System_ThreadResume");
12515
12516         /* put result into place */
12517         {
12518                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12519                 if (rsym->liveFrom != rsym->liveTo) {   
12520                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12521                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12522                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12523                 }
12524         }
12525         unsavermask(rsave);
12526 }
12527
12528 /*-----------------------------------------------------------------*/
12529 /* genSystemProcessResume -                                        */
12530 /*-----------------------------------------------------------------*/
12531 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12532 {
12533         bitVect *rsave ;
12534         operand *pid;
12535
12536         assert (nparms==1);
12537         /* save registers that need to be saved */
12538         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12539                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12540         
12541         pid = parms[0];
12542         
12543         /* pid into ACC */
12544         aopOp(pid,ic,FALSE,FALSE);
12545         emitcode ("mov","a,%s",
12546                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12547         freeAsmop (pid, NULL, ic, FALSE);
12548         
12549         emitcode ("lcall","System_ProcessResume");
12550
12551         unsavermask(rsave);
12552 }
12553
12554 /*-----------------------------------------------------------------*/
12555 /* genSystem -                                                     */
12556 /*-----------------------------------------------------------------*/
12557 static void genSystem (iCode *ic,int nparms,char *name)
12558 {
12559         assert(nparms == 0);
12560
12561         emitcode ("lcall","System_%s",name);
12562 }
12563
12564 /*-----------------------------------------------------------------*/
12565 /* genSystemPoll -                                                  */
12566 /*-----------------------------------------------------------------*/
12567 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12568 {
12569         bitVect *rsave ;
12570         operand *fp;
12571
12572         assert (nparms==1);
12573         /* save registers that need to be saved */
12574         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12575                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12576
12577         fp = parms[0];
12578         aopOp (fp,ic,FALSE,FALSE);
12579         if (AOP_TYPE (fp) == AOP_IMMD) {
12580                 emitcode ("mov", "dptr,%s", 
12581                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12582         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12583                 emitcode ("mov","dpl,%s",
12584                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12585                 emitcode ("mov","dph,%s",
12586                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12587                 emitcode ("mov","dpx,%s",
12588                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12589         }
12590         freeAsmop (fp, NULL, ic, FALSE);
12591
12592         emitcode ("lcall","System_%sPoll",name);
12593
12594         /* put result into place */
12595         {
12596                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12597                 if (rsym->liveFrom != rsym->liveTo) {   
12598                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12599                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12600                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12601                 }
12602         }
12603         unsavermask(rsave);
12604 }
12605
12606 /*-----------------------------------------------------------------*/
12607 /* genSystemGetCurrentID -                                         */
12608 /*-----------------------------------------------------------------*/
12609 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12610 {
12611         assert (nparms==0);
12612
12613         emitcode ("lcall","System_GetCurrent%sId",name);
12614         /* put result into place */
12615         {
12616                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12617                 if (rsym->liveFrom != rsym->liveTo) {   
12618                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12619                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12620                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12621                 }
12622         }
12623 }
12624
12625 /*-----------------------------------------------------------------*/
12626 /* genDummyRead - generate code for dummy read of volatiles        */
12627 /*-----------------------------------------------------------------*/
12628 static void
12629 genDummyRead (iCode * ic)
12630 {
12631   operand *right;
12632   int size, offset;
12633
12634   D(emitcode(";     genDummyRead",""));
12635
12636   right = IC_RIGHT (ic);
12637
12638   aopOp (right, ic, FALSE, FALSE);
12639
12640   /* if the result is a bit */
12641   if (AOP_TYPE (right) == AOP_CRY)
12642     {
12643       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12644       goto release;
12645     }
12646
12647   /* bit variables done */
12648   /* general case */
12649   size = AOP_SIZE (right);
12650   offset = 0;
12651   while (size--)
12652     {
12653       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12654       offset++;
12655     }
12656
12657 release:
12658   freeAsmop (right, NULL, ic, TRUE);
12659 }
12660
12661 /*-----------------------------------------------------------------*/
12662 /* genBuiltIn - calls the appropriate function to  generating code */
12663 /* for a built in function                                         */
12664 /*-----------------------------------------------------------------*/
12665 static void genBuiltIn (iCode *ic)
12666 {
12667         operand *bi_parms[MAX_BUILTIN_ARGS];
12668         int nbi_parms;
12669         iCode *bi_iCode;
12670         symbol *bif;
12671
12672         /* get all the arguments for a built in function */
12673         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12674
12675         /* which function is it */
12676         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12677         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12678                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12679         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12680                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12681         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12682                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12683         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12684                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12685         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12686                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12687         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12688                 genInp(bi_iCode,nbi_parms,bi_parms);
12689         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12690                 genOutp(bi_iCode,nbi_parms,bi_parms);
12691         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12692                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12693                 /* JavaNative builtIns */               
12694         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12695                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12696         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12697                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12698         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12699                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12700         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12701                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12702         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12703                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12704         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12705                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12706         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12707                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12708         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12709                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12710         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12711                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12712         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12713                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12714         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12715                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12716         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12717                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12718         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12719                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12720         } else if (strcmp(bif->name,"MM_Free")==0) {
12721                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12722         } else if (strcmp(bif->name,"MM_Deref")==0) {
12723                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12724         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12725                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12726         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12727                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12728         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12729                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12730         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12731                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12732         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12733                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12734         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12735                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12736         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12737                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12738         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12739                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12740         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12741                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12742         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12743                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12744         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12745                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12746         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12747                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12748         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12749                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12750         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12751                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12752         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12753                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12754         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12755                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12756         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12757                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12758         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12759                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12760         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12761                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12762         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12763                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12764         } else {
12765                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12766                 return ;
12767         }
12768         return ;    
12769 }
12770
12771 /*-----------------------------------------------------------------*/
12772 /* gen390Code - generate code for Dallas 390 based controllers     */
12773 /*-----------------------------------------------------------------*/
12774 void
12775 gen390Code (iCode * lic)
12776 {
12777   iCode *ic;
12778   int cln = 0;
12779
12780   lineHead = lineCurr = NULL;
12781   dptrn[1][0] = "dpl1";
12782   dptrn[1][1] = "dph1";
12783   dptrn[1][2] = "dpx1";
12784   
12785   if (options.model == MODEL_FLAT24) {
12786     fReturnSizeDS390 = 5;
12787     fReturn = fReturn24;
12788   } else {
12789     fReturnSizeDS390 = 4;
12790     fReturn = fReturn16;
12791     options.stack10bit=0;
12792   }
12793 #if 1
12794   /* print the allocation information */
12795   if (allocInfo && currFunc)
12796     printAllocInfo (currFunc, codeOutFile);
12797 #endif
12798   /* if debug information required */
12799   if (options.debug && currFunc)
12800     {
12801       debugFile->writeFunction(currFunc);
12802       _G.debugLine = 1;
12803       if (IS_STATIC (currFunc->etype))
12804         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12805       else
12806         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12807       _G.debugLine = 0;
12808     }
12809   /* stack pointer name */
12810   if (options.useXstack)
12811     spname = "_spx";
12812   else
12813     spname = "sp";
12814
12815
12816   for (ic = lic; ic; ic = ic->next)
12817     {
12818
12819       if (ic->lineno && cln != ic->lineno)
12820         {
12821           if (options.debug)
12822             {
12823               _G.debugLine = 1;
12824               emitcode ("", "C$%s$%d$%d$%d ==.",
12825                         FileBaseName (ic->filename), ic->lineno,
12826                         ic->level, ic->block);
12827               _G.debugLine = 0;
12828             }
12829           if (!options.noCcodeInAsm) {
12830             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12831                       printCLine(ic->filename, ic->lineno));
12832           }
12833           cln = ic->lineno;
12834         }
12835       if (options.iCodeInAsm) {
12836         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12837       }
12838       /* if the result is marked as
12839          spilt and rematerializable or code for
12840          this has already been generated then
12841          do nothing */
12842       if (resultRemat (ic) || ic->generated)
12843         continue;
12844
12845       /* depending on the operation */
12846       switch (ic->op)
12847         {
12848         case '!':
12849           genNot (ic);
12850           break;
12851
12852         case '~':
12853           genCpl (ic);
12854           break;
12855
12856         case UNARYMINUS:
12857           genUminus (ic);
12858           break;
12859
12860         case IPUSH:
12861           genIpush (ic);
12862           break;
12863
12864         case IPOP:
12865           /* IPOP happens only when trying to restore a
12866              spilt live range, if there is an ifx statement
12867              following this pop then the if statement might
12868              be using some of the registers being popped which
12869              would destory the contents of the register so
12870              we need to check for this condition and handle it */
12871           if (ic->next &&
12872               ic->next->op == IFX &&
12873               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12874             genIfx (ic->next, ic);
12875           else
12876             genIpop (ic);
12877           break;
12878
12879         case CALL:
12880           genCall (ic);
12881           break;
12882
12883         case PCALL:
12884           genPcall (ic);
12885           break;
12886
12887         case FUNCTION:
12888           genFunction (ic);
12889           break;
12890
12891         case ENDFUNCTION:
12892           genEndFunction (ic);
12893           break;
12894
12895         case RETURN:
12896           genRet (ic);
12897           break;
12898
12899         case LABEL:
12900           genLabel (ic);
12901           break;
12902
12903         case GOTO:
12904           genGoto (ic);
12905           break;
12906
12907         case '+':
12908           genPlus (ic);
12909           break;
12910
12911         case '-':
12912           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12913             genMinus (ic);
12914           break;
12915
12916         case '*':
12917           genMult (ic);
12918           break;
12919
12920         case '/':
12921           genDiv (ic);
12922           break;
12923
12924         case '%':
12925           genMod (ic);
12926           break;
12927
12928         case '>':
12929           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12930           break;
12931
12932         case '<':
12933           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12934           break;
12935
12936         case LE_OP:
12937         case GE_OP:
12938         case NE_OP:
12939
12940           /* note these two are xlated by algebraic equivalence
12941              during parsing SDCC.y */
12942           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12943                   "got '>=' or '<=' shouldn't have come here");
12944           break;
12945
12946         case EQ_OP:
12947           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12948           break;
12949
12950         case AND_OP:
12951           genAndOp (ic);
12952           break;
12953
12954         case OR_OP:
12955           genOrOp (ic);
12956           break;
12957
12958         case '^':
12959           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12960           break;
12961
12962         case '|':
12963           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12964           break;
12965
12966         case BITWISEAND:
12967           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12968           break;
12969
12970         case INLINEASM:
12971           genInline (ic);
12972           break;
12973
12974         case RRC:
12975           genRRC (ic);
12976           break;
12977
12978         case RLC:
12979           genRLC (ic);
12980           break;
12981
12982         case GETHBIT:
12983           genGetHbit (ic);
12984           break;
12985
12986         case LEFT_OP:
12987           genLeftShift (ic);
12988           break;
12989
12990         case RIGHT_OP:
12991           genRightShift (ic);
12992           break;
12993
12994         case GET_VALUE_AT_ADDRESS:
12995           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12996           break;
12997
12998         case '=':
12999           if (POINTER_SET (ic))
13000             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13001           else
13002             genAssign (ic);
13003           break;
13004
13005         case IFX:
13006           genIfx (ic, NULL);
13007           break;
13008
13009         case ADDRESS_OF:
13010           genAddrOf (ic);
13011           break;
13012
13013         case JUMPTABLE:
13014           genJumpTab (ic);
13015           break;
13016
13017         case CAST:
13018           genCast (ic);
13019           break;
13020
13021         case RECEIVE:
13022           genReceive (ic);
13023           break;
13024
13025         case SEND:
13026           if (ic->builtinSEND) genBuiltIn(ic);
13027           else addSet (&_G.sendSet, ic);
13028           break;
13029
13030         case DUMMY_READ_VOLATILE:
13031           genDummyRead (ic);
13032           break;
13033
13034 #if 0 // obsolete, and buggy for != xdata
13035         case ARRAYINIT:
13036             genArrayInit(ic);
13037             break;
13038 #endif
13039             
13040         default:
13041           ic = ic;
13042         }
13043     }
13044
13045
13046   /* now we are ready to call the
13047      peep hole optimizer */
13048   if (!options.nopeep)
13049     peepHole (&lineHead);
13050
13051   /* now do the actual printing */
13052   printLine (lineHead, codeOutFile);
13053   return;
13054 }