* src/z80/gen.h,
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "common.h"
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #define BETTER_LITERAL_SHIFT
40
41 char *aopLiteral (value * val, int offset);
42 extern int allocInfo;
43
44 /* this is the down and dirty file with all kinds of
45    kludgy & hacky stuff. This is what it is all about
46    CODE GENERATION for a specific MCU . some of the
47    routines may be reusable, will have to see */
48
49 static char *zero = "#0";
50 static char *one = "#1";
51 static char *spname;
52
53 #define D(x) x
54
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
57
58 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
65 {"a", "b"};
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
69
70 static struct
71   {
72     short r0Pushed;
73     short r1Pushed;
74     short accInUse;
75     short bInUse;
76     short inLine;
77     short debugLine;
78     short nRegsSaved;
79     short dptrInUse;
80     short dptr1InUse;
81     set *sendSet;
82   }
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       
1010       if (sym->usl.spillLoc)
1011         {
1012           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013             {
1014               /* force a new aop if sizes differ */
1015               sym->usl.spillLoc->aop = NULL;
1016             }
1017           sym->aop = op->aop = aop =
1018                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1019           aop->size = getSize (sym->type);
1020           return;
1021         }
1022       
1023       /* else must be a dummy iTemp */
1024       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1025       aop->size = getSize (sym->type);
1026       return;
1027     }
1028
1029   /* must be in a register */
1030   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1031   aop->size = sym->nRegs;
1032   for (i = 0; i < sym->nRegs; i++)
1033     aop->aopu.aop_reg[i] = sym->regs[i];
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* freeAsmop - free up the asmop given to an operand               */
1038 /*----------------------------------------------------------------*/
1039 static void
1040 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1041 {
1042   asmop *aop;
1043
1044   if (!op)
1045     aop = aaop;
1046   else
1047     aop = op->aop;
1048
1049   if (!aop)
1050     return;
1051
1052   if (aop->freed)
1053     goto dealloc;
1054
1055   aop->freed = 1;
1056
1057   /* depending on the asmop type only three cases need work AOP_RO
1058      , AOP_R1 && AOP_STK */
1059   switch (aop->type)
1060     {
1061     case AOP_R0:
1062       if (_G.r0Pushed)
1063         {
1064           if (pop)
1065             {
1066               emitcode ("pop", "ar0");
1067               _G.r0Pushed--;
1068             }
1069         }
1070       bitVectUnSetBit (ic->rUsed, R0_IDX);
1071       break;
1072
1073     case AOP_R1:
1074       if (_G.r1Pushed)
1075         {
1076           if (pop)
1077             {
1078               emitcode ("pop", "ar1");
1079               _G.r1Pushed--;
1080             }
1081         }
1082       bitVectUnSetBit (ic->rUsed, R1_IDX);
1083       break;
1084
1085     case AOP_STK:
1086       {
1087         int sz = aop->size;
1088         int stk = aop->aopu.aop_stk + aop->size;
1089         bitVectUnSetBit (ic->rUsed, R0_IDX);
1090         bitVectUnSetBit (ic->rUsed, R1_IDX);
1091
1092         getFreePtr (ic, &aop, FALSE);
1093
1094         if (options.stack10bit)
1095           {
1096             /* I'm not sure what to do here yet... */
1097             /* #STUB */
1098             fprintf (stderr,
1099                      "*** Warning: probably generating bad code for "
1100                      "10 bit stack mode.\n");
1101           }
1102
1103         if (stk)
1104           {
1105             emitcode ("mov", "a,_bp");
1106             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1107             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1108           }
1109         else
1110           {
1111             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1112           }
1113
1114         while (sz--)
1115           {
1116             emitcode ("pop", "acc");
1117             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1118             if (!sz)
1119               break;
1120             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1121           }
1122         op->aop = aop;
1123         freeAsmop (op, NULL, ic, TRUE);
1124         if (_G.r0Pushed)
1125           {
1126             emitcode ("pop", "ar0");
1127             _G.r0Pushed--;
1128           }
1129
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135       }
1136     case AOP_DPTR2:
1137         if (_G.dptr1InUse) {
1138             emitcode ("pop","dpx1");
1139             emitcode ("pop","dph1");
1140             emitcode ("pop","dpl1");
1141         }
1142         break;
1143     case AOP_DPTR:
1144         if (_G.dptrInUse) {
1145             emitcode ("pop","dpx");
1146             emitcode ("pop","dph");
1147             emitcode ("pop","dpl");
1148         }
1149         break;
1150     }
1151 dealloc:
1152   /* all other cases just dealloc */
1153   if (op)
1154     {
1155       op->aop = NULL;
1156       if (IS_SYMOP (op))
1157         {
1158           OP_SYMBOL (op)->aop = NULL;
1159           /* if the symbol has a spill */
1160           if (SPIL_LOC (op))
1161             SPIL_LOC (op)->aop = NULL;
1162         }
1163     }
1164 }
1165
1166 #define DEFAULT_ACC_WARNING 0
1167 static int saveAccWarn = DEFAULT_ACC_WARNING;
1168
1169 /*-------------------------------------------------------------------*/
1170 /* aopGet - for fetching value of the aop                            */
1171 /*                                                                   */
1172 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1173 /* in the accumulator. Set it to the name of a free register         */
1174 /* if acc must be preserved; the register will be used to preserve   */
1175 /* acc temporarily and to return the result byte.                    */
1176 /*-------------------------------------------------------------------*/
1177
1178 static char *
1179 aopGet (asmop *aop,
1180         int   offset,
1181         bool  bit16,
1182         bool  dname,
1183         char  *saveAcc)
1184 {
1185   /* offset is greater than
1186      size then zero */
1187   if (offset > (aop->size - 1) &&
1188       aop->type != AOP_LIT)
1189     return zero;
1190
1191   /* depending on type */
1192   switch (aop->type)
1193     {
1194     case AOP_DUMMY:
1195       return zero;
1196
1197     case AOP_R0:
1198     case AOP_R1:
1199       /* if we need to increment it */
1200       while (offset > aop->coff)
1201         {
1202           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1203           aop->coff++;
1204         }
1205
1206       while (offset < aop->coff)
1207         {
1208           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1209           aop->coff--;
1210         }
1211
1212       aop->coff = offset;
1213       if (aop->paged)
1214         {
1215           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1216           return (dname ? "acc" : "a");
1217         }
1218       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1219       return Safe_strdup(buffer);       
1220
1221     case AOP_DPTRn:
1222         assert(offset <= 3);
1223         return dptrn[aop->aopu.dptr][offset];
1224
1225     case AOP_DPTR:
1226     case AOP_DPTR2:
1227
1228       if (aop->type == AOP_DPTR2)
1229         {
1230           genSetDPTR (1);
1231         }
1232         
1233       if (saveAcc)
1234         {
1235             TR_AP("#1");
1236 //          if (aop->type != AOP_DPTR2)
1237 //          {
1238 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1239 //              emitcode(";", "spanky: saveAcc for DPTR");
1240 //          }
1241             
1242             emitcode ("xch", "a, %s", saveAcc);
1243         }
1244
1245       _flushLazyDPS ();
1246
1247       while (offset > aop->coff)
1248         {
1249           emitcode ("inc", "dptr");
1250           aop->coff++;
1251         }
1252
1253       while (offset < aop->coff)
1254         {
1255           emitcode ("lcall", "__decdptr");
1256           aop->coff--;
1257         }
1258
1259       aop->coff = offset;
1260       if (aop->code)
1261         {
1262           emitcode ("clr", "a");
1263           emitcode ("movc", "a,@a+dptr");
1264         }
1265       else
1266         {
1267           emitcode ("movx", "a,@dptr");
1268         }
1269
1270       if (aop->type == AOP_DPTR2)
1271         {
1272           genSetDPTR (0);
1273         }
1274         
1275         if (saveAcc)
1276         {
1277        TR_AP("#2");
1278               emitcode ("xch", "a, %s", saveAcc);
1279 //            if (strcmp(saveAcc, "_ap"))
1280 //            {
1281 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1282 //            }
1283                   
1284               return saveAcc;
1285         }
1286       return (dname ? "acc" : "a");
1287
1288     case AOP_IMMD:
1289       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1290       {
1291           SNPRINTF(buffer, sizeof(buffer), 
1292                    "%s",aop->aopu.aop_immd.aop_immd2);
1293       } 
1294       else if (bit16)
1295       {
1296          SNPRINTF(buffer, sizeof(buffer), 
1297                   "#%s", aop->aopu.aop_immd.aop_immd1);
1298       }
1299       else if (offset) 
1300       {
1301           switch (offset) {
1302           case 1:
1303               tsprintf(buffer, sizeof(buffer),
1304                        "#!his",aop->aopu.aop_immd.aop_immd1);
1305               break;
1306           case 2:
1307               tsprintf(buffer, sizeof(buffer), 
1308                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1309               break;
1310           case 3:
1311               tsprintf(buffer, sizeof(buffer),
1312                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1313               break;
1314           default: /* should not need this (just in case) */
1315               SNPRINTF (buffer, sizeof(buffer), 
1316                         "#(%s >> %d)",
1317                        aop->aopu.aop_immd.aop_immd1,
1318                        offset * 8);
1319           }
1320       }
1321       else
1322       {
1323         SNPRINTF (buffer, sizeof(buffer), 
1324                   "#%s", aop->aopu.aop_immd.aop_immd1);
1325       }
1326       return Safe_strdup(buffer);       
1327
1328     case AOP_DIR:
1329       if (offset)
1330       {
1331         SNPRINTF (buffer, sizeof(buffer),
1332                   "(%s + %d)",
1333                  aop->aopu.aop_dir,
1334                  offset);
1335       }
1336       else
1337       {
1338         SNPRINTF(buffer, sizeof(buffer), 
1339                  "%s", aop->aopu.aop_dir);
1340       }
1341
1342       return Safe_strdup(buffer);
1343
1344     case AOP_REG:
1345       if (dname)
1346         return aop->aopu.aop_reg[offset]->dname;
1347       else
1348         return aop->aopu.aop_reg[offset]->name;
1349
1350     case AOP_CRY:
1351       emitcode ("clr", "a");
1352       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353       emitcode ("rlc", "a");
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_ACC:
1357       if (!offset && dname)
1358         return "acc";
1359       return aop->aopu.aop_str[offset];
1360
1361     case AOP_LIT:
1362       return aopLiteral (aop->aopu.aop_lit, offset);
1363
1364     case AOP_STR:
1365       aop->coff = offset;
1366       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1367           dname)
1368         return "acc";
1369
1370       return aop->aopu.aop_str[offset];
1371
1372     }
1373
1374   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375           "aopget got unsupported aop->type");
1376   exit (1);
1377     
1378   return NULL;  // not reached, but makes compiler happy.
1379 }
1380 /*-----------------------------------------------------------------*/
1381 /* aopPut - puts a string for a aop                                */
1382 /*-----------------------------------------------------------------*/
1383 static void
1384 aopPut (asmop * aop, char *s, int offset)
1385 {
1386   if (aop->size && offset > (aop->size - 1))
1387     {
1388       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1389               "aopPut got offset > aop->size");
1390       exit (1);
1391     }
1392
1393   /* will assign value to value */
1394   /* depending on where it is ofcourse */
1395   switch (aop->type)
1396     {
1397     case AOP_DUMMY:
1398       MOVA (s);         /* read s in case it was volatile */
1399       break;
1400       
1401     case AOP_DIR:
1402         if (offset)
1403         {
1404             SNPRINTF (buffer, sizeof(buffer),
1405                       "(%s + %d)",
1406                       aop->aopu.aop_dir, offset);
1407         }
1408         else
1409         {
1410             SNPRINTF (buffer, sizeof(buffer), 
1411                      "%s", aop->aopu.aop_dir);
1412         }
1413         
1414
1415         if (strcmp (buffer, s))
1416         {
1417             emitcode ("mov", "%s,%s", buffer, s);
1418         }
1419       break;
1420
1421     case AOP_REG:
1422       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1423           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1424         {
1425           if (*s == '@' ||
1426               strcmp (s, "r0") == 0 ||
1427               strcmp (s, "r1") == 0 ||
1428               strcmp (s, "r2") == 0 ||
1429               strcmp (s, "r3") == 0 ||
1430               strcmp (s, "r4") == 0 ||
1431               strcmp (s, "r5") == 0 ||
1432               strcmp (s, "r6") == 0 ||
1433               strcmp (s, "r7") == 0)
1434             {
1435                 emitcode ("mov", "%s,%s",
1436                           aop->aopu.aop_reg[offset]->dname, s);
1437             }
1438             else
1439             {
1440                 emitcode ("mov", "%s,%s",
1441                           aop->aopu.aop_reg[offset]->name, s);
1442             }
1443         }
1444       break;
1445
1446     case AOP_DPTRn:
1447         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1448         break;
1449
1450     case AOP_DPTR:
1451     case AOP_DPTR2:
1452
1453       if (aop->type == AOP_DPTR2)
1454         {
1455           genSetDPTR (1);
1456         }
1457       _flushLazyDPS ();
1458
1459       if (aop->code)
1460         {
1461           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462                   "aopPut writting to code space");
1463           exit (1);
1464         }
1465
1466       while (offset > aop->coff)
1467         {
1468           aop->coff++;
1469           emitcode ("inc", "dptr");
1470         }
1471
1472       while (offset < aop->coff)
1473         {
1474           aop->coff--;
1475           emitcode ("lcall", "__decdptr");
1476         }
1477
1478       aop->coff = offset;
1479
1480       /* if not in accumulater */
1481       MOVA (s);
1482
1483       emitcode ("movx", "@dptr,a");
1484
1485       if (aop->type == AOP_DPTR2)
1486         {
1487           genSetDPTR (0);
1488         }
1489       break;
1490
1491     case AOP_R0:
1492     case AOP_R1:
1493       while (offset > aop->coff)
1494         {
1495           aop->coff++;
1496           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1497         }
1498       while (offset < aop->coff)
1499         {
1500           aop->coff--;
1501           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1502         }
1503       aop->coff = offset;
1504
1505       if (aop->paged)
1506         {
1507           MOVA (s);
1508           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1509
1510         }
1511       else if (*s == '@')
1512         {
1513           MOVA (s);
1514           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1515         }
1516       else if (strcmp (s, "r0") == 0 ||
1517                strcmp (s, "r1") == 0 ||
1518                strcmp (s, "r2") == 0 ||
1519                strcmp (s, "r3") == 0 ||
1520                strcmp (s, "r4") == 0 ||
1521                strcmp (s, "r5") == 0 ||
1522                strcmp (s, "r6") == 0 ||
1523                strcmp (s, "r7") == 0)
1524         {
1525           char buff[10];
1526           SNPRINTF(buff, sizeof(buff), 
1527                    "a%s", s);
1528           emitcode ("mov", "@%s,%s",
1529                     aop->aopu.aop_ptr->name, buff);
1530         }
1531         else
1532         {
1533             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1534         }
1535       break;
1536
1537     case AOP_STK:
1538       if (strcmp (s, "a") == 0)
1539         emitcode ("push", "acc");
1540       else
1541         if (*s=='@') {
1542           MOVA(s);
1543           emitcode ("push", "acc");
1544         } else {
1545           emitcode ("push", s);
1546         }
1547
1548       break;
1549
1550     case AOP_CRY:
1551       /* if bit variable */
1552       if (!aop->aopu.aop_dir)
1553         {
1554           emitcode ("clr", "a");
1555           emitcode ("rlc", "a");
1556         }
1557       else
1558         {
1559           if (s == zero)
1560             emitcode ("clr", "%s", aop->aopu.aop_dir);
1561           else if (s == one)
1562             emitcode ("setb", "%s", aop->aopu.aop_dir);
1563           else if (!strcmp (s, "c"))
1564             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1565           else
1566             {
1567               if (strcmp (s, "a"))
1568                 {
1569                   MOVA (s);
1570                 }
1571               {
1572                 /* set C, if a >= 1 */
1573                 emitcode ("add", "a,#!constbyte",0xff);
1574                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1575               }
1576             }
1577         }
1578       break;
1579
1580     case AOP_STR:
1581       aop->coff = offset;
1582       if (strcmp (aop->aopu.aop_str[offset], s))
1583         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1584       break;
1585
1586     case AOP_ACC:
1587       aop->coff = offset;
1588       if (!offset && (strcmp (s, "acc") == 0))
1589         break;
1590
1591       if (strcmp (aop->aopu.aop_str[offset], s))
1592         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1593       break;
1594
1595     default:
1596       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1597               "aopPut got unsupported aop->type");
1598       exit (1);
1599     }
1600
1601 }
1602
1603
1604 /*--------------------------------------------------------------------*/
1605 /* reAdjustPreg - points a register back to where it should (coff==0) */
1606 /*--------------------------------------------------------------------*/
1607 static void
1608 reAdjustPreg (asmop * aop)
1609 {
1610   if ((aop->coff==0) || (aop->size <= 1)) {
1611     return;
1612   }
1613
1614   switch (aop->type)
1615     {
1616     case AOP_R0:
1617     case AOP_R1:
1618       while (aop->coff--)
1619         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1620       break;
1621     case AOP_DPTR:
1622     case AOP_DPTR2:
1623       if (aop->type == AOP_DPTR2)
1624         {
1625           genSetDPTR (1);
1626           _flushLazyDPS ();
1627         }
1628       while (aop->coff--)
1629         {
1630           emitcode ("lcall", "__decdptr");
1631         }
1632
1633       if (aop->type == AOP_DPTR2)
1634         {
1635           genSetDPTR (0);
1636         }
1637       break;
1638
1639     }
1640   aop->coff=0;
1641 }
1642
1643 #define AOP(op) op->aop
1644 #define AOP_TYPE(op) AOP(op)->type
1645 #define AOP_SIZE(op) AOP(op)->size
1646 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1647                        AOP_TYPE(x) == AOP_R0))
1648
1649 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1650                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1651                          AOP(x)->paged))
1652
1653 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1654                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1655                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1656 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1657 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1658 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1659
1660 // The following two macros can be used even if the aop has not yet been aopOp'd.
1661 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1662 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1663
1664 /* Workaround for DS80C390 bug: div ab may return bogus results
1665  * if A is accessed in instruction immediately before the div.
1666  *
1667  * Will be fixed in B4 rev of processor, Dallas claims.
1668  */
1669
1670 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1671     if (!AOP_NEEDSACC(RIGHT))         \
1672     {               \
1673       /* We can load A first, then B, since     \
1674        * B (the RIGHT operand) won't clobber A,   \
1675        * thus avoiding touching A right before the div. \
1676        */             \
1677       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1678       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1679       MOVA(L);            \
1680       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1681       MOVB(L); \
1682     }               \
1683     else              \
1684     {               \
1685       /* Just stuff in a nop after loading A. */    \
1686       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1687       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1688       MOVA(L);            \
1689       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1690     }
1691
1692
1693 /*-----------------------------------------------------------------*/
1694 /* opIsGptr: returns non-zero if the passed operand is       */
1695 /* a generic pointer type.             */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 opIsGptr (operand * op)
1699 {
1700   sym_link *type = operandType (op);
1701
1702   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1703     {
1704       return 1;
1705     }
1706   return 0;
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* getDataSize - get the operand data size                         */
1711 /*-----------------------------------------------------------------*/
1712 static int
1713 getDataSize (operand * op)
1714 {
1715   int size;
1716   size = AOP_SIZE (op);
1717   if (size == GPTRSIZE)
1718     {
1719       sym_link *type = operandType (op);
1720       if (IS_GENPTR (type))
1721         {
1722           /* generic pointer; arithmetic operations
1723            * should ignore the high byte (pointer type).
1724            */
1725           size--;
1726         }
1727     }
1728   return size;
1729 }
1730
1731 /*-----------------------------------------------------------------*/
1732 /* outAcc - output Acc                                             */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 outAcc (operand * result)
1736 {
1737   int size, offset;
1738   size = getDataSize (result);
1739   if (size)
1740     {
1741       aopPut (AOP (result), "a", 0);
1742       size--;
1743       offset = 1;
1744       /* unsigned or positive */
1745       while (size--)
1746         {
1747           aopPut (AOP (result), zero, offset++);
1748         }
1749     }
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* outBitC - output a bit C                                        */
1754 /*-----------------------------------------------------------------*/
1755 static void
1756 outBitC (operand * result)
1757 {
1758   /* if the result is bit */
1759   if (AOP_TYPE (result) == AOP_CRY)
1760     {
1761       aopPut (AOP (result), "c", 0);
1762     }
1763   else
1764     {
1765       emitcode ("clr", "a");
1766       emitcode ("rlc", "a");
1767       outAcc (result);
1768     }
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* toBoolean - emit code for orl a,operator(sizeop)                */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 toBoolean (operand * oper)
1776 {
1777   int   size = AOP_SIZE (oper) - 1;
1778   int   offset = 1;
1779   bool usedB = FALSE;
1780
1781   /* The generic part of a generic pointer should
1782    * not participate in it's truth value.
1783    *
1784    * i.e. 0x10000000 is zero.
1785    */
1786   if (opIsGptr (oper))
1787     {
1788       D (emitcode (";", "toBoolean: generic ptr special case."););
1789       size--;
1790     }
1791
1792   _startLazyDPSEvaluation ();
1793   if (AOP_NEEDSACC (oper) && size)
1794     {
1795       usedB = TRUE;
1796       if (_G.bInUse)
1797       {
1798           emitcode ("push", "b");
1799       }
1800       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1801     }
1802   else
1803     {
1804       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1805     }
1806     
1807   while (size--)
1808     {
1809       if (usedB)
1810         {
1811           emitcode ("orl", "b,%s",
1812                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1813         }
1814       else
1815         {
1816           emitcode ("orl", "a,%s",
1817                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1818         }
1819     }
1820   _endLazyDPSEvaluation ();
1821
1822   if (usedB)
1823     {
1824       emitcode ("mov", "a,b");
1825       if (_G.bInUse)
1826       {
1827           emitcode ("pop", "b");
1828       }
1829         
1830     }
1831 }
1832
1833
1834 /*-----------------------------------------------------------------*/
1835 /* genNot - generate code for ! operation                          */
1836 /*-----------------------------------------------------------------*/
1837 static void
1838 genNot (iCode * ic)
1839 {
1840   symbol *tlbl;
1841
1842   D (emitcode (";", "genNot "););
1843
1844   /* assign asmOps to operand & result */
1845   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1847
1848   /* if in bit space then a special case */
1849   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1850     {
1851       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1852       emitcode ("cpl", "c");
1853       outBitC (IC_RESULT (ic));
1854       goto release;
1855     }
1856
1857   toBoolean (IC_LEFT (ic));
1858
1859   tlbl = newiTempLabel (NULL);
1860   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1861   emitcode ("", "!tlabeldef", tlbl->key + 100);
1862   outBitC (IC_RESULT (ic));
1863
1864 release:
1865   /* release the aops */
1866   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1867   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1868 }
1869
1870
1871 /*-----------------------------------------------------------------*/
1872 /* genCpl - generate code for complement                           */
1873 /*-----------------------------------------------------------------*/
1874 static void
1875 genCpl (iCode * ic)
1876 {
1877   int offset = 0;
1878   int size;
1879   symbol *tlbl;
1880
1881   D (emitcode (";", "genCpl "););
1882
1883
1884   /* assign asmOps to operand & result */
1885   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1887
1888   /* special case if in bit space */
1889   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1890     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1891       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892       emitcode ("cpl", "c");
1893       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1894       goto release;
1895     }
1896     tlbl=newiTempLabel(NULL);
1897     emitcode ("cjne", "%s,#0x01,%05d$", 
1898               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1899     emitcode ("", "%05d$:", tlbl->key+100);
1900     outBitC (IC_RESULT(ic));
1901     goto release;
1902   }
1903
1904   size = AOP_SIZE (IC_RESULT (ic));
1905   _startLazyDPSEvaluation ();
1906   while (size--)
1907     {
1908       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1909       emitcode ("cpl", "a");
1910       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1911     }
1912   _endLazyDPSEvaluation ();
1913
1914
1915 release:
1916   /* release the aops */
1917   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1918   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* genUminusFloat - unary minus for floating points                */
1923 /*-----------------------------------------------------------------*/
1924 static void
1925 genUminusFloat (operand * op, operand * result)
1926 {
1927   int size, offset = 0;
1928     
1929   D(emitcode (";", "genUminusFloat"););
1930   
1931   /* for this we just copy and then flip the bit */
1932     
1933   _startLazyDPSEvaluation ();
1934   size = AOP_SIZE (op) - 1;
1935
1936   while (size--)
1937   {
1938       aopPut (AOP (result),
1939               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1940               offset);
1941       offset++;
1942     }
1943   
1944   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1945
1946   emitcode ("cpl", "acc.7");
1947   aopPut (AOP (result), "a", offset);    
1948   _endLazyDPSEvaluation ();
1949 }
1950
1951 /*-----------------------------------------------------------------*/
1952 /* genUminus - unary minus code generation                         */
1953 /*-----------------------------------------------------------------*/
1954 static void
1955 genUminus (iCode * ic)
1956 {
1957   int offset, size;
1958   sym_link *optype;
1959
1960   D (emitcode (";", "genUminus "););
1961
1962   /* assign asmops */
1963   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1964   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1965
1966   /* if both in bit space then special
1967      case */
1968   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1970     {
1971
1972       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973       emitcode ("cpl", "c");
1974       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1975       goto release;
1976     }
1977
1978   optype = operandType (IC_LEFT (ic));
1979
1980   /* if float then do float stuff */
1981   if (IS_FLOAT (optype))
1982     {
1983       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1984       goto release;
1985     }
1986
1987   /* otherwise subtract from zero */
1988   size = AOP_SIZE (IC_LEFT (ic));
1989   offset = 0;
1990   _startLazyDPSEvaluation ();
1991   while (size--)
1992     {
1993       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994       if (!strcmp (l, "a"))
1995         {
1996           if (offset == 0)
1997             SETC;
1998           emitcode ("cpl", "a");
1999           emitcode ("addc", "a,#0");
2000         }
2001       else
2002         {
2003           if (offset == 0)
2004             CLRC;
2005           emitcode ("clr", "a");
2006           emitcode ("subb", "a,%s", l);
2007         }
2008       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2009     }
2010   _endLazyDPSEvaluation ();
2011
2012   /* if any remaining bytes in the result */
2013   /* we just need to propagate the sign   */
2014   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2015     {
2016       emitcode ("rlc", "a");
2017       emitcode ("subb", "a,acc");
2018       while (size--)
2019         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2020     }
2021
2022 release:
2023   /* release the aops */
2024   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026 }
2027
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask                         */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2032 {
2033     int i;
2034     if (options.useXstack) {
2035         if (bitVectBitValue (rs_mask, R0_IDX))
2036             emitcode ("mov", "b,r0");
2037         emitcode ("mov", "r0,%s", spname);
2038         for (i = 0; i < ds390_nRegs; i++) {
2039             if (bitVectBitValue (rs_mask, i)) {
2040                 if (i == R0_IDX)
2041                     emitcode ("mov", "a,b");
2042                 else
2043                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044                 emitcode ("movx", "@r0,a");
2045                 emitcode ("inc", "r0");
2046             }
2047         }
2048         emitcode ("mov", "%s,r0", spname);
2049         if (bitVectBitValue (rs_mask, R0_IDX))
2050             emitcode ("mov", "r0,b");
2051     } else {
2052         for (i = 0; i < ds390_nRegs; i++) {
2053             if (bitVectBitValue (rs_mask, i))
2054                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2055         }
2056     }
2057 }
2058
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers     */
2061 /*-----------------------------------------------------------------*/
2062 static void
2063 saveRegisters (iCode * lic)
2064 {
2065   iCode *ic;
2066   bitVect *rsave;
2067
2068   /* look for call */
2069   for (ic = lic; ic; ic = ic->next)
2070     if (ic->op == CALL || ic->op == PCALL)
2071       break;
2072
2073   if (!ic)
2074     {
2075       fprintf (stderr, "found parameter push with no function call\n");
2076       return;
2077     }
2078
2079   /* if the registers have been saved already then
2080      do nothing */
2081   if (ic->regsSaved 
2082       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2083     return ;
2084
2085   /* special case if DPTR alive across a function call then must save it 
2086      even though callee saves */
2087   if (IS_SYMOP(IC_LEFT(ic)) &&
2088       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2089       int i;
2090       rsave = newBitVect(ic->rMask->size);
2091       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092           if (bitVectBitValue(ic->rMask,i))
2093               rsave = bitVectSetBit(rsave,i);
2094       }
2095       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2096   } else {
2097     /* safe the registers in use at this time but skip the
2098        ones for the result */
2099     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100                            ds390_rUmaskForOp (IC_RESULT(ic)));
2101   }
2102   ic->regsSaved = 1;
2103   savermask(rsave);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask                        */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2110 {
2111     int i;
2112     if (options.useXstack) {
2113         emitcode ("mov", "r0,%s", spname);
2114         for (i = ds390_nRegs; i >= 0; i--) {
2115             if (bitVectBitValue (rs_mask, i)) {
2116                 emitcode ("dec", "r0");
2117                 emitcode ("movx", "a,@r0");
2118                 if (i == R0_IDX)
2119                     emitcode ("mov", "b,a");
2120                 else
2121                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2122             }       
2123         }
2124         emitcode ("mov", "%s,r0", spname);
2125         if (bitVectBitValue (rs_mask, R0_IDX))
2126             emitcode ("mov", "r0,b");
2127     } else {
2128         for (i = ds390_nRegs; i >= 0; i--) {
2129             if (bitVectBitValue (rs_mask, i))
2130                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2131         }
2132     }
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers                      */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 unsaveRegisters (iCode * ic)
2140 {
2141   bitVect *rsave;
2142
2143   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2144       int i;
2145       rsave = newBitVect(ic->rMask->size);
2146       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147           if (bitVectBitValue(ic->rMask,i))
2148               rsave = bitVectSetBit(rsave,i);
2149       }
2150       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2151   } else {
2152     /* restore the registers in use at this time but skip the
2153        ones for the result */
2154     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2155                            ds390_rUmaskForOp (IC_RESULT(ic)));
2156   }
2157   unsavermask(rsave);
2158 }
2159
2160
2161 /*-----------------------------------------------------------------*/
2162 /* pushSide -                */
2163 /*-----------------------------------------------------------------*/
2164 static void
2165 pushSide (operand * oper, int size)
2166 {
2167   int offset = 0;
2168   _startLazyDPSEvaluation ();
2169   while (size--)
2170     {
2171       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172       if (AOP_TYPE (oper) != AOP_REG &&
2173           AOP_TYPE (oper) != AOP_DIR &&
2174           strcmp (l, "a"))
2175         {
2176           emitcode ("mov", "a,%s", l);
2177           emitcode ("push", "acc");
2178         }
2179       else
2180         emitcode ("push", "%s", l);
2181     }
2182   _endLazyDPSEvaluation ();
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue -               */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 assignResultValue (operand * oper)
2190 {
2191   int offset = 0;
2192   int size = AOP_SIZE (oper);
2193   bool pushedAcc = FALSE;
2194
2195   if (size == fReturnSizeDS390)
2196   {
2197       /* I don't think this case can ever happen... */
2198       /* ACC is the last part of this. If writing the result
2199        * uses AC, we must preserve it.
2200        */
2201       if (AOP_NEEDSACC(oper))
2202       {
2203           emitcode(";", "assignResultValue special case for ACC.");
2204           emitcode("push", "acc");
2205           pushedAcc = TRUE;
2206           size--;
2207       }
2208   }
2209     
2210     
2211   _startLazyDPSEvaluation ();
2212   while (size--)
2213     {
2214       aopPut (AOP (oper), fReturn[offset], offset);
2215       offset++;
2216     }
2217   _endLazyDPSEvaluation ();
2218     
2219   if (pushedAcc)
2220     {
2221         emitcode("pop", "acc");
2222         aopPut(AOP(oper), "a", offset);
2223     }
2224 }
2225
2226
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack                       */
2229 /*-----------------------------------------------------------------*/
2230 static void
2231 genXpush (iCode * ic)
2232 {
2233   asmop *aop = newAsmop (0);
2234   regs *r;
2235   int size, offset = 0;
2236
2237   D (emitcode (";", "genXpush ");
2238     );
2239
2240   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241   r = getFreePtr (ic, &aop, FALSE);
2242
2243
2244   emitcode ("mov", "%s,_spx", r->name);
2245
2246   size = AOP_SIZE (IC_LEFT (ic));
2247   _startLazyDPSEvaluation ();
2248   while (size--)
2249     {
2250
2251       MOVA (aopGet (AOP (IC_LEFT (ic)),
2252                         offset++, FALSE, FALSE, NULL));
2253       emitcode ("movx", "@%s,a", r->name);
2254       emitcode ("inc", "%s", r->name);
2255
2256     }
2257   _endLazyDPSEvaluation ();
2258
2259
2260   emitcode ("mov", "_spx,%s", r->name);
2261
2262   freeAsmop (NULL, aop, ic, TRUE);
2263   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex  */
2268 /*-----------------------------------------------------------------*/
2269 static void
2270 genIpush (iCode * ic)
2271 {
2272   int size, offset = 0;
2273   char *l;
2274
2275   D (emitcode (";", "genIpush ");
2276     );
2277
2278   /* if this is not a parm push : ie. it is spill push
2279      and spill push is always done on the local stack */
2280   if (!ic->parmPush)
2281     {
2282
2283       /* and the item is spilt then do nothing */
2284       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2285         return;
2286
2287       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288       size = AOP_SIZE (IC_LEFT (ic));
2289       /* push it on the stack */
2290       _startLazyDPSEvaluation ();
2291       while (size--)
2292         {
2293           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2294           if (*l == '#')
2295             {
2296               MOVA (l);
2297               l = "acc";
2298             }
2299           emitcode ("push", "%s", l);
2300         }
2301       _endLazyDPSEvaluation ();
2302       return;
2303     }
2304
2305   /* this is a paramter push: in this case we call
2306      the routine to find the call and save those
2307      registers that need to be saved */
2308   saveRegisters (ic);
2309
2310   /* if use external stack then call the external
2311      stack pushing routine */
2312   if (options.useXstack)
2313     {
2314       genXpush (ic);
2315       return;
2316     }
2317
2318   /* then do the push */
2319   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2320
2321   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322   size = AOP_SIZE (IC_LEFT (ic));
2323
2324   _startLazyDPSEvaluation ();
2325   while (size--)
2326     {
2327       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2330           strcmp (l, "acc"))
2331         {
2332           emitcode ("mov", "a,%s", l);
2333           emitcode ("push", "acc");
2334         }
2335       else
2336         {
2337             emitcode ("push", "%s", l);
2338         }
2339     }
2340   _endLazyDPSEvaluation ();
2341
2342   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling   */
2347 /*-----------------------------------------------------------------*/
2348 static void
2349 genIpop (iCode * ic)
2350 {
2351   int size, offset;
2352
2353   D (emitcode (";", "genIpop ");
2354     );
2355
2356
2357   /* if the temp was not pushed then */
2358   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2359     return;
2360
2361   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362   size = AOP_SIZE (IC_LEFT (ic));
2363   offset = (size - 1);
2364   _startLazyDPSEvaluation ();
2365   while (size--)
2366     {
2367       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368                                      FALSE, TRUE, NULL));
2369     }
2370   _endLazyDPSEvaluation ();
2371
2372   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack            */
2377 /*-----------------------------------------------------------------*/
2378 static void
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2380 {
2381   int i;
2382   asmop *aop = NULL;
2383   regs *r = NULL;
2384
2385   if (options.useXstack)
2386   {
2387       if (!ic)
2388       {
2389           /* Assume r0 is available for use. */
2390           r = ds390_regWithIdx (R0_IDX);;          
2391       } 
2392       else
2393       {
2394           aop = newAsmop (0);
2395           r = getFreePtr (ic, &aop, FALSE);
2396       }
2397       emitcode ("mov", "%s,_spx", r->name);      
2398   }
2399   
2400   if (popPsw)
2401     {
2402       if (options.useXstack)
2403       {
2404           emitcode ("movx", "a,@%s", r->name);
2405           emitcode ("mov", "psw,a");
2406           emitcode ("dec", "%s", r->name);
2407         }
2408       else
2409       {
2410         emitcode ("pop", "psw");
2411       }
2412     }
2413
2414   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2415     {
2416       if (options.useXstack)
2417         {
2418           emitcode ("movx", "a,@%s", r->name);
2419           emitcode ("mov", "(%s+%d),a",
2420                     regs390[i].base, 8 * bank + regs390[i].offset);
2421           emitcode ("dec", "%s", r->name);
2422
2423         }
2424       else
2425         emitcode ("pop", "(%s+%d)",
2426                   regs390[i].base, 8 * bank + regs390[i].offset);
2427     }
2428
2429   if (options.useXstack)
2430     {
2431       emitcode ("mov", "_spx,%s", r->name);
2432     }
2433     
2434   if (aop)
2435   {
2436       freeAsmop (NULL, aop, ic, TRUE);  
2437   }    
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack          */
2442 /*-----------------------------------------------------------------*/
2443 static void
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2445 {
2446   int i;
2447   asmop *aop = NULL;
2448   regs *r = NULL;
2449
2450   if (options.useXstack)
2451     {
2452         if (!ic)
2453         {
2454           /* Assume r0 is available for use. */
2455                   r = ds390_regWithIdx (R0_IDX);;
2456         }
2457         else
2458         {
2459           aop = newAsmop (0);
2460           r = getFreePtr (ic, &aop, FALSE);
2461         }
2462         emitcode ("mov", "%s,_spx", r->name);    
2463     }
2464
2465   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2466     {
2467       if (options.useXstack)
2468         {
2469           emitcode ("inc", "%s", r->name);
2470           emitcode ("mov", "a,(%s+%d)",
2471                     regs390[i].base, 8 * bank + regs390[i].offset);
2472           emitcode ("movx", "@%s,a", r->name);
2473         }
2474       else
2475         emitcode ("push", "(%s+%d)",
2476                   regs390[i].base, 8 * bank + regs390[i].offset);
2477     }
2478
2479   if (pushPsw)
2480     {
2481       if (options.useXstack)
2482         {
2483           emitcode ("mov", "a,psw");
2484           emitcode ("movx", "@%s,a", r->name);
2485           emitcode ("inc", "%s", r->name);
2486           emitcode ("mov", "_spx,%s", r->name);
2487         }
2488       else
2489       {
2490         emitcode ("push", "psw");
2491       }
2492
2493       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2494     }
2495   
2496   if (aop)
2497   {
2498        freeAsmop (NULL, aop, ic, TRUE);
2499   }    
2500     
2501   if (ic)
2502   {  
2503       ic->bankSaved = 1;
2504   }
2505 }
2506
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND                                     */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2511 {
2512     iCode *sic;
2513     int sendCount = 0 ;
2514     static int rb1_count = 0;
2515
2516     for (sic = setFirstItem (sendSet); sic;
2517          sic = setNextItem (sendSet)) {     
2518         int size, offset = 0;
2519         
2520         size=getSize(operandType(IC_LEFT(sic)));
2521         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522         if (sendCount == 0) { /* first parameter */
2523             // we know that dpl(hxb) is the result, so
2524             rb1_count = 0 ;
2525             _startLazyDPSEvaluation ();
2526             if (size>1) {
2527                 aopOp (IC_LEFT (sic), sic, FALSE, 
2528                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2529             } else {
2530                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2531             }
2532             while (size--) {
2533                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534                                   FALSE, FALSE, NULL);
2535                 if (strcmp (l, fReturn[offset])) {
2536                     emitcode ("mov", "%s,%s",
2537                               fReturn[offset],
2538                               l);
2539                 }
2540                 offset++;
2541             }
2542             _endLazyDPSEvaluation ();
2543             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2544             rb1_count =0;
2545         } else { /* if more parameter in registers */
2546             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2547             while (size--) {
2548                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549                                                                 FALSE, FALSE, NULL));
2550             }
2551             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2552         }
2553         sendCount++;
2554     }
2555 }
2556
2557 static void
2558 adjustEsp(const char *reg)
2559 {
2560     emitcode ("anl","%s,#3", reg);
2561     if (TARGET_IS_DS400)
2562     {
2563         emitcode ("orl","%s,#!constbyte",
2564                   reg,
2565                   (options.stack_loc >> 8) & 0xff);
2566     }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement                            */
2571 /*-----------------------------------------------------------------*/
2572 static void
2573 genCall (iCode * ic)
2574 {
2575   sym_link *dtype;
2576   bool restoreBank = FALSE;
2577   bool swapBanks = FALSE;
2578
2579   D (emitcode (";", "genCall "););
2580
2581   /* if we are calling a not _naked function that is not using
2582      the same register bank then we need to save the
2583      destination registers on the stack */
2584   dtype = operandType (IC_LEFT (ic));
2585   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587       IFFUNC_ISISR (currFunc->type))
2588   {
2589       if (!ic->bankSaved) 
2590       {
2591            /* This is unexpected; the bank should have been saved in
2592             * genFunction.
2593             */
2594            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2595            restoreBank = TRUE;
2596       }
2597       swapBanks = TRUE;
2598   }
2599   
2600     /* if caller saves & we have not saved then */
2601     if (!ic->regsSaved)
2602       saveRegisters (ic);
2603   
2604   /* if send set is not empty the assign */
2605   /* We've saved all the registers we care about;
2606   * therefore, we may clobber any register not used
2607   * in the calling convention (i.e. anything not in
2608   * fReturn.
2609   */
2610   if (_G.sendSet)
2611     {
2612         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613             genSend(reverseSet(_G.sendSet));
2614         } else {
2615             genSend(_G.sendSet);
2616         }
2617       _G.sendSet = NULL;
2618     }  
2619     
2620   if (swapBanks)
2621   {
2622         emitcode ("mov", "psw,#!constbyte", 
2623            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2624   }
2625
2626   /* make the call */
2627   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628                             OP_SYMBOL (IC_LEFT (ic))->rname :
2629                             OP_SYMBOL (IC_LEFT (ic))->name));
2630
2631   if (swapBanks)
2632   {
2633        emitcode ("mov", "psw,#!constbyte", 
2634           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2635   }
2636
2637   /* if we need assign a result value */
2638   if ((IS_ITEMP (IC_RESULT (ic)) &&
2639        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642       IS_TRUE_SYMOP (IC_RESULT (ic)))
2643     {
2644       if (isOperandInFarSpace (IC_RESULT (ic))
2645           && getSize (operandType (IC_RESULT (ic))) <= 2)
2646         {
2647           int size = getSize (operandType (IC_RESULT (ic)));
2648
2649           /* Special case for 1 or 2 byte return in far space. */
2650           MOVA (fReturn[0]);
2651           if (size > 1)
2652             {
2653               emitcode ("mov", "b,%s", fReturn[1]);
2654             }
2655
2656           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2658
2659           if (size > 1)
2660             {
2661               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2662             }
2663           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2664         }
2665       else
2666         {
2667           _G.accInUse++;
2668           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2669           _G.accInUse--;
2670
2671           assignResultValue (IC_RESULT (ic));
2672
2673           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2674         }
2675     }
2676
2677   /* adjust the stack for parameters if
2678      required */
2679   if (ic->parmBytes) {
2680       int i;
2681       if (options.stack10bit) {
2682           if (ic->parmBytes <= 10) {
2683               emitcode(";","stack adjustment for parms");
2684               for (i=0; i < ic->parmBytes ; i++) {
2685                   emitcode("pop","acc");
2686               }
2687           } else {            
2688               PROTECT_SP;
2689               emitcode ("clr","c");
2690               emitcode ("mov","a,sp");
2691               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692               emitcode ("mov","sp,a");
2693               emitcode ("mov","a,esp");
2694               adjustEsp("a");
2695               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696               emitcode ("mov","esp,a");   
2697               UNPROTECT_SP;
2698           }
2699       } else {
2700           if (ic->parmBytes > 3) {
2701               emitcode ("mov", "a,%s", spname);
2702               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703               emitcode ("mov", "%s,a", spname);
2704           } else
2705               for (i = 0; i < ic->parmBytes; i++)
2706                   emitcode ("dec", "%s", spname);
2707       }
2708   }
2709
2710   /* if we hade saved some registers then unsave them */
2711   if (ic->regsSaved)
2712     unsaveRegisters (ic);
2713
2714   /* if register bank was saved then pop them */
2715   if (restoreBank)
2716     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2717 }
2718
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement                */
2721 /*-----------------------------------------------------------------*/
2722 static void
2723 genPcall (iCode * ic)
2724 {
2725   sym_link *dtype;
2726   symbol *rlbl = newiTempLabel (NULL);
2727   bool restoreBank=FALSE;
2728
2729   D (emitcode (";", "genPcall ");
2730     );
2731
2732
2733   /* if caller saves & we have not saved then */
2734   if (!ic->regsSaved)
2735     saveRegisters (ic);
2736
2737   /* if we are calling a function that is not using
2738      the same register bank then we need to save the
2739      destination registers on the stack */
2740   dtype = operandType (IC_LEFT (ic));
2741   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742       IFFUNC_ISISR (currFunc->type) &&
2743       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2745     restoreBank=TRUE;
2746   }
2747
2748   /* push the return address on to the stack */
2749   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750   emitcode ("push", "acc");
2751   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752   emitcode ("push", "acc");
2753
2754   if (options.model == MODEL_FLAT24)
2755     {
2756       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757       emitcode ("push", "acc");
2758     }
2759
2760   /* now push the calling address */
2761   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2762
2763   pushSide (IC_LEFT (ic), FPTRSIZE);
2764
2765   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2766
2767   /* if send set is not empty the assign */
2768   if (_G.sendSet)
2769     {
2770         genSend(reverseSet(_G.sendSet));
2771         _G.sendSet = NULL;
2772     }
2773
2774   emitcode ("ret", "");
2775   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2776
2777
2778   /* if we need assign a result value */
2779   if ((IS_ITEMP (IC_RESULT (ic)) &&
2780        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782       IS_TRUE_SYMOP (IC_RESULT (ic)))
2783     {
2784
2785       _G.accInUse++;
2786       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2787       _G.accInUse--;
2788
2789       assignResultValue (IC_RESULT (ic));
2790
2791       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2792     }
2793
2794   /* adjust the stack for parameters if
2795      required */
2796   if (ic->parmBytes)
2797     {
2798       int i;
2799       if (options.stack10bit) {
2800           if (ic->parmBytes <= 10) {
2801               emitcode(";","stack adjustment for parms");
2802               for (i=0; i < ic->parmBytes ; i++) {
2803                   emitcode("pop","acc");
2804               }
2805           } else {            
2806               PROTECT_SP;
2807               emitcode ("clr","c");
2808               emitcode ("mov","a,sp");
2809               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810               emitcode ("mov","sp,a");
2811               emitcode ("mov","a,esp");
2812               adjustEsp("a");
2813               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814               emitcode ("mov","esp,a");   
2815               UNPROTECT_SP;
2816           }
2817       } else {
2818           if (ic->parmBytes > 3) {
2819               emitcode ("mov", "a,%s", spname);
2820               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821               emitcode ("mov", "%s,a", spname);
2822           }
2823           else
2824               for (i = 0; i < ic->parmBytes; i++)
2825                   emitcode ("dec", "%s", spname);
2826           
2827       }
2828     }
2829   /* if register bank was saved then unsave them */
2830   if (restoreBank)
2831     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2832   
2833   /* if we hade saved some registers then
2834      unsave them */
2835   if (ic->regsSaved)
2836     unsaveRegisters (ic);
2837
2838 }
2839
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result  is rematerializable                       */
2842 /*-----------------------------------------------------------------*/
2843 static int
2844 resultRemat (iCode * ic)
2845 {
2846   if (SKIP_IC (ic) || ic->op == IFX)
2847     return 0;
2848
2849   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2850     {
2851       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852       if (sym->remat && !POINTER_SET (ic))
2853         return 1;
2854     }
2855
2856   return 0;
2857 }
2858
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2861 #else
2862 #define STRCASECMP strcasecmp
2863 #endif
2864
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2867 /*-----------------------------------------------------------------*/
2868 static int
2869 regsCmp(void *p1, void *p2)
2870 {
2871   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2872 }
2873
2874 static bool
2875 inExcludeList (char *s)
2876 {
2877   const char *p = setFirstItem(options.excludeRegsSet);
2878
2879   if (p == NULL || STRCASECMP(p, "none") == 0)
2880     return FALSE;
2881
2882
2883   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2884 }
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry                 */
2888 /*-----------------------------------------------------------------*/
2889 static void
2890 genFunction (iCode * ic)
2891 {
2892   symbol *sym;
2893   sym_link *ftype;
2894   bool   switchedPSW = FALSE;
2895
2896   D (emitcode (";", "genFunction "););
2897
2898   _G.nRegsSaved = 0;
2899   /* create the function header */
2900   emitcode (";", "-----------------------------------------");
2901   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902   emitcode (";", "-----------------------------------------");
2903
2904   emitcode ("", "%s:", sym->rname);
2905   ftype = operandType (IC_LEFT (ic));
2906
2907   if (IFFUNC_ISNAKED(ftype))
2908   {
2909       emitcode(";", "naked function: no prologue.");
2910       return;
2911   }
2912   
2913   if (options.stack_probe) 
2914       emitcode ("lcall","__stack_probe");
2915
2916   /* here we need to generate the equates for the
2917      register bank if required */
2918   if (FUNC_REGBANK (ftype) != rbank)
2919     {
2920       int i;
2921
2922       rbank = FUNC_REGBANK (ftype);
2923       for (i = 0; i < ds390_nRegs; i++)
2924         {
2925           if (regs390[i].print) {
2926               if (strcmp (regs390[i].base, "0") == 0)
2927                   emitcode ("", "%s !equ !constbyte",
2928                             regs390[i].dname,
2929                             8 * rbank + regs390[i].offset);
2930               else
2931                   emitcode ("", "%s !equ %s + !constbyte",
2932                             regs390[i].dname,
2933                             regs390[i].base,
2934                             8 * rbank + regs390[i].offset);
2935           }
2936         }
2937     }
2938
2939   /* if this is an interrupt service routine then
2940      save acc, b, dpl, dph  */
2941   if (IFFUNC_ISISR (sym->type))
2942       { /* is ISR */
2943       if (!inExcludeList ("acc"))
2944         emitcode ("push", "acc");
2945       if (!inExcludeList ("b"))
2946         emitcode ("push", "b");
2947       if (!inExcludeList ("dpl"))
2948         emitcode ("push", "dpl");
2949       if (!inExcludeList ("dph"))
2950         emitcode ("push", "dph");
2951       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2952         {
2953           emitcode ("push", "dpx");
2954           /* Make sure we're using standard DPTR */
2955           emitcode ("push", "dps");
2956           emitcode ("mov", "dps,#0");
2957           if (options.stack10bit)
2958             {
2959               /* This ISR could conceivably use DPTR2. Better save it. */
2960               emitcode ("push", "dpl1");
2961               emitcode ("push", "dph1");
2962               emitcode ("push", "dpx1");
2963               emitcode ("push",  DP2_RESULT_REG);
2964             }
2965         }
2966       /* if this isr has no bank i.e. is going to
2967          run with bank 0 , then we need to save more
2968          registers :-) */
2969       if (!FUNC_REGBANK (sym->type))
2970         {
2971             int i;
2972
2973           /* if this function does not call any other
2974              function then we can be economical and
2975              save only those registers that are used */
2976           if (!IFFUNC_HASFCALL(sym->type))
2977             {
2978
2979               /* if any registers used */
2980               if (sym->regsUsed)
2981                 {
2982                   /* save the registers used */
2983                   for (i = 0; i < sym->regsUsed->size; i++)
2984                     {
2985                       if (bitVectBitValue (sym->regsUsed, i) ||
2986                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2988                     }
2989                 }
2990
2991             }
2992           else
2993             {
2994               /* this function has  a function call cannot
2995                  determines register usage so we will have to push the
2996                  entire bank */
2997               saveRBank (0, ic, FALSE);
2998               if (options.parms_in_bank1) {
2999                   for (i=0; i < 8 ; i++ ) {
3000                       emitcode ("push","%s",rb1regs[i]);
3001                   }
3002               }
3003             }
3004         }
3005         else
3006         {
3007             /* This ISR uses a non-zero bank.
3008              *
3009              * We assume that the bank is available for our
3010              * exclusive use.
3011              *
3012              * However, if this ISR calls a function which uses some
3013              * other bank, we must save that bank entirely.
3014              */
3015             unsigned long banksToSave = 0;
3016             
3017             if (IFFUNC_HASFCALL(sym->type))
3018             {
3019
3020 #define MAX_REGISTER_BANKS 4
3021
3022                 iCode *i;
3023                 int ix;
3024
3025                 for (i = ic; i; i = i->next)
3026                 {
3027                     if (i->op == ENDFUNCTION)
3028                     {
3029                         /* we got to the end OK. */
3030                         break;
3031                     }
3032                     
3033                     if (i->op == CALL)
3034                     {
3035                         sym_link *dtype;
3036                         
3037                         dtype = operandType (IC_LEFT(i));
3038                         if (dtype 
3039                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3040                         {
3041                              /* Mark this bank for saving. */
3042                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3043                              {
3044                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3045                              }
3046                              else
3047                              {
3048                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3049                              }
3050                              
3051                              /* And note that we don't need to do it in 
3052                               * genCall.
3053                               */
3054                              i->bankSaved = 1;
3055                         }
3056                     }
3057                     if (i->op == PCALL)
3058                     {
3059                         /* This is a mess; we have no idea what
3060                          * register bank the called function might
3061                          * use.
3062                          *
3063                          * The only thing I can think of to do is
3064                          * throw a warning and hope.
3065                          */
3066                         werror(W_FUNCPTR_IN_USING_ISR);   
3067                     }
3068                 }
3069
3070                 if (banksToSave && options.useXstack)
3071                 {
3072                     /* Since we aren't passing it an ic, 
3073                      * saveRBank will assume r0 is available to abuse.
3074                      *
3075                      * So switch to our (trashable) bank now, so
3076                      * the caller's R0 isn't trashed.
3077                      */
3078                     emitcode ("push", "psw");
3079                     emitcode ("mov", "psw,#!constbyte", 
3080                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3081                     switchedPSW = TRUE;
3082                 }
3083                 
3084                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3085                 {
3086                      if (banksToSave & (1 << ix))
3087                      {
3088                          saveRBank(ix, NULL, FALSE);
3089                      }
3090                 }
3091             }
3092             // TODO: this needs a closer look
3093             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3094         }
3095     }
3096   else
3097     {
3098       /* if callee-save to be used for this function
3099          then save the registers being used in this function */
3100       if (IFFUNC_CALLEESAVES(sym->type))
3101         {
3102           int i;
3103
3104           /* if any registers used */
3105           if (sym->regsUsed)
3106             {
3107               /* save the registers used */
3108               for (i = 0; i < sym->regsUsed->size; i++)
3109                 {
3110                   if (bitVectBitValue (sym->regsUsed, i) ||
3111                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3112                     {
3113                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3114                       _G.nRegsSaved++;
3115                     }
3116                 }
3117             }
3118         }
3119     }
3120
3121   /* set the register bank to the desired value */
3122   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3123    && !switchedPSW)
3124     {
3125       emitcode ("push", "psw");
3126       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3127     }
3128
3129   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131       if (options.stack10bit) {
3132           emitcode ("push","_bpx");
3133           emitcode ("push","_bpx+1");
3134           emitcode ("mov","_bpx,%s",spname);
3135           emitcode ("mov","_bpx+1,esp");
3136           adjustEsp("_bpx+1");
3137       } else {
3138           if (options.useXstack) {
3139               emitcode ("mov", "r0,%s", spname);
3140               emitcode ("mov", "a,_bp");
3141               emitcode ("movx", "@r0,a");
3142               emitcode ("inc", "%s", spname);
3143           } else {
3144               /* set up the stack */
3145               emitcode ("push", "_bp"); /* save the callers stack  */
3146           }
3147           emitcode ("mov", "_bp,%s", spname);
3148       }
3149   }
3150
3151   /* adjust the stack for the function */
3152   if (sym->stack) {
3153       int i = sym->stack;
3154       if (options.stack10bit) {
3155           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3156           assert (sym->recvSize <= 4);
3157           if (sym->stack <= 8) {
3158               while (i--) emitcode ("push","acc");
3159           } else {
3160               PROTECT_SP;
3161               emitcode ("mov","a,sp");
3162               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163               emitcode ("mov","sp,a");
3164               emitcode ("mov","a,esp");
3165               adjustEsp("a");
3166               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167               emitcode ("mov","esp,a");
3168               UNPROTECT_SP;
3169           }
3170       } else {
3171           if (i > 256)
3172               werror (W_STACK_OVERFLOW, sym->name);
3173           
3174           if (i > 3 && sym->recvSize < 4) {
3175               
3176               emitcode ("mov", "a,sp");
3177               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178               emitcode ("mov", "sp,a");
3179               
3180           } else
3181               while (i--)
3182                   emitcode ("inc", "sp");
3183       }
3184   }
3185
3186   if (sym->xstack)
3187     {
3188
3189       emitcode ("mov", "a,_spx");
3190       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191       emitcode ("mov", "_spx,a");
3192     }
3193   
3194   /* if critical function then turn interrupts off */
3195   if (IFFUNC_ISCRITICAL (ftype))
3196     {
3197       emitcode ("mov", "c,ea");
3198       emitcode ("push", "psw"); /* save old ea via c in psw */
3199       emitcode ("clr", "ea");
3200     }
3201
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* genEndFunction - generates epilogue for functions               */
3206 /*-----------------------------------------------------------------*/
3207 static void
3208 genEndFunction (iCode * ic)
3209 {
3210   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3211
3212   D (emitcode (";", "genEndFunction "););
3213
3214   if (IFFUNC_ISNAKED(sym->type))
3215   {
3216       emitcode(";", "naked function: no epilogue.");
3217       return;
3218   }
3219
3220   if (IFFUNC_ISCRITICAL (sym->type))
3221     {
3222       emitcode ("pop", "psw"); /* restore ea via c in psw */
3223       emitcode ("mov", "ea,c");
3224     }
3225   
3226   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3227        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3228
3229       if (options.stack10bit) {
3230           PROTECT_SP;     
3231           emitcode ("mov", "sp,_bpx", spname);
3232           emitcode ("mov", "esp,_bpx+1", spname);
3233           UNPROTECT_SP;
3234       } else {
3235           emitcode ("mov", "%s,_bp", spname);
3236       }
3237   }
3238
3239   /* if use external stack but some variables were
3240      added to the local stack then decrement the
3241      local stack */
3242   if (options.useXstack && sym->stack) {
3243       emitcode ("mov", "a,sp");
3244       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3245       emitcode ("mov", "sp,a");
3246   }
3247
3248
3249   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3250        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3251
3252       if (options.useXstack) {
3253           emitcode ("mov", "r0,%s", spname);
3254           emitcode ("movx", "a,@r0");
3255           emitcode ("mov", "_bp,a");
3256           emitcode ("dec", "%s", spname);
3257       } else {
3258           if (options.stack10bit) {
3259               emitcode ("pop", "_bpx+1");
3260               emitcode ("pop", "_bpx");
3261           } else {
3262               emitcode ("pop", "_bp");
3263           }
3264       }
3265   }
3266
3267   /* restore the register bank  */
3268   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3269   {
3270     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3271      || !options.useXstack)
3272     {
3273         /* Special case of ISR using non-zero bank with useXstack
3274          * is handled below.
3275          */
3276         emitcode ("pop", "psw");
3277     }
3278   } 
3279
3280   if (IFFUNC_ISISR (sym->type))
3281       { /* is ISR */  
3282
3283       /* now we need to restore the registers */
3284       /* if this isr has no bank i.e. is going to
3285          run with bank 0 , then we need to save more
3286          registers :-) */
3287       if (!FUNC_REGBANK (sym->type))
3288         {
3289             int i;
3290           /* if this function does not call any other
3291              function then we can be economical and
3292              save only those registers that are used */
3293           if (!IFFUNC_HASFCALL(sym->type))
3294             {
3295
3296               /* if any registers used */
3297               if (sym->regsUsed)
3298                 {
3299                   /* save the registers used */
3300                   for (i = sym->regsUsed->size; i >= 0; i--)
3301                     {
3302                       if (bitVectBitValue (sym->regsUsed, i) ||
3303                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3304                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3305                     }
3306                 }
3307
3308             }
3309           else
3310             {
3311               /* this function has  a function call cannot
3312                  determines register usage so we will have to pop the
3313                  entire bank */
3314               if (options.parms_in_bank1) {
3315                   for (i = 7 ; i >= 0 ; i-- ) {
3316                       emitcode ("pop","%s",rb1regs[i]);
3317                   }
3318               }
3319               unsaveRBank (0, ic, FALSE);
3320             }
3321         }
3322         else
3323         {
3324             /* This ISR uses a non-zero bank.
3325              *
3326              * Restore any register banks saved by genFunction
3327              * in reverse order.
3328              */
3329             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3330             int ix;
3331           
3332             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3333             {
3334                 if (savedBanks & (1 << ix))
3335                 {
3336                     unsaveRBank(ix, NULL, FALSE);
3337                 }
3338             }
3339             
3340             if (options.useXstack)
3341             {
3342                 /* Restore bank AFTER calling unsaveRBank,
3343                  * since it can trash r0.
3344                  */
3345                 emitcode ("pop", "psw");
3346             }
3347         }
3348
3349       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3350         {
3351           if (options.stack10bit)
3352             {
3353               emitcode ("pop", DP2_RESULT_REG);
3354               emitcode ("pop", "dpx1");
3355               emitcode ("pop", "dph1");
3356               emitcode ("pop", "dpl1");
3357             }
3358           emitcode ("pop", "dps");
3359           emitcode ("pop", "dpx");
3360         }
3361       if (!inExcludeList ("dph"))
3362         emitcode ("pop", "dph");
3363       if (!inExcludeList ("dpl"))
3364         emitcode ("pop", "dpl");
3365       if (!inExcludeList ("b"))
3366         emitcode ("pop", "b");
3367       if (!inExcludeList ("acc"))
3368         emitcode ("pop", "acc");
3369
3370       /* if debug then send end of function */
3371       if (options.debug && currFunc) {
3372           _G.debugLine = 1;
3373           emitcode ("", "C$%s$%d$%d$%d ==.",
3374                     FileBaseName (ic->filename), currFunc->lastLine,
3375                     ic->level, ic->block);
3376           if (IS_STATIC (currFunc->etype))
3377             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3378           else
3379             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3380           _G.debugLine = 0;
3381         }
3382
3383       emitcode ("reti", "");
3384     }
3385   else
3386     {
3387       if (IFFUNC_CALLEESAVES(sym->type))
3388         {
3389           int i;
3390
3391           /* if any registers used */
3392           if (sym->regsUsed)
3393             {
3394               /* save the registers used */
3395               for (i = sym->regsUsed->size; i >= 0; i--)
3396                 {
3397                   if (bitVectBitValue (sym->regsUsed, i) ||
3398                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3399                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3400                 }
3401             }
3402
3403         }
3404
3405       /* if debug then send end of function */
3406       if (options.debug && currFunc)
3407         {
3408           _G.debugLine = 1;
3409           emitcode ("", "C$%s$%d$%d$%d ==.",
3410                     FileBaseName (ic->filename), currFunc->lastLine,
3411                     ic->level, ic->block);
3412           if (IS_STATIC (currFunc->etype))
3413             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3414           else
3415             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3416           _G.debugLine = 0;
3417         }
3418
3419       emitcode ("ret", "");
3420     }
3421
3422 }
3423
3424 /*-----------------------------------------------------------------*/
3425 /* genJavaNativeRet - generate code for return JavaNative          */
3426 /*-----------------------------------------------------------------*/
3427 static void genJavaNativeRet(iCode *ic)
3428 {
3429     int i, size;
3430
3431     aopOp (IC_LEFT (ic), ic, FALSE, 
3432            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3433     size = AOP_SIZE (IC_LEFT (ic));
3434
3435     assert (size <= 4);
3436
3437     /* it is assigned to GPR0-R3 then push them */
3438     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3439         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3440         for (i = 0 ; i < size ; i++ ) {
3441             emitcode ("push","%s",
3442                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3443         }
3444         for (i = (size-1) ; i >= 0 ; i--) {
3445             emitcode ("pop","a%s",javaRet[i]);
3446         }
3447     } else {
3448         for (i = 0 ; i < size ; i++) 
3449             emitcode ("mov","%s,%s",javaRet[i],
3450                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3451     }
3452     for (i = size ; i < 4 ; i++ )
3453             emitcode ("mov","%s,#0",javaRet[i]);
3454     return;
3455 }
3456
3457 /*-----------------------------------------------------------------*/
3458 /* genRet - generate code for return statement                     */
3459 /*-----------------------------------------------------------------*/
3460 static void
3461 genRet (iCode * ic)
3462 {
3463   int size, offset = 0, pushed = 0;
3464
3465   D (emitcode (";", "genRet "););
3466
3467   /* if we have no return value then
3468      just generate the "ret" */
3469   if (!IC_LEFT (ic))
3470     goto jumpret;
3471
3472   /* if this is a JavaNative function then return 
3473      value in different register */
3474   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3475       genJavaNativeRet(ic);
3476       goto jumpret;
3477   }
3478   /* we have something to return then
3479      move the return value into place */
3480   aopOp (IC_LEFT (ic), ic, FALSE, 
3481          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3482   size = AOP_SIZE (IC_LEFT (ic));
3483
3484   _startLazyDPSEvaluation ();
3485   while (size--)
3486     {
3487       char *l;
3488       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3489         {
3490           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3491                       FALSE, TRUE, NULL);
3492           emitcode ("push", "%s", l);
3493           pushed++;
3494         }
3495       else
3496         {
3497           /* Since A is the last element of fReturn,
3498            * is is OK to clobber it in the aopGet.
3499            */
3500           l = aopGet (AOP (IC_LEFT (ic)), offset,
3501                       FALSE, FALSE, NULL);
3502           if (strcmp (fReturn[offset], l))
3503             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3504         }
3505     }
3506   _endLazyDPSEvaluation ();
3507
3508   if (pushed)
3509     {
3510       while (pushed)
3511         {
3512           pushed--;
3513           if (strcmp (fReturn[pushed], "a"))
3514             emitcode ("pop", fReturn[pushed]);
3515           else
3516             emitcode ("pop", "acc");
3517         }
3518     }
3519   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3520
3521 jumpret:
3522   /* generate a jump to the return label
3523      if the next is not the return statement */
3524   if (!(ic->next && ic->next->op == LABEL &&
3525         IC_LABEL (ic->next) == returnLabel))
3526
3527     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3528
3529 }
3530
3531 /*-----------------------------------------------------------------*/
3532 /* genLabel - generates a label                                    */
3533 /*-----------------------------------------------------------------*/
3534 static void
3535 genLabel (iCode * ic)
3536 {
3537   /* special case never generate */
3538   if (IC_LABEL (ic) == entryLabel)
3539     return;
3540
3541   D (emitcode (";", "genLabel ");
3542     );
3543
3544   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3545 }
3546
3547 /*-----------------------------------------------------------------*/
3548 /* genGoto - generates a ljmp                                      */
3549 /*-----------------------------------------------------------------*/
3550 static void
3551 genGoto (iCode * ic)
3552 {
3553   D (emitcode (";", "genGoto ");
3554     );
3555   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3556 }
3557
3558 /*-----------------------------------------------------------------*/
3559 /* findLabelBackwards: walks back through the iCode chain looking  */
3560 /* for the given label. Returns number of iCode instructions     */
3561 /* between that label and given ic.          */
3562 /* Returns zero if label not found.          */
3563 /*-----------------------------------------------------------------*/
3564 static int
3565 findLabelBackwards (iCode * ic, int key)
3566 {
3567   int count = 0;
3568
3569   while (ic->prev)
3570     {
3571       ic = ic->prev;
3572       count++;
3573
3574       /* If we have any pushes or pops, we cannot predict the distance.
3575          I don't like this at all, this should be dealt with in the 
3576          back-end */
3577       if (ic->op == IPUSH || ic->op == IPOP) {
3578         return 0;
3579       }
3580
3581       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3582         {
3583           /* printf("findLabelBackwards = %d\n", count); */
3584           return count;
3585         }
3586     }
3587
3588   return 0;
3589 }
3590
3591 /*-----------------------------------------------------------------*/
3592 /* genPlusIncr :- does addition with increment if possible         */
3593 /*-----------------------------------------------------------------*/
3594 static bool
3595 genPlusIncr (iCode * ic)
3596 {
3597   unsigned int icount;
3598   unsigned int size = getDataSize (IC_RESULT (ic));
3599
3600   /* will try to generate an increment */
3601   /* if the right side is not a literal
3602      we cannot */
3603   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3604     return FALSE;
3605
3606   /* if the literal value of the right hand side
3607      is greater than 4 then it is not worth it */
3608   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3609     return FALSE;
3610
3611   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3612       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3613       while (icount--) {
3614           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3615       }
3616       return TRUE;
3617   }
3618   /* if increment 16 bits in register */
3619   if (
3620        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3621        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3622        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3623        (size > 1) &&
3624        (icount == 1))
3625     {
3626       symbol  *tlbl;
3627       int     emitTlbl;
3628       int     labelRange;
3629       char    *l;
3630
3631       /* If the next instruction is a goto and the goto target
3632        * is <= 5 instructions previous to this, we can generate
3633        * jumps straight to that target.
3634        */
3635       if (ic->next && ic->next->op == GOTO
3636           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3637           && labelRange <= 5)
3638         {
3639           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3640           tlbl = IC_LABEL (ic->next);
3641           emitTlbl = 0;
3642         }
3643       else
3644         {
3645           tlbl = newiTempLabel (NULL);
3646           emitTlbl = 1;
3647         }
3648         
3649       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3650       emitcode ("inc", "%s", l);
3651       
3652       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653           IS_AOP_PREG (IC_RESULT (ic)))
3654       {   
3655         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3656       }
3657       else
3658       {
3659           emitcode ("clr", "a");
3660           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3661       }
3662
3663       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3664       emitcode ("inc", "%s", l);
3665       if (size > 2)
3666         {
3667             if (!strcmp(l, "acc"))
3668             {
3669                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3670             }
3671             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3672                      IS_AOP_PREG (IC_RESULT (ic)))
3673             {
3674                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3675             }
3676             else
3677             {
3678                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3679             }
3680
3681             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3682             emitcode ("inc", "%s", l);
3683         }
3684       if (size > 3)
3685         {
3686             if (!strcmp(l, "acc"))
3687             {
3688                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3689             }
3690             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3691                      IS_AOP_PREG (IC_RESULT (ic)))
3692             {
3693                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3694             }
3695             else
3696             {
3697                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3698             }
3699
3700             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3701             emitcode ("inc", "%s", l);  }
3702
3703       if (emitTlbl)
3704         {
3705           emitcode ("", "!tlabeldef", tlbl->key + 100);
3706         }
3707       return TRUE;
3708     }
3709
3710   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3711       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3712       options.model == MODEL_FLAT24 ) {
3713
3714       switch (size) {
3715       case 3:
3716           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3717       case 2:
3718           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3719       case 1:
3720           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3721           break;
3722       }
3723       while (icount--) emitcode ("inc","dptr");      
3724       return TRUE;
3725   }
3726
3727   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3728       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3729       icount <= 5 ) {
3730       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3731       while (icount--) emitcode ("inc","dptr");
3732       emitcode ("mov","dps,#0");
3733       return TRUE;
3734   }
3735
3736   /* if the sizes are greater than 1 then we cannot */
3737   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738       AOP_SIZE (IC_LEFT (ic)) > 1)
3739     return FALSE;
3740
3741   /* we can if the aops of the left & result match or
3742      if they are in registers and the registers are the
3743      same */
3744   if (
3745        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3748     {
3749
3750       if (icount > 3)
3751         {
3752           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3753           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3754           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3755         }
3756       else
3757         {
3758
3759           _startLazyDPSEvaluation ();
3760           while (icount--)
3761             {
3762               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3763             }
3764           _endLazyDPSEvaluation ();
3765         }
3766
3767       return TRUE;
3768     }
3769
3770   return FALSE;
3771 }
3772
3773 /*-----------------------------------------------------------------*/
3774 /* outBitAcc - output a bit in acc                                 */
3775 /*-----------------------------------------------------------------*/
3776 static void
3777 outBitAcc (operand * result)
3778 {
3779   symbol *tlbl = newiTempLabel (NULL);
3780   /* if the result is a bit */
3781   if (AOP_TYPE (result) == AOP_CRY)
3782     {
3783       aopPut (AOP (result), "a", 0);
3784     }
3785   else
3786     {
3787       emitcode ("jz", "!tlabel", tlbl->key + 100);
3788       emitcode ("mov", "a,%s", one);
3789       emitcode ("", "!tlabeldef", tlbl->key + 100);
3790       outAcc (result);
3791     }
3792 }
3793
3794 /*-----------------------------------------------------------------*/
3795 /* genPlusBits - generates code for addition of two bits           */
3796 /*-----------------------------------------------------------------*/
3797 static void
3798 genPlusBits (iCode * ic)
3799 {
3800   D (emitcode (";", "genPlusBits "););
3801     
3802   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3803     {
3804       symbol *lbl = newiTempLabel (NULL);
3805       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807       emitcode ("cpl", "c");
3808       emitcode ("", "!tlabeldef", (lbl->key + 100));
3809       outBitC (IC_RESULT (ic));
3810     }
3811   else
3812     {
3813       emitcode ("clr", "a");
3814       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3815       emitcode ("rlc", "a");
3816       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3817       emitcode ("addc", "a,#0");
3818       outAcc (IC_RESULT (ic));
3819     }
3820 }
3821
3822 static void
3823 adjustArithmeticResult (iCode * ic)
3824 {
3825   if (opIsGptr (IC_RESULT (ic)) &&
3826       opIsGptr (IC_LEFT (ic)) &&
3827       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3828     {
3829       aopPut (AOP (IC_RESULT (ic)),
3830               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3831               GPTRSIZE - 1);
3832     }
3833
3834   if (opIsGptr (IC_RESULT (ic)) &&
3835       opIsGptr (IC_RIGHT (ic)) &&
3836       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3837     {
3838       aopPut (AOP (IC_RESULT (ic)),
3839             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3840               GPTRSIZE - 1);
3841     }
3842
3843   if (opIsGptr (IC_RESULT (ic)) &&
3844       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3845       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3846       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3847       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3848     {
3849       char buff[5];
3850       SNPRINTF (buff, sizeof(buff), 
3851                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3852       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3853     }
3854 }
3855
3856 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3857 // generates the result if possible. If result is generated, returns TRUE; otherwise
3858 // returns false and caller must deal with fact that result isn't aopOp'd.
3859 bool aopOp3(iCode * ic)
3860 {
3861     bool dp1InUse, dp2InUse;
3862     bool useDp2;
3863     
3864     // First, generate the right opcode. DPTR may be used if neither left nor result are
3865     // of type AOP_STR.
3866     
3867 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3868 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3869 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3870 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3871 //      );
3872 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3873 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3874 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3875 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3876 //      );
3877     
3878     // Right uses DPTR unless left or result is an AOP_STR; however,
3879     // if right is an AOP_STR, it must use DPTR regardless.
3880     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3881      && !AOP_IS_STR(IC_RIGHT(ic)))
3882     {
3883         useDp2 = TRUE;
3884     }
3885     else
3886     {
3887         useDp2 = FALSE;
3888     }
3889         
3890     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3891     
3892     // if the right used DPTR, left MUST use DPTR2.
3893     // if the right used DPTR2, left MUST use DPTR.
3894     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3895     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3896     // enabling us to assign DPTR to result.
3897      
3898     if (AOP_USESDPTR(IC_RIGHT(ic)))
3899     {
3900         useDp2 = TRUE;
3901     }
3902     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3903     {
3904         useDp2 = FALSE;
3905     }
3906     else
3907     {
3908         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3909         {
3910             useDp2 = TRUE;
3911         }
3912         else
3913         {
3914             useDp2 = FALSE;
3915         }
3916     }
3917
3918     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3919     
3920     // We've op'd the left & right. So, if left or right are the same operand as result, 
3921     // we know aopOp will succeed, and we can just do it & bail.
3922     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3923         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3924     {
3925 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3926         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3927         return TRUE;
3928     }
3929     
3930     // Note which dptrs are currently in use.
3931     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3932     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3933     
3934     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3935     // generate it.
3936     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3937     {
3938         return FALSE;
3939     }
3940     
3941     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3942     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3943     {
3944         return FALSE;
3945     }
3946     
3947     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3948     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3949     {
3950         return FALSE;
3951     }
3952
3953     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3954
3955     // Some sanity checking...
3956     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3957     {
3958         fprintf(stderr,
3959                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3960                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3961         emitcode(";", ">>> unexpected DPTR here.");
3962     }
3963     
3964     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3965     {
3966         fprintf(stderr,
3967                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3968                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3969         emitcode(";", ">>> unexpected DPTR2 here.");
3970     }    
3971     
3972     return TRUE;
3973 }
3974
3975 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3976 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3977 // will be set TRUE. The caller must then handle the case specially, noting
3978 // that the IC_RESULT operand is not aopOp'd.
3979 // 
3980 #define AOP_OP_3_NOFATAL(ic, rc) \
3981             do { rc = !aopOp3(ic); } while (0)
3982
3983 // aopOp the left & right operands of an ic.
3984 #define AOP_OP_2(ic) \
3985     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3986     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3987
3988 // convienience macro.
3989 #define AOP_SET_LOCALS(ic) \
3990     left = IC_LEFT(ic); \
3991     right = IC_RIGHT(ic); \
3992     result = IC_RESULT(ic);
3993
3994
3995 // Given an integer value of pushedSize bytes on the stack,
3996 // adjust it to be resultSize bytes, either by discarding
3997 // the most significant bytes or by zero-padding.
3998 //
3999 // On exit from this macro, pushedSize will have been adjusted to
4000 // equal resultSize, and ACC may be trashed.
4001 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4002       /* If the pushed data is bigger than the result,          \
4003        * simply discard unused bytes. Icky, but works.          \
4004        */                                                       \
4005       while (pushedSize > resultSize)                           \
4006       {                                                         \
4007           D (emitcode (";", "discarding unused result byte."););\
4008           emitcode ("pop", "acc");                              \
4009           pushedSize--;                                         \
4010       }                                                         \
4011       if (pushedSize < resultSize)                              \
4012       {                                                         \
4013           emitcode ("clr", "a");                                \
4014           /* Conversly, we haven't pushed enough here.          \
4015            * just zero-pad, and all is well.                    \
4016            */                                                   \
4017           while (pushedSize < resultSize)                       \
4018           {                                                     \
4019               emitcode("push", "acc");                          \
4020               pushedSize++;                                     \
4021           }                                                     \
4022       }                                                         \
4023       assert(pushedSize == resultSize);
4024
4025 /*-----------------------------------------------------------------*/
4026 /* genPlus - generates code for addition                           */
4027 /*-----------------------------------------------------------------*/
4028 static void
4029 genPlus (iCode * ic)
4030 {
4031   int size, offset = 0;
4032   bool pushResult;
4033   int rSize;
4034
4035   D (emitcode (";", "genPlus "););
4036
4037   /* special cases :- */
4038   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4039       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4040       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4041       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4042       if (size <= 9) {
4043           while (size--) emitcode ("inc","dptr");
4044       } else {
4045           emitcode ("mov","a,dpl");
4046           emitcode ("add","a,#!constbyte",size & 0xff);
4047           emitcode ("mov","dpl,a");
4048           emitcode ("mov","a,dph");
4049           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4050           emitcode ("mov","dph,a");
4051           emitcode ("mov","a,dpx");
4052           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4053           emitcode ("mov","dpx,a");
4054       }
4055       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4056       return ;
4057   }
4058   if ( IS_SYMOP(IC_LEFT(ic)) && 
4059        OP_SYMBOL(IC_LEFT(ic))->remat &&
4060        isOperandInFarSpace(IC_RIGHT(ic))) {
4061       operand *op = IC_RIGHT(ic);
4062       IC_RIGHT(ic) = IC_LEFT(ic);
4063       IC_LEFT(ic) = op;
4064   }
4065                 
4066   AOP_OP_3_NOFATAL (ic, pushResult);
4067     
4068   if (pushResult)
4069     {
4070       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4071     }
4072
4073   if (!pushResult)
4074     {
4075       /* if literal, literal on the right or
4076          if left requires ACC or right is already
4077          in ACC */
4078       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4079        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4080           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4081         {
4082           operand *t = IC_RIGHT (ic);
4083           IC_RIGHT (ic) = IC_LEFT (ic);
4084           IC_LEFT (ic) = t;
4085           emitcode (";", "Swapped plus args.");
4086         }
4087
4088       /* if both left & right are in bit
4089          space */
4090       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4091           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4092         {
4093           genPlusBits (ic);
4094           goto release;
4095         }
4096
4097       /* if left in bit space & right literal */
4098       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4099           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4100         {
4101           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4102           /* if result in bit space */
4103           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4104             {
4105               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4106                 emitcode ("cpl", "c");
4107               outBitC (IC_RESULT (ic));
4108             }
4109           else
4110             {
4111               size = getDataSize (IC_RESULT (ic));
4112               _startLazyDPSEvaluation ();
4113               while (size--)
4114                 {
4115                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4116                   emitcode ("addc", "a,#0");
4117                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4118                 }
4119               _endLazyDPSEvaluation ();
4120             }
4121           goto release;
4122         }
4123
4124       /* if I can do an increment instead
4125          of add then GOOD for ME */
4126       if (genPlusIncr (ic) == TRUE)
4127         {
4128           emitcode (";", "did genPlusIncr");
4129           goto release;
4130         }
4131
4132     }
4133   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4134
4135   _startLazyDPSEvaluation ();
4136   while (size--)
4137     {
4138       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4139         {
4140           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4141           if (offset == 0)
4142             emitcode ("add", "a,%s",
4143                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4144           else
4145             emitcode ("addc", "a,%s",
4146                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4147         }
4148       else
4149         {
4150           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4151           {
4152               /* right is going to use ACC or we would have taken the
4153                * above branch.
4154                */
4155               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4156        TR_AP("#3");
4157               D(emitcode(";", "+ AOP_ACC special case."););
4158               emitcode("xch", "a, %s", DP2_RESULT_REG);
4159           }
4160           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4161           if (offset == 0)
4162           {
4163             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4164             {
4165          TR_AP("#4");
4166                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4167             }
4168             else
4169             {
4170                 emitcode ("add", "a,%s",
4171                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4172                                   DP2_RESULT_REG));
4173             }
4174           }
4175           else
4176           {
4177             emitcode ("addc", "a,%s",
4178                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4179                           DP2_RESULT_REG));
4180           }
4181         }
4182       if (!pushResult)
4183         {
4184           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4185         }
4186       else
4187         {
4188           emitcode ("push", "acc");
4189         }
4190       offset++;
4191     }
4192   _endLazyDPSEvaluation ();
4193
4194   if (pushResult)
4195     {
4196       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4197
4198       size = getDataSize (IC_LEFT (ic));
4199       rSize = getDataSize (IC_RESULT (ic));
4200
4201       ADJUST_PUSHED_RESULT(size, rSize);
4202
4203       _startLazyDPSEvaluation ();
4204       while (size--)
4205         {
4206           emitcode ("pop", "acc");
4207           aopPut (AOP (IC_RESULT (ic)), "a", size);
4208         }
4209       _endLazyDPSEvaluation ();
4210     }
4211
4212   adjustArithmeticResult (ic);
4213
4214 release:
4215   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4217   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4218 }
4219
4220 /*-----------------------------------------------------------------*/
4221 /* genMinusDec :- does subtraction with deccrement if possible     */
4222 /*-----------------------------------------------------------------*/
4223 static bool
4224 genMinusDec (iCode * ic)
4225 {
4226   unsigned int icount;
4227   unsigned int size = getDataSize (IC_RESULT (ic));
4228
4229   /* will try to generate an increment */
4230   /* if the right side is not a literal
4231      we cannot */
4232   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4233     return FALSE;
4234
4235   /* if the literal value of the right hand side
4236      is greater than 4 then it is not worth it */
4237   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4238     return FALSE;
4239
4240   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4241       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4242       while (icount--) {
4243           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4244       }
4245       return TRUE;
4246   }
4247   /* if decrement 16 bits in register */
4248   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4249       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4250       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4251       (size > 1) &&
4252       (icount == 1))
4253     {
4254       symbol *tlbl;
4255       int    emitTlbl;
4256       int    labelRange;
4257       char   *l;
4258
4259       /* If the next instruction is a goto and the goto target
4260          * is <= 5 instructions previous to this, we can generate
4261          * jumps straight to that target.
4262        */
4263       if (ic->next && ic->next->op == GOTO
4264           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4265           && labelRange <= 5)
4266         {
4267           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4268           tlbl = IC_LABEL (ic->next);
4269           emitTlbl = 0;
4270         }
4271       else
4272         {
4273           tlbl = newiTempLabel (NULL);
4274           emitTlbl = 1;
4275         }
4276
4277       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4278       emitcode ("dec", "%s", l);
4279  
4280       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4281           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4282           IS_AOP_PREG (IC_RESULT (ic)))
4283       {     
4284           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4285       }
4286       else
4287       {
4288           emitcode ("mov", "a,#!constbyte",0xff);
4289           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4290       }
4291       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4292       emitcode ("dec", "%s", l);
4293       if (size > 2)
4294         {
4295             if (!strcmp(l, "acc"))
4296             {
4297                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4298             }
4299             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4300                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4301                      IS_AOP_PREG (IC_RESULT (ic)))
4302             {       
4303                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4304             }
4305             else
4306             {
4307                 emitcode ("mov", "a,#!constbyte",0xff);
4308                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4309             }
4310             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4311             emitcode ("dec", "%s", l);
4312         }
4313       if (size > 3)
4314         {
4315             if (!strcmp(l, "acc"))
4316             {
4317                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4318             }
4319             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4320                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4321                      IS_AOP_PREG (IC_RESULT (ic)))
4322             {       
4323                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4324             }
4325             else
4326             {
4327                 emitcode ("mov", "a,#!constbyte",0xff);
4328                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4329             }       
4330             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4331             emitcode ("dec", "%s", l);
4332         }
4333       if (emitTlbl)
4334         {
4335           emitcode ("", "!tlabeldef", tlbl->key + 100);
4336         }
4337       return TRUE;
4338     }
4339
4340   /* if the sizes are greater than 1 then we cannot */
4341   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4342       AOP_SIZE (IC_LEFT (ic)) > 1)
4343     return FALSE;
4344
4345   /* we can if the aops of the left & result match or
4346      if they are in registers and the registers are the
4347      same */
4348   if (
4349        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4350        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4351        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4352     {
4353
4354       _startLazyDPSEvaluation ();
4355       while (icount--)
4356         {
4357           emitcode ("dec", "%s",
4358                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4359         }
4360       _endLazyDPSEvaluation ();
4361
4362       return TRUE;
4363     }
4364
4365   return FALSE;
4366 }
4367
4368 /*-----------------------------------------------------------------*/
4369 /* addSign - complete with sign                                    */
4370 /*-----------------------------------------------------------------*/
4371 static void
4372 addSign (operand * result, int offset, int sign)
4373 {
4374   int size = (getDataSize (result) - offset);
4375   if (size > 0)
4376     {
4377       _startLazyDPSEvaluation();
4378       if (sign)
4379         {
4380           emitcode ("rlc", "a");
4381           emitcode ("subb", "a,acc");
4382           while (size--)
4383           {
4384             aopPut (AOP (result), "a", offset++);
4385           }
4386         }
4387       else
4388       {
4389         while (size--)
4390         {
4391           aopPut (AOP (result), zero, offset++);
4392         }
4393       }
4394       _endLazyDPSEvaluation();
4395     }
4396 }
4397
4398 /*-----------------------------------------------------------------*/
4399 /* genMinusBits - generates code for subtraction  of two bits      */
4400 /*-----------------------------------------------------------------*/
4401 static void
4402 genMinusBits (iCode * ic)
4403 {
4404   symbol *lbl = newiTempLabel (NULL);
4405
4406   D (emitcode (";", "genMinusBits "););
4407
4408   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4409     {
4410       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4411       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4412       emitcode ("cpl", "c");
4413       emitcode ("", "!tlabeldef", (lbl->key + 100));
4414       outBitC (IC_RESULT (ic));
4415     }
4416   else
4417     {
4418       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4419       emitcode ("subb", "a,acc");
4420       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4421       emitcode ("inc", "a");
4422       emitcode ("", "!tlabeldef", (lbl->key + 100));
4423       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4424       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4425     }
4426 }
4427
4428 /*-----------------------------------------------------------------*/
4429 /* genMinus - generates code for subtraction                       */
4430 /*-----------------------------------------------------------------*/
4431 static void
4432 genMinus (iCode * ic)
4433 {
4434     int size, offset = 0;
4435     int rSize;
4436     long lit = 0L;
4437     bool pushResult;
4438
4439     D (emitcode (";", "genMinus "););
4440
4441     AOP_OP_3_NOFATAL(ic, pushResult);   
4442
4443     if (!pushResult)
4444     {
4445       /* special cases :- */
4446       /* if both left & right are in bit space */
4447       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4448           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4449         {
4450           genMinusBits (ic);
4451           goto release;
4452         }
4453
4454       /* if I can do an decrement instead
4455          of subtract then GOOD for ME */
4456       if (genMinusDec (ic) == TRUE)
4457         goto release;
4458
4459     }
4460
4461   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4462
4463   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4464     {
4465       CLRC;
4466     }
4467   else
4468     {
4469       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4470       lit = -lit;
4471     }
4472
4473
4474   /* if literal, add a,#-lit, else normal subb */
4475   _startLazyDPSEvaluation ();
4476   while (size--) {
4477       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4478           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4479               emitcode ("mov","b,%s",
4480                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4481               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4482               emitcode ("subb","a,b");
4483           } else {
4484               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485               emitcode ("subb", "a,%s",
4486                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4487                                 DP2_RESULT_REG));
4488           }
4489       } else {
4490           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4491           /* first add without previous c */
4492           if (!offset) {
4493               if (!size && lit==-1) {
4494                   emitcode ("dec", "a");
4495               } else {
4496                   emitcode ("add", "a,#!constbyte",
4497                             (unsigned int) (lit & 0x0FFL));
4498               }
4499           } else {
4500               emitcode ("addc", "a,#!constbyte",
4501                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4502           }
4503       }
4504       
4505       if (pushResult) {
4506           emitcode ("push", "acc");
4507       } else {
4508           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4509       }
4510       offset++;
4511   }
4512   _endLazyDPSEvaluation ();
4513   
4514   if (pushResult)
4515     {
4516       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4517
4518       size = getDataSize (IC_LEFT (ic));
4519       rSize = getDataSize (IC_RESULT (ic));
4520
4521       ADJUST_PUSHED_RESULT(size, rSize);
4522
4523       _startLazyDPSEvaluation ();
4524       while (size--)
4525         {
4526           emitcode ("pop", "acc");
4527           aopPut (AOP (IC_RESULT (ic)), "a", size);
4528         }
4529       _endLazyDPSEvaluation ();
4530     }
4531
4532   adjustArithmeticResult (ic);
4533
4534 release:
4535   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4538 }
4539
4540
4541 /*-----------------------------------------------------------------*/
4542 /* genMultbits :- multiplication of bits                           */
4543 /*-----------------------------------------------------------------*/
4544 static void
4545 genMultbits (operand * left,
4546              operand * right,
4547              operand * result,
4548              iCode   * ic)
4549 {
4550   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4551   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4552   aopOp(result, ic, TRUE, FALSE);
4553   outBitC (result);
4554 }
4555
4556
4557 /*-----------------------------------------------------------------*/
4558 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4559 /*-----------------------------------------------------------------*/
4560 static void
4561 genMultOneByte (operand * left,
4562                 operand * right,
4563                 operand * result,
4564                 iCode   * ic)
4565 {
4566   sym_link *opetype = operandType (result);
4567   symbol *lbl;
4568
4569
4570   /* (if two literals: the value is computed before) */
4571   /* if one literal, literal on the right */
4572   if (AOP_TYPE (left) == AOP_LIT)
4573     {
4574       operand *t = right;
4575       right = left;
4576       left = t;
4577       emitcode (";", "swapped left and right");
4578     }
4579
4580   if (SPEC_USIGN(opetype)
4581       // ignore the sign of left and right, what else can we do?
4582       || (SPEC_USIGN(operandType(left)) && 
4583           SPEC_USIGN(operandType(right)))) {
4584     // just an unsigned 8*8=8/16 multiply
4585     //emitcode (";","unsigned");
4586     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4587     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4588     emitcode ("mul", "ab");
4589    
4590     _G.accInUse++; _G.bInUse++;
4591     aopOp(result, ic, TRUE, FALSE);
4592       
4593       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4594       {
4595           // this should never happen
4596           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4597                    AOP_SIZE(result), __FILE__, lineno);
4598           exit (1);
4599       }      
4600       
4601     aopPut (AOP (result), "a", 0);
4602     _G.accInUse--; _G.bInUse--;
4603     if (AOP_SIZE(result)==2) 
4604     {
4605       aopPut (AOP (result), "b", 1);
4606     }
4607     return;
4608   }
4609
4610   // we have to do a signed multiply
4611
4612   emitcode (";", "signed");
4613   emitcode ("clr", "F0"); // reset sign flag
4614   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4615
4616   lbl=newiTempLabel(NULL);
4617   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4618   // left side is negative, 8-bit two's complement, this fails for -128
4619   emitcode ("setb", "F0"); // set sign flag
4620   emitcode ("cpl", "a");
4621   emitcode ("inc", "a");
4622
4623   emitcode ("", "!tlabeldef", lbl->key+100);
4624
4625   /* if literal */
4626   if (AOP_TYPE(right)==AOP_LIT) {
4627     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4628     /* AND literal negative */
4629     if ((int) val < 0) {
4630       emitcode ("cpl", "F0"); // complement sign flag
4631       emitcode ("mov", "b,#!constbyte", -val);
4632     } else {
4633       emitcode ("mov", "b,#!constbyte", val);
4634     }
4635   } else {
4636     lbl=newiTempLabel(NULL);
4637     emitcode ("mov", "b,a");
4638     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4639     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4640     // right side is negative, 8-bit two's complement
4641     emitcode ("cpl", "F0"); // complement sign flag
4642     emitcode ("cpl", "a");
4643     emitcode ("inc", "a");
4644     emitcode ("", "!tlabeldef", lbl->key+100);
4645   }
4646   emitcode ("mul", "ab");
4647     
4648   _G.accInUse++;_G.bInUse++;
4649   aopOp(result, ic, TRUE, FALSE);
4650     
4651   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4652   {
4653     // this should never happen
4654       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4655                AOP_SIZE(result), __FILE__, lineno);
4656       exit (1);
4657   }    
4658     
4659   lbl=newiTempLabel(NULL);
4660   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4661   // only ONE op was negative, we have to do a 8/16-bit two's complement
4662   emitcode ("cpl", "a"); // lsb
4663   if (AOP_SIZE(result)==1) {
4664     emitcode ("inc", "a");
4665   } else {
4666     emitcode ("add", "a,#1");
4667     emitcode ("xch", "a,b");
4668     emitcode ("cpl", "a"); // msb
4669     emitcode ("addc", "a,#0");
4670     emitcode ("xch", "a,b");
4671   }
4672
4673   emitcode ("", "!tlabeldef", lbl->key+100);
4674   aopPut (AOP (result), "a", 0);
4675   _G.accInUse--;_G.bInUse--;
4676   if (AOP_SIZE(result)==2) {
4677     aopPut (AOP (result), "b", 1);
4678   }
4679 }
4680
4681 /*-----------------------------------------------------------------*/
4682 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4683 /*-----------------------------------------------------------------*/
4684 static void genMultTwoByte (operand *left, operand *right, 
4685                             operand *result, iCode *ic)
4686 {
4687         sym_link *retype = getSpec(operandType(right));
4688         sym_link *letype = getSpec(operandType(left));
4689         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4690         symbol *lbl;
4691
4692         if (AOP_TYPE (left) == AOP_LIT) {
4693                 operand *t = right;
4694                 right = left;
4695                 left = t;
4696         }
4697         /* save EA bit in F1 */
4698         lbl = newiTempLabel(NULL);
4699         emitcode ("setb","F1");
4700         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4701         emitcode ("clr","F1");
4702         emitcode("","!tlabeldef",lbl->key+100);
4703
4704         /* load up MB with right */
4705         if (!umult) {
4706                 emitcode("clr","F0");
4707                 if (AOP_TYPE(right) == AOP_LIT) {
4708                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4709                         if (val < 0) {
4710                                 emitcode("setb","F0");
4711                                 val = -val;
4712                         }
4713                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4714                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4715                 } else {
4716                         lbl = newiTempLabel(NULL);
4717                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4718                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4719                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4720                         emitcode ("xch", "a,b");
4721                         emitcode ("cpl","a");
4722                         emitcode ("add", "a,#1");
4723                         emitcode ("xch", "a,b");
4724                         emitcode ("cpl", "a"); // msb
4725                         emitcode ("addc", "a,#0");
4726                         emitcode ("setb","F0");
4727                         emitcode ("","!tlabeldef",lbl->key+100);
4728                         emitcode ("mov","mb,b");
4729                         emitcode ("mov","mb,a");
4730                 }
4731         } else {
4732                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4733                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4734         }
4735         /* load up MA with left */
4736         if (!umult) {
4737                 lbl = newiTempLabel(NULL);
4738                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4739                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4740                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4741                 emitcode ("xch", "a,b");
4742                 emitcode ("cpl","a");
4743                 emitcode ("add", "a,#1");
4744                 emitcode ("xch", "a,b");
4745                 emitcode ("cpl", "a"); // msb
4746                 emitcode ("addc","a,#0");
4747                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4748                 emitcode ("setb","F0");
4749                 emitcode ("","!tlabeldef",lbl->key+100);
4750                 emitcode ("mov","ma,b");
4751                 emitcode ("mov","ma,a");
4752         } else {
4753                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4754                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4755         }
4756         /* wait for multiplication to finish */
4757         lbl = newiTempLabel(NULL);
4758         emitcode("","!tlabeldef", lbl->key+100);
4759         emitcode("mov","a,mcnt1");
4760         emitcode("anl","a,#!constbyte",0x80);
4761         emitcode("jnz","!tlabel",lbl->key+100);
4762         
4763         freeAsmop (left, NULL, ic, TRUE);
4764         freeAsmop (right, NULL, ic,TRUE);
4765         aopOp(result, ic, TRUE, FALSE);
4766
4767         /* if unsigned then simple */   
4768         if (umult) {
4769                 emitcode ("mov","a,ma");
4770                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4771                 emitcode ("mov","a,ma");
4772                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4773                 aopPut(AOP(result),"ma",1);
4774                 aopPut(AOP(result),"ma",0);
4775         } else {
4776                 emitcode("push","ma");
4777                 emitcode("push","ma");
4778                 emitcode("push","ma");
4779                 MOVA("ma");
4780                 /* negate result if needed */
4781                 lbl = newiTempLabel(NULL);      
4782                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4783                 emitcode("cpl","a");
4784                 emitcode("add","a,#1");
4785                 emitcode("","!tlabeldef", lbl->key+100);
4786                 if (AOP_TYPE(result) == AOP_ACC)
4787                 {
4788                     D(emitcode(";", "ACC special case."););
4789                     /* We know result is the only live aop, and 
4790                      * it's obviously not a DPTR2, so AP is available.
4791                      */
4792                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4793                 }
4794                 else
4795                 {
4796                     aopPut(AOP(result),"a",0);
4797                 }
4798             
4799                 emitcode("pop","acc");
4800                 lbl = newiTempLabel(NULL);      
4801                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4802                 emitcode("cpl","a");
4803                 emitcode("addc","a,#0");
4804                 emitcode("","!tlabeldef", lbl->key+100);
4805                 aopPut(AOP(result),"a",1);
4806                 emitcode("pop","acc");
4807                 if (AOP_SIZE(result) >= 3) {
4808                         lbl = newiTempLabel(NULL);      
4809                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4810                         emitcode("cpl","a");
4811                         emitcode("addc","a,#0");                        
4812                         emitcode("","!tlabeldef", lbl->key+100);
4813                         aopPut(AOP(result),"a",2);
4814                 }
4815                 emitcode("pop","acc");
4816                 if (AOP_SIZE(result) >= 4) {
4817                         lbl = newiTempLabel(NULL);      
4818                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4819                         emitcode("cpl","a");
4820                         emitcode("addc","a,#0");                        
4821                         emitcode("","!tlabeldef", lbl->key+100);
4822                         aopPut(AOP(result),"a",3);
4823                 }
4824                 if (AOP_TYPE(result) == AOP_ACC)
4825                 {
4826                     /* We stashed the result away above. */
4827                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4828                 }           
4829                 
4830         }
4831         freeAsmop (result, NULL, ic, TRUE);
4832
4833         /* restore EA bit in F1 */
4834         lbl = newiTempLabel(NULL);
4835         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4836         emitcode ("setb","EA");
4837         emitcode("","!tlabeldef",lbl->key+100);
4838         return ;
4839 }
4840
4841 /*-----------------------------------------------------------------*/
4842 /* genMult - generates code for multiplication                     */
4843 /*-----------------------------------------------------------------*/
4844 static void
4845 genMult (iCode * ic)
4846 {
4847   operand *left = IC_LEFT (ic);
4848   operand *right = IC_RIGHT (ic);
4849   operand *result = IC_RESULT (ic);
4850
4851   D (emitcode (";", "genMult "););
4852
4853   /* assign the amsops */
4854   AOP_OP_2 (ic);
4855
4856   /* special cases first */
4857   /* both are bits */
4858   if (AOP_TYPE (left) == AOP_CRY &&
4859       AOP_TYPE (right) == AOP_CRY)
4860     {
4861       genMultbits (left, right, result, ic);
4862       goto release;
4863     }
4864
4865   /* if both are of size == 1 */
4866   if (AOP_SIZE (left) == 1 &&
4867       AOP_SIZE (right) == 1)
4868     {
4869       genMultOneByte (left, right, result, ic);
4870       goto release;
4871     }
4872
4873   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4874           /* use the ds390 ARITHMETIC accel UNIT */
4875           genMultTwoByte (left, right, result, ic);
4876           return ;
4877   }
4878   /* should have been converted to function call */
4879   assert (0);
4880
4881 release:
4882   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4883   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884   freeAsmop (result, NULL, ic, TRUE);
4885 }
4886
4887 /*-----------------------------------------------------------------*/
4888 /* genDivbits :- division of bits                                  */
4889 /*-----------------------------------------------------------------*/
4890 static void
4891 genDivbits (operand * left,
4892             operand * right,
4893             operand * result,
4894             iCode   * ic)
4895 {
4896
4897   char *l;
4898
4899   /* the result must be bit */
4900   LOAD_AB_FOR_DIV (left, right, l);
4901   emitcode ("div", "ab");
4902   emitcode ("rrc", "a");
4903   aopOp(result, ic, TRUE, FALSE);
4904     
4905   aopPut (AOP (result), "c", 0);
4906 }
4907
4908 /*-----------------------------------------------------------------*/
4909 /* genDivOneByte : 8 bit division                                  */
4910 /*-----------------------------------------------------------------*/
4911 static void
4912 genDivOneByte (operand * left,
4913                operand * right,
4914                operand * result,
4915                iCode   * ic)
4916 {
4917   sym_link *opetype = operandType (result);
4918   char *l;
4919   symbol *lbl;
4920   int size, offset;
4921
4922   offset = 1;
4923   /* signed or unsigned */
4924   if (SPEC_USIGN (opetype))
4925     {
4926         /* unsigned is easy */
4927         LOAD_AB_FOR_DIV (left, right, l);
4928         emitcode ("div", "ab");
4929
4930         _G.accInUse++;
4931         aopOp(result, ic, TRUE, FALSE);
4932         aopPut (AOP (result), "a", 0);
4933         _G.accInUse--;
4934
4935         size = AOP_SIZE (result) - 1;
4936         
4937         while (size--)
4938         {
4939             aopPut (AOP (result), zero, offset++);
4940         }
4941       return;
4942     }
4943
4944   /* signed is a little bit more difficult */
4945
4946   /* save the signs of the operands */
4947   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4948   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4949   emitcode ("push", "acc");     /* save it on the stack */
4950
4951   /* now sign adjust for both left & right */
4952   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4953   lbl = newiTempLabel (NULL);
4954   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4955   emitcode ("cpl", "a");
4956   emitcode ("inc", "a");
4957   emitcode ("", "!tlabeldef", (lbl->key + 100));
4958   emitcode ("mov", "b,a");
4959
4960   /* sign adjust left side */
4961   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4962
4963   lbl = newiTempLabel (NULL);
4964   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4965   emitcode ("cpl", "a");
4966   emitcode ("inc", "a");
4967   emitcode ("", "!tlabeldef", (lbl->key + 100));
4968
4969   /* now the division */
4970   emitcode ("nop", "; workaround for DS80C390 div bug.");
4971   emitcode ("div", "ab");
4972   /* we are interested in the lower order
4973      only */
4974   emitcode ("mov", "b,a");
4975   lbl = newiTempLabel (NULL);
4976   emitcode ("pop", "acc");
4977   /* if there was an over flow we don't
4978      adjust the sign of the result */
4979   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4980   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4981   CLRC;
4982   emitcode ("clr", "a");
4983   emitcode ("subb", "a,b");
4984   emitcode ("mov", "b,a");
4985   emitcode ("", "!tlabeldef", (lbl->key + 100));
4986
4987   /* now we are done */
4988   _G.accInUse++;     _G.bInUse++;
4989     aopOp(result, ic, TRUE, FALSE);
4990     
4991     aopPut (AOP (result), "b", 0);
4992     
4993     size = AOP_SIZE (result) - 1;
4994     
4995     if (size > 0)
4996     {
4997       emitcode ("mov", "c,b.7");
4998       emitcode ("subb", "a,acc");
4999     }
5000     while (size--)
5001     {
5002         aopPut (AOP (result), "a", offset++);
5003     }
5004     _G.accInUse--;     _G.bInUse--;
5005
5006 }
5007
5008 /*-----------------------------------------------------------------*/
5009 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5010 /*-----------------------------------------------------------------*/
5011 static void genDivTwoByte (operand *left, operand *right, 
5012                             operand *result, iCode *ic)
5013 {
5014         sym_link *retype = getSpec(operandType(right));
5015         sym_link *letype = getSpec(operandType(left));
5016         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5017         symbol *lbl;
5018
5019         /* save EA bit in F1 */
5020         lbl = newiTempLabel(NULL);
5021         emitcode ("setb","F1");
5022         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5023         emitcode ("clr","F1");
5024         emitcode("","!tlabeldef",lbl->key+100);
5025
5026         /* load up MA with left */
5027         if (!umult) {
5028                 emitcode("clr","F0");
5029                 lbl = newiTempLabel(NULL);
5030                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5031                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5032                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5033                 emitcode ("xch", "a,b");
5034                 emitcode ("cpl","a");
5035                 emitcode ("add", "a,#1");
5036                 emitcode ("xch", "a,b");
5037                 emitcode ("cpl", "a"); // msb
5038                 emitcode ("addc","a,#0");
5039                 emitcode ("setb","F0");
5040                 emitcode ("","!tlabeldef",lbl->key+100);
5041                 emitcode ("mov","ma,b");
5042                 emitcode ("mov","ma,a");
5043         } else {
5044                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5045                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5046         }
5047
5048         /* load up MB with right */
5049         if (!umult) {
5050                 if (AOP_TYPE(right) == AOP_LIT) {
5051                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5052                         if (val < 0) {
5053                                 lbl = newiTempLabel(NULL);
5054                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5055                                 emitcode("setb","F0");
5056                                 emitcode ("","!tlabeldef",lbl->key+100);
5057                                 val = -val;
5058                         } 
5059                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5060                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5061                 } else {
5062                         lbl = newiTempLabel(NULL);
5063                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5064                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5065                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5066                         emitcode ("xch", "a,b");
5067                         emitcode ("cpl","a");
5068                         emitcode ("add", "a,#1");
5069                         emitcode ("xch", "a,b");
5070                         emitcode ("cpl", "a"); // msb
5071                         emitcode ("addc", "a,#0");
5072                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5073                         emitcode ("setb","F0");
5074                         emitcode ("","!tlabeldef",lbl->key+100);
5075                         emitcode ("mov","mb,b");
5076                         emitcode ("mov","mb,a");
5077                 }
5078         } else {
5079                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5080                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5081         }
5082
5083         /* wait for multiplication to finish */
5084         lbl = newiTempLabel(NULL);
5085         emitcode("","!tlabeldef", lbl->key+100);
5086         emitcode("mov","a,mcnt1");
5087         emitcode("anl","a,#!constbyte",0x80);
5088         emitcode("jnz","!tlabel",lbl->key+100);
5089         
5090         freeAsmop (left, NULL, ic, TRUE);
5091         freeAsmop (right, NULL, ic,TRUE);
5092         aopOp(result, ic, TRUE, FALSE);
5093
5094         /* if unsigned then simple */   
5095         if (umult) {
5096                 aopPut(AOP(result),"ma",1);
5097                 aopPut(AOP(result),"ma",0);
5098         } else {
5099                 emitcode("push","ma");
5100                 MOVA("ma");
5101                 /* negate result if needed */
5102                 lbl = newiTempLabel(NULL);      
5103                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5104                 emitcode("cpl","a");
5105                 emitcode("add","a,#1");
5106                 emitcode("","!tlabeldef", lbl->key+100);
5107                 aopPut(AOP(result),"a",0);
5108                 emitcode("pop","acc");
5109                 lbl = newiTempLabel(NULL);      
5110                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5111                 emitcode("cpl","a");
5112                 emitcode("addc","a,#0");
5113                 emitcode("","!tlabeldef", lbl->key+100);
5114                 aopPut(AOP(result),"a",1);
5115         }
5116         freeAsmop (result, NULL, ic, TRUE);
5117         /* restore EA bit in F1 */
5118         lbl = newiTempLabel(NULL);
5119         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5120         emitcode ("setb","EA");
5121         emitcode("","!tlabeldef",lbl->key+100);
5122         return ;
5123 }
5124
5125 /*-----------------------------------------------------------------*/
5126 /* genDiv - generates code for division                            */
5127 /*-----------------------------------------------------------------*/
5128 static void
5129 genDiv (iCode * ic)
5130 {
5131   operand *left = IC_LEFT (ic);
5132   operand *right = IC_RIGHT (ic);
5133   operand *result = IC_RESULT (ic);
5134
5135   D (emitcode (";", "genDiv "););
5136
5137   /* assign the amsops */
5138   AOP_OP_2 (ic);
5139
5140   /* special cases first */
5141   /* both are bits */
5142   if (AOP_TYPE (left) == AOP_CRY &&
5143       AOP_TYPE (right) == AOP_CRY)
5144     {
5145       genDivbits (left, right, result, ic);
5146       goto release;
5147     }
5148
5149   /* if both are of size == 1 */
5150   if (AOP_SIZE (left) == 1 &&
5151       AOP_SIZE (right) == 1)
5152     {
5153       genDivOneByte (left, right, result, ic);
5154       goto release;
5155     }
5156
5157   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5158           /* use the ds390 ARITHMETIC accel UNIT */
5159           genDivTwoByte (left, right, result, ic);
5160           return ;
5161   }
5162   /* should have been converted to function call */
5163   assert (0);
5164 release:
5165   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5166   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5167   freeAsmop (result, NULL, ic, TRUE);
5168 }
5169
5170 /*-----------------------------------------------------------------*/
5171 /* genModbits :- modulus of bits                                   */
5172 /*-----------------------------------------------------------------*/
5173 static void
5174 genModbits (operand * left,
5175             operand * right,
5176             operand * result,
5177             iCode   * ic)
5178 {
5179
5180   char *l;
5181
5182   /* the result must be bit */
5183   LOAD_AB_FOR_DIV (left, right, l);
5184   emitcode ("div", "ab");
5185   emitcode ("mov", "a,b");
5186   emitcode ("rrc", "a");
5187   aopOp(result, ic, TRUE, FALSE);
5188   aopPut (AOP (result), "c", 0);
5189 }
5190
5191 /*-----------------------------------------------------------------*/
5192 /* genModOneByte : 8 bit modulus                                   */
5193 /*-----------------------------------------------------------------*/
5194 static void
5195 genModOneByte (operand * left,
5196                operand * right,
5197                operand * result,
5198                iCode   * ic)
5199 {
5200   sym_link *opetype = operandType (result);
5201   char *l;
5202   symbol *lbl;
5203
5204   /* signed or unsigned */
5205   if (SPEC_USIGN (opetype))
5206     {
5207       /* unsigned is easy */
5208       LOAD_AB_FOR_DIV (left, right, l);
5209       emitcode ("div", "ab");
5210       aopOp(result, ic, TRUE, FALSE);   
5211       aopPut (AOP (result), "b", 0);
5212       return;
5213     }
5214
5215   /* signed is a little bit more difficult */
5216
5217   /* save the signs of the operands */
5218   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5219
5220   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5221   emitcode ("push", "acc");     /* save it on the stack */
5222
5223   /* now sign adjust for both left & right */
5224   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5225
5226   lbl = newiTempLabel (NULL);
5227   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5228   emitcode ("cpl", "a");
5229   emitcode ("inc", "a");
5230   emitcode ("", "!tlabeldef", (lbl->key + 100));
5231   emitcode ("mov", "b,a");
5232
5233   /* sign adjust left side */
5234   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5235
5236   lbl = newiTempLabel (NULL);
5237   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5238   emitcode ("cpl", "a");
5239   emitcode ("inc", "a");
5240   emitcode ("", "!tlabeldef", (lbl->key + 100));
5241
5242   /* now the multiplication */
5243   emitcode ("nop", "; workaround for DS80C390 div bug.");
5244   emitcode ("div", "ab");
5245   /* we are interested in the lower order
5246      only */
5247   lbl = newiTempLabel (NULL);
5248   emitcode ("pop", "acc");
5249   /* if there was an over flow we don't
5250      adjust the sign of the result */
5251   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5252   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5253   CLRC;
5254   emitcode ("clr", "a");
5255   emitcode ("subb", "a,b");
5256   emitcode ("mov", "b,a");
5257   emitcode ("", "!tlabeldef", (lbl->key + 100));
5258   
5259   _G.bInUse++;
5260   /* now we are done */
5261   aopOp(result, ic, TRUE, FALSE);    
5262   aopPut (AOP (result), "b", 0);
5263   _G.bInUse--;
5264
5265 }
5266
5267 /*-----------------------------------------------------------------*/
5268 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5269 /*-----------------------------------------------------------------*/
5270 static void genModTwoByte (operand *left, operand *right, 
5271                             operand *result, iCode *ic)
5272 {
5273         sym_link *retype = getSpec(operandType(right));
5274         sym_link *letype = getSpec(operandType(left));
5275         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5276         symbol *lbl;
5277
5278         /* load up MA with left */
5279         /* save EA bit in F1 */
5280         lbl = newiTempLabel(NULL);
5281         emitcode ("setb","F1");
5282         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5283         emitcode ("clr","F1");
5284         emitcode("","!tlabeldef",lbl->key+100);
5285
5286         if (!umult) {
5287                 lbl = newiTempLabel(NULL);
5288                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5289                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5290                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5291                 emitcode ("xch", "a,b");
5292                 emitcode ("cpl","a");
5293                 emitcode ("add", "a,#1");
5294                 emitcode ("xch", "a,b");
5295                 emitcode ("cpl", "a"); // msb
5296                 emitcode ("addc","a,#0");
5297                 emitcode ("","!tlabeldef",lbl->key+100);
5298                 emitcode ("mov","ma,b");
5299                 emitcode ("mov","ma,a");
5300         } else {
5301                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5302                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5303         }
5304
5305         /* load up MB with right */
5306         if (!umult) {
5307                 if (AOP_TYPE(right) == AOP_LIT) {
5308                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5309                         if (val < 0) {
5310                                 val = -val;
5311                         } 
5312                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5313                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5314                 } else {
5315                         lbl = newiTempLabel(NULL);
5316                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5317                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5318                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5319                         emitcode ("xch", "a,b");
5320                         emitcode ("cpl","a");
5321                         emitcode ("add", "a,#1");
5322                         emitcode ("xch", "a,b");
5323                         emitcode ("cpl", "a"); // msb
5324                         emitcode ("addc", "a,#0");
5325                         emitcode ("","!tlabeldef",lbl->key+100);
5326                         emitcode ("mov","mb,b");
5327                         emitcode ("mov","mb,a");
5328                 }
5329         } else {
5330                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5331                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5332         }
5333
5334         /* wait for multiplication to finish */
5335         lbl = newiTempLabel(NULL);
5336         emitcode("","!tlabeldef", lbl->key+100);
5337         emitcode("mov","a,mcnt1");
5338         emitcode("anl","a,#!constbyte",0x80);
5339         emitcode("jnz","!tlabel",lbl->key+100);
5340         
5341         freeAsmop (left, NULL, ic, TRUE);
5342         freeAsmop (right, NULL, ic,TRUE);
5343         aopOp(result, ic, TRUE, FALSE);
5344
5345         aopPut(AOP(result),"mb",1);
5346         aopPut(AOP(result),"mb",0);
5347         freeAsmop (result, NULL, ic, TRUE);
5348
5349         /* restore EA bit in F1 */
5350         lbl = newiTempLabel(NULL);
5351         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5352         emitcode ("setb","EA");
5353         emitcode("","!tlabeldef",lbl->key+100);
5354         return ;
5355 }
5356
5357 /*-----------------------------------------------------------------*/
5358 /* genMod - generates code for division                            */
5359 /*-----------------------------------------------------------------*/
5360 static void
5361 genMod (iCode * ic)
5362 {
5363   operand *left = IC_LEFT (ic);
5364   operand *right = IC_RIGHT (ic);
5365   operand *result = IC_RESULT (ic);
5366
5367   D (emitcode (";", "genMod "); );
5368
5369   /* assign the amsops */
5370   AOP_OP_2 (ic);
5371
5372   /* special cases first */
5373   /* both are bits */
5374   if (AOP_TYPE (left) == AOP_CRY &&
5375       AOP_TYPE (right) == AOP_CRY)
5376     {
5377       genModbits (left, right, result, ic);
5378       goto release;
5379     }
5380
5381   /* if both are of size == 1 */
5382   if (AOP_SIZE (left) == 1 &&
5383       AOP_SIZE (right) == 1)
5384     {
5385       genModOneByte (left, right, result, ic);
5386       goto release;
5387     }
5388
5389   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5390           /* use the ds390 ARITHMETIC accel UNIT */
5391           genModTwoByte (left, right, result, ic);
5392           return ;
5393   }
5394
5395   /* should have been converted to function call */
5396   assert (0);
5397
5398 release:
5399   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5400   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5401   freeAsmop (result, NULL, ic, TRUE);
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* genIfxJump :- will create a jump depending on the ifx           */
5406 /*-----------------------------------------------------------------*/
5407 static void
5408 genIfxJump (iCode * ic, char *jval)
5409 {
5410   symbol *jlbl;
5411   symbol *tlbl = newiTempLabel (NULL);
5412   char *inst;
5413
5414   D (emitcode (";", "genIfxJump"););
5415
5416   /* if true label then we jump if condition
5417      supplied is true */
5418   if (IC_TRUE (ic))
5419     {
5420       jlbl = IC_TRUE (ic);
5421       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5422                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5423     }
5424   else
5425     {
5426       /* false label is present */
5427       jlbl = IC_FALSE (ic);
5428       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5429                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5430     }
5431   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5432     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5433   else
5434     emitcode (inst, "!tlabel", tlbl->key + 100);
5435   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5436   emitcode ("", "!tlabeldef", tlbl->key + 100);
5437
5438   /* mark the icode as generated */
5439   ic->generated = 1;
5440 }
5441
5442 /*-----------------------------------------------------------------*/
5443 /* genCmp :- greater or less than comparison                       */
5444 /*-----------------------------------------------------------------*/
5445 static void
5446 genCmp (operand * left, operand * right,
5447         iCode * ic, iCode * ifx, int sign)
5448 {
5449   int size, offset = 0;
5450   unsigned long lit = 0L;
5451   operand *result;
5452
5453   D (emitcode (";", "genCmp"););
5454
5455   result = IC_RESULT (ic);
5456
5457   /* if left & right are bit variables */
5458   if (AOP_TYPE (left) == AOP_CRY &&
5459       AOP_TYPE (right) == AOP_CRY)
5460     {
5461       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5462       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5463     }
5464   else
5465     {
5466       /* subtract right from left if at the
5467          end the carry flag is set then we know that
5468          left is greater than right */
5469       size = max (AOP_SIZE (left), AOP_SIZE (right));
5470
5471       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5472       if ((size == 1) && !sign 
5473           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5474         {
5475           symbol *lbl = newiTempLabel (NULL);
5476           emitcode ("cjne", "%s,%s,!tlabel",
5477                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5478                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5479                     lbl->key + 100);
5480           emitcode ("", "!tlabeldef", lbl->key + 100);
5481         }
5482       else
5483         {
5484           if (AOP_TYPE (right) == AOP_LIT)
5485             {
5486               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5487               /* optimize if(x < 0) or if(x >= 0) */
5488               if (lit == 0L)
5489                 {
5490                   if (!sign)
5491                     {
5492                       CLRC;
5493                     }
5494                   else
5495                     {
5496                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5497
5498                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5499                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500
5501                       aopOp (result, ic, FALSE, FALSE);
5502
5503                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5504                         {
5505                           freeAsmop (result, NULL, ic, TRUE);
5506                           genIfxJump (ifx, "acc.7");
5507                           return;
5508                         }
5509                       else
5510                         {
5511                           emitcode ("rlc", "a");
5512                         }
5513                       goto release_freedLR;
5514                     }
5515                   goto release;
5516                 }
5517             }
5518           CLRC;
5519           while (size--)
5520             {
5521               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5522               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5523               // emitcode (";", "genCmp #2");
5524               if (sign && (size == 0))
5525                 {
5526                   // emitcode (";", "genCmp #3");
5527                   emitcode ("xrl", "a,#!constbyte",0x80);
5528                   if (AOP_TYPE (right) == AOP_LIT)
5529                     {
5530                       unsigned long lit = (unsigned long)
5531                       floatFromVal (AOP (right)->aopu.aop_lit);
5532                       // emitcode (";", "genCmp #3.1");
5533                       emitcode ("subb", "a,#!constbyte",
5534                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5535                     }
5536                   else
5537                     {
5538                       // emitcode (";", "genCmp #3.2");
5539                       saveAccWarn = 0;  
5540                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5541                       saveAccWarn = DEFAULT_ACC_WARNING;
5542                       emitcode ("xrl", "b,#!constbyte",0x80);
5543                       emitcode ("subb", "a,b");
5544                     }
5545                 }
5546               else
5547                 {
5548                   const char *s;
5549
5550                   // emitcode (";", "genCmp #4");
5551                   saveAccWarn = 0;
5552                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5553                   saveAccWarn = DEFAULT_ACC_WARNING;
5554
5555                   emitcode ("subb", "a,%s", s);
5556                 }
5557             }
5558         }
5559     }
5560
5561 release:
5562 /* Don't need the left & right operands any more; do need the result. */
5563   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5564   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5565
5566   aopOp (result, ic, FALSE, FALSE);
5567
5568 release_freedLR:
5569
5570   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5571     {
5572       outBitC (result);
5573     }
5574   else
5575     {
5576       /* if the result is used in the next
5577          ifx conditional branch then generate
5578          code a little differently */
5579       if (ifx)
5580         {
5581           genIfxJump (ifx, "c");
5582         }
5583       else
5584         {
5585           outBitC (result);
5586         }
5587       /* leave the result in acc */
5588     }
5589   freeAsmop (result, NULL, ic, TRUE);
5590 }
5591
5592 /*-----------------------------------------------------------------*/
5593 /* genCmpGt :- greater than comparison                             */
5594 /*-----------------------------------------------------------------*/
5595 static void
5596 genCmpGt (iCode * ic, iCode * ifx)
5597 {
5598   operand *left, *right;
5599   sym_link *letype, *retype;
5600   int sign;
5601
5602   D (emitcode (";", "genCmpGt ");
5603     );
5604
5605   left = IC_LEFT (ic);
5606   right = IC_RIGHT (ic);
5607
5608   letype = getSpec (operandType (left));
5609   retype = getSpec (operandType (right));
5610   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5611
5612   /* assign the left & right amsops */
5613   AOP_OP_2 (ic);
5614
5615   genCmp (right, left, ic, ifx, sign);
5616 }
5617
5618 /*-----------------------------------------------------------------*/
5619 /* genCmpLt - less than comparisons                                */
5620 /*-----------------------------------------------------------------*/
5621 static void
5622 genCmpLt (iCode * ic, iCode * ifx)
5623 {
5624   operand *left, *right;
5625   sym_link *letype, *retype;
5626   int sign;
5627
5628   D (emitcode (";", "genCmpLt "););
5629
5630   left = IC_LEFT (ic);
5631   right = IC_RIGHT (ic);
5632
5633   letype = getSpec (operandType (left));
5634   retype = getSpec (operandType (right));
5635   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5636
5637   /* assign the left & right amsops */
5638   AOP_OP_2 (ic);
5639
5640   genCmp (left, right, ic, ifx, sign);
5641 }
5642
5643 /*-----------------------------------------------------------------*/
5644 /* gencjneshort - compare and jump if not equal                    */
5645 /*-----------------------------------------------------------------*/
5646 static void
5647 gencjneshort (operand * left, operand * right, symbol * lbl)
5648 {
5649   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5650   int offset = 0;
5651   unsigned long lit = 0L;
5652
5653   D (emitcode (";", "gencjneshort");
5654     );
5655
5656   /* if the left side is a literal or
5657      if the right is in a pointer register and left
5658      is not */
5659   if ((AOP_TYPE (left) == AOP_LIT) ||
5660       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5661     {
5662       operand *t = right;
5663       right = left;
5664       left = t;
5665     }
5666
5667   if (AOP_TYPE (right) == AOP_LIT)
5668     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5669
5670   if (opIsGptr (left) || opIsGptr (right))
5671     {
5672       /* We are comparing a generic pointer to something.
5673        * Exclude the generic type byte from the comparison.
5674        */
5675       size--;
5676       D (emitcode (";", "cjneshort: generic ptr special case."););
5677     }
5678
5679
5680   /* if the right side is a literal then anything goes */
5681   if (AOP_TYPE (right) == AOP_LIT &&
5682       AOP_TYPE (left) != AOP_DIR)
5683     {
5684       while (size--)
5685         {
5686           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5687           emitcode ("cjne", "a,%s,!tlabel",
5688                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5689                     lbl->key + 100);
5690           offset++;
5691         }
5692     }
5693
5694   /* if the right side is in a register or in direct space or
5695      if the left is a pointer register & right is not */
5696   else if (AOP_TYPE (right) == AOP_REG ||
5697            AOP_TYPE (right) == AOP_DIR ||
5698            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5699            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5700     {
5701       while (size--)
5702         {
5703           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5704           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5705               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5706             emitcode ("jnz", "!tlabel", lbl->key + 100);
5707           else
5708             emitcode ("cjne", "a,%s,!tlabel",
5709                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5710                       lbl->key + 100);
5711           offset++;
5712         }
5713     }
5714   else
5715     {
5716       /* right is a pointer reg need both a & b */
5717       while (size--)
5718         {
5719           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5720           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5721           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5722           offset++;
5723         }
5724     }
5725 }
5726
5727 /*-----------------------------------------------------------------*/
5728 /* gencjne - compare and jump if not equal                         */
5729 /*-----------------------------------------------------------------*/
5730 static void
5731 gencjne (operand * left, operand * right, symbol * lbl)
5732 {
5733   symbol *tlbl = newiTempLabel (NULL);
5734
5735   D (emitcode (";", "gencjne");
5736     );
5737
5738   gencjneshort (left, right, lbl);
5739
5740   emitcode ("mov", "a,%s", one);
5741   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5742   emitcode ("", "!tlabeldef", lbl->key + 100);
5743   emitcode ("clr", "a");
5744   emitcode ("", "!tlabeldef", tlbl->key + 100);
5745 }
5746
5747 /*-----------------------------------------------------------------*/
5748 /* genCmpEq - generates code for equal to                          */
5749 /*-----------------------------------------------------------------*/
5750 static void
5751 genCmpEq (iCode * ic, iCode * ifx)
5752 {
5753   operand *left, *right, *result;
5754
5755   D (emitcode (";", "genCmpEq ");
5756     );
5757
5758   AOP_OP_2 (ic);
5759   AOP_SET_LOCALS (ic);
5760
5761   /* if literal, literal on the right or
5762      if the right is in a pointer register and left
5763      is not */
5764   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5765       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5766     {
5767       operand *t = IC_RIGHT (ic);
5768       IC_RIGHT (ic) = IC_LEFT (ic);
5769       IC_LEFT (ic) = t;
5770     }
5771
5772   if (ifx &&                    /* !AOP_SIZE(result) */
5773       OP_SYMBOL (result) &&
5774       OP_SYMBOL (result)->regType == REG_CND)
5775     {
5776       symbol *tlbl;
5777       /* if they are both bit variables */
5778       if (AOP_TYPE (left) == AOP_CRY &&
5779           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5780         {
5781           if (AOP_TYPE (right) == AOP_LIT)
5782             {
5783               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5784               if (lit == 0L)
5785                 {
5786                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787                   emitcode ("cpl", "c");
5788                 }
5789               else if (lit == 1L)
5790                 {
5791                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5792                 }
5793               else
5794                 {
5795                   emitcode ("clr", "c");
5796                 }
5797               /* AOP_TYPE(right) == AOP_CRY */
5798             }
5799           else
5800             {
5801               symbol *lbl = newiTempLabel (NULL);
5802               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5803               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5804               emitcode ("cpl", "c");
5805               emitcode ("", "!tlabeldef", (lbl->key + 100));
5806             }
5807           /* if true label then we jump if condition
5808              supplied is true */
5809           tlbl = newiTempLabel (NULL);
5810           if (IC_TRUE (ifx))
5811             {
5812               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5813               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5814             }
5815           else
5816             {
5817               emitcode ("jc", "!tlabel", tlbl->key + 100);
5818               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5819             }
5820           emitcode ("", "!tlabeldef", tlbl->key + 100);
5821         }
5822       else
5823         {
5824           tlbl = newiTempLabel (NULL);
5825           gencjneshort (left, right, tlbl);
5826           if (IC_TRUE (ifx))
5827             {
5828               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5829               emitcode ("", "!tlabeldef", tlbl->key + 100);
5830             }
5831           else
5832             {
5833               symbol *lbl = newiTempLabel (NULL);
5834               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5835               emitcode ("", "!tlabeldef", tlbl->key + 100);
5836               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5837               emitcode ("", "!tlabeldef", lbl->key + 100);
5838             }
5839         }
5840       /* mark the icode as generated */
5841       ifx->generated = 1;
5842
5843       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5844       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5845       return;
5846     }
5847
5848   /* if they are both bit variables */
5849   if (AOP_TYPE (left) == AOP_CRY &&
5850       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5851     {
5852       if (AOP_TYPE (right) == AOP_LIT)
5853         {
5854           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5855           if (lit == 0L)
5856             {
5857               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5858               emitcode ("cpl", "c");
5859             }
5860           else if (lit == 1L)
5861             {
5862               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5863             }
5864           else
5865             {
5866               emitcode ("clr", "c");
5867             }
5868           /* AOP_TYPE(right) == AOP_CRY */
5869         }
5870       else
5871         {
5872           symbol *lbl = newiTempLabel (NULL);
5873           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5874           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5875           emitcode ("cpl", "c");
5876           emitcode ("", "!tlabeldef", (lbl->key + 100));
5877         }
5878
5879       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5880       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5881
5882       aopOp (result, ic, TRUE, FALSE);
5883
5884       /* c = 1 if egal */
5885       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5886         {
5887           outBitC (result);
5888           goto release;
5889         }
5890       if (ifx)
5891         {
5892           genIfxJump (ifx, "c");
5893           goto release;
5894         }
5895       /* if the result is used in an arithmetic operation
5896          then put the result in place */
5897       outBitC (result);
5898     }
5899   else
5900     {
5901       gencjne (left, right, newiTempLabel (NULL));
5902
5903       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5904       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5905
5906       aopOp (result, ic, TRUE, FALSE);
5907
5908       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5909         {
5910           aopPut (AOP (result), "a", 0);
5911           goto release;
5912         }
5913       if (ifx)
5914         {
5915           genIfxJump (ifx, "a");
5916           goto release;
5917         }
5918       /* if the result is used in an arithmetic operation
5919          then put the result in place */
5920       if (AOP_TYPE (result) != AOP_CRY)
5921         outAcc (result);
5922       /* leave the result in acc */
5923     }
5924
5925 release:
5926   freeAsmop (result, NULL, ic, TRUE);
5927 }
5928
5929 /*-----------------------------------------------------------------*/
5930 /* ifxForOp - returns the icode containing the ifx for operand     */
5931 /*-----------------------------------------------------------------*/
5932 static iCode *
5933 ifxForOp (operand * op, iCode * ic)
5934 {
5935   /* if true symbol then needs to be assigned */
5936   if (IS_TRUE_SYMOP (op))
5937     return NULL;
5938
5939   /* if this has register type condition and
5940      the next instruction is ifx with the same operand
5941      and live to of the operand is upto the ifx only then */
5942   if (ic->next &&
5943       ic->next->op == IFX &&
5944       IC_COND (ic->next)->key == op->key &&
5945       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5946     return ic->next;
5947
5948   return NULL;
5949 }
5950 /*-----------------------------------------------------------------*/
5951 /* hasInc - operand is incremented before any other use            */
5952 /*-----------------------------------------------------------------*/
5953 static iCode *
5954 hasInc (operand *op, iCode *ic, int osize)
5955 {
5956   sym_link *type = operandType(op);
5957   sym_link *retype = getSpec (type);
5958   iCode *lic = ic->next;
5959   int isize ;
5960   
5961   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5962   if (!IS_SYMOP(op)) return NULL;
5963
5964   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5965   if (IS_AGGREGATE(type->next)) return NULL;
5966   if (osize != (isize = getSize(type->next))) return NULL;
5967
5968   while (lic) {
5969       /* if operand of the form op = op + <sizeof *op> */
5970       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5971           isOperandEqual(IC_RESULT(lic),op) && 
5972           isOperandLiteral(IC_RIGHT(lic)) &&
5973           operandLitValue(IC_RIGHT(lic)) == isize) {
5974           return lic;
5975       }
5976       /* if the operand used or deffed */
5977       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5978           return NULL;
5979       }
5980       /* if GOTO or IFX */
5981       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5982       lic = lic->next;
5983   }
5984   return NULL;
5985 }
5986
5987 /*-----------------------------------------------------------------*/
5988 /* genAndOp - for && operation                                     */
5989 /*-----------------------------------------------------------------*/
5990 static void
5991 genAndOp (iCode * ic)
5992 {
5993   operand *left, *right, *result;
5994   symbol *tlbl;
5995
5996   D (emitcode (";", "genAndOp "););
5997
5998   /* note here that && operations that are in an
5999      if statement are taken away by backPatchLabels
6000      only those used in arthmetic operations remain */
6001   AOP_OP_2 (ic);
6002   AOP_SET_LOCALS (ic);
6003
6004   /* if both are bit variables */
6005   if (AOP_TYPE (left) == AOP_CRY &&
6006       AOP_TYPE (right) == AOP_CRY)
6007     {
6008       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6009       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6010       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6012   
6013       aopOp (result,ic,FALSE, FALSE);
6014       outBitC (result);
6015     }
6016   else
6017     {
6018       tlbl = newiTempLabel (NULL);
6019       toBoolean (left);
6020       emitcode ("jz", "!tlabel", tlbl->key + 100);
6021       toBoolean (right);
6022       emitcode ("", "!tlabeldef", tlbl->key + 100);
6023       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6025   
6026       aopOp (result,ic,FALSE, FALSE);
6027       outBitAcc (result);
6028     }
6029     freeAsmop (result, NULL, ic, TRUE);
6030 }
6031
6032
6033 /*-----------------------------------------------------------------*/
6034 /* genOrOp - for || operation                                      */
6035 /*-----------------------------------------------------------------*/
6036 static void
6037 genOrOp (iCode * ic)
6038 {
6039   operand *left, *right, *result;
6040   symbol *tlbl;
6041
6042   D (emitcode (";", "genOrOp "););
6043
6044   /* note here that || operations that are in an
6045      if statement are taken away by backPatchLabels
6046      only those used in arthmetic operations remain */
6047   AOP_OP_2 (ic);
6048   AOP_SET_LOCALS (ic);
6049
6050   /* if both are bit variables */
6051   if (AOP_TYPE (left) == AOP_CRY &&
6052       AOP_TYPE (right) == AOP_CRY)
6053     {
6054       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6055       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6056       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6057       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6058   
6059       aopOp (result,ic,FALSE, FALSE);
6060       
6061       outBitC (result);
6062     }
6063   else
6064     {
6065       tlbl = newiTempLabel (NULL);
6066       toBoolean (left);
6067       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6068       toBoolean (right);
6069       emitcode ("", "!tlabeldef", tlbl->key + 100);
6070       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6071       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6072   
6073       aopOp (result,ic,FALSE, FALSE);
6074       
6075       outBitAcc (result);
6076     }
6077
6078   freeAsmop (result, NULL, ic, TRUE);
6079 }
6080
6081 /*-----------------------------------------------------------------*/
6082 /* isLiteralBit - test if lit == 2^n                               */
6083 /*-----------------------------------------------------------------*/
6084 static int
6085 isLiteralBit (unsigned long lit)
6086 {
6087   unsigned long pw[32] =
6088   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6089    0x100L, 0x200L, 0x400L, 0x800L,
6090    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6091    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6092    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6093    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6094    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6095   int idx;
6096
6097   for (idx = 0; idx < 32; idx++)
6098     if (lit == pw[idx])
6099       return idx + 1;
6100   return 0;
6101 }
6102
6103 /*-----------------------------------------------------------------*/
6104 /* continueIfTrue -                                                */
6105 /*-----------------------------------------------------------------*/
6106 static void
6107 continueIfTrue (iCode * ic)
6108 {
6109   if (IC_TRUE (ic))
6110     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6111   ic->generated = 1;
6112 }
6113
6114 /*-----------------------------------------------------------------*/
6115 /* jmpIfTrue -                                                     */
6116 /*-----------------------------------------------------------------*/
6117 static void
6118 jumpIfTrue (iCode * ic)
6119 {
6120   if (!IC_TRUE (ic))
6121     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6122   ic->generated = 1;
6123 }
6124
6125 /*-----------------------------------------------------------------*/
6126 /* jmpTrueOrFalse -                                                */
6127 /*-----------------------------------------------------------------*/
6128 static void
6129 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6130 {
6131   // ugly but optimized by peephole
6132   if (IC_TRUE (ic))
6133     {
6134       symbol *nlbl = newiTempLabel (NULL);
6135       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6136       emitcode ("", "!tlabeldef", tlbl->key + 100);
6137       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6138       emitcode ("", "!tlabeldef", nlbl->key + 100);
6139     }
6140   else
6141     {
6142       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6143       emitcode ("", "!tlabeldef", tlbl->key + 100);
6144     }
6145   ic->generated = 1;
6146 }
6147
6148 // Generate code to perform a bit-wise logic operation
6149 // on two operands in far space (assumed to already have been 
6150 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6151 // in far space. This requires pushing the result on the stack
6152 // then popping it into the result.
6153 static void
6154 genFarFarLogicOp(iCode *ic, char *logicOp)
6155 {
6156       int size, resultSize, compSize;
6157       int offset = 0;
6158       
6159       TR_AP("#5");
6160       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6161       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6162                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6163       
6164       _startLazyDPSEvaluation();
6165       for (size = compSize; (size--); offset++)
6166       {
6167           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6168           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6169           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6170           
6171           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6172           emitcode ("push", "acc");
6173       }
6174       _endLazyDPSEvaluation();
6175      
6176       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6177       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6178       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6179      
6180       resultSize = AOP_SIZE(IC_RESULT(ic));
6181
6182       ADJUST_PUSHED_RESULT(compSize, resultSize);
6183
6184       _startLazyDPSEvaluation();
6185       while (compSize--)
6186       {
6187           emitcode ("pop", "acc");
6188           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6189       }
6190       _endLazyDPSEvaluation();
6191       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6192 }
6193
6194
6195 /*-----------------------------------------------------------------*/
6196 /* genAnd  - code for and                                          */
6197 /*-----------------------------------------------------------------*/
6198 static void
6199 genAnd (iCode * ic, iCode * ifx)
6200 {
6201   operand *left, *right, *result;
6202   int size, offset = 0;
6203   unsigned long lit = 0L;
6204   int bytelit;
6205   char buff[10];
6206   bool pushResult;
6207
6208   D (emitcode (";", "genAnd "););
6209
6210   AOP_OP_3_NOFATAL (ic, pushResult);
6211   AOP_SET_LOCALS (ic);
6212
6213   if (pushResult)
6214   {
6215       genFarFarLogicOp(ic, "anl");
6216       return;
6217   }  
6218
6219 #ifdef DEBUG_TYPE
6220   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6221             AOP_TYPE (result),
6222             AOP_TYPE (left), AOP_TYPE (right));
6223   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6224             AOP_SIZE (result),
6225             AOP_SIZE (left), AOP_SIZE (right));
6226 #endif
6227
6228   /* if left is a literal & right is not then exchange them */
6229   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6230 #ifdef LOGIC_OPS_BROKEN      
6231     ||  AOP_NEEDSACC (left)
6232 #endif
6233     )
6234     {
6235       operand *tmp = right;
6236       right = left;
6237       left = tmp;
6238     }
6239
6240   /* if result = right then exchange them */
6241   if (sameRegs (AOP (result), AOP (right)))
6242     {
6243       operand *tmp = right;
6244       right = left;
6245       left = tmp;
6246     }
6247
6248   /* if right is bit then exchange them */
6249   if (AOP_TYPE (right) == AOP_CRY &&
6250       AOP_TYPE (left) != AOP_CRY)
6251     {
6252       operand *tmp = right;
6253       right = left;
6254       left = tmp;
6255     }
6256   if (AOP_TYPE (right) == AOP_LIT)
6257     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6258
6259   size = AOP_SIZE (result);
6260
6261   // if(bit & yy)
6262   // result = bit & yy;
6263   if (AOP_TYPE (left) == AOP_CRY)
6264     {
6265       // c = bit & literal;
6266       if (AOP_TYPE (right) == AOP_LIT)
6267         {
6268           if (lit & 1)
6269             {
6270               if (size && sameRegs (AOP (result), AOP (left)))
6271                 // no change
6272                 goto release;
6273               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6274             }
6275           else
6276             {
6277               // bit(result) = 0;
6278               if (size && (AOP_TYPE (result) == AOP_CRY))
6279                 {
6280                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6281                   goto release;
6282                 }
6283               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6284                 {
6285                   jumpIfTrue (ifx);
6286                   goto release;
6287                 }
6288               emitcode ("clr", "c");
6289             }
6290         }
6291       else
6292         {
6293           if (AOP_TYPE (right) == AOP_CRY)
6294             {
6295               // c = bit & bit;
6296               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6297               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6298             }
6299           else
6300             {
6301               // c = bit & val;
6302               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6303               // c = lsb
6304               emitcode ("rrc", "a");
6305               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6306             }
6307         }
6308       // bit = c
6309       // val = c
6310       if (size)
6311         outBitC (result);
6312       // if(bit & ...)
6313       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6314         genIfxJump (ifx, "c");
6315       goto release;
6316     }
6317
6318   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6319   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6320   if ((AOP_TYPE (right) == AOP_LIT) &&
6321       (AOP_TYPE (result) == AOP_CRY) &&
6322       (AOP_TYPE (left) != AOP_CRY))
6323     {
6324       int posbit = isLiteralBit (lit);
6325       /* left &  2^n */
6326       if (posbit)
6327         {
6328           posbit--;
6329           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6330           // bit = left & 2^n
6331           if (size)
6332             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6333           // if(left &  2^n)
6334           else
6335             {
6336               if (ifx)
6337                 {
6338                   SNPRINTF (buff, sizeof(buff), 
6339                             "acc.%d", posbit & 0x07);
6340                   genIfxJump (ifx, buff);
6341                 }
6342               else 
6343                   {
6344                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6345                   }
6346               goto release;
6347             }
6348         }
6349       else
6350         {
6351           symbol *tlbl = newiTempLabel (NULL);
6352           int sizel = AOP_SIZE (left);
6353           if (size)
6354             emitcode ("setb", "c");
6355           while (sizel--)
6356             {
6357               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6358                 {
6359                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6360                   // byte ==  2^n ?
6361                   if ((posbit = isLiteralBit (bytelit)) != 0)
6362                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6363                   else
6364                     {
6365                       if (bytelit != 0x0FFL)
6366                         emitcode ("anl", "a,%s",
6367                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6368                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6369                     }
6370                 }
6371               offset++;
6372             }
6373           // bit = left & literal
6374           if (size)
6375             {
6376               emitcode ("clr", "c");
6377               emitcode ("", "!tlabeldef", tlbl->key + 100);
6378             }
6379           // if(left & literal)
6380           else
6381             {
6382               if (ifx)
6383                 jmpTrueOrFalse (ifx, tlbl);
6384               goto release;
6385             }
6386         }
6387       outBitC (result);
6388       goto release;
6389     }
6390
6391   /* if left is same as result */
6392   if (sameRegs (AOP (result), AOP (left)))
6393     {
6394       for (; size--; offset++)
6395         {
6396           if (AOP_TYPE (right) == AOP_LIT)
6397             {
6398               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6399                 continue;
6400               else if (bytelit == 0)
6401                 aopPut (AOP (result), zero, offset);
6402               else if (IS_AOP_PREG (result))
6403                 {
6404                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6405                   emitcode ("anl", "a,%s",
6406                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6407                   aopPut (AOP (result), "a", offset);
6408                 }
6409               else
6410                 emitcode ("anl", "%s,%s",
6411                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6412                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6413             }
6414           else
6415             {
6416               if (AOP_TYPE (left) == AOP_ACC)
6417                 emitcode ("anl", "a,%s",
6418                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6419               else
6420                 {
6421                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6422                   if (IS_AOP_PREG (result))
6423                     {
6424                       emitcode ("anl", "a,%s",
6425                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6426                       aopPut (AOP (result), "a", offset);
6427                     }
6428                   else
6429                     emitcode ("anl", "%s,a",
6430                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6431                 }
6432             }
6433         }
6434     }
6435   else
6436     {
6437       // left & result in different registers
6438       if (AOP_TYPE (result) == AOP_CRY)
6439         {
6440           // result = bit
6441           // if(size), result in bit
6442           // if(!size && ifx), conditional oper: if(left & right)
6443           symbol *tlbl = newiTempLabel (NULL);
6444           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6445           if (size)
6446             emitcode ("setb", "c");
6447           while (sizer--)
6448             {
6449               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6450                 emitcode ("anl", "a,%s",
6451                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6452               } else {
6453                 if (AOP_TYPE(left)==AOP_ACC) {
6454                   emitcode("mov", "b,a");
6455                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6456                   emitcode("anl", "a,b");
6457                 }else {
6458                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6459                   emitcode ("anl", "a,%s",
6460                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6461                 }
6462               }
6463               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6464               offset++;
6465             }
6466           if (size)
6467             {
6468               CLRC;
6469               emitcode ("", "!tlabeldef", tlbl->key + 100);
6470               outBitC (result);
6471             }
6472           else if (ifx)
6473             jmpTrueOrFalse (ifx, tlbl);
6474         }
6475       else
6476         {
6477           for (; (size--); offset++)
6478             {
6479               // normal case
6480               // result = left & right
6481               if (AOP_TYPE (right) == AOP_LIT)
6482                 {
6483                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6484                     {
6485                       aopPut (AOP (result),
6486                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6487                               offset);
6488                       continue;
6489                     }
6490                   else if (bytelit == 0)
6491                     {
6492                       aopPut (AOP (result), zero, offset);
6493                       continue;
6494                     }
6495                   D (emitcode (";", "better literal AND."););
6496                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6497                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6498                                                     FALSE, FALSE, DP2_RESULT_REG));
6499
6500                 }
6501               else
6502                 {
6503                   // faster than result <- left, anl result,right
6504                   // and better if result is SFR
6505                   if (AOP_TYPE (left) == AOP_ACC)
6506                     {
6507                       emitcode ("anl", "a,%s", 
6508                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6509                     }
6510                   else
6511                     {
6512                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6513                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6514                       {
6515                           emitcode("mov", "b,a");
6516                           rOp = "b";
6517                       }
6518                         
6519                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6520                       emitcode ("anl", "a,%s", rOp);
6521                     }                   
6522                 }
6523               aopPut (AOP (result), "a", offset);
6524             }
6525         }
6526     }
6527
6528 release:
6529   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6530   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6531   freeAsmop (result, NULL, ic, TRUE);
6532 }
6533
6534
6535 /*-----------------------------------------------------------------*/
6536 /* genOr  - code for or                                            */
6537 /*-----------------------------------------------------------------*/
6538 static void
6539 genOr (iCode * ic, iCode * ifx)
6540 {
6541   operand *left, *right, *result;
6542   int size, offset = 0;
6543   unsigned long lit = 0L;
6544   bool     pushResult;
6545
6546   D (emitcode (";", "genOr "););
6547
6548   AOP_OP_3_NOFATAL (ic, pushResult);
6549   AOP_SET_LOCALS (ic);
6550
6551   if (pushResult)
6552   {
6553       genFarFarLogicOp(ic, "orl");
6554       return;
6555   }
6556
6557
6558 #ifdef DEBUG_TYPE
6559   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6560             AOP_TYPE (result),
6561             AOP_TYPE (left), AOP_TYPE (right));
6562   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6563             AOP_SIZE (result),
6564             AOP_SIZE (left), AOP_SIZE (right));
6565 #endif
6566
6567   /* if left is a literal & right is not then exchange them */
6568   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6569 #ifdef LOGIC_OPS_BROKEN
6570    || AOP_NEEDSACC (left) // I think this is a net loss now.
6571 #endif      
6572       )
6573     {
6574       operand *tmp = right;
6575       right = left;
6576       left = tmp;
6577     }
6578
6579   /* if result = right then exchange them */
6580   if (sameRegs (AOP (result), AOP (right)))
6581     {
6582       operand *tmp = right;
6583       right = left;
6584       left = tmp;
6585     }
6586
6587   /* if right is bit then exchange them */
6588   if (AOP_TYPE (right) == AOP_CRY &&
6589       AOP_TYPE (left) != AOP_CRY)
6590     {
6591       operand *tmp = right;
6592       right = left;
6593       left = tmp;
6594     }
6595   if (AOP_TYPE (right) == AOP_LIT)
6596     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6597
6598   size = AOP_SIZE (result);
6599
6600   // if(bit | yy)
6601   // xx = bit | yy;
6602   if (AOP_TYPE (left) == AOP_CRY)
6603     {
6604       if (AOP_TYPE (right) == AOP_LIT)
6605         {
6606           // c = bit & literal;
6607           if (lit)
6608             {
6609               // lit != 0 => result = 1
6610               if (AOP_TYPE (result) == AOP_CRY)
6611                 {
6612                   if (size)
6613                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6614                   else if (ifx)
6615                     continueIfTrue (ifx);
6616                   goto release;
6617                 }
6618               emitcode ("setb", "c");
6619             }
6620           else
6621             {
6622               // lit == 0 => result = left
6623               if (size && sameRegs (AOP (result), AOP (left)))
6624                 goto release;
6625               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6626             }
6627         }
6628       else
6629         {
6630           if (AOP_TYPE (right) == AOP_CRY)
6631             {
6632               // c = bit | bit;
6633               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6634               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6635             }
6636           else
6637             {
6638               // c = bit | val;
6639               symbol *tlbl = newiTempLabel (NULL);
6640               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6641                 emitcode ("setb", "c");
6642               emitcode ("jb", "%s,!tlabel",
6643                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6644               toBoolean (right);
6645               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6646               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6647                 {
6648                   jmpTrueOrFalse (ifx, tlbl);
6649                   goto release;
6650                 }
6651               else
6652                 {
6653                   CLRC;
6654                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6655                 }
6656             }
6657         }
6658       // bit = c
6659       // val = c
6660       if (size)
6661         outBitC (result);
6662       // if(bit | ...)
6663       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6664            genIfxJump (ifx, "c");
6665       goto release;
6666     }
6667
6668   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6669   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6670   if ((AOP_TYPE (right) == AOP_LIT) &&
6671       (AOP_TYPE (result) == AOP_CRY) &&
6672       (AOP_TYPE (left) != AOP_CRY))
6673     {
6674       if (lit)
6675         {
6676           // result = 1
6677           if (size)
6678             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6679           else
6680             continueIfTrue (ifx);
6681           goto release;
6682         }
6683       else
6684         {
6685           // lit = 0, result = boolean(left)
6686           if (size)
6687             emitcode ("setb", "c");
6688           toBoolean (right);
6689           if (size)
6690             {
6691               symbol *tlbl = newiTempLabel (NULL);
6692               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6693               CLRC;
6694               emitcode ("", "!tlabeldef", tlbl->key + 100);
6695             }
6696           else
6697             {
6698               genIfxJump (ifx, "a");
6699               goto release;
6700             }
6701         }
6702       outBitC (result);
6703       goto release;
6704     }
6705
6706   /* if left is same as result */
6707   if (sameRegs (AOP (result), AOP (left)))
6708     {
6709       for (; size--; offset++)
6710         {
6711           if (AOP_TYPE (right) == AOP_LIT)
6712             {
6713               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6714                 {
6715                   continue;
6716                 }
6717               else
6718                 {
6719                   if (IS_AOP_PREG (left))
6720                     {
6721                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6722                       emitcode ("orl", "a,%s",
6723                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6724                       aopPut (AOP (result), "a", offset);
6725                     }
6726                   else
6727                     {
6728                       emitcode ("orl", "%s,%s",
6729                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6730                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6731                     }
6732                 }
6733             }
6734           else
6735             {
6736               if (AOP_TYPE (left) == AOP_ACC)
6737                 {
6738                   emitcode ("orl", "a,%s",
6739                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6740                 }
6741               else
6742                 {
6743                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6744                   if (IS_AOP_PREG (left))
6745                     {
6746                       emitcode ("orl", "a,%s", 
6747                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6748                       aopPut (AOP (result), "a", offset);
6749                     }
6750                   else
6751                     {
6752                       emitcode ("orl", "%s,a",
6753                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6754                     }
6755                 }
6756             }
6757         }
6758     }
6759   else
6760     {
6761       // left & result in different registers
6762       if (AOP_TYPE (result) == AOP_CRY)
6763         {
6764           // result = bit
6765           // if(size), result in bit
6766           // if(!size && ifx), conditional oper: if(left | right)
6767           symbol *tlbl = newiTempLabel (NULL);
6768           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6769           if (size)
6770             emitcode ("setb", "c");
6771           while (sizer--)
6772             {
6773               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6774                 emitcode ("orl", "a,%s",
6775                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6776               } else {
6777                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6778                 emitcode ("orl", "a,%s",
6779                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6780               }
6781               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6782               offset++;
6783             }
6784           if (size)
6785             {
6786               CLRC;
6787               emitcode ("", "!tlabeldef", tlbl->key + 100);
6788               outBitC (result);
6789             }
6790           else if (ifx)
6791             jmpTrueOrFalse (ifx, tlbl);
6792         }
6793       else
6794         {
6795             _startLazyDPSEvaluation();
6796           for (; (size--); offset++)
6797             {
6798               // normal case
6799               // result = left & right
6800               if (AOP_TYPE (right) == AOP_LIT)
6801                 {
6802                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6803                     {
6804                       aopPut (AOP (result),
6805                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6806                               offset);
6807                       continue;
6808                     }
6809                   D (emitcode (";", "better literal OR."););
6810                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6811                   emitcode ("orl", "a, %s",
6812                             aopGet (AOP (right), offset,
6813                                     FALSE, FALSE, DP2_RESULT_REG));
6814
6815                 }
6816               else
6817                 {
6818                   // faster than result <- left, anl result,right
6819                   // and better if result is SFR
6820                   if (AOP_TYPE (left) == AOP_ACC)
6821                     {
6822                       emitcode ("orl", "a,%s",
6823                                 aopGet (AOP (right), offset,
6824                                         FALSE, FALSE, DP2_RESULT_REG));
6825                     }
6826                   else
6827                     {
6828                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6829                         
6830                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6831                       {
6832                           emitcode("mov", "b,a");
6833                           rOp = "b";
6834                       }
6835                         
6836                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6837                       emitcode ("orl", "a,%s", rOp);
6838                     }
6839                 }
6840               aopPut (AOP (result), "a", offset);
6841             }
6842             _endLazyDPSEvaluation();
6843         }
6844     }
6845
6846 release:
6847   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6848   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6849   freeAsmop (result, NULL, ic, TRUE);
6850 }
6851
6852 /*-----------------------------------------------------------------*/
6853 /* genXor - code for xclusive or                                   */
6854 /*-----------------------------------------------------------------*/
6855 static void
6856 genXor (iCode * ic, iCode * ifx)
6857 {
6858   operand *left, *right, *result;
6859   int size, offset = 0;
6860   unsigned long lit = 0L;
6861   bool pushResult;
6862
6863   D (emitcode (";", "genXor "););
6864
6865   AOP_OP_3_NOFATAL (ic, pushResult);
6866   AOP_SET_LOCALS (ic);
6867
6868   if (pushResult)
6869   {
6870       genFarFarLogicOp(ic, "xrl");
6871       return;
6872   }  
6873
6874 #ifdef DEBUG_TYPE
6875   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6876             AOP_TYPE (result),
6877             AOP_TYPE (left), AOP_TYPE (right));
6878   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6879             AOP_SIZE (result),
6880             AOP_SIZE (left), AOP_SIZE (right));
6881 #endif
6882
6883   /* if left is a literal & right is not ||
6884      if left needs acc & right does not */
6885   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6886 #ifdef LOGIC_OPS_BROKEN      
6887       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6888 #endif
6889      )
6890     {
6891       operand *tmp = right;
6892       right = left;
6893       left = tmp;
6894     }
6895
6896   /* if result = right then exchange them */
6897   if (sameRegs (AOP (result), AOP (right)))
6898     {
6899       operand *tmp = right;
6900       right = left;
6901       left = tmp;
6902     }
6903
6904   /* if right is bit then exchange them */
6905   if (AOP_TYPE (right) == AOP_CRY &&
6906       AOP_TYPE (left) != AOP_CRY)
6907     {
6908       operand *tmp = right;
6909       right = left;
6910       left = tmp;
6911     }
6912   if (AOP_TYPE (right) == AOP_LIT)
6913     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6914
6915   size = AOP_SIZE (result);
6916
6917   // if(bit ^ yy)
6918   // xx = bit ^ yy;
6919   if (AOP_TYPE (left) == AOP_CRY)
6920     {
6921       if (AOP_TYPE (right) == AOP_LIT)
6922         {
6923           // c = bit & literal;
6924           if (lit >> 1)
6925             {
6926               // lit>>1  != 0 => result = 1
6927               if (AOP_TYPE (result) == AOP_CRY)
6928                 {
6929                   if (size)
6930                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6931                   else if (ifx)
6932                     continueIfTrue (ifx);
6933                   goto release;
6934                 }
6935               emitcode ("setb", "c");
6936             }
6937           else
6938             {
6939               // lit == (0 or 1)
6940               if (lit == 0)
6941                 {
6942                   // lit == 0, result = left
6943                   if (size && sameRegs (AOP (result), AOP (left)))
6944                     goto release;
6945                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6946                 }
6947               else
6948                 {
6949                   // lit == 1, result = not(left)
6950                   if (size && sameRegs (AOP (result), AOP (left)))
6951                     {
6952                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6953                       goto release;
6954                     }
6955                   else
6956                     {
6957                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6958                       emitcode ("cpl", "c");
6959                     }
6960                 }
6961             }
6962
6963         }
6964       else
6965         {
6966           // right != literal
6967           symbol *tlbl = newiTempLabel (NULL);
6968           if (AOP_TYPE (right) == AOP_CRY)
6969             {
6970               // c = bit ^ bit;
6971               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6972             }
6973           else
6974             {
6975               int sizer = AOP_SIZE (right);
6976               // c = bit ^ val
6977               // if val>>1 != 0, result = 1
6978               emitcode ("setb", "c");
6979               while (sizer)
6980                 {
6981                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6982                   if (sizer == 1)
6983                     // test the msb of the lsb
6984                     emitcode ("anl", "a,#!constbyte",0xfe);
6985                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6986                   sizer--;
6987                 }
6988               // val = (0,1)
6989               emitcode ("rrc", "a");
6990             }
6991           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6992           emitcode ("cpl", "c");
6993           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6994         }
6995       // bit = c
6996       // val = c
6997       if (size)
6998         outBitC (result);
6999       // if(bit | ...)
7000       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7001         genIfxJump (ifx, "c");
7002       goto release;
7003     }
7004
7005   if (sameRegs (AOP (result), AOP (left)))
7006     {
7007       /* if left is same as result */
7008       for (; size--; offset++)
7009         {
7010           if (AOP_TYPE (right) == AOP_LIT)
7011             {
7012               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7013                 continue;
7014               else if (IS_AOP_PREG (left))
7015                 {
7016                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7017                   emitcode ("xrl", "a,%s",
7018                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7019                   aopPut (AOP (result), "a", offset);
7020                 }
7021               else
7022                 emitcode ("xrl", "%s,%s",
7023                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7024                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7025             }
7026           else
7027             {
7028               if (AOP_TYPE (left) == AOP_ACC)
7029                 emitcode ("xrl", "a,%s",
7030                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7031               else
7032                 {
7033                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7034                   if (IS_AOP_PREG (left))
7035                     {
7036                       emitcode ("xrl", "a,%s",
7037                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7038                       aopPut (AOP (result), "a", offset);
7039                     }
7040                   else
7041                     emitcode ("xrl", "%s,a",
7042                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7043                 }
7044             }
7045         }
7046     }
7047   else
7048     {
7049       // left & result in different registers
7050       if (AOP_TYPE (result) == AOP_CRY)
7051         {
7052           // result = bit
7053           // if(size), result in bit
7054           // if(!size && ifx), conditional oper: if(left ^ right)
7055           symbol *tlbl = newiTempLabel (NULL);
7056           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7057                   
7058           if (size)
7059             emitcode ("setb", "c");
7060           while (sizer--)
7061             {
7062               if ((AOP_TYPE (right) == AOP_LIT) &&
7063                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7064                 {
7065                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7066                 }
7067               else
7068                 {
7069                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7070                     emitcode ("xrl", "a,%s",
7071                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7072                   } else {
7073                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7074                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7075                       {
7076                           emitcode("mov", "b,a");
7077                           rOp = "b";
7078                       }
7079                         
7080                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7081                       emitcode ("xrl", "a,%s", rOp);                  
7082                   }
7083                 }
7084               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7085               offset++;
7086             }
7087           if (size)
7088             {
7089               CLRC;
7090               emitcode ("", "!tlabeldef", tlbl->key + 100);
7091               outBitC (result);
7092             }
7093           else if (ifx)
7094             jmpTrueOrFalse (ifx, tlbl);
7095         }
7096       else
7097         {
7098         for (; (size--); offset++)
7099           {
7100             // normal case
7101             // result = left & right
7102             if (AOP_TYPE (right) == AOP_LIT)
7103               {
7104                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7105                   {
7106                     aopPut (AOP (result),
7107                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7108                             offset);
7109                     continue;
7110                   }
7111                 D (emitcode (";", "better literal XOR."););
7112                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7113                 emitcode ("xrl", "a, %s",
7114                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7115               }
7116             else
7117               {
7118                 // faster than result <- left, anl result,right
7119                 // and better if result is SFR
7120                 if (AOP_TYPE (left) == AOP_ACC)
7121                   {
7122                     emitcode ("xrl", "a,%s",
7123                               aopGet (AOP (right), offset,
7124                                       FALSE, FALSE, DP2_RESULT_REG));
7125                   }
7126                 else
7127                   {
7128                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7129                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7130                       {
7131                           emitcode("mov", "b,a");
7132                           rOp = "b";
7133                       }
7134                         
7135                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7136                       emitcode ("xrl", "a,%s", rOp);
7137                   }
7138               }
7139             aopPut (AOP (result), "a", offset);
7140           }
7141         }
7142         
7143     }
7144
7145 release:
7146   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7147   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7148   freeAsmop (result, NULL, ic, TRUE);
7149 }
7150
7151 /*-----------------------------------------------------------------*/
7152 /* genInline - write the inline code out                           */
7153 /*-----------------------------------------------------------------*/
7154 static void
7155 genInline (iCode * ic)
7156 {
7157   char *buffer, *bp, *bp1;
7158
7159   D (emitcode (";", "genInline "); );
7160
7161   _G.inLine += (!options.asmpeep);
7162
7163   buffer = Safe_strdup(IC_INLINE(ic));
7164   bp = buffer;
7165   bp1 = buffer;
7166
7167   /* emit each line as a code */
7168   while (*bp)
7169     {
7170       if (*bp == '\n')
7171         {
7172           *bp++ = '\0';
7173           emitcode (bp1, "");
7174           bp1 = bp;
7175         }
7176       else
7177         {
7178           if (*bp == ':')
7179             {
7180               bp++;
7181               *bp = '\0';
7182               bp++;
7183               emitcode (bp1, "");
7184               bp1 = bp;
7185             }
7186           else
7187             bp++;
7188         }
7189     }
7190   if (bp1 != bp)
7191     emitcode (bp1, "");
7192   /*     emitcode("",buffer); */
7193   _G.inLine -= (!options.asmpeep);
7194 }
7195
7196 /*-----------------------------------------------------------------*/
7197 /* genRRC - rotate right with carry                                */
7198 /*-----------------------------------------------------------------*/
7199 static void
7200 genRRC (iCode * ic)
7201 {
7202   operand *left, *result;
7203   int     size, offset;
7204
7205   D (emitcode (";", "genRRC "););
7206
7207   /* rotate right with carry */
7208   left = IC_LEFT (ic);
7209   result = IC_RESULT (ic);
7210   aopOp (left, ic, FALSE, FALSE);
7211   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7212
7213   /* move it to the result */
7214   size = AOP_SIZE (result);
7215   offset = size - 1;
7216   CLRC;
7217
7218   _startLazyDPSEvaluation ();
7219   while (size--)
7220     {
7221       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7222       emitcode ("rrc", "a");
7223       if (AOP_SIZE (result) > 1)
7224         aopPut (AOP (result), "a", offset--);
7225     }
7226   _endLazyDPSEvaluation ();
7227
7228   /* now we need to put the carry into the
7229      highest order byte of the result */
7230   if (AOP_SIZE (result) > 1)
7231     {
7232       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7233     }
7234   emitcode ("mov", "acc.7,c");
7235   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7236   freeAsmop (left, NULL, ic, TRUE);
7237   freeAsmop (result, NULL, ic, TRUE);
7238 }
7239
7240 /*-----------------------------------------------------------------*/
7241 /* genRLC - generate code for rotate left with carry               */
7242 /*-----------------------------------------------------------------*/
7243 static void
7244 genRLC (iCode * ic)
7245 {
7246   operand *left, *result;
7247   int size, offset;
7248   char *l;
7249
7250   D (emitcode (";", "genRLC "););
7251
7252   /* rotate right with carry */
7253   left = IC_LEFT (ic);
7254   result = IC_RESULT (ic);
7255   aopOp (left, ic, FALSE, FALSE);
7256   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7257
7258   /* move it to the result */
7259   size = AOP_SIZE (result);
7260   offset = 0;
7261   if (size--)
7262     {
7263       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7264       MOVA (l);
7265       emitcode ("add", "a,acc");
7266       if (AOP_SIZE (result) > 1)
7267         {
7268           aopPut (AOP (result), "a", offset++);
7269         }
7270
7271       _startLazyDPSEvaluation ();
7272       while (size--)
7273         {
7274           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7275           MOVA (l);
7276           emitcode ("rlc", "a");
7277           if (AOP_SIZE (result) > 1)
7278             aopPut (AOP (result), "a", offset++);
7279         }
7280       _endLazyDPSEvaluation ();
7281     }
7282   /* now we need to put the carry into the
7283      highest order byte of the result */
7284   if (AOP_SIZE (result) > 1)
7285     {
7286       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7287       MOVA (l);
7288     }
7289   emitcode ("mov", "acc.0,c");
7290   aopPut (AOP (result), "a", 0);
7291   freeAsmop (left, NULL, ic, TRUE);
7292   freeAsmop (result, NULL, ic, TRUE);
7293 }
7294
7295 /*-----------------------------------------------------------------*/
7296 /* genGetHbit - generates code get highest order bit               */
7297 /*-----------------------------------------------------------------*/
7298 static void
7299 genGetHbit (iCode * ic)
7300 {
7301   operand *left, *result;
7302   left = IC_LEFT (ic);
7303   result = IC_RESULT (ic);
7304   aopOp (left, ic, FALSE, FALSE);
7305   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7306
7307   D (emitcode (";", "genGetHbit "););
7308
7309   /* get the highest order byte into a */
7310   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7311   if (AOP_TYPE (result) == AOP_CRY)
7312     {
7313       emitcode ("rlc", "a");
7314       outBitC (result);
7315     }
7316   else
7317     {
7318       emitcode ("rl", "a");
7319       emitcode ("anl", "a,#1");
7320       outAcc (result);
7321     }
7322
7323
7324   freeAsmop (left, NULL, ic, TRUE);
7325   freeAsmop (result, NULL, ic, TRUE);
7326 }
7327
7328 /*-----------------------------------------------------------------*/
7329 /* AccRol - rotate left accumulator by known count                 */
7330 /*-----------------------------------------------------------------*/
7331 static void
7332 AccRol (int shCount)
7333 {
7334   shCount &= 0x0007;            // shCount : 0..7
7335
7336   switch (shCount)
7337     {
7338     case 0:
7339       break;
7340     case 1:
7341       emitcode ("rl", "a");
7342       break;
7343     case 2:
7344       emitcode ("rl", "a");
7345       emitcode ("rl", "a");
7346       break;
7347     case 3:
7348       emitcode ("swap", "a");
7349       emitcode ("rr", "a");
7350       break;
7351     case 4:
7352       emitcode ("swap", "a");
7353       break;
7354     case 5:
7355       emitcode ("swap", "a");
7356       emitcode ("rl", "a");
7357       break;
7358     case 6:
7359       emitcode ("rr", "a");
7360       emitcode ("rr", "a");
7361       break;
7362     case 7:
7363       emitcode ("rr", "a");
7364       break;
7365     }
7366 }
7367
7368 /*-----------------------------------------------------------------*/
7369 /* AccLsh - left shift accumulator by known count                  */
7370 /*-----------------------------------------------------------------*/
7371 static void
7372 AccLsh (int shCount)
7373 {
7374   if (shCount != 0)
7375     {
7376       if (shCount == 1)
7377         emitcode ("add", "a,acc");
7378       else if (shCount == 2)
7379         {
7380           emitcode ("add", "a,acc");
7381           emitcode ("add", "a,acc");
7382         }
7383       else
7384         {
7385           /* rotate left accumulator */
7386           AccRol (shCount);
7387           /* and kill the lower order bits */
7388           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7389         }
7390     }
7391 }
7392
7393 /*-----------------------------------------------------------------*/
7394 /* AccRsh - right shift accumulator by known count                 */
7395 /*-----------------------------------------------------------------*/
7396 static void
7397 AccRsh (int shCount)
7398 {
7399   if (shCount != 0)
7400     {
7401       if (shCount == 1)
7402         {
7403           CLRC;
7404           emitcode ("rrc", "a");
7405         }
7406       else
7407         {
7408           /* rotate right accumulator */
7409           AccRol (8 - shCount);
7410           /* and kill the higher order bits */
7411           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7412         }
7413     }
7414 }
7415
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* AccSRsh - signed right shift accumulator by known count                 */
7419 /*-----------------------------------------------------------------*/
7420 static void
7421 AccSRsh (int shCount)
7422 {
7423   symbol *tlbl;
7424   if (shCount != 0)
7425     {
7426       if (shCount == 1)
7427         {
7428           emitcode ("mov", "c,acc.7");
7429           emitcode ("rrc", "a");
7430         }
7431       else if (shCount == 2)
7432         {
7433           emitcode ("mov", "c,acc.7");
7434           emitcode ("rrc", "a");
7435           emitcode ("mov", "c,acc.7");
7436           emitcode ("rrc", "a");
7437         }
7438       else
7439         {
7440           tlbl = newiTempLabel (NULL);
7441           /* rotate right accumulator */
7442           AccRol (8 - shCount);
7443           /* and kill the higher order bits */
7444           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7445           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7446           emitcode ("orl", "a,#!constbyte",
7447                     (unsigned char) ~SRMask[shCount]);
7448           emitcode ("", "!tlabeldef", tlbl->key + 100);
7449         }
7450     }
7451 }
7452 #endif
7453
7454 #ifdef BETTER_LITERAL_SHIFT
7455 /*-----------------------------------------------------------------*/
7456 /* shiftR1Left2Result - shift right one byte from left to result   */
7457 /*-----------------------------------------------------------------*/
7458 static void
7459 shiftR1Left2Result (operand * left, int offl,
7460                     operand * result, int offr,
7461                     int shCount, int sign)
7462 {
7463   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7464   /* shift right accumulator */
7465   if (sign)
7466     AccSRsh (shCount);
7467   else
7468     AccRsh (shCount);
7469   aopPut (AOP (result), "a", offr);
7470 }
7471 #endif
7472
7473 #ifdef BETTER_LITERAL_SHIFT
7474 /*-----------------------------------------------------------------*/
7475 /* shiftL1Left2Result - shift left one byte from left to result    */
7476 /*-----------------------------------------------------------------*/
7477 static void
7478 shiftL1Left2Result (operand * left, int offl,
7479                     operand * result, int offr, int shCount)
7480 {
7481   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7482   /* shift left accumulator */
7483   AccLsh (shCount);
7484   aopPut (AOP (result), "a", offr);
7485 }
7486 #endif
7487
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* movLeft2Result - move byte from left to result                  */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 movLeft2Result (operand * left, int offl,
7494                 operand * result, int offr, int sign)
7495 {
7496   char *l;
7497   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7498   {
7499       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7500
7501       if (*l == '@' && (IS_AOP_PREG (result)))
7502       {
7503           emitcode ("mov", "a,%s", l);
7504           aopPut (AOP (result), "a", offr);
7505       }
7506       else
7507       {
7508           if (!sign)
7509           {
7510             aopPut (AOP (result), l, offr);
7511           }
7512           else
7513             {
7514               /* MSB sign in acc.7 ! */
7515               if (getDataSize (left) == offl + 1)
7516                 {
7517                   emitcode ("mov", "a,%s", l);
7518                   aopPut (AOP (result), "a", offr);
7519                 }
7520             }
7521       }
7522   }
7523 }
7524 #endif
7525
7526 #ifdef BETTER_LITERAL_SHIFT
7527 /*-----------------------------------------------------------------*/
7528 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7529 /*-----------------------------------------------------------------*/
7530 static void
7531 AccAXRrl1 (char *x)
7532 {
7533   emitcode ("rrc", "a");
7534   emitcode ("xch", "a,%s", x);
7535   emitcode ("rrc", "a");
7536   emitcode ("xch", "a,%s", x);
7537 }
7538 #endif
7539
7540 #ifdef BETTER_LITERAL_SHIFT
7541 //REMOVE ME!!!
7542 /*-----------------------------------------------------------------*/
7543 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7544 /*-----------------------------------------------------------------*/
7545 static void
7546 AccAXLrl1 (char *x)
7547 {
7548   emitcode ("xch", "a,%s", x);
7549   emitcode ("rlc", "a");
7550   emitcode ("xch", "a,%s", x);
7551   emitcode ("rlc", "a");
7552 }
7553 #endif
7554
7555 #ifdef BETTER_LITERAL_SHIFT
7556 /*-----------------------------------------------------------------*/
7557 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7558 /*-----------------------------------------------------------------*/
7559 static void
7560 AccAXLsh1 (char *x)
7561 {
7562   emitcode ("xch", "a,%s", x);
7563   emitcode ("add", "a,acc");
7564   emitcode ("xch", "a,%s", x);
7565   emitcode ("rlc", "a");
7566 }
7567 #endif
7568
7569 #ifdef BETTER_LITERAL_SHIFT
7570 /*-----------------------------------------------------------------*/
7571 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7572 /*-----------------------------------------------------------------*/
7573 static void
7574 AccAXLsh (char *x, int shCount)
7575 {
7576   switch (shCount)
7577     {
7578     case 0:
7579       break;
7580     case 1:
7581       AccAXLsh1 (x);
7582       break;
7583     case 2:
7584       AccAXLsh1 (x);
7585       AccAXLsh1 (x);
7586       break;
7587     case 3:
7588     case 4:
7589     case 5:                     // AAAAABBB:CCCCCDDD
7590
7591       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7592
7593       emitcode ("anl", "a,#!constbyte",
7594                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7595
7596       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7597
7598       AccRol (shCount);         // DDDCCCCC:BBB00000
7599
7600       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7601
7602       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7603
7604       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7605
7606       emitcode ("anl", "a,#!constbyte",
7607                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7608
7609       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7610
7611       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7612
7613       break;
7614     case 6:                     // AAAAAABB:CCCCCCDD
7615       emitcode ("anl", "a,#!constbyte",
7616                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7617       emitcode ("mov", "c,acc.0");      // c = B
7618       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7619 #if 0
7620       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7621       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7622 #else
7623       emitcode("rrc","a"); 
7624       emitcode("xch","a,%s", x); 
7625       emitcode("rrc","a"); 
7626       emitcode("mov","c,acc.0"); //<< get correct bit 
7627       emitcode("xch","a,%s", x); 
7628
7629       emitcode("rrc","a"); 
7630       emitcode("xch","a,%s", x); 
7631       emitcode("rrc","a"); 
7632       emitcode("xch","a,%s", x); 
7633 #endif
7634       break;
7635     case 7:                     // a:x <<= 7
7636
7637       emitcode ("anl", "a,#!constbyte",
7638                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7639
7640       emitcode ("mov", "c,acc.0");      // c = B
7641
7642       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7643
7644       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7645
7646       break;
7647     default:
7648       break;
7649     }
7650 }
7651 #endif
7652
7653 #ifdef BETTER_LITERAL_SHIFT
7654 //REMOVE ME!!!
7655 /*-----------------------------------------------------------------*/
7656 /* AccAXRsh - right shift a:x known count (0..7)                   */
7657 /*-----------------------------------------------------------------*/
7658 static void
7659 AccAXRsh (char *x, int shCount)
7660 {
7661   switch (shCount)
7662     {
7663     case 0:
7664       break;
7665     case 1:
7666       CLRC;
7667       AccAXRrl1 (x);            // 0->a:x
7668
7669       break;
7670     case 2:
7671       CLRC;
7672       AccAXRrl1 (x);            // 0->a:x
7673
7674       CLRC;
7675       AccAXRrl1 (x);            // 0->a:x
7676
7677       break;
7678     case 3:
7679     case 4:
7680     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7681
7682       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7683
7684       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7685
7686       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7687
7688       emitcode ("anl", "a,#!constbyte",
7689                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7690
7691       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7692
7693       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7694
7695       emitcode ("anl", "a,#!constbyte",
7696                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7697
7698       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7699
7700       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7701
7702       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7703
7704       break;
7705     case 6:                     // AABBBBBB:CCDDDDDD
7706
7707       emitcode ("mov", "c,acc.7");
7708       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7709
7710       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7711
7712       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7713
7714       emitcode ("anl", "a,#!constbyte",
7715                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7716
7717       break;
7718     case 7:                     // ABBBBBBB:CDDDDDDD
7719
7720       emitcode ("mov", "c,acc.7");      // c = A
7721
7722       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7723
7724       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7725
7726       emitcode ("anl", "a,#!constbyte",
7727                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7728
7729       break;
7730     default:
7731       break;
7732     }
7733 }
7734 #endif
7735
7736 #ifdef BETTER_LITERAL_SHIFT
7737 /*-----------------------------------------------------------------*/
7738 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7739 /*-----------------------------------------------------------------*/
7740 static void
7741 AccAXRshS (char *x, int shCount)
7742 {
7743   symbol *tlbl;
7744   switch (shCount)
7745     {
7746     case 0:
7747       break;
7748     case 1:
7749       emitcode ("mov", "c,acc.7");
7750       AccAXRrl1 (x);            // s->a:x
7751
7752       break;
7753     case 2:
7754       emitcode ("mov", "c,acc.7");
7755       AccAXRrl1 (x);            // s->a:x
7756
7757       emitcode ("mov", "c,acc.7");
7758       AccAXRrl1 (x);            // s->a:x
7759
7760       break;
7761     case 3:
7762     case 4:
7763     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7764
7765       tlbl = newiTempLabel (NULL);
7766       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7767
7768       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7769
7770       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7771
7772       emitcode ("anl", "a,#!constbyte",
7773                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7774
7775       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7776
7777       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7778
7779       emitcode ("anl", "a,#!constbyte",
7780                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7781
7782       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7783
7784       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7785
7786       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7787
7788       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789       emitcode ("orl", "a,#!constbyte",
7790                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7791
7792       emitcode ("", "!tlabeldef", tlbl->key + 100);
7793       break;                    // SSSSAAAA:BBBCCCCC
7794
7795     case 6:                     // AABBBBBB:CCDDDDDD
7796
7797       tlbl = newiTempLabel (NULL);
7798       emitcode ("mov", "c,acc.7");
7799       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7800
7801       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7802
7803       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7804
7805       emitcode ("anl", "a,#!constbyte",
7806                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7807
7808       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7809       emitcode ("orl", "a,#!constbyte",
7810                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7811
7812       emitcode ("", "!tlabeldef", tlbl->key + 100);
7813       break;
7814     case 7:                     // ABBBBBBB:CDDDDDDD
7815
7816       tlbl = newiTempLabel (NULL);
7817       emitcode ("mov", "c,acc.7");      // c = A
7818
7819       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7820
7821       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7822
7823       emitcode ("anl", "a,#!constbyte",
7824                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7825
7826       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7827       emitcode ("orl", "a,#!constbyte",
7828                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7829
7830       emitcode ("", "!tlabeldef", tlbl->key + 100);
7831       break;
7832     default:
7833       break;
7834     }
7835 }
7836 #endif
7837
7838 #ifdef BETTER_LITERAL_SHIFT
7839 static void
7840 _loadLeftIntoAx(char    **lsb, 
7841                 operand *left, 
7842                 operand *result,
7843                 int     offl,
7844                 int     offr)
7845 {
7846   // Get the initial value from left into a pair of registers.
7847   // MSB must be in A, LSB can be any register.
7848   //
7849   // If the result is held in registers, it is an optimization
7850   // if the LSB can be held in the register which will hold the,
7851   // result LSB since this saves us from having to copy it into
7852   // the result following AccAXLsh.
7853   //
7854   // If the result is addressed indirectly, this is not a gain.
7855   if (AOP_NEEDSACC(result))
7856   {
7857        char *leftByte;
7858        
7859        _startLazyDPSEvaluation();
7860       if (AOP_TYPE(left) == AOP_DPTR2)
7861        {
7862            // Get MSB in A.
7863            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7864            // get LSB in DP2_RESULT_REG.
7865            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7866            assert(!strcmp(leftByte, DP2_RESULT_REG));
7867        }
7868        else
7869        {
7870            // get LSB into DP2_RESULT_REG
7871            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7872            if (strcmp(leftByte, DP2_RESULT_REG))
7873            {
7874                TR_AP("#7");
7875                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7876            }
7877            // And MSB in A.
7878            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7879            assert(strcmp(leftByte, DP2_RESULT_REG));
7880            MOVA(leftByte);
7881        }
7882        _endLazyDPSEvaluation();
7883        *lsb = DP2_RESULT_REG;
7884   }
7885   else
7886   {
7887       if (sameRegs (AOP (result), AOP (left)) &&
7888         ((offl + MSB16) == offr))
7889       {
7890           /* don't crash result[offr] */
7891           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7892           emitcode ("xch", "a,%s", 
7893                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7894       }
7895       else
7896       {
7897           movLeft2Result (left, offl, result, offr, 0);
7898           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7899       }
7900       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7901       assert(strcmp(*lsb,"a"));      
7902   }
7903 }
7904
7905 static void
7906 _storeAxResults(char    *lsb,
7907                 operand *result,
7908                 int     offr)
7909 {
7910   _startLazyDPSEvaluation();
7911   if (AOP_NEEDSACC(result))
7912   {
7913       /* We have to explicitly update the result LSB.
7914        */
7915       emitcode("xch","a,%s", lsb);
7916       aopPut(AOP(result), "a", offr);
7917       emitcode("mov","a,%s", lsb);
7918   }
7919   if (getDataSize (result) > 1)
7920   {
7921       aopPut (AOP (result), "a", offr + MSB16);
7922   }
7923   _endLazyDPSEvaluation();
7924 }
7925
7926 /*-----------------------------------------------------------------*/
7927 /* shiftL2Left2Result - shift left two bytes from left to result   */
7928 /*-----------------------------------------------------------------*/
7929 static void
7930 shiftL2Left2Result (operand * left, int offl,
7931                     operand * result, int offr, int shCount)
7932 {
7933   char *lsb;
7934
7935   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7936   
7937   AccAXLsh (lsb, shCount);
7938   
7939   _storeAxResults(lsb, result, offr);
7940 }
7941 #endif
7942
7943 #ifdef BETTER_LITERAL_SHIFT
7944 /*-----------------------------------------------------------------*/
7945 /* shiftR2Left2Result - shift right two bytes from left to result  */
7946 /*-----------------------------------------------------------------*/
7947 static void
7948 shiftR2Left2Result (operand * left, int offl,
7949                     operand * result, int offr,
7950                     int shCount, int sign)
7951 {
7952   char *lsb;
7953   
7954   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7955   
7956   /* a:x >> shCount (x = lsb(result)) */
7957   if (sign)
7958   {
7959      AccAXRshS(lsb, shCount);
7960   }
7961   else
7962   {
7963     AccAXRsh(lsb, shCount);
7964   }
7965   
7966   _storeAxResults(lsb, result, offr);
7967 }
7968 #endif
7969
7970 /*-----------------------------------------------------------------*/
7971 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 shiftLLeftOrResult (operand * left, int offl,
7975                     operand * result, int offr, int shCount)
7976 {
7977   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7978   /* shift left accumulator */
7979   AccLsh (shCount);
7980   /* or with result */
7981   emitcode ("orl", "a,%s",
7982             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7983   /* back to result */
7984   aopPut (AOP (result), "a", offr);
7985 }
7986
7987 #if 0
7988 //REMOVE ME!!!
7989 /*-----------------------------------------------------------------*/
7990 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7991 /*-----------------------------------------------------------------*/
7992 static void
7993 shiftRLeftOrResult (operand * left, int offl,
7994                     operand * result, int offr, int shCount)
7995 {
7996   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7997   /* shift right accumulator */
7998   AccRsh (shCount);
7999   /* or with result */
8000   emitcode ("orl", "a,%s",
8001             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8002   /* back to result */
8003   aopPut (AOP (result), "a", offr);
8004 }
8005 #endif
8006
8007 #ifdef BETTER_LITERAL_SHIFT
8008 /*-----------------------------------------------------------------*/
8009 /* genlshOne - left shift a one byte quantity by known count       */
8010 /*-----------------------------------------------------------------*/
8011 static void
8012 genlshOne (operand * result, operand * left, int shCount)
8013 {
8014   D (emitcode (";", "genlshOne "););
8015   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8016 }
8017 #endif
8018
8019 #ifdef BETTER_LITERAL_SHIFT
8020 /*-----------------------------------------------------------------*/
8021 /* genlshTwo - left shift two bytes by known amount != 0           */
8022 /*-----------------------------------------------------------------*/
8023 static void
8024 genlshTwo (operand * result, operand * left, int shCount)
8025 {
8026   int size;
8027
8028   D (emitcode (";", "genlshTwo "););
8029
8030   size = getDataSize (result);
8031
8032   /* if shCount >= 8 */
8033   if (shCount >= 8)
8034   {
8035       shCount -= 8;
8036
8037       _startLazyDPSEvaluation();
8038
8039       if (size > 1)
8040         {
8041           if (shCount)
8042           {
8043             _endLazyDPSEvaluation();
8044             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8045             aopPut (AOP (result), zero, LSB);       
8046           }
8047           else
8048           {
8049             movLeft2Result (left, LSB, result, MSB16, 0);
8050             aopPut (AOP (result), zero, LSB);
8051             _endLazyDPSEvaluation();
8052           }
8053         }
8054         else
8055         {
8056           aopPut (AOP (result), zero, LSB);
8057           _endLazyDPSEvaluation();
8058         }
8059   }
8060
8061   /*  1 <= shCount <= 7 */
8062   else
8063     {
8064       if (size == 1)
8065       {
8066         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8067       }
8068       else
8069       {
8070         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8071       }
8072     }
8073 }
8074 #endif
8075
8076 #if 0
8077 //REMOVE ME!!!
8078 /*-----------------------------------------------------------------*/
8079 /* shiftLLong - shift left one long from left to result            */
8080 /* offl = LSB or MSB16                                             */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 shiftLLong (operand * left, operand * result, int offr)
8084 {
8085   char *l;
8086   int size = AOP_SIZE (result);
8087
8088   if (size >= LSB + offr)
8089     {
8090       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8091       MOVA (l);
8092       emitcode ("add", "a,acc");
8093       if (sameRegs (AOP (left), AOP (result)) &&
8094           size >= MSB16 + offr && offr != LSB)
8095         emitcode ("xch", "a,%s",
8096                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8097       else
8098         aopPut (AOP (result), "a", LSB + offr);
8099     }
8100
8101   if (size >= MSB16 + offr)
8102     {
8103       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8104         {
8105           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8106         }
8107       emitcode ("rlc", "a");
8108       if (sameRegs (AOP (left), AOP (result)) &&
8109           size >= MSB24 + offr && offr != LSB)
8110         emitcode ("xch", "a,%s",
8111                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8112       else
8113         aopPut (AOP (result), "a", MSB16 + offr);
8114     }
8115
8116   if (size >= MSB24 + offr)
8117     {
8118       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8119         {
8120           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8121         }
8122       emitcode ("rlc", "a");
8123       if (sameRegs (AOP (left), AOP (result)) &&
8124           size >= MSB32 + offr && offr != LSB)
8125         emitcode ("xch", "a,%s",
8126                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8127       else
8128         aopPut (AOP (result), "a", MSB24 + offr);
8129     }
8130
8131   if (size > MSB32 + offr)
8132     {
8133       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8134         {
8135           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8136         }
8137       emitcode ("rlc", "a");
8138       aopPut (AOP (result), "a", MSB32 + offr);
8139     }
8140   if (offr != LSB)
8141     aopPut (AOP (result), zero, LSB);
8142 }
8143 #endif
8144
8145 #if 0
8146 //REMOVE ME!!!
8147 /*-----------------------------------------------------------------*/
8148 /* genlshFour - shift four byte by a known amount != 0             */
8149 /*-----------------------------------------------------------------*/
8150 static void
8151 genlshFour (operand * result, operand * left, int shCount)
8152 {
8153   int size;
8154
8155   D (emitcode (";", "genlshFour ");
8156     );
8157
8158   size = AOP_SIZE (result);
8159
8160   /* if shifting more that 3 bytes */
8161   if (shCount >= 24)
8162     {
8163       shCount -= 24;
8164       if (shCount)
8165         /* lowest order of left goes to the highest
8166            order of the destination */
8167         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8168       else
8169         movLeft2Result (left, LSB, result, MSB32, 0);
8170       aopPut (AOP (result), zero, LSB);
8171       aopPut (AOP (result), zero, MSB16);
8172       aopPut (AOP (result), zero, MSB24);
8173       return;
8174     }
8175
8176   /* more than two bytes */
8177   else if (shCount >= 16)
8178     {
8179       /* lower order two bytes goes to higher order two bytes */
8180       shCount -= 16;
8181       /* if some more remaining */
8182       if (shCount)
8183         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8184       else
8185         {
8186           movLeft2Result (left, MSB16, result, MSB32, 0);
8187           movLeft2Result (left, LSB, result, MSB24, 0);
8188         }
8189       aopPut (AOP (result), zero, MSB16);
8190       aopPut (AOP (result), zero, LSB);
8191       return;
8192     }
8193
8194   /* if more than 1 byte */
8195   else if (shCount >= 8)
8196     {
8197       /* lower order three bytes goes to higher order  three bytes */
8198       shCount -= 8;
8199       if (size == 2)
8200         {
8201           if (shCount)
8202             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8203           else
8204             movLeft2Result (left, LSB, result, MSB16, 0);
8205         }
8206       else
8207         {                       /* size = 4 */
8208           if (shCount == 0)
8209             {
8210               movLeft2Result (left, MSB24, result, MSB32, 0);
8211               movLeft2Result (left, MSB16, result, MSB24, 0);
8212               movLeft2Result (left, LSB, result, MSB16, 0);
8213               aopPut (AOP (result), zero, LSB);
8214             }
8215           else if (shCount == 1)
8216             shiftLLong (left, result, MSB16);
8217           else
8218             {
8219               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8220               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8221               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8222               aopPut (AOP (result), zero, LSB);
8223             }
8224         }
8225     }
8226
8227   /* 1 <= shCount <= 7 */
8228   else if (shCount <= 2)
8229     {
8230       shiftLLong (left, result, LSB);
8231       if (shCount == 2)
8232         shiftLLong (result, result, LSB);
8233     }
8234   /* 3 <= shCount <= 7, optimize */
8235   else
8236     {
8237       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8238       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8239       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8240     }
8241 }
8242 #endif
8243
8244 #ifdef BETTER_LITERAL_SHIFT
8245 /*-----------------------------------------------------------------*/
8246 /* genLeftShiftLiteral - left shifting by known count              */
8247 /*-----------------------------------------------------------------*/
8248 static bool
8249 genLeftShiftLiteral (operand * left,
8250                      operand * right,
8251                      operand * result,
8252                      iCode * ic)
8253 {
8254   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8255   int size;
8256
8257   size = getSize (operandType (result));
8258
8259   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8260
8261   /* We only handle certain easy cases so far. */
8262   if ((shCount != 0)
8263    && (shCount < (size * 8))
8264    && (size != 1)
8265    && (size != 2))
8266   {
8267       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8268       return FALSE;
8269   }
8270
8271   freeAsmop (right, NULL, ic, TRUE);
8272
8273   aopOp(left, ic, FALSE, FALSE);
8274   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8275
8276 #if 0 // debug spew
8277   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8278   {
8279         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8280         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8281         {
8282            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8283         }
8284   }
8285   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8286   {
8287         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8288         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8289         {
8290            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8291         }       
8292   }  
8293 #endif
8294   
8295 #if VIEW_SIZE
8296   emitcode ("; shift left ", "result %d, left %d", size,
8297             AOP_SIZE (left));
8298 #endif
8299
8300   /* I suppose that the left size >= result size */
8301   if (shCount == 0)
8302   {
8303         _startLazyDPSEvaluation();
8304         while (size--)
8305         {
8306           movLeft2Result (left, size, result, size, 0);
8307         }
8308         _endLazyDPSEvaluation();
8309   }
8310   else if (shCount >= (size * 8))
8311   {
8312     _startLazyDPSEvaluation();
8313     while (size--)
8314     {
8315       aopPut (AOP (result), zero, size);
8316     }
8317     _endLazyDPSEvaluation();
8318   }
8319   else
8320   {
8321       switch (size)
8322         {
8323         case 1:
8324           genlshOne (result, left, shCount);
8325           break;
8326
8327         case 2:
8328           genlshTwo (result, left, shCount);
8329           break;
8330 #if 0
8331         case 4:
8332           genlshFour (result, left, shCount);
8333           break;
8334 #endif
8335         default:
8336           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8337           break;
8338         }
8339     }
8340   freeAsmop (left, NULL, ic, TRUE);
8341   freeAsmop (result, NULL, ic, TRUE);
8342   return TRUE;
8343 }
8344 #endif
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genLeftShift - generates code for left shifting                 */
8348 /*-----------------------------------------------------------------*/
8349 static void
8350 genLeftShift (iCode * ic)
8351 {
8352   operand *left, *right, *result;
8353   int size, offset;
8354   char *l;
8355   symbol *tlbl, *tlbl1;
8356
8357   D (emitcode (";", "genLeftShift "););
8358
8359   right = IC_RIGHT (ic);
8360   left = IC_LEFT (ic);
8361   result = IC_RESULT (ic);
8362
8363   aopOp (right, ic, FALSE, FALSE);
8364
8365
8366 #ifdef BETTER_LITERAL_SHIFT
8367   /* if the shift count is known then do it
8368      as efficiently as possible */
8369   if (AOP_TYPE (right) == AOP_LIT)
8370     {
8371       if (genLeftShiftLiteral (left, right, result, ic))
8372       {
8373         return;
8374       }
8375     }
8376 #endif
8377
8378   /* shift count is unknown then we have to form
8379      a loop get the loop count in B : Note: we take
8380      only the lower order byte since shifting
8381      more that 32 bits make no sense anyway, ( the
8382      largest size of an object can be only 32 bits ) */
8383
8384   if (AOP_TYPE (right) == AOP_LIT)
8385   {
8386       /* Really should be handled by genLeftShiftLiteral,
8387        * but since I'm too lazy to fix that today, at least we can make
8388        * some small improvement.
8389        */
8390        emitcode("mov", "b,#!constbyte",
8391                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8392   }
8393   else
8394   {
8395       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8396       emitcode ("inc", "b");
8397   }
8398   freeAsmop (right, NULL, ic, TRUE);
8399   aopOp (left, ic, FALSE, FALSE);
8400   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8401
8402   /* now move the left to the result if they are not the
8403      same */
8404   if (!sameRegs (AOP (left), AOP (result)) &&
8405       AOP_SIZE (result) > 1)
8406     {
8407
8408       size = AOP_SIZE (result);
8409       offset = 0;
8410       _startLazyDPSEvaluation ();
8411       while (size--)
8412         {
8413           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8414           if (*l == '@' && (IS_AOP_PREG (result)))
8415             {
8416
8417               emitcode ("mov", "a,%s", l);
8418               aopPut (AOP (result), "a", offset);
8419             }
8420           else
8421             aopPut (AOP (result), l, offset);
8422           offset++;
8423         }
8424       _endLazyDPSEvaluation ();
8425     }
8426
8427   tlbl = newiTempLabel (NULL);
8428   size = AOP_SIZE (result);
8429   offset = 0;
8430   tlbl1 = newiTempLabel (NULL);
8431
8432   /* if it is only one byte then */
8433   if (size == 1)
8434     {
8435       symbol *tlbl1 = newiTempLabel (NULL);
8436
8437       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8438       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8439       emitcode ("", "!tlabeldef", tlbl->key + 100);
8440       emitcode ("add", "a,acc");
8441       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8442       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8443       aopPut (AOP (result), "a", 0);
8444       goto release;
8445     }
8446
8447   reAdjustPreg (AOP (result));
8448
8449   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8450   emitcode ("", "!tlabeldef", tlbl->key + 100);
8451   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8452   emitcode ("add", "a,acc");
8453   aopPut (AOP (result), "a", offset++);
8454   _startLazyDPSEvaluation ();
8455   while (--size)
8456     {
8457       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8458       emitcode ("rlc", "a");
8459       aopPut (AOP (result), "a", offset++);
8460     }
8461   _endLazyDPSEvaluation ();
8462   reAdjustPreg (AOP (result));
8463
8464   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8465   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8466 release:
8467   freeAsmop (left, NULL, ic, TRUE);
8468   freeAsmop (result, NULL, ic, TRUE);
8469 }
8470
8471 #ifdef BETTER_LITERAL_SHIFT
8472 /*-----------------------------------------------------------------*/
8473 /* genrshOne - right shift a one byte quantity by known count      */
8474 /*-----------------------------------------------------------------*/
8475 static void
8476 genrshOne (operand * result, operand * left,
8477            int shCount, int sign)
8478 {
8479   D (emitcode (";", "genrshOne"););
8480   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8481 }
8482 #endif
8483
8484 #ifdef BETTER_LITERAL_SHIFT
8485 /*-----------------------------------------------------------------*/
8486 /* genrshTwo - right shift two bytes by known amount != 0          */
8487 /*-----------------------------------------------------------------*/
8488 static void
8489 genrshTwo (operand * result, operand * left,
8490            int shCount, int sign)
8491 {
8492   D (emitcode (";", "genrshTwo"););
8493
8494   /* if shCount >= 8 */
8495   if (shCount >= 8)
8496     {
8497       shCount -= 8;
8498       _startLazyDPSEvaluation();
8499       if (shCount)
8500       {
8501         shiftR1Left2Result (left, MSB16, result, LSB,
8502                             shCount, sign);
8503       }                     
8504       else
8505       {
8506         movLeft2Result (left, MSB16, result, LSB, sign);
8507       }
8508       addSign (result, MSB16, sign);
8509       _endLazyDPSEvaluation();
8510     }
8511
8512   /*  1 <= shCount <= 7 */
8513   else
8514   {
8515     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8516   }
8517 }
8518 #endif
8519
8520 /*-----------------------------------------------------------------*/
8521 /* shiftRLong - shift right one long from left to result           */
8522 /* offl = LSB or MSB16                                             */
8523 /*-----------------------------------------------------------------*/
8524 static void
8525 shiftRLong (operand * left, int offl,
8526             operand * result, int sign)
8527 {
8528   int isSameRegs=sameRegs(AOP(left),AOP(result));
8529
8530   if (isSameRegs && offl>1) {
8531     // we are in big trouble, but this shouldn't happen
8532     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8533   }
8534
8535   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8536   
8537   if (offl==MSB16) {
8538     // shift is > 8
8539     if (sign) {
8540       emitcode ("rlc", "a");
8541       emitcode ("subb", "a,acc");
8542       emitcode ("xch", "a,%s",
8543                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8544     } else {
8545       aopPut (AOP(result), zero, MSB32);
8546     }
8547   }
8548
8549   if (!sign) {
8550     emitcode ("clr", "c");
8551   } else {
8552     emitcode ("mov", "c,acc.7");
8553   }
8554
8555   emitcode ("rrc", "a");
8556
8557   if (isSameRegs && offl==MSB16) {
8558     emitcode ("xch",
8559               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8560   } else {
8561     aopPut (AOP (result), "a", MSB32);
8562     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8563   }
8564
8565   emitcode ("rrc", "a");
8566   if (isSameRegs && offl==1) {
8567     emitcode ("xch", "a,%s",
8568               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8569   } else {
8570     aopPut (AOP (result), "a", MSB24);
8571     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8572   }
8573   emitcode ("rrc", "a");
8574   aopPut (AOP (result), "a", MSB16 - offl);
8575
8576   if (offl == LSB)
8577     {
8578       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8579       emitcode ("rrc", "a");
8580       aopPut (AOP (result), "a", LSB);
8581     }
8582 }
8583
8584 /*-----------------------------------------------------------------*/
8585 /* genrshFour - shift four byte by a known amount != 0             */
8586 /*-----------------------------------------------------------------*/
8587 static void
8588 genrshFour (operand * result, operand * left,
8589             int shCount, int sign)
8590 {
8591   D (emitcode (";", "genrshFour"););
8592
8593   /* if shifting more that 3 bytes */
8594   if (shCount >= 24)
8595     {
8596       shCount -= 24;
8597       _startLazyDPSEvaluation();
8598       if (shCount)
8599         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8600       else
8601         movLeft2Result (left, MSB32, result, LSB, sign);
8602       addSign (result, MSB16, sign);
8603       _endLazyDPSEvaluation();
8604     }
8605   else if (shCount >= 16)
8606     {
8607       shCount -= 16;
8608       _startLazyDPSEvaluation();
8609       if (shCount)
8610         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8611       else
8612         {
8613           movLeft2Result (left, MSB24, result, LSB, 0);
8614           movLeft2Result (left, MSB32, result, MSB16, sign);
8615         }
8616       addSign (result, MSB24, sign);
8617       _endLazyDPSEvaluation();
8618     }
8619   else if (shCount >= 8)
8620     {
8621       shCount -= 8;
8622       _startLazyDPSEvaluation();
8623       if (shCount == 1)
8624         {
8625             shiftRLong (left, MSB16, result, sign);
8626         }
8627       else if (shCount == 0)
8628         {
8629           movLeft2Result (left, MSB16, result, LSB, 0);
8630           movLeft2Result (left, MSB24, result, MSB16, 0);
8631           movLeft2Result (left, MSB32, result, MSB24, sign);
8632           addSign (result, MSB32, sign);
8633         }
8634       else
8635         {
8636           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8637           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8638           /* the last shift is signed */
8639           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8640           addSign (result, MSB32, sign);
8641         }
8642         _endLazyDPSEvaluation();
8643     }
8644   else
8645     {   
8646         /* 1 <= shCount <= 7 */
8647       if (shCount <= 2)
8648         {
8649           shiftRLong (left, LSB, result, sign);
8650           if (shCount == 2)
8651             shiftRLong (result, LSB, result, sign);
8652         }
8653       else
8654         {
8655           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8656           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8657           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8658         }
8659     }
8660 }
8661
8662 #ifdef BETTER_LITERAL_SHIFT
8663 /*-----------------------------------------------------------------*/
8664 /* genRightShiftLiteral - right shifting by known count            */
8665 /*-----------------------------------------------------------------*/
8666 static bool
8667 genRightShiftLiteral (operand * left,
8668                       operand * right,
8669                       operand * result,
8670                       iCode * ic,
8671                       int sign)
8672 {
8673   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8674   int size;
8675
8676   size = getSize (operandType (result));
8677
8678   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8679
8680   /* We only handle certain easy cases so far. */
8681   if ((shCount != 0)
8682    && (shCount < (size * 8))
8683    && (size != 1)
8684    && (size != 2)
8685    && (size != 4))
8686   {
8687       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8688       return FALSE;
8689   }
8690
8691   freeAsmop (right, NULL, ic, TRUE);
8692
8693   aopOp (left, ic, FALSE, FALSE);
8694   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8695
8696 #if VIEW_SIZE
8697   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8698             AOP_SIZE (left));
8699 #endif
8700
8701   /* test the LEFT size !!! */
8702
8703   /* I suppose that the left size >= result size */
8704   if (shCount == 0)
8705   {
8706       size = getDataSize (result);
8707       _startLazyDPSEvaluation();
8708       while (size--)
8709       {
8710         movLeft2Result (left, size, result, size, 0);
8711       }
8712       _endLazyDPSEvaluation();
8713   }
8714   else if (shCount >= (size * 8))
8715     {
8716       if (sign)
8717       {
8718         /* get sign in acc.7 */
8719         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8720       }
8721       addSign (result, LSB, sign);
8722     }
8723   else
8724     {
8725       switch (size)
8726         {
8727         case 1:
8728           genrshOne (result, left, shCount, sign);
8729           break;
8730
8731         case 2:
8732           genrshTwo (result, left, shCount, sign);
8733           break;
8734 #if 1
8735         case 4:
8736           genrshFour (result, left, shCount, sign);
8737           break;
8738 #endif    
8739         default:
8740           break;
8741         }
8742     }
8743   freeAsmop (left, NULL, ic, TRUE);
8744   freeAsmop (result, NULL, ic, TRUE);
8745   
8746   return TRUE;
8747 }
8748 #endif
8749
8750 /*-----------------------------------------------------------------*/
8751 /* genSignedRightShift - right shift of signed number              */
8752 /*-----------------------------------------------------------------*/
8753 static void
8754 genSignedRightShift (iCode * ic)
8755 {
8756   operand *right, *left, *result;
8757   int size, offset;
8758   char *l;
8759   symbol *tlbl, *tlbl1;
8760
8761   D (emitcode (";", "genSignedRightShift "););
8762
8763   /* we do it the hard way put the shift count in b
8764      and loop thru preserving the sign */
8765
8766   right = IC_RIGHT (ic);
8767   left = IC_LEFT (ic);
8768   result = IC_RESULT (ic);
8769
8770   aopOp (right, ic, FALSE, FALSE);
8771
8772 #ifdef BETTER_LITERAL_SHIFT
8773   if (AOP_TYPE (right) == AOP_LIT)
8774     {
8775       if (genRightShiftLiteral (left, right, result, ic, 1))
8776       {
8777         return;
8778       }
8779     }
8780 #endif
8781   /* shift count is unknown then we have to form
8782      a loop get the loop count in B : Note: we take
8783      only the lower order byte since shifting
8784      more that 32 bits make no sense anyway, ( the
8785      largest size of an object can be only 32 bits ) */
8786
8787   if (AOP_TYPE (right) == AOP_LIT)
8788   {
8789       /* Really should be handled by genRightShiftLiteral,
8790        * but since I'm too lazy to fix that today, at least we can make
8791        * some small improvement.
8792        */
8793        emitcode("mov", "b,#!constbyte",
8794                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8795   }
8796   else
8797   {
8798         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8799         emitcode ("inc", "b");
8800   }
8801   freeAsmop (right, NULL, ic, TRUE);
8802   aopOp (left, ic, FALSE, FALSE);
8803   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8804
8805   /* now move the left to the result if they are not the
8806      same */
8807   if (!sameRegs (AOP (left), AOP (result)) &&
8808       AOP_SIZE (result) > 1)
8809     {
8810
8811       size = AOP_SIZE (result);
8812       offset = 0;
8813       _startLazyDPSEvaluation ();
8814       while (size--)
8815         {
8816           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8817           if (*l == '@' && IS_AOP_PREG (result))
8818             {
8819
8820               emitcode ("mov", "a,%s", l);
8821               aopPut (AOP (result), "a", offset);
8822             }
8823           else
8824             aopPut (AOP (result), l, offset);
8825           offset++;
8826         }
8827       _endLazyDPSEvaluation ();
8828     }
8829
8830   /* mov the highest order bit to OVR */
8831   tlbl = newiTempLabel (NULL);
8832   tlbl1 = newiTempLabel (NULL);
8833
8834   size = AOP_SIZE (result);
8835   offset = size - 1;
8836   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8837   emitcode ("rlc", "a");
8838   emitcode ("mov", "ov,c");
8839   /* if it is only one byte then */
8840   if (size == 1)
8841     {
8842       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8843       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8844       emitcode ("", "!tlabeldef", tlbl->key + 100);
8845       emitcode ("mov", "c,ov");
8846       emitcode ("rrc", "a");
8847       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8848       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8849       aopPut (AOP (result), "a", 0);
8850       goto release;
8851     }
8852
8853   reAdjustPreg (AOP (result));
8854   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8855   emitcode ("", "!tlabeldef", tlbl->key + 100);
8856   emitcode ("mov", "c,ov");
8857   _startLazyDPSEvaluation ();
8858   while (size--)
8859     {
8860       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8861       emitcode ("rrc", "a");
8862       aopPut (AOP (result), "a", offset--);
8863     }
8864   _endLazyDPSEvaluation ();
8865   reAdjustPreg (AOP (result));
8866   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8867   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8868
8869 release:
8870   freeAsmop (left, NULL, ic, TRUE);
8871   freeAsmop (result, NULL, ic, TRUE);
8872 }
8873
8874 /*-----------------------------------------------------------------*/
8875 /* genRightShift - generate code for right shifting                */
8876 /*-----------------------------------------------------------------*/
8877 static void
8878 genRightShift (iCode * ic)
8879 {
8880   operand *right, *left, *result;
8881   sym_link *retype;
8882   int size, offset;
8883   char *l;
8884   symbol *tlbl, *tlbl1;
8885
8886   D (emitcode (";", "genRightShift "););
8887
8888   /* if signed then we do it the hard way preserve the
8889      sign bit moving it inwards */
8890   retype = getSpec (operandType (IC_RESULT (ic)));
8891
8892   if (!SPEC_USIGN (retype))
8893     {
8894       genSignedRightShift (ic);
8895       return;
8896     }
8897
8898   /* signed & unsigned types are treated the same : i.e. the
8899      signed is NOT propagated inwards : quoting from the
8900      ANSI - standard : "for E1 >> E2, is equivalent to division
8901      by 2**E2 if unsigned or if it has a non-negative value,
8902      otherwise the result is implementation defined ", MY definition
8903      is that the sign does not get propagated */
8904
8905   right = IC_RIGHT (ic);
8906   left = IC_LEFT (ic);
8907   result = IC_RESULT (ic);
8908
8909   aopOp (right, ic, FALSE, FALSE);
8910
8911 #ifdef BETTER_LITERAL_SHIFT
8912   /* if the shift count is known then do it
8913      as efficiently as possible */
8914   if (AOP_TYPE (right) == AOP_LIT)
8915     {
8916       if (genRightShiftLiteral (left, right, result, ic, 0))
8917       {
8918         return;
8919       }
8920     }
8921 #endif
8922
8923   /* shift count is unknown then we have to form
8924      a loop get the loop count in B : Note: we take
8925      only the lower order byte since shifting
8926      more that 32 bits make no sense anyway, ( the
8927      largest size of an object can be only 32 bits ) */
8928   
8929   if (AOP_TYPE (right) == AOP_LIT)
8930   {
8931       /* Really should be handled by genRightShiftLiteral,
8932        * but since I'm too lazy to fix that today, at least we can make
8933        * some small improvement.
8934        */
8935        emitcode("mov", "b,#!constbyte",
8936                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8937   }
8938   else
8939   {
8940       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8941       emitcode ("inc", "b");
8942   }
8943   freeAsmop (right, NULL, ic, TRUE);
8944   aopOp (left, ic, FALSE, FALSE);
8945   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8946
8947   /* now move the left to the result if they are not the
8948      same */
8949   if (!sameRegs (AOP (left), AOP (result)) &&
8950       AOP_SIZE (result) > 1)
8951     {
8952
8953       size = AOP_SIZE (result);
8954       offset = 0;
8955       _startLazyDPSEvaluation ();
8956       while (size--)
8957         {
8958           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8959           if (*l == '@' && IS_AOP_PREG (result))
8960             {
8961
8962               emitcode ("mov", "a,%s", l);
8963               aopPut (AOP (result), "a", offset);
8964             }
8965           else
8966             aopPut (AOP (result), l, offset);
8967           offset++;
8968         }
8969       _endLazyDPSEvaluation ();
8970     }
8971
8972   tlbl = newiTempLabel (NULL);
8973   tlbl1 = newiTempLabel (NULL);
8974   size = AOP_SIZE (result);
8975   offset = size - 1;
8976
8977   /* if it is only one byte then */
8978   if (size == 1)
8979     {
8980       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8981       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8982       emitcode ("", "!tlabeldef", tlbl->key + 100);
8983       CLRC;
8984       emitcode ("rrc", "a");
8985       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8986       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8987       aopPut (AOP (result), "a", 0);
8988       goto release;
8989     }
8990
8991   reAdjustPreg (AOP (result));
8992   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8993   emitcode ("", "!tlabeldef", tlbl->key + 100);
8994   CLRC;
8995   _startLazyDPSEvaluation ();
8996   while (size--)
8997     {
8998       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8999       emitcode ("rrc", "a");
9000       aopPut (AOP (result), "a", offset--);
9001     }
9002   _endLazyDPSEvaluation ();
9003   reAdjustPreg (AOP (result));
9004
9005   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9006   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9007
9008 release:
9009   freeAsmop (left, NULL, ic, TRUE);
9010   freeAsmop (result, NULL, ic, TRUE);
9011 }
9012
9013
9014 /*-----------------------------------------------------------------*/
9015 /* emitPtrByteGet - emits code to get a byte into A through a      */
9016 /*                  pointer register (R0, R1, or DPTR). The        */
9017 /*                  original value of A can be preserved in B.     */
9018 /*-----------------------------------------------------------------*/
9019 static void
9020 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9021 {
9022   switch (p_type)
9023     {
9024     case IPOINTER:
9025     case POINTER:
9026       if (preserveAinB)
9027         emitcode ("mov", "b,a");
9028       emitcode ("mov", "a,@%s", rname);
9029       break;
9030
9031     case PPOINTER:
9032       if (preserveAinB)
9033         emitcode ("mov", "b,a");
9034       emitcode ("movx", "a,@%s", rname);
9035       break;
9036       
9037     case FPOINTER:
9038       if (preserveAinB)
9039         emitcode ("mov", "b,a");
9040       emitcode ("movx", "a,@dptr");
9041       break;
9042
9043     case CPOINTER:
9044       if (preserveAinB)
9045         emitcode ("mov", "b,a");
9046       emitcode ("clr", "a");
9047       emitcode ("movc", "a,@a+dptr");
9048       break;
9049
9050     case GPOINTER:
9051       if (preserveAinB)
9052         {
9053           emitcode ("push", "b");
9054           emitcode ("push", "acc");
9055         }
9056       emitcode ("lcall", "__gptrget");
9057       if (preserveAinB)
9058         emitcode ("pop", "b");
9059       break;
9060     }
9061 }
9062
9063 /*-----------------------------------------------------------------*/
9064 /* emitPtrByteSet - emits code to set a byte from src through a    */
9065 /*                  pointer register (R0, R1, or DPTR).            */
9066 /*-----------------------------------------------------------------*/
9067 static void
9068 emitPtrByteSet (char *rname, int p_type, char *src)
9069 {
9070   switch (p_type)
9071     {
9072     case IPOINTER:
9073     case POINTER:
9074       if (*src=='@')
9075         {
9076           MOVA (src);
9077           emitcode ("mov", "@%s,a", rname);
9078         }
9079       else
9080         emitcode ("mov", "@%s,%s", rname, src);
9081       break;
9082
9083     case PPOINTER:
9084       MOVA (src);
9085       emitcode ("movx", "@%s,a", rname);
9086       break;
9087       
9088     case FPOINTER:
9089       MOVA (src);
9090       emitcode ("movx", "@dptr,a");
9091       break;
9092
9093     case GPOINTER:
9094       MOVA (src);
9095       emitcode ("lcall", "__gptrput");
9096       break;
9097     }
9098 }
9099
9100 /*-----------------------------------------------------------------*/
9101 /* genUnpackBits - generates code for unpacking bits               */
9102 /*-----------------------------------------------------------------*/
9103 static void
9104 genUnpackBits (operand * result, char *rname, int ptype)
9105 {
9106   int offset = 0;       /* result byte offset */
9107   int rsize;            /* result size */
9108   int rlen = 0;         /* remaining bitfield length */
9109   sym_link *etype;      /* bitfield type information */
9110   int blen;             /* bitfield length */
9111   int bstr;             /* bitfield starting bit within byte */
9112
9113   D(emitcode (";     genUnpackBits",""));
9114
9115   etype = getSpec (operandType (result));
9116   rsize = getSize (operandType (result));
9117   blen = SPEC_BLEN (etype);
9118   bstr = SPEC_BSTR (etype);
9119
9120   /* If the bitfield length is less than a byte */
9121   if (blen < 8)
9122     {
9123       emitPtrByteGet (rname, ptype, FALSE);
9124       AccRsh (bstr);
9125       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9126       aopPut (AOP (result), "a", offset++);
9127       goto finish;
9128     }
9129
9130   /* Bit field did not fit in a byte. Copy all
9131      but the partial byte at the end.  */
9132   for (rlen=blen;rlen>=8;rlen-=8)
9133     {
9134       emitPtrByteGet (rname, ptype, FALSE);
9135       aopPut (AOP (result), "a", offset++);
9136       if (rlen>8)
9137         emitcode ("inc", "%s", rname);
9138     }
9139
9140   /* Handle the partial byte at the end */
9141   if (rlen)
9142     {
9143       emitPtrByteGet (rname, ptype, FALSE);
9144       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9145       aopPut (AOP (result), "a", offset++);
9146     }
9147
9148 finish:
9149   if (offset < rsize)
9150     {
9151       rsize -= offset;
9152       while (rsize--)
9153         aopPut (AOP (result), zero, offset++);
9154     }
9155 }
9156
9157
9158 /*-----------------------------------------------------------------*/
9159 /* genDataPointerGet - generates code when ptr offset is known     */
9160 /*-----------------------------------------------------------------*/
9161 static void
9162 genDataPointerGet (operand * left,
9163                    operand * result,
9164                    iCode * ic)
9165 {
9166   char *l;
9167   char buff[256];
9168   int size, offset = 0;
9169   aopOp (result, ic, TRUE, FALSE);
9170
9171   /* get the string representation of the name */
9172   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9173   size = AOP_SIZE (result);
9174   _startLazyDPSEvaluation ();
9175   while (size--)
9176     {
9177         if (offset)
9178         {
9179             SNPRINTF (buff, sizeof(buff), 
9180                       "(%s + %d)", l + 1, offset);
9181         }
9182         else
9183         {
9184             SNPRINTF (buff, sizeof(buff), 
9185                       "%s", l + 1);
9186         }
9187       aopPut (AOP (result), buff, offset++);
9188     }
9189   _endLazyDPSEvaluation ();
9190
9191   freeAsmop (left, NULL, ic, TRUE);
9192   freeAsmop (result, NULL, ic, TRUE);
9193 }
9194
9195 /*-----------------------------------------------------------------*/
9196 /* genNearPointerGet - emitcode for near pointer fetch             */
9197 /*-----------------------------------------------------------------*/
9198 static void
9199 genNearPointerGet (operand * left,
9200                    operand * result,
9201                    iCode * ic,
9202                    iCode *pi)
9203 {
9204   asmop *aop = NULL;
9205   regs *preg;
9206   char *rname;
9207   sym_link *rtype, *retype, *letype;
9208   sym_link *ltype = operandType (left);
9209   char buff[80];
9210
9211   rtype = operandType (result);
9212   retype = getSpec (rtype);
9213   letype = getSpec (ltype);
9214
9215   aopOp (left, ic, FALSE, FALSE);
9216
9217   /* if left is rematerialisable and
9218      result is not bit variable type and
9219      the left is pointer to data space i.e
9220      lower 128 bytes of space */
9221   if (AOP_TYPE (left) == AOP_IMMD &&
9222       !IS_BITVAR (retype) &&
9223       !IS_BITVAR (letype) &&
9224       DCL_TYPE (ltype) == POINTER)
9225     {
9226       genDataPointerGet (left, result, ic);
9227       return;
9228     }
9229
9230   /* if the value is already in a pointer register
9231      then don't need anything more */
9232   if (!AOP_INPREG (AOP (left)))
9233     {
9234       /* otherwise get a free pointer register */
9235       aop = newAsmop (0);
9236       preg = getFreePtr (ic, &aop, FALSE);
9237       emitcode ("mov", "%s,%s",
9238                 preg->name,
9239                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9240       rname = preg->name;
9241     }
9242   else
9243     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9244
9245   freeAsmop (left, NULL, ic, TRUE);
9246   aopOp (result, ic, FALSE, FALSE);
9247
9248   /* if bitfield then unpack the bits */
9249   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9250     genUnpackBits (result, rname, POINTER);
9251   else
9252     {
9253       /* we have can just get the values */
9254       int size = AOP_SIZE (result);
9255       int offset = 0;
9256
9257       while (size--)
9258         {
9259           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9260             {
9261
9262               emitcode ("mov", "a,@%s", rname);
9263               aopPut (AOP (result), "a", offset);
9264             }
9265           else
9266             {
9267               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9268               aopPut (AOP (result), buff, offset);
9269             }
9270           offset++;
9271           if (size || pi)
9272             {
9273                 emitcode ("inc", "%s", rname);
9274             }
9275         }
9276     }
9277
9278   /* now some housekeeping stuff */
9279   if (aop)
9280     {
9281       /* we had to allocate for this iCode */
9282       if (pi) { /* post increment present */
9283         aopPut(AOP ( left ),rname,0);
9284       }
9285       freeAsmop (NULL, aop, ic, TRUE);
9286     }
9287   else
9288     {
9289       /* we did not allocate which means left
9290          already in a pointer register, then
9291          if size > 0 && this could be used again
9292          we have to point it back to where it
9293          belongs */
9294       if (AOP_SIZE (result) > 1 &&
9295           !OP_SYMBOL (left)->remat &&
9296           (OP_SYMBOL (left)->liveTo > ic->seq ||
9297            ic->depth) &&
9298           !pi)
9299         {
9300           int size = AOP_SIZE (result) - 1;
9301           while (size--)
9302             emitcode ("dec", "%s", rname);
9303         }
9304     }
9305
9306   /* done */
9307   freeAsmop (result, NULL, ic, TRUE);
9308   if (pi) pi->generated = 1;
9309 }
9310
9311 /*-----------------------------------------------------------------*/
9312 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9313 /*-----------------------------------------------------------------*/
9314 static void
9315 genPagedPointerGet (operand * left,
9316                     operand * result,
9317                     iCode * ic,
9318                     iCode * pi)
9319 {
9320   asmop *aop = NULL;
9321   regs *preg;
9322   char *rname;
9323   sym_link *rtype, *retype, *letype;
9324
9325   rtype = operandType (result);
9326   retype = getSpec (rtype);
9327   letype = getSpec (operandType (left));
9328   aopOp (left, ic, FALSE, FALSE);
9329
9330   /* if the value is already in a pointer register
9331      then don't need anything more */
9332   if (!AOP_INPREG (AOP (left)))
9333     {
9334       /* otherwise get a free pointer register */
9335       aop = newAsmop (0);
9336       preg = getFreePtr (ic, &aop, FALSE);
9337       emitcode ("mov", "%s,%s",
9338                 preg->name,
9339                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9340       rname = preg->name;
9341     }
9342   else
9343     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9344
9345   freeAsmop (left, NULL, ic, TRUE);
9346   aopOp (result, ic, FALSE, FALSE);
9347
9348   /* if bitfield then unpack the bits */
9349   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9350     genUnpackBits (result, rname, PPOINTER);
9351   else
9352     {
9353       /* we have can just get the values */
9354       int size = AOP_SIZE (result);
9355       int offset = 0;
9356
9357       while (size--)
9358         {
9359
9360           emitcode ("movx", "a,@%s", rname);
9361           aopPut (AOP (result), "a", offset);
9362
9363           offset++;
9364
9365           if (size || pi)
9366             emitcode ("inc", "%s", rname);
9367         }
9368     }
9369
9370   /* now some housekeeping stuff */
9371   if (aop)
9372     {
9373       /* we had to allocate for this iCode */
9374       if (pi) aopPut ( AOP (left), rname, 0);
9375       freeAsmop (NULL, aop, ic, TRUE);
9376     }
9377   else
9378     {
9379       /* we did not allocate which means left
9380          already in a pointer register, then
9381          if size > 0 && this could be used again
9382          we have to point it back to where it
9383          belongs */
9384       if (AOP_SIZE (result) > 1 &&
9385           !OP_SYMBOL (left)->remat &&
9386           (OP_SYMBOL (left)->liveTo > ic->seq ||
9387            ic->depth) &&
9388           !pi)
9389         {
9390           int size = AOP_SIZE (result) - 1;
9391           while (size--)
9392             emitcode ("dec", "%s", rname);
9393         }
9394     }
9395
9396   /* done */
9397   freeAsmop (result, NULL, ic, TRUE);
9398   if (pi) pi->generated = 1;
9399 }
9400
9401 /*-----------------------------------------------------------------*/
9402 /* genFarPointerGet - gget value from far space                    */
9403 /*-----------------------------------------------------------------*/
9404 static void
9405 genFarPointerGet (operand * left,
9406                   operand * result, iCode * ic, iCode *pi)
9407 {
9408     int size, offset, dopi=1;
9409   sym_link *retype = getSpec (operandType (result));
9410   sym_link *letype = getSpec (operandType (left));
9411   D (emitcode (";", "genFarPointerGet"););
9412
9413   aopOp (left, ic, FALSE, FALSE);
9414
9415   /* if the operand is already in dptr
9416      then we do nothing else we move the value to dptr */
9417   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9418     {
9419       /* if this is remateriazable */
9420       if (AOP_TYPE (left) == AOP_IMMD)
9421         {
9422           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9423         }
9424       else
9425         {
9426           /* we need to get it byte by byte */
9427           _startLazyDPSEvaluation ();
9428           if (AOP_TYPE (left) != AOP_DPTR)
9429             {
9430               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9431               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9432               if (options.model == MODEL_FLAT24)
9433                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9434             }
9435           else
9436             {
9437               /* We need to generate a load to DPTR indirect through DPTR. */
9438               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9439               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9440               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9441               if (options.model == MODEL_FLAT24)
9442                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9443               emitcode ("pop", "dph");
9444               emitcode ("pop", "dpl");
9445               dopi =0;
9446             }
9447           _endLazyDPSEvaluation ();
9448         }
9449     }
9450   /* so dptr know contains the address */
9451   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9452
9453   /* if bit then unpack */
9454   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9455       if (AOP_INDPTRn(left)) {
9456           genSetDPTR(AOP(left)->aopu.dptr);
9457       }
9458       genUnpackBits (result, "dptr", FPOINTER);
9459       if (AOP_INDPTRn(left)) {
9460           genSetDPTR(0);
9461       }
9462   } else
9463     {
9464       size = AOP_SIZE (result);
9465       offset = 0;
9466
9467       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9468           while (size--) {
9469               genSetDPTR(AOP(left)->aopu.dptr);
9470               emitcode ("movx", "a,@dptr");
9471               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9472                   emitcode ("inc", "dptr");
9473               genSetDPTR (0);
9474               aopPut (AOP (result), "a", offset++);
9475           }
9476       } else {
9477           _startLazyDPSEvaluation ();
9478           while (size--) {
9479               if (AOP_INDPTRn(left)) {
9480                   genSetDPTR(AOP(left)->aopu.dptr);
9481               } else {
9482                   genSetDPTR (0);
9483               }
9484               _flushLazyDPS ();
9485               
9486               emitcode ("movx", "a,@dptr");
9487               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9488                   emitcode ("inc", "dptr");
9489               
9490               aopPut (AOP (result), "a", offset++);
9491           }
9492           _endLazyDPSEvaluation ();
9493       }
9494     }
9495   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9496       if (!AOP_INDPTRn(left)) {
9497           _startLazyDPSEvaluation ();
9498           aopPut ( AOP (left), "dpl", 0);
9499           aopPut ( AOP (left), "dph", 1);
9500           if (options.model == MODEL_FLAT24)
9501               aopPut ( AOP (left), "dpx", 2);
9502           _endLazyDPSEvaluation ();
9503       }
9504     pi->generated = 1;
9505   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9506              AOP_SIZE(result) > 1 &&
9507              IS_SYMOP(left) &&
9508              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9509       
9510       size = AOP_SIZE (result) - 1;
9511       if (AOP_INDPTRn(left)) {
9512           genSetDPTR(AOP(left)->aopu.dptr);
9513       }
9514       while (size--) emitcode ("lcall","__decdptr");
9515       if (AOP_INDPTRn(left)) {
9516           genSetDPTR(0);
9517       }
9518   }
9519
9520   freeAsmop (left, NULL, ic, TRUE);
9521   freeAsmop (result, NULL, ic, TRUE);
9522 }
9523
9524 /*-----------------------------------------------------------------*/
9525 /* genCodePointerGet - get value from code space                  */
9526 /*-----------------------------------------------------------------*/
9527 static void
9528 genCodePointerGet (operand * left,
9529                     operand * result, iCode * ic, iCode *pi)
9530 {
9531   int size, offset, dopi=1;
9532   sym_link *retype = getSpec (operandType (result));
9533
9534   aopOp (left, ic, FALSE, FALSE);
9535
9536   /* if the operand is already in dptr
9537      then we do nothing else we move the value to dptr */
9538   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9539     {
9540       /* if this is remateriazable */
9541       if (AOP_TYPE (left) == AOP_IMMD)
9542         {
9543           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9544         }
9545       else
9546         {                       /* we need to get it byte by byte */
9547           _startLazyDPSEvaluation ();
9548           if (AOP_TYPE (left) != AOP_DPTR)
9549             {
9550               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9551               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9552               if (options.model == MODEL_FLAT24)
9553                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9554             }
9555           else
9556             {
9557               /* We need to generate a load to DPTR indirect through DPTR. */
9558               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9559               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9560               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9561               if (options.model == MODEL_FLAT24)
9562                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9563               emitcode ("pop", "dph");
9564               emitcode ("pop", "dpl");
9565               dopi=0;
9566             }
9567           _endLazyDPSEvaluation ();
9568         }
9569     }
9570   /* so dptr know contains the address */
9571   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9572
9573   /* if bit then unpack */
9574   if (IS_BITVAR (retype)) {
9575       if (AOP_INDPTRn(left)) {
9576           genSetDPTR(AOP(left)->aopu.dptr);
9577       }
9578       genUnpackBits (result, "dptr", CPOINTER);
9579       if (AOP_INDPTRn(left)) {
9580           genSetDPTR(0);
9581       }
9582   } else
9583     {
9584       size = AOP_SIZE (result);
9585       offset = 0;
9586       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9587           while (size--) {
9588               genSetDPTR(AOP(left)->aopu.dptr);
9589               emitcode ("clr", "a");
9590               emitcode ("movc", "a,@a+dptr");
9591               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9592                   emitcode ("inc", "dptr");
9593               genSetDPTR (0);
9594               aopPut (AOP (result), "a", offset++);
9595           }
9596       } else {
9597           _startLazyDPSEvaluation ();
9598           while (size--)
9599               {
9600                   if (AOP_INDPTRn(left)) {
9601                       genSetDPTR(AOP(left)->aopu.dptr);
9602                   } else {
9603                       genSetDPTR (0);
9604                   }
9605                   _flushLazyDPS ();
9606                   
9607                   emitcode ("clr", "a");
9608                   emitcode ("movc", "a,@a+dptr");
9609                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9610                       emitcode ("inc", "dptr");
9611                   aopPut (AOP (result), "a", offset++);
9612               }
9613           _endLazyDPSEvaluation ();
9614       }
9615     }
9616   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9617       if (!AOP_INDPTRn(left)) {
9618           _startLazyDPSEvaluation ();
9619           
9620           aopPut ( AOP (left), "dpl", 0);
9621           aopPut ( AOP (left), "dph", 1);
9622           if (options.model == MODEL_FLAT24)
9623               aopPut ( AOP (left), "dpx", 2);
9624
9625           _endLazyDPSEvaluation ();
9626       }
9627       pi->generated = 1;
9628   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9629              AOP_SIZE(result) > 1 &&
9630              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9631       
9632       size = AOP_SIZE (result) - 1;
9633       if (AOP_INDPTRn(left)) {
9634           genSetDPTR(AOP(left)->aopu.dptr);
9635       }
9636       while (size--) emitcode ("lcall","__decdptr");
9637       if (AOP_INDPTRn(left)) {
9638           genSetDPTR(0);
9639       }
9640   }
9641   
9642   freeAsmop (left, NULL, ic, TRUE);
9643   freeAsmop (result, NULL, ic, TRUE);
9644 }
9645
9646 /*-----------------------------------------------------------------*/
9647 /* genGenPointerGet - gget value from generic pointer space        */
9648 /*-----------------------------------------------------------------*/
9649 static void
9650 genGenPointerGet (operand * left,
9651                   operand * result, iCode * ic, iCode * pi)
9652 {
9653   int size, offset;
9654   sym_link *retype = getSpec (operandType (result));
9655   sym_link *letype = getSpec (operandType (left));
9656
9657   D (emitcode (";", "genGenPointerGet "); );
9658
9659   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9660
9661   /* if the operand is already in dptr
9662      then we do nothing else we move the value to dptr */
9663   if (AOP_TYPE (left) != AOP_STR)
9664     {
9665       /* if this is remateriazable */
9666       if (AOP_TYPE (left) == AOP_IMMD)
9667         {
9668           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9669           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9670             {
9671                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9672             }
9673             else
9674             {
9675                 emitcode ("mov", "b,#%d", pointerCode (retype));
9676             }
9677         }
9678       else
9679         {                       /* we need to get it byte by byte */
9680             _startLazyDPSEvaluation ();
9681             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9682             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9683             if (options.model == MODEL_FLAT24) {
9684                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9685                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9686             } else {
9687                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9688             }
9689             _endLazyDPSEvaluation ();
9690         }
9691     }
9692
9693   /* so dptr-b now contains the address */
9694   _G.bInUse++;
9695   aopOp (result, ic, FALSE, TRUE);
9696   _G.bInUse--;
9697
9698   /* if bit then unpack */
9699   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9700   {
9701     genUnpackBits (result, "dptr", GPOINTER);
9702   }
9703   else
9704     {
9705         size = AOP_SIZE (result);
9706         offset = 0;
9707
9708         while (size--)
9709         {
9710             if (size)
9711             {
9712                 // Get two bytes at a time, results in _AP & A.
9713                 // dptr will be incremented ONCE by __gptrgetWord.
9714                 //
9715                 // Note: any change here must be coordinated
9716                 // with the implementation of __gptrgetWord
9717                 // in device/lib/_gptrget.c
9718                 emitcode ("lcall", "__gptrgetWord");
9719                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9720                 aopPut (AOP (result), "a", offset++);
9721                 size--;
9722             }
9723             else
9724             {
9725                 // Only one byte to get.
9726                 emitcode ("lcall", "__gptrget");
9727                 aopPut (AOP (result), "a", offset++);
9728             }
9729             
9730             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9731             {
9732                 emitcode ("inc", "dptr");
9733             }
9734         }
9735     }
9736
9737   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9738     _startLazyDPSEvaluation ();
9739       
9740     aopPut ( AOP (left), "dpl", 0);
9741     aopPut ( AOP (left), "dph", 1);
9742     if (options.model == MODEL_FLAT24) {
9743         aopPut ( AOP (left), "dpx", 2);
9744         aopPut ( AOP (left), "b", 3);   
9745     } else  aopPut ( AOP (left), "b", 2);       
9746     
9747     _endLazyDPSEvaluation ();
9748       
9749     pi->generated = 1;
9750   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9751              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9752       
9753       size = AOP_SIZE (result) - 1;
9754       while (size--) emitcode ("lcall","__decdptr");
9755   }
9756
9757   freeAsmop (left, NULL, ic, TRUE);
9758   freeAsmop (result, NULL, ic, TRUE);
9759 }
9760
9761 /*-----------------------------------------------------------------*/
9762 /* genPointerGet - generate code for pointer get                   */
9763 /*-----------------------------------------------------------------*/
9764 static void
9765 genPointerGet (iCode * ic, iCode *pi)
9766 {
9767   operand *left, *result;
9768   sym_link *type, *etype;
9769   int p_type;
9770
9771   D (emitcode (";", "genPointerGet ");
9772     );
9773
9774   left = IC_LEFT (ic);
9775   result = IC_RESULT (ic);
9776
9777   /* depending on the type of pointer we need to
9778      move it to the correct pointer register */
9779   type = operandType (left);
9780   etype = getSpec (type);
9781   /* if left is of type of pointer then it is simple */
9782   if (IS_PTR (type) && !IS_FUNC (type->next))
9783     p_type = DCL_TYPE (type);
9784   else
9785     {
9786       /* we have to go by the storage class */
9787       p_type = PTR_TYPE (SPEC_OCLS (etype));
9788     }
9789   /* special case when cast remat */
9790   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9791       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9792           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9793           type = operandType (left);
9794           p_type = DCL_TYPE (type);
9795   }
9796   /* now that we have the pointer type we assign
9797      the pointer values */
9798   switch (p_type)
9799     {
9800
9801     case POINTER:
9802     case IPOINTER:
9803       genNearPointerGet (left, result, ic, pi);
9804       break;
9805
9806     case PPOINTER:
9807       genPagedPointerGet (left, result, ic, pi);
9808       break;
9809
9810     case FPOINTER:
9811       genFarPointerGet (left, result, ic, pi);
9812       break;
9813
9814     case CPOINTER:
9815       genCodePointerGet (left, result, ic, pi);
9816       break;
9817
9818     case GPOINTER:
9819       genGenPointerGet (left, result, ic, pi);
9820       break;
9821     }
9822
9823 }
9824
9825 /*-----------------------------------------------------------------*/
9826 /* genPackBits - generates code for packed bit storage             */
9827 /*-----------------------------------------------------------------*/
9828 static void
9829 genPackBits (sym_link * etype,
9830              operand * right,
9831              char *rname, int p_type)
9832 {
9833   int offset = 0;       /* source byte offset */
9834   int rlen = 0;         /* remaining bitfield length */
9835   int blen;             /* bitfield length */
9836   int bstr;             /* bitfield starting bit within byte */
9837   int litval;           /* source literal value (if AOP_LIT) */
9838   unsigned char mask;   /* bitmask within current byte */
9839
9840   D(emitcode (";     genPackBits",""));
9841
9842   blen = SPEC_BLEN (etype);
9843   bstr = SPEC_BSTR (etype);
9844
9845   /* If the bitfield length is less than a byte */
9846   if (blen < 8)
9847     {
9848       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9849               (unsigned char) (0xFF >> (8 - bstr)));
9850
9851       if (AOP_TYPE (right) == AOP_LIT)
9852         {
9853           /* Case with a bitfield length <8 and literal source
9854           */
9855           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9856           litval <<= bstr;
9857           litval &= (~mask) & 0xff;
9858           emitPtrByteGet (rname, p_type, FALSE);
9859           if ((mask|litval)!=0xff)
9860             emitcode ("anl","a,#!constbyte", mask);
9861           if (litval)
9862             emitcode ("orl","a,#!constbyte", litval);
9863         }
9864       else
9865         {
9866           if ((blen==1) && (p_type!=GPOINTER))
9867             {
9868               /* Case with a bitfield length == 1 and no generic pointer
9869               */
9870               if (AOP_TYPE (right) == AOP_CRY)
9871                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9872               else
9873                 {
9874                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9875                   emitcode ("rrc","a");
9876                 }
9877               emitPtrByteGet (rname, p_type, FALSE);
9878               emitcode ("mov","acc.%d,c",bstr);
9879             }
9880           else
9881             {
9882               /* Case with a bitfield length < 8 and arbitrary source
9883               */
9884               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9885               /* shift and mask source value */
9886               AccLsh (bstr);
9887               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9888
9889               /* transfer A to B and get next byte */
9890               emitPtrByteGet (rname, p_type, TRUE);
9891
9892               emitcode ("anl", "a,#!constbyte", mask);
9893               emitcode ("orl", "a,b");
9894               if (p_type == GPOINTER)
9895                 emitcode ("pop", "b");
9896            }
9897         }
9898
9899       emitPtrByteSet (rname, p_type, "a");
9900       return;
9901     }
9902
9903   /* Bit length is greater than 7 bits. In this case, copy  */
9904   /* all except the partial byte at the end                 */
9905   for (rlen=blen;rlen>=8;rlen-=8)
9906     {
9907       emitPtrByteSet (rname, p_type, 
9908                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9909       if (rlen>8)
9910         emitcode ("inc", "%s", rname);
9911     }
9912
9913   /* If there was a partial byte at the end */
9914   if (rlen)
9915     {
9916       mask = (((unsigned char) -1 << rlen) & 0xff);
9917       
9918       if (AOP_TYPE (right) == AOP_LIT)
9919         {
9920           /* Case with partial byte and literal source
9921           */
9922           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9923           litval >>= (blen-rlen);
9924           litval &= (~mask) & 0xff;
9925           emitPtrByteGet (rname, p_type, FALSE);
9926           if ((mask|litval)!=0xff)
9927             emitcode ("anl","a,#!constbyte", mask);
9928           if (litval)
9929             emitcode ("orl","a,#!constbyte", litval);
9930         }
9931       else
9932         {
9933           /* Case with partial byte and arbitrary source
9934           */
9935           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9936           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9937
9938           /* transfer A to B and get next byte */
9939           emitPtrByteGet (rname, p_type, TRUE);
9940
9941           emitcode ("anl", "a,#!constbyte", mask);
9942           emitcode ("orl", "a,b");
9943           if (p_type == GPOINTER)
9944             emitcode ("pop", "b");
9945         }
9946       emitPtrByteSet (rname, p_type, "a");
9947     }
9948
9949 }
9950
9951
9952 /*-----------------------------------------------------------------*/
9953 /* genDataPointerSet - remat pointer to data space                 */
9954 /*-----------------------------------------------------------------*/
9955 static void
9956 genDataPointerSet (operand * right,
9957                    operand * result,
9958                    iCode * ic)
9959 {
9960   int size, offset = 0;
9961   char *l, buff[256];
9962
9963   aopOp (right, ic, FALSE, FALSE);
9964
9965   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9966   size = AOP_SIZE (right);
9967   while (size--)
9968     {
9969       if (offset)
9970         {
9971             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9972         }
9973       else
9974         {
9975             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9976         }
9977         
9978       emitcode ("mov", "%s,%s", buff,
9979                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9980     }
9981
9982   freeAsmop (right, NULL, ic, TRUE);
9983   freeAsmop (result, NULL, ic, TRUE);
9984 }
9985
9986 /*-----------------------------------------------------------------*/
9987 /* genNearPointerSet - emitcode for near pointer put                */
9988 /*-----------------------------------------------------------------*/
9989 static void
9990 genNearPointerSet (operand * right,
9991                    operand * result,
9992                    iCode * ic,
9993                    iCode * pi)
9994 {
9995   asmop *aop = NULL;
9996   char *rname, *l;
9997   sym_link *retype, *letype;
9998   sym_link *ptype = operandType (result);
9999
10000   retype = getSpec (operandType (right));
10001   letype = getSpec (ptype);
10002
10003   aopOp (result, ic, FALSE, FALSE);
10004
10005   /* if the result is rematerializable &
10006      in data space & not a bit variable */
10007   if (AOP_TYPE (result) == AOP_IMMD &&
10008       DCL_TYPE (ptype) == POINTER &&
10009       !IS_BITVAR (retype) &&
10010       !IS_BITVAR (letype))
10011     {
10012       genDataPointerSet (right, result, ic);
10013       return;
10014     }
10015
10016   /* if the value is already in a pointer register
10017      then don't need anything more */
10018   if (!AOP_INPREG (AOP (result)))
10019     {
10020       /* otherwise get a free pointer register */
10021       regs *preg;
10022         
10023       aop = newAsmop (0);
10024       preg = getFreePtr (ic, &aop, FALSE);
10025       emitcode ("mov", "%s,%s",
10026                 preg->name,
10027                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10028       rname = preg->name;
10029     }
10030   else
10031     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10032
10033   aopOp (right, ic, FALSE, FALSE);
10034
10035   /* if bitfield then unpack the bits */
10036   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10037     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10038   else
10039     {
10040       /* we have can just get the values */
10041       int size = AOP_SIZE (right);
10042       int offset = 0;
10043
10044       while (size--)
10045         {
10046           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10047           if (*l == '@')
10048             {
10049               MOVA (l);
10050               emitcode ("mov", "@%s,a", rname);
10051             }
10052           else
10053             emitcode ("mov", "@%s,%s", rname, l);
10054           if (size || pi)
10055             emitcode ("inc", "%s", rname);
10056           offset++;
10057         }
10058     }
10059
10060   /* now some housekeeping stuff */
10061   if (aop)
10062     {
10063       /* we had to allocate for this iCode */
10064       if (pi) aopPut (AOP (result),rname,0);
10065       freeAsmop (NULL, aop, ic, TRUE);
10066     }
10067   else
10068     {
10069       /* we did not allocate which means left
10070          already in a pointer register, then
10071          if size > 0 && this could be used again
10072          we have to point it back to where it
10073          belongs */
10074       if (AOP_SIZE (right) > 1 &&
10075           !OP_SYMBOL (result)->remat &&
10076           (OP_SYMBOL (result)->liveTo > ic->seq ||
10077            ic->depth) &&
10078           !pi)
10079         {
10080           int size = AOP_SIZE (right) - 1;
10081           while (size--)
10082             emitcode ("dec", "%s", rname);
10083         }
10084     }
10085
10086   /* done */
10087   if (pi) pi->generated = 1;
10088   freeAsmop (result, NULL, ic, TRUE);
10089   freeAsmop (right, NULL, ic, TRUE);
10090
10091
10092 }
10093
10094 /*-----------------------------------------------------------------*/
10095 /* genPagedPointerSet - emitcode for Paged pointer put             */
10096 /*-----------------------------------------------------------------*/
10097 static void
10098 genPagedPointerSet (operand * right,
10099                     operand * result,
10100                     iCode * ic,
10101                     iCode *pi)
10102 {
10103   asmop *aop = NULL;
10104   char *rname;
10105   sym_link *retype, *letype;
10106
10107   retype = getSpec (operandType (right));
10108   letype = getSpec (operandType (result));
10109
10110   aopOp (result, ic, FALSE, FALSE);
10111
10112   /* if the value is already in a pointer register
10113      then don't need anything more */
10114   if (!AOP_INPREG (AOP (result)))
10115     {
10116       /* otherwise get a free pointer register */
10117       regs *preg;
10118         
10119       aop = newAsmop (0);
10120       preg = getFreePtr (ic, &aop, FALSE);
10121       emitcode ("mov", "%s,%s",
10122                 preg->name,
10123                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10124       rname = preg->name;
10125     }
10126   else
10127     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10128
10129   aopOp (right, ic, FALSE, FALSE);
10130
10131   /* if bitfield then unpack the bits */
10132   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10133     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10134   else
10135     {
10136       /* we have can just get the values */
10137       int size = AOP_SIZE (right);
10138       int offset = 0;
10139
10140       while (size--)
10141         {
10142           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10143
10144           emitcode ("movx", "@%s,a", rname);
10145
10146           if (size || pi)
10147             emitcode ("inc", "%s", rname);
10148
10149           offset++;
10150         }
10151     }
10152
10153   /* now some housekeeping stuff */
10154   if (aop)
10155     {
10156       if (pi) aopPut (AOP (result),rname,0);
10157       /* we had to allocate for this iCode */
10158       freeAsmop (NULL, aop, ic, TRUE);
10159     }
10160   else
10161     {
10162       /* we did not allocate which means left
10163          already in a pointer register, then
10164          if size > 0 && this could be used again
10165          we have to point it back to where it
10166          belongs */
10167       if (AOP_SIZE (right) > 1 &&
10168           !OP_SYMBOL (result)->remat &&
10169           (OP_SYMBOL (result)->liveTo > ic->seq ||
10170            ic->depth) &&
10171           !pi)
10172         {
10173           int size = AOP_SIZE (right) - 1;
10174           while (size--)
10175             emitcode ("dec", "%s", rname);
10176         }
10177     }
10178
10179   /* done */
10180   if (pi) pi->generated = 1;
10181   freeAsmop (result, NULL, ic, TRUE);
10182   freeAsmop (right, NULL, ic, TRUE);
10183
10184
10185 }
10186
10187 /*-----------------------------------------------------------------*/
10188 /* genFarPointerSet - set value from far space                     */
10189 /*-----------------------------------------------------------------*/
10190 static void
10191 genFarPointerSet (operand * right,
10192                   operand * result, iCode * ic, iCode *pi)
10193 {
10194   int size, offset, dopi=1;
10195   sym_link *retype = getSpec (operandType (right));
10196   sym_link *letype = getSpec (operandType (result));
10197
10198   aopOp (result, ic, FALSE, FALSE);
10199
10200   /* if the operand is already in dptr
10201      then we do nothing else we move the value to dptr */
10202   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10203     {
10204       /* if this is remateriazable */
10205       if (AOP_TYPE (result) == AOP_IMMD)
10206         emitcode ("mov", "dptr,%s", 
10207                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10208       else
10209         {
10210           /* we need to get it byte by byte */
10211           _startLazyDPSEvaluation ();
10212           if (AOP_TYPE (result) != AOP_DPTR)
10213             {
10214               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10215               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10216               if (options.model == MODEL_FLAT24)
10217                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10218             }
10219           else
10220             {
10221               /* We need to generate a load to DPTR indirect through DPTR. */
10222               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10223                 
10224               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10225               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10226               if (options.model == MODEL_FLAT24)
10227                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10228               emitcode ("pop", "dph");
10229               emitcode ("pop", "dpl");
10230               dopi=0;
10231             }
10232           _endLazyDPSEvaluation ();
10233         }
10234     }
10235   /* so dptr know contains the address */
10236   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10237
10238   /* if bit then unpack */
10239   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10240       if (AOP_INDPTRn(result)) {
10241           genSetDPTR(AOP(result)->aopu.dptr);
10242       }
10243       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10244       if (AOP_INDPTRn(result)) {
10245           genSetDPTR(0);
10246       }
10247   } else {
10248       size = AOP_SIZE (right);
10249       offset = 0;
10250       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10251           while (size--) {
10252               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10253               
10254               genSetDPTR(AOP(result)->aopu.dptr);
10255               emitcode ("movx", "@dptr,a");
10256               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10257                   emitcode ("inc", "dptr");
10258               genSetDPTR (0);
10259           }
10260       } else {
10261           _startLazyDPSEvaluation ();
10262           while (size--) {
10263               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10264               
10265               if (AOP_INDPTRn(result)) {
10266                   genSetDPTR(AOP(result)->aopu.dptr);
10267               } else {
10268                   genSetDPTR (0);
10269               }
10270               _flushLazyDPS ();
10271               
10272               emitcode ("movx", "@dptr,a");
10273               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10274                   emitcode ("inc", "dptr");
10275           }
10276           _endLazyDPSEvaluation ();
10277       }
10278   }
10279   
10280   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10281       if (!AOP_INDPTRn(result)) {
10282           _startLazyDPSEvaluation ();
10283           
10284           aopPut (AOP(result),"dpl",0);
10285           aopPut (AOP(result),"dph",1);
10286           if (options.model == MODEL_FLAT24)
10287               aopPut (AOP(result),"dpx",2);
10288
10289           _endLazyDPSEvaluation ();
10290       }
10291       pi->generated=1;
10292   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10293              AOP_SIZE(right) > 1 &&
10294              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10295       
10296       size = AOP_SIZE (right) - 1;
10297       if (AOP_INDPTRn(result)) {
10298           genSetDPTR(AOP(result)->aopu.dptr);
10299       } 
10300       while (size--) emitcode ("lcall","__decdptr");
10301       if (AOP_INDPTRn(result)) {
10302           genSetDPTR(0);
10303       }
10304   }
10305   freeAsmop (result, NULL, ic, TRUE);
10306   freeAsmop (right, NULL, ic, TRUE);
10307 }
10308
10309 /*-----------------------------------------------------------------*/
10310 /* genGenPointerSet - set value from generic pointer space         */
10311 /*-----------------------------------------------------------------*/
10312 static void
10313 genGenPointerSet (operand * right,
10314                   operand * result, iCode * ic, iCode *pi)
10315 {
10316   int size, offset;
10317   sym_link *retype = getSpec (operandType (right));
10318   sym_link *letype = getSpec (operandType (result));
10319
10320   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10321
10322   /* if the operand is already in dptr
10323      then we do nothing else we move the value to dptr */
10324   if (AOP_TYPE (result) != AOP_STR)
10325     {
10326       _startLazyDPSEvaluation ();
10327       /* if this is remateriazable */
10328       if (AOP_TYPE (result) == AOP_IMMD)
10329         {
10330           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10331           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10332           {
10333               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10334           }
10335           else
10336           {
10337               emitcode ("mov", 
10338                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10339           }
10340         }
10341       else
10342         {                       /* we need to get it byte by byte */
10343           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10344           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10345           if (options.model == MODEL_FLAT24) {
10346             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10347             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10348           } else {
10349             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10350           }
10351         }
10352       _endLazyDPSEvaluation ();
10353     }
10354   /* so dptr + b now contains the address */
10355   _G.bInUse++;
10356   aopOp (right, ic, FALSE, TRUE);
10357   _G.bInUse--;
10358     
10359
10360   /* if bit then unpack */
10361   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10362     {
10363         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10364     }
10365   else
10366     {
10367         size = AOP_SIZE (right);
10368         offset = 0;
10369
10370         _startLazyDPSEvaluation ();
10371         while (size--)
10372         {
10373             if (size)
10374             {
10375                 // Set two bytes at a time, passed in _AP & A.
10376                 // dptr will be incremented ONCE by __gptrputWord.
10377                 //
10378                 // Note: any change here must be coordinated
10379                 // with the implementation of __gptrputWord
10380                 // in device/lib/_gptrput.c
10381                 emitcode("mov", "_ap, %s", 
10382                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10383                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10384                 
10385                 genSetDPTR (0);
10386                 _flushLazyDPS ();
10387                 emitcode ("lcall", "__gptrputWord");
10388                 size--;
10389             }
10390             else
10391             {
10392                 // Only one byte to put.
10393                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10394
10395                 genSetDPTR (0);
10396                 _flushLazyDPS ();               
10397                 emitcode ("lcall", "__gptrput");
10398             }
10399             
10400             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10401             {
10402                 emitcode ("inc", "dptr");
10403             }
10404         }
10405         _endLazyDPSEvaluation ();
10406     }
10407
10408   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10409       _startLazyDPSEvaluation ();
10410       
10411       aopPut (AOP(result),"dpl",0);
10412       aopPut (AOP(result),"dph",1);
10413       if (options.model == MODEL_FLAT24) {
10414           aopPut (AOP(result),"dpx",2);
10415           aopPut (AOP(result),"b",3);
10416       } else {
10417           aopPut (AOP(result),"b",2);
10418       }
10419       _endLazyDPSEvaluation ();
10420       
10421       pi->generated=1;
10422   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10423              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10424       
10425       size = AOP_SIZE (right) - 1;
10426       while (size--) emitcode ("lcall","__decdptr");
10427   }
10428   freeAsmop (result, NULL, ic, TRUE);
10429   freeAsmop (right, NULL, ic, TRUE);
10430 }
10431
10432 /*-----------------------------------------------------------------*/
10433 /* genPointerSet - stores the value into a pointer location        */
10434 /*-----------------------------------------------------------------*/
10435 static void
10436 genPointerSet (iCode * ic, iCode *pi)
10437 {
10438   operand *right, *result;
10439   sym_link *type, *etype;
10440   int p_type;
10441
10442   D (emitcode (";", "genPointerSet "););
10443
10444   right = IC_RIGHT (ic);
10445   result = IC_RESULT (ic);
10446
10447   /* depending on the type of pointer we need to
10448      move it to the correct pointer register */
10449   type = operandType (result);
10450   etype = getSpec (type);
10451   /* if left is of type of pointer then it is simple */
10452   if (IS_PTR (type) && !IS_FUNC (type->next))
10453     {
10454       p_type = DCL_TYPE (type);
10455     }
10456   else
10457     {
10458       /* we have to go by the storage class */
10459       p_type = PTR_TYPE (SPEC_OCLS (etype));
10460     }
10461   /* special case when cast remat */
10462   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10463       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10464           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10465           type = operandType (result);
10466           p_type = DCL_TYPE (type);
10467   }
10468
10469   /* now that we have the pointer type we assign
10470      the pointer values */
10471   switch (p_type)
10472     {
10473
10474     case POINTER:
10475     case IPOINTER:
10476       genNearPointerSet (right, result, ic, pi);
10477       break;
10478
10479     case PPOINTER:
10480       genPagedPointerSet (right, result, ic, pi);
10481       break;
10482
10483     case FPOINTER:
10484       genFarPointerSet (right, result, ic, pi);
10485       break;
10486
10487     case GPOINTER:
10488       genGenPointerSet (right, result, ic, pi);
10489       break;
10490
10491     default:
10492       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10493               "genPointerSet: illegal pointer type");
10494     }
10495
10496 }
10497
10498 /*-----------------------------------------------------------------*/
10499 /* genIfx - generate code for Ifx statement                        */
10500 /*-----------------------------------------------------------------*/
10501 static void
10502 genIfx (iCode * ic, iCode * popIc)
10503 {
10504   operand *cond = IC_COND (ic);
10505   int isbit = 0;
10506
10507   D (emitcode (";", "genIfx "););
10508
10509   aopOp (cond, ic, FALSE, FALSE);
10510
10511   /* get the value into acc */
10512   if (AOP_TYPE (cond) != AOP_CRY)
10513     {
10514         toBoolean (cond);
10515     }
10516   else
10517     {
10518         isbit = 1;
10519     }
10520     
10521   /* the result is now in the accumulator */
10522   freeAsmop (cond, NULL, ic, TRUE);
10523
10524   /* if there was something to be popped then do it */
10525   if (popIc)
10526     genIpop (popIc);
10527
10528   /* if the condition is  a bit variable */
10529   if (isbit && IS_ITEMP (cond) &&
10530       SPIL_LOC (cond))
10531     {
10532         genIfxJump (ic, SPIL_LOC (cond)->rname);
10533     }
10534   else if (isbit && !IS_ITEMP (cond))
10535     {
10536         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10537     }
10538   else
10539     {
10540         genIfxJump (ic, "a");
10541     }
10542
10543   ic->generated = 1;
10544 }
10545
10546 /*-----------------------------------------------------------------*/
10547 /* genAddrOf - generates code for address of                       */
10548 /*-----------------------------------------------------------------*/
10549 static void
10550 genAddrOf (iCode * ic)
10551 {
10552   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10553   int size, offset;
10554
10555   D (emitcode (";", "genAddrOf ");
10556     );
10557
10558   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10559
10560   /* if the operand is on the stack then we
10561      need to get the stack offset of this
10562      variable */
10563   if (sym->onStack) {
10564       
10565       /* if 10 bit stack */
10566       if (options.stack10bit) {
10567           char buff[10];
10568           int  offset;
10569           
10570           tsprintf(buff, sizeof(buff), 
10571                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10572           /* if it has an offset then we need to compute it */
10573 /*        emitcode ("subb", "a,#!constbyte", */
10574 /*                  -((sym->stack < 0) ? */
10575 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10576 /*                    ((short) sym->stack)) & 0xff); */
10577 /*        emitcode ("mov","b,a"); */
10578 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10579 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10580 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10581           if (sym->stack) {
10582               emitcode ("mov", "a,_bpx");
10583               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10584                                              ((char) (sym->stack - _G.nRegsSaved)) :
10585                                              ((char) sym->stack )) & 0xff);
10586               emitcode ("mov", "b,a");
10587               emitcode ("mov", "a,_bpx+1");
10588               
10589               offset = (((sym->stack < 0) ? 
10590                          ((short) (sym->stack - _G.nRegsSaved)) :
10591                          ((short) sym->stack )) >> 8) & 0xff;
10592           
10593               emitcode ("addc","a,#!constbyte", offset);
10594
10595               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10596               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10597               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10598           } else {
10599               /* we can just move _bp */
10600               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10601               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10602               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10603           }       
10604       } else {
10605           /* if it has an offset then we need to compute it */
10606           if (sym->stack) {
10607               emitcode ("mov", "a,_bp");
10608               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10609               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10610           } else {
10611               /* we can just move _bp */
10612               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10613           }
10614           /* fill the result with zero */
10615           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10616           
10617           
10618           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10619               fprintf (stderr,
10620                        "*** warning: pointer to stack var truncated.\n");
10621           }
10622
10623           offset = 1;
10624           while (size--) {
10625               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10626           }      
10627       }
10628       goto release;
10629   }
10630
10631   /* object not on stack then we need the name */
10632   size = AOP_SIZE (IC_RESULT (ic));
10633   offset = 0;
10634
10635   while (size--)
10636     {
10637       char s[SDCC_NAME_MAX];
10638       if (offset) {
10639           switch (offset) {
10640           case 1:
10641               tsprintf(s, sizeof(s), "#!his",sym->rname);
10642               break;
10643           case 2:
10644               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10645               break;
10646           case 3:
10647               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10648               break;
10649           default: /* should not need this (just in case) */
10650               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10651                        sym->rname,
10652                        offset * 8);
10653           }
10654       } 
10655       else
10656       {
10657           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10658       }
10659         
10660       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10661     }
10662
10663 release:
10664   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10665
10666 }
10667
10668 #if 0 // obsolete, and buggy for != xdata
10669 /*-----------------------------------------------------------------*/
10670 /* genArrayInit - generates code for address of                       */
10671 /*-----------------------------------------------------------------*/
10672 static void
10673 genArrayInit (iCode * ic)
10674 {
10675     literalList *iLoop;
10676     int         ix, count;
10677     int         elementSize = 0, eIndex;
10678     unsigned    val, lastVal;
10679     sym_link    *type;
10680     operand     *left=IC_LEFT(ic);
10681     
10682     D (emitcode (";", "genArrayInit "););
10683
10684     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10685     
10686     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10687     {
10688         // Load immediate value into DPTR.
10689         emitcode("mov", "dptr, %s",
10690              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10691     }
10692     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10693     {
10694 #if 0
10695       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10696               "Unexpected operand to genArrayInit.\n");
10697       exit(1);
10698 #else
10699       // a regression because of SDCCcse.c:1.52
10700       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10701       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10702       if (options.model == MODEL_FLAT24)
10703         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10704 #endif
10705     }
10706     
10707     type = operandType(IC_LEFT(ic));
10708     
10709     if (type && type->next)
10710     {
10711         elementSize = getSize(type->next);
10712     }
10713     else
10714     {
10715         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10716                                 "can't determine element size in genArrayInit.\n");
10717         exit(1);
10718     }
10719     
10720     iLoop = IC_ARRAYILIST(ic);
10721     lastVal = 0xffff;
10722     
10723     while (iLoop)
10724     {
10725         bool firstpass = TRUE;
10726         
10727         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10728                  iLoop->count, (int)iLoop->literalValue, elementSize);
10729         
10730         ix = iLoop->count;
10731         
10732         while (ix)
10733         {
10734             symbol *tlbl = NULL;
10735             
10736             count = ix > 256 ? 256 : ix;
10737             
10738             if (count > 1)
10739             {
10740                 tlbl = newiTempLabel (NULL);
10741                 if (firstpass || (count & 0xff))
10742                 {
10743                     emitcode("mov", "b, #!constbyte", count & 0xff);
10744                 }
10745                 
10746                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10747             }
10748             
10749             firstpass = FALSE;
10750                 
10751             for (eIndex = 0; eIndex < elementSize; eIndex++)
10752             {
10753                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10754                 if (val != lastVal)
10755                 {
10756                     emitcode("mov", "a, #!constbyte", val);
10757                     lastVal = val;
10758                 }
10759                 
10760                 emitcode("movx", "@dptr, a");
10761                 emitcode("inc", "dptr");
10762             }
10763             
10764             if (count > 1)
10765             {
10766                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10767             }
10768             
10769             ix -= count;
10770         }
10771         
10772         iLoop = iLoop->next;
10773     }
10774     
10775     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10776 }
10777 #endif
10778
10779 /*-----------------------------------------------------------------*/
10780 /* genFarFarAssign - assignment when both are in far space         */
10781 /*-----------------------------------------------------------------*/
10782 static void
10783 genFarFarAssign (operand * result, operand * right, iCode * ic)
10784 {
10785   int size = AOP_SIZE (right);
10786   int offset = 0;
10787   symbol *rSym = NULL;
10788
10789   if (size == 1)
10790   {
10791       /* quick & easy case. */
10792       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10793       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10794       freeAsmop (right, NULL, ic, FALSE);
10795       /* now assign DPTR to result */
10796       _G.accInUse++;
10797       aopOp(result, ic, FALSE, FALSE);
10798       _G.accInUse--;
10799       aopPut(AOP(result), "a", 0);
10800       freeAsmop(result, NULL, ic, FALSE);
10801       return;
10802   }
10803   
10804   /* See if we've got an underlying symbol to abuse. */
10805   if (IS_SYMOP(result) && OP_SYMBOL(result))
10806   {
10807       if (IS_TRUE_SYMOP(result))
10808       {
10809           rSym = OP_SYMBOL(result);
10810       }
10811       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10812       {
10813           rSym = OP_SYMBOL(result)->usl.spillLoc;
10814       }
10815   }
10816              
10817   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10818   {
10819       /* We can use the '390 auto-toggle feature to good effect here. */
10820       
10821       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10822       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10823       emitcode ("mov", "dptr,#%s", rSym->rname); 
10824       /* DP2 = result, DP1 = right, DP1 is current. */
10825       while (size)
10826       {
10827           emitcode("movx", "a,@dptr");
10828           emitcode("movx", "@dptr,a");
10829           if (--size)
10830           {
10831                emitcode("inc", "dptr");
10832                emitcode("inc", "dptr");
10833           }
10834       }
10835       emitcode("mov", "dps,#0");
10836       freeAsmop (right, NULL, ic, FALSE);
10837 #if 0
10838 some alternative code for processors without auto-toggle
10839 no time to test now, so later well put in...kpb
10840         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10841         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10842         emitcode ("mov", "dptr,#%s", rSym->rname); 
10843         /* DP2 = result, DP1 = right, DP1 is current. */
10844         while (size)
10845         {
10846           --size;
10847           emitcode("movx", "a,@dptr");
10848           if (size)
10849             emitcode("inc", "dptr");
10850           emitcode("inc", "dps");
10851           emitcode("movx", "@dptr,a");
10852           if (size)
10853             emitcode("inc", "dptr");
10854           emitcode("inc", "dps");
10855         }
10856         emitcode("mov", "dps,#0");
10857         freeAsmop (right, NULL, ic, FALSE);
10858 #endif
10859   }
10860   else
10861   {
10862       D (emitcode (";", "genFarFarAssign"););
10863       aopOp (result, ic, TRUE, TRUE);
10864
10865       _startLazyDPSEvaluation ();
10866       
10867       while (size--)
10868         {
10869           aopPut (AOP (result),
10870                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10871           offset++;
10872         }
10873       _endLazyDPSEvaluation ();
10874       freeAsmop (result, NULL, ic, FALSE);
10875       freeAsmop (right, NULL, ic, FALSE);
10876   }
10877 }
10878
10879 /*-----------------------------------------------------------------*/
10880 /* genAssign - generate code for assignment                        */
10881 /*-----------------------------------------------------------------*/
10882 static void
10883 genAssign (iCode * ic)
10884 {
10885   operand *result, *right;
10886   int size, offset;
10887   unsigned long lit = 0L;
10888
10889   D (emitcode (";", "genAssign ");
10890     );
10891
10892   result = IC_RESULT (ic);
10893   right = IC_RIGHT (ic);
10894
10895   /* if they are the same */
10896   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10897     return;
10898
10899   aopOp (right, ic, FALSE, FALSE);
10900
10901   emitcode (";", "genAssign: resultIsFar = %s",
10902             isOperandInFarSpace (result) ?
10903             "TRUE" : "FALSE");
10904
10905   /* special case both in far space */
10906   if ((AOP_TYPE (right) == AOP_DPTR ||
10907        AOP_TYPE (right) == AOP_DPTR2) &&
10908   /* IS_TRUE_SYMOP(result)       && */
10909       isOperandInFarSpace (result))
10910     {
10911       genFarFarAssign (result, right, ic);
10912       return;
10913     }
10914
10915   aopOp (result, ic, TRUE, FALSE);
10916
10917   /* if they are the same registers */
10918   if (sameRegs (AOP (right), AOP (result)))
10919     goto release;
10920
10921   /* if the result is a bit */
10922   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10923     {
10924       /* if the right size is a literal then
10925          we know what the value is */
10926       if (AOP_TYPE (right) == AOP_LIT)
10927         {
10928           if (((int) operandLitValue (right)))
10929             aopPut (AOP (result), one, 0);
10930           else
10931             aopPut (AOP (result), zero, 0);
10932           goto release;
10933         }
10934
10935       /* the right is also a bit variable */
10936       if (AOP_TYPE (right) == AOP_CRY)
10937         {
10938           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10939           aopPut (AOP (result), "c", 0);
10940           goto release;
10941         }
10942
10943       /* we need to or */
10944       toBoolean (right);
10945       aopPut (AOP (result), "a", 0);
10946       goto release;
10947     }
10948
10949   /* bit variables done */
10950   /* general case */
10951   size = AOP_SIZE (result);
10952   offset = 0;
10953   if (AOP_TYPE (right) == AOP_LIT)
10954     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10955
10956   if ((size > 1) &&
10957       (AOP_TYPE (result) != AOP_REG) &&
10958       (AOP_TYPE (right) == AOP_LIT) &&
10959       !IS_FLOAT (operandType (right)))
10960     {
10961       _startLazyDPSEvaluation ();
10962       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10963         {
10964           aopPut (AOP (result),
10965                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10966                   offset);
10967           offset++;
10968           size--;
10969         }
10970       /* And now fill the rest with zeros. */
10971       if (size)
10972         {
10973           emitcode ("clr", "a");
10974         }
10975       while (size--)
10976         {
10977           aopPut (AOP (result), "a", offset++);
10978         }
10979       _endLazyDPSEvaluation ();
10980     }
10981   else
10982     {
10983       _startLazyDPSEvaluation ();
10984       while (size--)
10985         {
10986           aopPut (AOP (result),
10987                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10988                   offset);
10989           offset++;
10990         }
10991       _endLazyDPSEvaluation ();
10992     }
10993
10994 release:
10995   freeAsmop (right, NULL, ic, FALSE);
10996   freeAsmop (result, NULL, ic, TRUE);
10997 }
10998
10999 /*-----------------------------------------------------------------*/
11000 /* genJumpTab - generates code for jump table                      */
11001 /*-----------------------------------------------------------------*/
11002 static void
11003 genJumpTab (iCode * ic)
11004 {
11005   symbol *jtab;
11006   char *l;
11007
11008   D (emitcode (";", "genJumpTab ");
11009     );
11010
11011   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11012   /* get the condition into accumulator */
11013   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11014   MOVA (l);
11015   /* multiply by four! */
11016   emitcode ("add", "a,acc");
11017   emitcode ("add", "a,acc");
11018   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11019
11020   jtab = newiTempLabel (NULL);
11021   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11022   emitcode ("jmp", "@a+dptr");
11023   emitcode ("", "!tlabeldef", jtab->key + 100);
11024   /* now generate the jump labels */
11025   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11026        jtab = setNextItem (IC_JTLABELS (ic)))
11027     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11028
11029 }
11030
11031 /*-----------------------------------------------------------------*/
11032 /* genCast - gen code for casting                                  */
11033 /*-----------------------------------------------------------------*/
11034 static void
11035 genCast (iCode * ic)
11036 {
11037   operand *result = IC_RESULT (ic);
11038   sym_link *ctype = operandType (IC_LEFT (ic));
11039   sym_link *rtype = operandType (IC_RIGHT (ic));
11040   operand *right = IC_RIGHT (ic);
11041   int size, offset;
11042
11043   D (emitcode (";", "genCast "););
11044
11045   /* if they are equivalent then do nothing */
11046   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11047     return;
11048
11049   aopOp (right, ic, FALSE, FALSE);
11050   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11051
11052   /* if the result is a bit */
11053   if (IS_BITVAR (OP_SYMBOL (result)->type)
11054       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11055     {
11056       /* if the right size is a literal then
11057          we know what the value is */
11058       if (AOP_TYPE (right) == AOP_LIT)
11059         {
11060           if (((int) operandLitValue (right)))
11061             aopPut (AOP (result), one, 0);
11062           else
11063             aopPut (AOP (result), zero, 0);
11064
11065           goto release;
11066         }
11067
11068       /* the right is also a bit variable */
11069       if (AOP_TYPE (right) == AOP_CRY)
11070         {
11071           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11072           aopPut (AOP (result), "c", 0);
11073           goto release;
11074         }
11075
11076       /* we need to or */
11077       toBoolean (right);
11078       aopPut (AOP (result), "a", 0);
11079       goto release;
11080     }
11081
11082   /* if they are the same size : or less */
11083   if (AOP_SIZE (result) <= AOP_SIZE (right))
11084     {
11085
11086       /* if they are in the same place */
11087       if (sameRegs (AOP (right), AOP (result)))
11088         goto release;
11089
11090       /* if they in different places then copy */
11091       size = AOP_SIZE (result);
11092       offset = 0;
11093       _startLazyDPSEvaluation ();
11094       while (size--)
11095         {
11096           aopPut (AOP (result),
11097                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11098                   offset);
11099           offset++;
11100         }
11101       _endLazyDPSEvaluation ();
11102       goto release;
11103     }
11104
11105
11106   /* if the result is of type pointer */
11107   if (IS_PTR (ctype))
11108     {
11109
11110       int p_type;
11111       sym_link *type = operandType (right);
11112
11113       /* pointer to generic pointer */
11114       if (IS_GENPTR (ctype))
11115         {
11116           if (IS_PTR (type))
11117             {
11118               p_type = DCL_TYPE (type);
11119             }
11120           else
11121             {
11122 #if OLD_CAST_BEHAVIOR
11123               /* KV: we are converting a non-pointer type to
11124                * a generic pointer. This (ifdef'd out) code
11125                * says that the resulting generic pointer
11126                * should have the same class as the storage
11127                * location of the non-pointer variable.
11128                *
11129                * For example, converting an int (which happens
11130                * to be stored in DATA space) to a pointer results
11131                * in a DATA generic pointer; if the original int
11132                * in XDATA space, so will be the resulting pointer.
11133                *
11134                * I don't like that behavior, and thus this change:
11135                * all such conversions will be forced to XDATA and
11136                * throw a warning. If you want some non-XDATA
11137                * type, or you want to suppress the warning, you
11138                * must go through an intermediate cast, like so:
11139                *
11140                * char _generic *gp = (char _xdata *)(intVar);
11141                */
11142               sym_link *etype = getSpec (type);
11143
11144               /* we have to go by the storage class */
11145               if (SPEC_OCLS (etype) != generic)
11146                 {
11147                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11148                 }
11149               else
11150 #endif
11151                 {
11152                   /* Converting unknown class (i.e. register variable)
11153                    * to generic pointer. This is not good, but
11154                    * we'll make a guess (and throw a warning).
11155                    */
11156                   p_type = FPOINTER;
11157                   werror (W_INT_TO_GEN_PTR_CAST);
11158                 }
11159             }
11160
11161           /* the first two bytes are known */
11162           size = GPTRSIZE - 1;
11163           offset = 0;
11164           _startLazyDPSEvaluation ();
11165           while (size--)
11166             {
11167               aopPut (AOP (result),
11168                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11169                       offset);
11170               offset++;
11171             }
11172           _endLazyDPSEvaluation ();
11173
11174           /* the last byte depending on type */
11175             {
11176                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11177                 char gpValStr[10];
11178             
11179                 if (gpVal == -1)
11180                 {
11181                     // pointerTypeToGPByte will have bitched.
11182                     exit(1);
11183                 }
11184             
11185                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11186                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11187             }
11188           goto release;
11189         }
11190
11191       /* just copy the pointers */
11192       size = AOP_SIZE (result);
11193       offset = 0;
11194       _startLazyDPSEvaluation ();
11195       while (size--)
11196         {
11197           aopPut (AOP (result),
11198                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11199                   offset);
11200           offset++;
11201         }
11202       _endLazyDPSEvaluation ();
11203       goto release;
11204     }
11205
11206   /* so we now know that the size of destination is greater
11207      than the size of the source */
11208   /* we move to result for the size of source */
11209   size = AOP_SIZE (right);
11210   offset = 0;
11211   _startLazyDPSEvaluation ();
11212   while (size--)
11213     {
11214       aopPut (AOP (result),
11215               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11216               offset);
11217       offset++;
11218     }
11219   _endLazyDPSEvaluation ();
11220
11221   /* now depending on the sign of the source && destination */
11222   size = AOP_SIZE (result) - AOP_SIZE (right);
11223   /* if unsigned or not an integral type */
11224   /* also, if the source is a bit, we don't need to sign extend, because
11225    * it can't possibly have set the sign bit.
11226    */
11227   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11228     {
11229       while (size--)
11230         {
11231           aopPut (AOP (result), zero, offset++);
11232         }
11233     }
11234   else
11235     {
11236       /* we need to extend the sign :{ */
11237       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11238                         FALSE, FALSE, NULL));
11239       emitcode ("rlc", "a");
11240       emitcode ("subb", "a,acc");
11241       while (size--)
11242         aopPut (AOP (result), "a", offset++);
11243     }
11244
11245   /* we are done hurray !!!! */
11246
11247 release:
11248   freeAsmop (right, NULL, ic, TRUE);
11249   freeAsmop (result, NULL, ic, TRUE);
11250
11251 }
11252
11253 /*-----------------------------------------------------------------*/
11254 /* genDjnz - generate decrement & jump if not zero instrucion      */
11255 /*-----------------------------------------------------------------*/
11256 static int
11257 genDjnz (iCode * ic, iCode * ifx)
11258 {
11259   symbol *lbl, *lbl1;
11260   if (!ifx)
11261     return 0;
11262
11263   /* if the if condition has a false label
11264      then we cannot save */
11265   if (IC_FALSE (ifx))
11266     return 0;
11267
11268   /* if the minus is not of the form
11269      a = a - 1 */
11270   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11271       !IS_OP_LITERAL (IC_RIGHT (ic)))
11272     return 0;
11273
11274   if (operandLitValue (IC_RIGHT (ic)) != 1)
11275     return 0;
11276
11277   /* if the size of this greater than one then no
11278      saving */
11279   if (getSize (operandType (IC_RESULT (ic))) > 1)
11280     return 0;
11281
11282   /* otherwise we can save BIG */
11283   D(emitcode(";", "genDjnz"););
11284
11285   lbl = newiTempLabel (NULL);
11286   lbl1 = newiTempLabel (NULL);
11287
11288   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11289
11290   if (AOP_NEEDSACC(IC_RESULT(ic)))
11291   {
11292       /* If the result is accessed indirectly via
11293        * the accumulator, we must explicitly write
11294        * it back after the decrement.
11295        */
11296       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11297       
11298       if (strcmp(rByte, "a"))
11299       {
11300            /* Something is hopelessly wrong */
11301            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11302                    __FILE__, __LINE__);
11303            /* We can just give up; the generated code will be inefficient,
11304             * but what the hey.
11305             */
11306            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11307            return 0;
11308       }
11309       emitcode ("dec", "%s", rByte);
11310       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11311       emitcode ("jnz", "!tlabel", lbl->key + 100);
11312   }
11313   else if (IS_AOP_PREG (IC_RESULT (ic)))
11314     {
11315       emitcode ("dec", "%s",
11316                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11317       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11318       emitcode ("jnz", "!tlabel", lbl->key + 100);
11319     }
11320   else
11321     {
11322       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11323                 lbl->key + 100);
11324     }
11325   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11326   emitcode ("", "!tlabeldef", lbl->key + 100);
11327   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11328   emitcode ("", "!tlabeldef", lbl1->key + 100);
11329
11330   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11331   ifx->generated = 1;
11332   return 1;
11333 }
11334
11335 /*-----------------------------------------------------------------*/
11336 /* genReceive - generate code for a receive iCode                  */
11337 /*-----------------------------------------------------------------*/
11338 static void
11339 genReceive (iCode * ic)
11340 {
11341     int size = getSize (operandType (IC_RESULT (ic)));
11342     int offset = 0;
11343     int rb1off ;
11344     
11345     D (emitcode (";", "genReceive "););
11346
11347     if (ic->argreg == 1) 
11348     {
11349         /* first parameter */
11350         if (AOP_IS_STR(IC_RESULT(ic)))
11351         {
11352             /* Nothing to do: it's already in the proper place. */
11353             return;
11354         }
11355         else
11356         {
11357             bool useDp2;
11358             
11359             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11360                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11361                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11362             
11363             _G.accInUse++;
11364             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11365             _G.accInUse--; 
11366             
11367             /* Sanity checking... */
11368             if (AOP_USESDPTR(IC_RESULT(ic)))
11369             {
11370                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11371                         "genReceive got unexpected DPTR.");
11372             }
11373             assignResultValue (IC_RESULT (ic));
11374         }
11375     } 
11376     else 
11377     { 
11378         /* second receive onwards */
11379         /* this gets a little tricky since unused recevies will be
11380          eliminated, we have saved the reg in the type field . and
11381          we use that to figure out which register to use */
11382         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11383         rb1off = ic->argreg;
11384         while (size--) 
11385         {
11386             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11387         }
11388     }
11389     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11390 }
11391
11392 /*-----------------------------------------------------------------*/
11393 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11394 /*-----------------------------------------------------------------*/
11395 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11396 {
11397     operand *from , *to , *count;
11398     symbol *lbl;
11399     bitVect *rsave;
11400     int i;
11401
11402     /* we know it has to be 3 parameters */
11403     assert (nparms == 3);
11404     
11405     rsave = newBitVect(16);
11406     /* save DPTR if it needs to be saved */
11407     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11408             if (bitVectBitValue(ic->rMask,i))
11409                     rsave = bitVectSetBit(rsave,i);
11410     }
11411     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11412                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11413     savermask(rsave);
11414     
11415     to = parms[0];
11416     from = parms[1];
11417     count = parms[2];
11418
11419     aopOp (from, ic->next, FALSE, FALSE);
11420
11421     /* get from into DPTR1 */
11422     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11423     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11424     if (options.model == MODEL_FLAT24) {
11425         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11426     }
11427
11428     freeAsmop (from, NULL, ic, FALSE);
11429     aopOp (to, ic, FALSE, FALSE);
11430     /* get "to" into DPTR */
11431     /* if the operand is already in dptr
11432        then we do nothing else we move the value to dptr */
11433     if (AOP_TYPE (to) != AOP_STR) {
11434         /* if already in DPTR then we need to push */
11435         if (AOP_TYPE(to) == AOP_DPTR) {
11436             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11437             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11438             if (options.model == MODEL_FLAT24)
11439                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11440             emitcode ("pop", "dph");
11441             emitcode ("pop", "dpl");        
11442         } else {
11443             _startLazyDPSEvaluation ();
11444             /* if this is remateriazable */
11445             if (AOP_TYPE (to) == AOP_IMMD) {
11446                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11447             } else {                    /* we need to get it byte by byte */
11448                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11449                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11450                 if (options.model == MODEL_FLAT24) {
11451                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11452                 }
11453             }
11454             _endLazyDPSEvaluation ();
11455         }
11456     }
11457     freeAsmop (to, NULL, ic, FALSE);
11458     _G.dptrInUse = _G.dptr1InUse = 1;
11459     aopOp (count, ic->next->next, FALSE,FALSE);
11460     lbl =newiTempLabel(NULL);
11461
11462     /* now for the actual copy */
11463     if (AOP_TYPE(count) == AOP_LIT && 
11464         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11465         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11466         if (fromc) {
11467             emitcode ("lcall","__bi_memcpyc2x_s");
11468         } else {
11469             emitcode ("lcall","__bi_memcpyx2x_s");
11470         }
11471         freeAsmop (count, NULL, ic, FALSE);
11472     } else {
11473         symbol *lbl1 = newiTempLabel(NULL);
11474         
11475         emitcode (";"," Auto increment but no djnz");
11476         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11477         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11478         freeAsmop (count, NULL, ic, FALSE);
11479         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11480         emitcode ("","!tlabeldef",lbl->key+100);
11481         if (fromc) {
11482             emitcode ("clr","a");
11483             emitcode ("movc", "a,@a+dptr");
11484         } else 
11485             emitcode ("movx", "a,@dptr");
11486         emitcode ("movx", "@dptr,a");
11487         emitcode ("inc", "dptr");
11488         emitcode ("inc", "dptr");
11489         emitcode ("mov","a,b");
11490         emitcode ("orl","a,_ap");
11491         emitcode ("jz","!tlabel",lbl1->key+100);
11492         emitcode ("mov","a,_ap");
11493         emitcode ("add","a,#!constbyte",0xFF);
11494         emitcode ("mov","_ap,a");
11495         emitcode ("mov","a,b");
11496         emitcode ("addc","a,#!constbyte",0xFF);
11497         emitcode ("mov","b,a");
11498         emitcode ("sjmp","!tlabel",lbl->key+100);
11499         emitcode ("","!tlabeldef",lbl1->key+100);
11500     }
11501     emitcode ("mov", "dps,#0"); 
11502     _G.dptrInUse = _G.dptr1InUse = 0;
11503     unsavermask(rsave);
11504
11505 }
11506
11507 /*-----------------------------------------------------------------*/
11508 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11509 /*-----------------------------------------------------------------*/
11510 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11511 {
11512     operand *from , *to , *count;
11513     symbol *lbl,*lbl2;
11514     bitVect *rsave;
11515     int i;
11516
11517     /* we know it has to be 3 parameters */
11518     assert (nparms == 3);
11519     
11520     rsave = newBitVect(16);
11521     /* save DPTR if it needs to be saved */
11522     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11523             if (bitVectBitValue(ic->rMask,i))
11524                     rsave = bitVectSetBit(rsave,i);
11525     }
11526     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11527                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11528     savermask(rsave);
11529     
11530     to = parms[0];
11531     from = parms[1];
11532     count = parms[2];
11533
11534     aopOp (from, ic->next, FALSE, FALSE);
11535
11536     /* get from into DPTR1 */
11537     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11538     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11539     if (options.model == MODEL_FLAT24) {
11540         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11541     }
11542
11543     freeAsmop (from, NULL, ic, FALSE);
11544     aopOp (to, ic, FALSE, FALSE);
11545     /* get "to" into DPTR */
11546     /* if the operand is already in dptr
11547        then we do nothing else we move the value to dptr */
11548     if (AOP_TYPE (to) != AOP_STR) {
11549         /* if already in DPTR then we need to push */
11550         if (AOP_TYPE(to) == AOP_DPTR) {
11551             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11552             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11553             if (options.model == MODEL_FLAT24)
11554                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11555             emitcode ("pop", "dph");
11556             emitcode ("pop", "dpl");        
11557         } else {
11558             _startLazyDPSEvaluation ();
11559             /* if this is remateriazable */
11560             if (AOP_TYPE (to) == AOP_IMMD) {
11561                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11562             } else {                    /* we need to get it byte by byte */
11563                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11564                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11565                 if (options.model == MODEL_FLAT24) {
11566                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11567                 }
11568             }
11569             _endLazyDPSEvaluation ();
11570         }
11571     }
11572     freeAsmop (to, NULL, ic, FALSE);
11573     _G.dptrInUse = _G.dptr1InUse = 1;
11574     aopOp (count, ic->next->next, FALSE,FALSE);
11575     lbl =newiTempLabel(NULL);
11576     lbl2 =newiTempLabel(NULL);
11577
11578     /* now for the actual compare */
11579     if (AOP_TYPE(count) == AOP_LIT && 
11580         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11581         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11582         if (fromc)
11583             emitcode("lcall","__bi_memcmpc2x_s");
11584         else
11585             emitcode("lcall","__bi_memcmpx2x_s");
11586         freeAsmop (count, NULL, ic, FALSE);
11587         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11588         aopPut(AOP(IC_RESULT(ic)),"a",0);
11589         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11590     } else {
11591         symbol *lbl1 = newiTempLabel(NULL);
11592
11593         emitcode("push","ar0");         
11594         emitcode (";"," Auto increment but no djnz");
11595         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11596         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11597         freeAsmop (count, NULL, ic, FALSE);
11598         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11599         emitcode ("","!tlabeldef",lbl->key+100);
11600         if (fromc) {
11601             emitcode ("clr","a");
11602             emitcode ("movc", "a,@a+dptr");
11603         } else 
11604             emitcode ("movx", "a,@dptr");
11605         emitcode ("mov","r0,a");
11606         emitcode ("movx", "a,@dptr");
11607         emitcode ("clr","c");
11608         emitcode ("subb","a,r0");
11609         emitcode ("jnz","!tlabel",lbl2->key+100);
11610         emitcode ("inc", "dptr");
11611         emitcode ("inc", "dptr");
11612         emitcode ("mov","a,b");
11613         emitcode ("orl","a,_ap");
11614         emitcode ("jz","!tlabel",lbl1->key+100);
11615         emitcode ("mov","a,_ap");
11616         emitcode ("add","a,#!constbyte",0xFF);
11617         emitcode ("mov","_ap,a");
11618         emitcode ("mov","a,b");
11619         emitcode ("addc","a,#!constbyte",0xFF);
11620         emitcode ("mov","b,a");
11621         emitcode ("sjmp","!tlabel",lbl->key+100);
11622         emitcode ("","!tlabeldef",lbl1->key+100);
11623         emitcode ("clr","a");
11624         emitcode ("","!tlabeldef",lbl2->key+100);
11625         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11626         aopPut(AOP(IC_RESULT(ic)),"a",0);
11627         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11628         emitcode("pop","ar0");
11629         emitcode ("mov", "dps,#0");      
11630     }
11631     _G.dptrInUse = _G.dptr1InUse = 0;
11632     unsavermask(rsave);
11633
11634 }
11635
11636 /*-----------------------------------------------------------------*/
11637 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11638 /* port, first parameter output area second parameter pointer to   */
11639 /* port third parameter count                                      */
11640 /*-----------------------------------------------------------------*/
11641 static void genInp( iCode *ic, int nparms, operand **parms)
11642 {
11643     operand *from , *to , *count;
11644     symbol *lbl;
11645     bitVect *rsave;
11646     int i;
11647
11648     /* we know it has to be 3 parameters */
11649     assert (nparms == 3);
11650     
11651     rsave = newBitVect(16);
11652     /* save DPTR if it needs to be saved */
11653     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11654             if (bitVectBitValue(ic->rMask,i))
11655                     rsave = bitVectSetBit(rsave,i);
11656     }
11657     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11658                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11659     savermask(rsave);
11660     
11661     to = parms[0];
11662     from = parms[1];
11663     count = parms[2];
11664
11665     aopOp (from, ic->next, FALSE, FALSE);
11666
11667     /* get from into DPTR1 */
11668     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11669     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11670     if (options.model == MODEL_FLAT24) {
11671         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11672     }
11673
11674     freeAsmop (from, NULL, ic, FALSE);
11675     aopOp (to, ic, FALSE, FALSE);
11676     /* get "to" into DPTR */
11677     /* if the operand is already in dptr
11678        then we do nothing else we move the value to dptr */
11679     if (AOP_TYPE (to) != AOP_STR) {
11680         /* if already in DPTR then we need to push */
11681         if (AOP_TYPE(to) == AOP_DPTR) {
11682             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11683             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11684             if (options.model == MODEL_FLAT24)
11685                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11686             emitcode ("pop", "dph");
11687             emitcode ("pop", "dpl");        
11688         } else {
11689             _startLazyDPSEvaluation ();
11690             /* if this is remateriazable */
11691             if (AOP_TYPE (to) == AOP_IMMD) {
11692                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11693             } else {                    /* we need to get it byte by byte */
11694                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11695                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11696                 if (options.model == MODEL_FLAT24) {
11697                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11698                 }
11699             }
11700             _endLazyDPSEvaluation ();
11701         }
11702     }
11703     freeAsmop (to, NULL, ic, FALSE);
11704
11705     _G.dptrInUse = _G.dptr1InUse = 1;
11706     aopOp (count, ic->next->next, FALSE,FALSE);
11707     lbl =newiTempLabel(NULL);
11708
11709     /* now for the actual copy */
11710     if (AOP_TYPE(count) == AOP_LIT && 
11711         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11712         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11713         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11714         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11715         freeAsmop (count, NULL, ic, FALSE);
11716         emitcode ("","!tlabeldef",lbl->key+100);
11717         emitcode ("movx", "a,@dptr");   /* read data from port */
11718         emitcode ("dec","dps");         /* switch to DPTR */
11719         emitcode ("movx", "@dptr,a");   /* save into location */
11720         emitcode ("inc", "dptr");       /* point to next area */
11721         emitcode ("inc","dps");         /* switch to DPTR2 */
11722         emitcode ("djnz","b,!tlabel",lbl->key+100);
11723     } else {
11724         symbol *lbl1 = newiTempLabel(NULL);
11725         
11726         emitcode (";"," Auto increment but no djnz");
11727         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11728         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11729         freeAsmop (count, NULL, ic, FALSE);
11730         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11731         emitcode ("","!tlabeldef",lbl->key+100);
11732         emitcode ("movx", "a,@dptr");
11733         emitcode ("dec","dps");         /* switch to DPTR */
11734         emitcode ("movx", "@dptr,a");
11735         emitcode ("inc", "dptr");
11736         emitcode ("inc","dps");         /* switch to DPTR2 */
11737 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11738 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11739         emitcode ("mov","a,b");
11740         emitcode ("orl","a,_ap");
11741         emitcode ("jz","!tlabel",lbl1->key+100);
11742         emitcode ("mov","a,_ap");
11743         emitcode ("add","a,#!constbyte",0xFF);
11744         emitcode ("mov","_ap,a");
11745         emitcode ("mov","a,b");
11746         emitcode ("addc","a,#!constbyte",0xFF);
11747         emitcode ("mov","b,a");
11748         emitcode ("sjmp","!tlabel",lbl->key+100);
11749         emitcode ("","!tlabeldef",lbl1->key+100);
11750     }
11751     emitcode ("mov", "dps,#0"); 
11752     _G.dptrInUse = _G.dptr1InUse = 0;
11753     unsavermask(rsave);
11754
11755 }
11756
11757 /*-----------------------------------------------------------------*/
11758 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11759 /* port, first parameter output area second parameter pointer to   */
11760 /* port third parameter count                                      */
11761 /*-----------------------------------------------------------------*/
11762 static void genOutp( iCode *ic, int nparms, operand **parms)
11763 {
11764     operand *from , *to , *count;
11765     symbol *lbl;
11766     bitVect *rsave;
11767     int i;
11768
11769     /* we know it has to be 3 parameters */
11770     assert (nparms == 3);
11771     
11772     rsave = newBitVect(16);
11773     /* save DPTR if it needs to be saved */
11774     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11775             if (bitVectBitValue(ic->rMask,i))
11776                     rsave = bitVectSetBit(rsave,i);
11777     }
11778     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11779                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11780     savermask(rsave);
11781     
11782     to = parms[0];
11783     from = parms[1];
11784     count = parms[2];
11785
11786     aopOp (from, ic->next, FALSE, FALSE);
11787
11788     /* get from into DPTR1 */
11789     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11790     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11791     if (options.model == MODEL_FLAT24) {
11792         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11793     }
11794
11795     freeAsmop (from, NULL, ic, FALSE);
11796     aopOp (to, ic, FALSE, FALSE);
11797     /* get "to" into DPTR */
11798     /* if the operand is already in dptr
11799        then we do nothing else we move the value to dptr */
11800     if (AOP_TYPE (to) != AOP_STR) {
11801         /* if already in DPTR then we need to push */
11802         if (AOP_TYPE(to) == AOP_DPTR) {
11803             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11804             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11805             if (options.model == MODEL_FLAT24)
11806                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11807             emitcode ("pop", "dph");
11808             emitcode ("pop", "dpl");        
11809         } else {
11810             _startLazyDPSEvaluation ();
11811             /* if this is remateriazable */
11812             if (AOP_TYPE (to) == AOP_IMMD) {
11813                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11814             } else {                    /* we need to get it byte by byte */
11815                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11816                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11817                 if (options.model == MODEL_FLAT24) {
11818                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11819                 }
11820             }
11821             _endLazyDPSEvaluation ();
11822         }
11823     }
11824     freeAsmop (to, NULL, ic, FALSE);
11825
11826     _G.dptrInUse = _G.dptr1InUse = 1;
11827     aopOp (count, ic->next->next, FALSE,FALSE);
11828     lbl =newiTempLabel(NULL);
11829
11830     /* now for the actual copy */
11831     if (AOP_TYPE(count) == AOP_LIT && 
11832         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11833         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11834         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11835         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11836         emitcode ("","!tlabeldef",lbl->key+100);
11837         emitcode ("movx", "a,@dptr");   /* read data from port */
11838         emitcode ("inc","dps");         /* switch to DPTR2 */
11839         emitcode ("movx", "@dptr,a");   /* save into location */
11840         emitcode ("inc", "dptr");       /* point to next area */
11841         emitcode ("dec","dps");         /* switch to DPTR */
11842         emitcode ("djnz","b,!tlabel",lbl->key+100);
11843         freeAsmop (count, NULL, ic, FALSE);
11844     } else {
11845         symbol *lbl1 = newiTempLabel(NULL);
11846         
11847         emitcode (";"," Auto increment but no djnz");
11848         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11849         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11850         freeAsmop (count, NULL, ic, FALSE);
11851         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11852         emitcode ("","!tlabeldef",lbl->key+100);
11853         emitcode ("movx", "a,@dptr");
11854         emitcode ("inc", "dptr");
11855         emitcode ("inc","dps");         /* switch to DPTR2 */
11856         emitcode ("movx", "@dptr,a");
11857         emitcode ("dec","dps");         /* switch to DPTR */
11858         emitcode ("mov","a,b");
11859         emitcode ("orl","a,_ap");
11860         emitcode ("jz","!tlabel",lbl1->key+100);
11861         emitcode ("mov","a,_ap");
11862         emitcode ("add","a,#!constbyte",0xFF);
11863         emitcode ("mov","_ap,a");
11864         emitcode ("mov","a,b");
11865         emitcode ("addc","a,#!constbyte",0xFF);
11866         emitcode ("mov","b,a");
11867         emitcode ("sjmp","!tlabel",lbl->key+100);
11868         emitcode ("","!tlabeldef",lbl1->key+100);
11869     }
11870     emitcode ("mov", "dps,#0"); 
11871     _G.dptrInUse = _G.dptr1InUse = 0;
11872     unsavermask(rsave);
11873
11874 }
11875
11876 /*-----------------------------------------------------------------*/
11877 /* genSwapW - swap lower & high order bytes                        */
11878 /*-----------------------------------------------------------------*/
11879 static void genSwapW(iCode *ic, int nparms, operand **parms)
11880 {
11881     operand *dest;
11882     operand *src;
11883     assert (nparms==1);
11884
11885     src = parms[0];
11886     dest=IC_RESULT(ic);
11887
11888     assert(getSize(operandType(src))==2);
11889
11890     aopOp (src, ic, FALSE, FALSE);
11891     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11892     _G.accInUse++;
11893     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11894     _G.accInUse--;
11895     freeAsmop (src, NULL, ic, FALSE);
11896     
11897     aopOp (dest,ic, FALSE, FALSE);
11898     aopPut(AOP(dest),"b",0);
11899     aopPut(AOP(dest),"a",1);
11900     freeAsmop (dest, NULL, ic, FALSE);    
11901 }
11902
11903 /*-----------------------------------------------------------------*/
11904 /* genMemsetX - gencode for memSetX data                           */
11905 /*-----------------------------------------------------------------*/
11906 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11907 {
11908     operand *to , *val , *count;
11909     symbol *lbl;
11910     char *l;
11911     int i;
11912     bitVect *rsave;
11913
11914     /* we know it has to be 3 parameters */
11915     assert (nparms == 3);
11916     
11917     to = parms[0];
11918     val = parms[1];
11919     count = parms[2];
11920         
11921     /* save DPTR if it needs to be saved */
11922     rsave = newBitVect(16);
11923     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11924             if (bitVectBitValue(ic->rMask,i))
11925                     rsave = bitVectSetBit(rsave,i);
11926     }
11927     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11928                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11929     savermask(rsave);
11930
11931     aopOp (to, ic, FALSE, FALSE);
11932     /* get "to" into DPTR */
11933     /* if the operand is already in dptr
11934        then we do nothing else we move the value to dptr */
11935     if (AOP_TYPE (to) != AOP_STR) {
11936         /* if already in DPTR then we need to push */
11937         if (AOP_TYPE(to) == AOP_DPTR) {
11938             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11939             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11940             if (options.model == MODEL_FLAT24)
11941                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11942             emitcode ("pop", "dph");
11943             emitcode ("pop", "dpl");        
11944         } else {
11945             _startLazyDPSEvaluation ();
11946             /* if this is remateriazable */
11947             if (AOP_TYPE (to) == AOP_IMMD) {
11948                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11949             } else {                    /* we need to get it byte by byte */
11950                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11951                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11952                 if (options.model == MODEL_FLAT24) {
11953                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11954                 }
11955             }
11956             _endLazyDPSEvaluation ();
11957         }
11958     }
11959     freeAsmop (to, NULL, ic, FALSE);
11960
11961     aopOp (val, ic->next->next, FALSE,FALSE);
11962     aopOp (count, ic->next->next, FALSE,FALSE);    
11963     lbl =newiTempLabel(NULL);
11964     /* now for the actual copy */
11965     if (AOP_TYPE(count) == AOP_LIT && 
11966         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11967         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11968         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11969         MOVA(l);
11970         emitcode ("","!tlabeldef",lbl->key+100);
11971         emitcode ("movx", "@dptr,a");
11972         emitcode ("inc", "dptr");
11973         emitcode ("djnz","b,!tlabel",lbl->key+100);
11974     } else {
11975         symbol *lbl1 = newiTempLabel(NULL);
11976         
11977         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11978         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11979         emitcode ("","!tlabeldef",lbl->key+100);
11980         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11981         emitcode ("movx", "@dptr,a");
11982         emitcode ("inc", "dptr");
11983         emitcode ("mov","a,b");
11984         emitcode ("orl","a,_ap");
11985         emitcode ("jz","!tlabel",lbl1->key+100);
11986         emitcode ("mov","a,_ap");
11987         emitcode ("add","a,#!constbyte",0xFF);
11988         emitcode ("mov","_ap,a");
11989         emitcode ("mov","a,b");
11990         emitcode ("addc","a,#!constbyte",0xFF);
11991         emitcode ("mov","b,a");
11992         emitcode ("sjmp","!tlabel",lbl->key+100);
11993         emitcode ("","!tlabeldef",lbl1->key+100);
11994     }
11995     freeAsmop (count, NULL, ic, FALSE);
11996     unsavermask(rsave);
11997 }
11998
11999 /*-----------------------------------------------------------------*/
12000 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12001 /*-----------------------------------------------------------------*/
12002 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12003 {
12004         bitVect *rsave ;
12005         operand *pnum, *result;
12006         int i;
12007     
12008         assert (nparms==1);
12009         /* save registers that need to be saved */
12010         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12011                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12012     
12013         pnum = parms[0]; 
12014         aopOp (pnum, ic, FALSE, FALSE);
12015         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12016         freeAsmop (pnum, NULL, ic, FALSE);
12017         emitcode ("lcall","NatLib_LoadPrimitive");
12018         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12019         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12020             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12021                 for (i = (size-1) ; i >= 0 ; i-- ) {
12022                         emitcode ("push","a%s",javaRet[i]);
12023                 }
12024                 for (i=0; i < size ; i++ ) {
12025                         emitcode ("pop","a%s",
12026                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12027                 }
12028         } else {
12029                 for (i = 0 ; i < size ; i++ ) {
12030                         aopPut(AOP(result),javaRet[i],i);
12031                 }
12032         }    
12033         freeAsmop (result, NULL, ic, FALSE);
12034         unsavermask(rsave);
12035 }
12036
12037 /*-----------------------------------------------------------------*/
12038 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12039 /*-----------------------------------------------------------------*/
12040 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12041 {
12042         bitVect *rsave ;
12043         operand *pnum, *result;
12044         int size = 3;
12045         int i;
12046     
12047         assert (nparms==1);
12048         /* save registers that need to be saved */
12049         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12050                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12051     
12052         pnum = parms[0]; 
12053         aopOp (pnum, ic, FALSE, FALSE);
12054         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12055         freeAsmop (pnum, NULL, ic, FALSE);
12056         emitcode ("lcall","NatLib_LoadPointer");
12057         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12058         if (AOP_TYPE(result)!=AOP_STR) {
12059                 for (i = 0 ; i < size ; i++ ) {
12060                         aopPut(AOP(result),fReturn[i],i);
12061                 }
12062         }    
12063         freeAsmop (result, NULL, ic, FALSE);
12064         unsavermask(rsave);
12065 }
12066
12067 /*-----------------------------------------------------------------*/
12068 /* genNatLibInstallStateBlock -                                    */
12069 /*-----------------------------------------------------------------*/
12070 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12071                                        operand **parms, const char *name)
12072 {
12073         bitVect *rsave ;
12074         operand *psb, *handle;
12075         assert (nparms==2);
12076
12077         /* save registers that need to be saved */
12078         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12079                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12080         psb = parms[0];
12081         handle = parms[1];
12082
12083         /* put pointer to state block into DPTR1 */
12084         aopOp (psb, ic, FALSE, FALSE);
12085         if (AOP_TYPE (psb) == AOP_IMMD) {
12086                 emitcode ("mov","dps,#1");
12087                 emitcode ("mov", "dptr,%s",
12088                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12089                 emitcode ("mov","dps,#0");
12090         } else {
12091                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12092                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12093                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12094         }
12095         freeAsmop (psb, NULL, ic, FALSE);
12096
12097         /* put libraryID into DPTR */
12098         emitcode ("mov","dptr,#LibraryID");
12099
12100         /* put handle into r3:r2 */
12101         aopOp (handle, ic, FALSE, FALSE);
12102         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12103                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12104                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12105                 emitcode ("pop","ar3");
12106                 emitcode ("pop","ar2");
12107         } else {        
12108                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12109                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12110         }
12111         freeAsmop (psb, NULL, ic, FALSE);
12112
12113         /* make the call */
12114         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12115
12116         /* put return value into place*/
12117         _G.accInUse++;
12118         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12119         _G.accInUse--;
12120         aopPut(AOP(IC_RESULT(ic)),"a",0);
12121         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12122         unsavermask(rsave);
12123 }
12124
12125 /*-----------------------------------------------------------------*/
12126 /* genNatLibRemoveStateBlock -                                     */
12127 /*-----------------------------------------------------------------*/
12128 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12129 {
12130         bitVect *rsave ;
12131
12132         assert(nparms==0);
12133
12134         /* save registers that need to be saved */
12135         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12136                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12137
12138         /* put libraryID into DPTR */
12139         emitcode ("mov","dptr,#LibraryID");
12140         /* make the call */
12141         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12142         unsavermask(rsave);
12143 }
12144
12145 /*-----------------------------------------------------------------*/
12146 /* genNatLibGetStateBlock -                                        */
12147 /*-----------------------------------------------------------------*/
12148 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12149                                    operand **parms,const char *name)
12150 {
12151         bitVect *rsave ;
12152         symbol *lbl = newiTempLabel(NULL);
12153         
12154         assert(nparms==0);
12155         /* save registers that need to be saved */
12156         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12157                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12158
12159         /* put libraryID into DPTR */
12160         emitcode ("mov","dptr,#LibraryID");
12161         /* make the call */
12162         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12163         emitcode ("jnz","!tlabel",lbl->key+100);
12164
12165         /* put return value into place */
12166         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12167         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12168                 emitcode ("push","ar3");
12169                 emitcode ("push","ar2");
12170                 emitcode ("pop","%s",
12171                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12172                 emitcode ("pop","%s",
12173                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12174         } else {
12175                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12176                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12177         }
12178         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12179         emitcode ("","!tlabeldef",lbl->key+100);
12180         unsavermask(rsave);
12181 }
12182
12183 /*-----------------------------------------------------------------*/
12184 /* genMMMalloc -                                                   */
12185 /*-----------------------------------------------------------------*/
12186 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12187                          int size, const char *name)
12188 {
12189         bitVect *rsave ;
12190         operand *bsize;
12191         symbol *rsym;
12192         symbol *lbl = newiTempLabel(NULL);
12193
12194         assert (nparms == 1);
12195         /* save registers that need to be saved */
12196         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12197                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12198         
12199         bsize=parms[0];
12200         aopOp (bsize,ic,FALSE,FALSE);
12201
12202         /* put the size in R4-R2 */
12203         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12204                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12205                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12206                 if (size==3) {
12207                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12208                         emitcode("pop","ar4");
12209                 }
12210                 emitcode("pop","ar3");
12211                 emitcode("pop","ar2");          
12212         } else {
12213                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12214                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12215                 if (size==3) {
12216                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12217                 }
12218         }
12219         freeAsmop (bsize, NULL, ic, FALSE);
12220
12221         /* make the call */
12222         emitcode ("lcall","MM_%s",name);
12223         emitcode ("jz","!tlabel",lbl->key+100);
12224         emitcode ("mov","r2,#!constbyte",0xff);
12225         emitcode ("mov","r3,#!constbyte",0xff);
12226         emitcode ("","!tlabeldef",lbl->key+100);
12227         /* we don't care about the pointer : we just save the handle */
12228         rsym = OP_SYMBOL(IC_RESULT(ic));
12229         if (rsym->liveFrom != rsym->liveTo) {
12230                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12231                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12232                         emitcode ("push","ar3");
12233                         emitcode ("push","ar2");
12234                         emitcode ("pop","%s",
12235                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12236                         emitcode ("pop","%s",
12237                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12238                 } else {
12239                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12240                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12241                 }
12242                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12243         }
12244         unsavermask(rsave);
12245 }
12246
12247 /*-----------------------------------------------------------------*/
12248 /* genMMDeref -                                                    */
12249 /*-----------------------------------------------------------------*/
12250 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12251 {
12252         bitVect *rsave ;
12253         operand *handle;
12254
12255         assert (nparms == 1);
12256         /* save registers that need to be saved */
12257         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12258                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12259         
12260         handle=parms[0];
12261         aopOp (handle,ic,FALSE,FALSE);
12262
12263         /* put the size in R4-R2 */
12264         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12265                 emitcode("push","%s",
12266                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12267                 emitcode("push","%s",
12268                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12269                 emitcode("pop","ar3");
12270                 emitcode("pop","ar2");          
12271         } else {
12272                 emitcode ("mov","r2,%s",
12273                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12274                 emitcode ("mov","r3,%s",
12275                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12276         }
12277         freeAsmop (handle, NULL, ic, FALSE);
12278
12279         /* make the call */
12280         emitcode ("lcall","MM_Deref");
12281         
12282         {
12283                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12284                 if (rsym->liveFrom != rsym->liveTo) {                   
12285                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12286                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12287                             _startLazyDPSEvaluation ();
12288                             
12289                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12290                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12291                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12292
12293                             _endLazyDPSEvaluation ();
12294                             
12295                         }
12296                 }
12297         }
12298         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12299         unsavermask(rsave);
12300 }
12301
12302 /*-----------------------------------------------------------------*/
12303 /* genMMUnrestrictedPersist -                                      */
12304 /*-----------------------------------------------------------------*/
12305 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12306 {
12307         bitVect *rsave ;
12308         operand *handle;
12309
12310         assert (nparms == 1);
12311         /* save registers that need to be saved */
12312         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12313                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12314         
12315         handle=parms[0];
12316         aopOp (handle,ic,FALSE,FALSE);
12317
12318         /* put the size in R3-R2 */
12319         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12320                 emitcode("push","%s",
12321                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12322                 emitcode("push","%s",
12323                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12324                 emitcode("pop","ar3");
12325                 emitcode("pop","ar2");          
12326         } else {
12327                 emitcode ("mov","r2,%s",
12328                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12329                 emitcode ("mov","r3,%s",
12330                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12331         }
12332         freeAsmop (handle, NULL, ic, FALSE);
12333
12334         /* make the call */
12335         emitcode ("lcall","MM_UnrestrictedPersist");
12336
12337         {
12338                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12339                 if (rsym->liveFrom != rsym->liveTo) {   
12340                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12341                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12342                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12343                 }
12344         }
12345         unsavermask(rsave);
12346 }
12347
12348 /*-----------------------------------------------------------------*/
12349 /* genSystemExecJavaProcess -                                      */
12350 /*-----------------------------------------------------------------*/
12351 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12352 {
12353         bitVect *rsave ;
12354         operand *handle, *pp;
12355
12356         assert (nparms==2);
12357         /* save registers that need to be saved */
12358         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12359                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12360         
12361         pp = parms[0];
12362         handle = parms[1];
12363         
12364         /* put the handle in R3-R2 */
12365         aopOp (handle,ic,FALSE,FALSE);
12366         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12367                 emitcode("push","%s",
12368                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12369                 emitcode("push","%s",
12370                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12371                 emitcode("pop","ar3");
12372                 emitcode("pop","ar2");          
12373         } else {
12374                 emitcode ("mov","r2,%s",
12375                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12376                 emitcode ("mov","r3,%s",
12377                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12378         }
12379         freeAsmop (handle, NULL, ic, FALSE);
12380         
12381         /* put pointer in DPTR */
12382         aopOp (pp,ic,FALSE,FALSE);
12383         if (AOP_TYPE(pp) == AOP_IMMD) {
12384                 emitcode ("mov", "dptr,%s",
12385                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12386         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12387                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12388                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12389                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12390         }
12391         freeAsmop (handle, NULL, ic, FALSE);
12392
12393         /* make the call */
12394         emitcode ("lcall","System_ExecJavaProcess");
12395         
12396         /* put result in place */
12397         {
12398                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12399                 if (rsym->liveFrom != rsym->liveTo) {   
12400                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12401                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12402                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12403                 }
12404         }
12405         
12406         unsavermask(rsave);
12407 }
12408
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemRTCRegisters -                                         */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12413                                   char *name)
12414 {
12415         bitVect *rsave ;
12416         operand *pp;
12417
12418         assert (nparms==1);
12419         /* save registers that need to be saved */
12420         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12421                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12422         
12423         pp=parms[0];
12424         /* put pointer in DPTR */
12425         aopOp (pp,ic,FALSE,FALSE);
12426         if (AOP_TYPE (pp) == AOP_IMMD) {
12427                 emitcode ("mov","dps,#1");
12428                 emitcode ("mov", "dptr,%s", 
12429                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12430                 emitcode ("mov","dps,#0");
12431         } else {
12432                 emitcode ("mov","dpl1,%s",
12433                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12434                 emitcode ("mov","dph1,%s",
12435                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12436                 emitcode ("mov","dpx1,%s",
12437                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12438         }
12439         freeAsmop (pp, NULL, ic, FALSE);
12440
12441         /* make the call */
12442         emitcode ("lcall","System_%sRTCRegisters",name);
12443
12444         unsavermask(rsave);
12445 }
12446
12447 /*-----------------------------------------------------------------*/
12448 /* genSystemThreadSleep -                                          */
12449 /*-----------------------------------------------------------------*/
12450 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12451 {
12452         bitVect *rsave ;
12453         operand *to, *s;
12454
12455         assert (nparms==1);
12456         /* save registers that need to be saved */
12457         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12458                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12459
12460         to = parms[0];
12461         aopOp(to,ic,FALSE,FALSE);
12462         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12463             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12464                 emitcode ("push","%s",
12465                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12466                 emitcode ("push","%s",
12467                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12468                 emitcode ("push","%s",
12469                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12470                 emitcode ("push","%s",
12471                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12472                 emitcode ("pop","ar3");
12473                 emitcode ("pop","ar2");
12474                 emitcode ("pop","ar1");
12475                 emitcode ("pop","ar0");
12476         } else {
12477                 emitcode ("mov","r0,%s",
12478                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12479                 emitcode ("mov","r1,%s",
12480                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12481                 emitcode ("mov","r2,%s",
12482                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12483                 emitcode ("mov","r3,%s",
12484                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12485         }
12486         freeAsmop (to, NULL, ic, FALSE);
12487
12488         /* suspend in acc */
12489         s = parms[1];
12490         aopOp(s,ic,FALSE,FALSE);
12491         emitcode ("mov","a,%s",
12492                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12493         freeAsmop (s, NULL, ic, FALSE);
12494
12495         /* make the call */
12496         emitcode ("lcall","System_%s",name);
12497
12498         unsavermask(rsave);
12499 }
12500
12501 /*-----------------------------------------------------------------*/
12502 /* genSystemThreadResume -                                         */
12503 /*-----------------------------------------------------------------*/
12504 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12505 {
12506         bitVect *rsave ;
12507         operand *tid,*pid;
12508
12509         assert (nparms==2);
12510         /* save registers that need to be saved */
12511         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12512                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12513         
12514         tid = parms[0];
12515         pid = parms[1];
12516         
12517         /* PID in R0 */
12518         aopOp(pid,ic,FALSE,FALSE);
12519         emitcode ("mov","r0,%s",
12520                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12521         freeAsmop (pid, NULL, ic, FALSE);
12522         
12523         /* tid into ACC */
12524         aopOp(tid,ic,FALSE,FALSE);
12525         emitcode ("mov","a,%s",
12526                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12527         freeAsmop (tid, NULL, ic, FALSE);
12528         
12529         emitcode ("lcall","System_ThreadResume");
12530
12531         /* put result into place */
12532         {
12533                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12534                 if (rsym->liveFrom != rsym->liveTo) {   
12535                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12536                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12537                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12538                 }
12539         }
12540         unsavermask(rsave);
12541 }
12542
12543 /*-----------------------------------------------------------------*/
12544 /* genSystemProcessResume -                                        */
12545 /*-----------------------------------------------------------------*/
12546 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12547 {
12548         bitVect *rsave ;
12549         operand *pid;
12550
12551         assert (nparms==1);
12552         /* save registers that need to be saved */
12553         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12555         
12556         pid = parms[0];
12557         
12558         /* pid into ACC */
12559         aopOp(pid,ic,FALSE,FALSE);
12560         emitcode ("mov","a,%s",
12561                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12562         freeAsmop (pid, NULL, ic, FALSE);
12563         
12564         emitcode ("lcall","System_ProcessResume");
12565
12566         unsavermask(rsave);
12567 }
12568
12569 /*-----------------------------------------------------------------*/
12570 /* genSystem -                                                     */
12571 /*-----------------------------------------------------------------*/
12572 static void genSystem (iCode *ic,int nparms,char *name)
12573 {
12574         assert(nparms == 0);
12575
12576         emitcode ("lcall","System_%s",name);
12577 }
12578
12579 /*-----------------------------------------------------------------*/
12580 /* genSystemPoll -                                                  */
12581 /*-----------------------------------------------------------------*/
12582 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12583 {
12584         bitVect *rsave ;
12585         operand *fp;
12586
12587         assert (nparms==1);
12588         /* save registers that need to be saved */
12589         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12590                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12591
12592         fp = parms[0];
12593         aopOp (fp,ic,FALSE,FALSE);
12594         if (AOP_TYPE (fp) == AOP_IMMD) {
12595                 emitcode ("mov", "dptr,%s", 
12596                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12597         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12598                 emitcode ("mov","dpl,%s",
12599                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12600                 emitcode ("mov","dph,%s",
12601                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12602                 emitcode ("mov","dpx,%s",
12603                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12604         }
12605         freeAsmop (fp, NULL, ic, FALSE);
12606
12607         emitcode ("lcall","System_%sPoll",name);
12608
12609         /* put result into place */
12610         {
12611                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12612                 if (rsym->liveFrom != rsym->liveTo) {   
12613                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12614                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12615                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12616                 }
12617         }
12618         unsavermask(rsave);
12619 }
12620
12621 /*-----------------------------------------------------------------*/
12622 /* genSystemGetCurrentID -                                         */
12623 /*-----------------------------------------------------------------*/
12624 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12625 {
12626         assert (nparms==0);
12627
12628         emitcode ("lcall","System_GetCurrent%sId",name);
12629         /* put result into place */
12630         {
12631                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12632                 if (rsym->liveFrom != rsym->liveTo) {   
12633                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12634                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12635                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12636                 }
12637         }
12638 }
12639
12640 /*-----------------------------------------------------------------*/
12641 /* genDummyRead - generate code for dummy read of volatiles        */
12642 /*-----------------------------------------------------------------*/
12643 static void
12644 genDummyRead (iCode * ic)
12645 {
12646   operand *right;
12647   int size, offset;
12648
12649   D(emitcode(";     genDummyRead",""));
12650
12651   right = IC_RIGHT (ic);
12652
12653   aopOp (right, ic, FALSE, FALSE);
12654
12655   /* if the result is a bit */
12656   if (AOP_TYPE (right) == AOP_CRY)
12657     {
12658       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12659       goto release;
12660     }
12661
12662   /* bit variables done */
12663   /* general case */
12664   size = AOP_SIZE (right);
12665   offset = 0;
12666   while (size--)
12667     {
12668       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12669       offset++;
12670     }
12671
12672 release:
12673   freeAsmop (right, NULL, ic, TRUE);
12674 }
12675
12676 /*-----------------------------------------------------------------*/
12677 /* genBuiltIn - calls the appropriate function to  generating code */
12678 /* for a built in function                                         */
12679 /*-----------------------------------------------------------------*/
12680 static void genBuiltIn (iCode *ic)
12681 {
12682         operand *bi_parms[MAX_BUILTIN_ARGS];
12683         int nbi_parms;
12684         iCode *bi_iCode;
12685         symbol *bif;
12686
12687         /* get all the arguments for a built in function */
12688         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12689
12690         /* which function is it */
12691         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12692         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12693                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12694         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12695                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12696         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12697                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12698         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12699                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12700         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12701                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12702         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12703                 genInp(bi_iCode,nbi_parms,bi_parms);
12704         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12705                 genOutp(bi_iCode,nbi_parms,bi_parms);
12706         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12707                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12708                 /* JavaNative builtIns */               
12709         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12710                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12711         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12712                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12713         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12714                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12715         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12716                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12717         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12718                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12719         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12720                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12721         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12722                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12723         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12724                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12725         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12726                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12727         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12728                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12729         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12730                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12731         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12732                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12733         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12734                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12735         } else if (strcmp(bif->name,"MM_Free")==0) {
12736                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12737         } else if (strcmp(bif->name,"MM_Deref")==0) {
12738                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12739         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12740                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12741         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12742                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12743         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12744                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12745         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12746                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12747         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12748                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12749         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12750                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12751         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12752                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12753         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12754                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12755         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12756                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12757         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12758                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12759         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12760                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12761         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12762                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12763         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12764                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12765         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12766                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12767         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12768                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12769         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12770                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12771         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12772                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12773         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12774                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12775         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12776                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12777         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12778                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12779         } else {
12780                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12781                 return ;
12782         }
12783         return ;    
12784 }
12785
12786 /*-----------------------------------------------------------------*/
12787 /* gen390Code - generate code for Dallas 390 based controllers     */
12788 /*-----------------------------------------------------------------*/
12789 void
12790 gen390Code (iCode * lic)
12791 {
12792   iCode *ic;
12793   int cln = 0;
12794
12795   lineHead = lineCurr = NULL;
12796   dptrn[1][0] = "dpl1";
12797   dptrn[1][1] = "dph1";
12798   dptrn[1][2] = "dpx1";
12799   
12800   if (options.model == MODEL_FLAT24) {
12801     fReturnSizeDS390 = 5;
12802     fReturn = fReturn24;
12803   } else {
12804     fReturnSizeDS390 = 4;
12805     fReturn = fReturn16;
12806     options.stack10bit=0;
12807   }
12808 #if 1
12809   /* print the allocation information */
12810   if (allocInfo && currFunc)
12811     printAllocInfo (currFunc, codeOutFile);
12812 #endif
12813   /* if debug information required */
12814   if (options.debug && currFunc)
12815     {
12816       debugFile->writeFunction(currFunc);
12817       _G.debugLine = 1;
12818       if (IS_STATIC (currFunc->etype))
12819         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12820       else
12821         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12822       _G.debugLine = 0;
12823     }
12824   /* stack pointer name */
12825   if (options.useXstack)
12826     spname = "_spx";
12827   else
12828     spname = "sp";
12829
12830
12831   for (ic = lic; ic; ic = ic->next)
12832     {
12833
12834       if (ic->lineno && cln != ic->lineno)
12835         {
12836           if (options.debug)
12837             {
12838               _G.debugLine = 1;
12839               emitcode ("", "C$%s$%d$%d$%d ==.",
12840                         FileBaseName (ic->filename), ic->lineno,
12841                         ic->level, ic->block);
12842               _G.debugLine = 0;
12843             }
12844           if (!options.noCcodeInAsm) {
12845             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12846                       printCLine(ic->filename, ic->lineno));
12847           }
12848           cln = ic->lineno;
12849         }
12850       if (options.iCodeInAsm) {
12851         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12852       }
12853       /* if the result is marked as
12854          spilt and rematerializable or code for
12855          this has already been generated then
12856          do nothing */
12857       if (resultRemat (ic) || ic->generated)
12858         continue;
12859
12860       /* depending on the operation */
12861       switch (ic->op)
12862         {
12863         case '!':
12864           genNot (ic);
12865           break;
12866
12867         case '~':
12868           genCpl (ic);
12869           break;
12870
12871         case UNARYMINUS:
12872           genUminus (ic);
12873           break;
12874
12875         case IPUSH:
12876           genIpush (ic);
12877           break;
12878
12879         case IPOP:
12880           /* IPOP happens only when trying to restore a
12881              spilt live range, if there is an ifx statement
12882              following this pop then the if statement might
12883              be using some of the registers being popped which
12884              would destory the contents of the register so
12885              we need to check for this condition and handle it */
12886           if (ic->next &&
12887               ic->next->op == IFX &&
12888               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12889             genIfx (ic->next, ic);
12890           else
12891             genIpop (ic);
12892           break;
12893
12894         case CALL:
12895           genCall (ic);
12896           break;
12897
12898         case PCALL:
12899           genPcall (ic);
12900           break;
12901
12902         case FUNCTION:
12903           genFunction (ic);
12904           break;
12905
12906         case ENDFUNCTION:
12907           genEndFunction (ic);
12908           break;
12909
12910         case RETURN:
12911           genRet (ic);
12912           break;
12913
12914         case LABEL:
12915           genLabel (ic);
12916           break;
12917
12918         case GOTO:
12919           genGoto (ic);
12920           break;
12921
12922         case '+':
12923           genPlus (ic);
12924           break;
12925
12926         case '-':
12927           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12928             genMinus (ic);
12929           break;
12930
12931         case '*':
12932           genMult (ic);
12933           break;
12934
12935         case '/':
12936           genDiv (ic);
12937           break;
12938
12939         case '%':
12940           genMod (ic);
12941           break;
12942
12943         case '>':
12944           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12945           break;
12946
12947         case '<':
12948           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12949           break;
12950
12951         case LE_OP:
12952         case GE_OP:
12953         case NE_OP:
12954
12955           /* note these two are xlated by algebraic equivalence
12956              during parsing SDCC.y */
12957           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12958                   "got '>=' or '<=' shouldn't have come here");
12959           break;
12960
12961         case EQ_OP:
12962           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12963           break;
12964
12965         case AND_OP:
12966           genAndOp (ic);
12967           break;
12968
12969         case OR_OP:
12970           genOrOp (ic);
12971           break;
12972
12973         case '^':
12974           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12975           break;
12976
12977         case '|':
12978           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12979           break;
12980
12981         case BITWISEAND:
12982           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12983           break;
12984
12985         case INLINEASM:
12986           genInline (ic);
12987           break;
12988
12989         case RRC:
12990           genRRC (ic);
12991           break;
12992
12993         case RLC:
12994           genRLC (ic);
12995           break;
12996
12997         case GETHBIT:
12998           genGetHbit (ic);
12999           break;
13000
13001         case LEFT_OP:
13002           genLeftShift (ic);
13003           break;
13004
13005         case RIGHT_OP:
13006           genRightShift (ic);
13007           break;
13008
13009         case GET_VALUE_AT_ADDRESS:
13010           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13011           break;
13012
13013         case '=':
13014           if (POINTER_SET (ic))
13015             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13016           else
13017             genAssign (ic);
13018           break;
13019
13020         case IFX:
13021           genIfx (ic, NULL);
13022           break;
13023
13024         case ADDRESS_OF:
13025           genAddrOf (ic);
13026           break;
13027
13028         case JUMPTABLE:
13029           genJumpTab (ic);
13030           break;
13031
13032         case CAST:
13033           genCast (ic);
13034           break;
13035
13036         case RECEIVE:
13037           genReceive (ic);
13038           break;
13039
13040         case SEND:
13041           if (ic->builtinSEND) genBuiltIn(ic);
13042           else addSet (&_G.sendSet, ic);
13043           break;
13044
13045         case DUMMY_READ_VOLATILE:
13046           genDummyRead (ic);
13047           break;
13048
13049 #if 0 // obsolete, and buggy for != xdata
13050         case ARRAYINIT:
13051             genArrayInit(ic);
13052             break;
13053 #endif
13054             
13055         default:
13056           ic = ic;
13057         }
13058     }
13059
13060
13061   /* now we are ready to call the
13062      peep hole optimizer */
13063   if (!options.nopeep)
13064     peepHole (&lineHead);
13065
13066   /* now do the actual printing */
13067   printLine (lineHead, codeOutFile);
13068   return;
13069 }