fixed bug #845089
[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_TYPE(IC_LEFT (ic)) == AOP_DPTR));
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.bInUse++;
2668           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2669           _G.bInUse--;
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       symbol *tlbl = newiTempLabel (NULL);
3198       emitcode ("setb", "c");
3199       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3200       emitcode ("clr", "c");
3201       emitcode ("", "%05d$:", (tlbl->key + 100));
3202       emitcode ("push", "psw"); /* save old ea via c in psw */
3203     }
3204
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208 /* genEndFunction - generates epilogue for functions               */
3209 /*-----------------------------------------------------------------*/
3210 static void
3211 genEndFunction (iCode * ic)
3212 {
3213   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3214
3215   D (emitcode (";", "genEndFunction "););
3216
3217   if (IFFUNC_ISNAKED(sym->type))
3218   {
3219       emitcode(";", "naked function: no epilogue.");
3220       return;
3221   }
3222
3223   if (IFFUNC_ISCRITICAL (sym->type))
3224     {
3225       emitcode ("pop", "psw"); /* restore ea via c in psw */
3226       emitcode ("mov", "ea,c");
3227     }
3228   
3229   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3230        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3231
3232       if (options.stack10bit) {
3233           PROTECT_SP;     
3234           emitcode ("mov", "sp,_bpx", spname);
3235           emitcode ("mov", "esp,_bpx+1", spname);
3236           UNPROTECT_SP;
3237       } else {
3238           emitcode ("mov", "%s,_bp", spname);
3239       }
3240   }
3241
3242   /* if use external stack but some variables were
3243      added to the local stack then decrement the
3244      local stack */
3245   if (options.useXstack && sym->stack) {
3246       emitcode ("mov", "a,sp");
3247       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3248       emitcode ("mov", "sp,a");
3249   }
3250
3251
3252   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3253        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3254
3255       if (options.useXstack) {
3256           emitcode ("mov", "r0,%s", spname);
3257           emitcode ("movx", "a,@r0");
3258           emitcode ("mov", "_bp,a");
3259           emitcode ("dec", "%s", spname);
3260       } else {
3261           if (options.stack10bit) {
3262               emitcode ("pop", "_bpx+1");
3263               emitcode ("pop", "_bpx");
3264           } else {
3265               emitcode ("pop", "_bp");
3266           }
3267       }
3268   }
3269
3270   /* restore the register bank  */
3271   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3272   {
3273     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3274      || !options.useXstack)
3275     {
3276         /* Special case of ISR using non-zero bank with useXstack
3277          * is handled below.
3278          */
3279         emitcode ("pop", "psw");
3280     }
3281   } 
3282
3283   if (IFFUNC_ISISR (sym->type))
3284       { /* is ISR */  
3285
3286       /* now we need to restore the registers */
3287       /* if this isr has no bank i.e. is going to
3288          run with bank 0 , then we need to save more
3289          registers :-) */
3290       if (!FUNC_REGBANK (sym->type))
3291         {
3292             int i;
3293           /* if this function does not call any other
3294              function then we can be economical and
3295              save only those registers that are used */
3296           if (!IFFUNC_HASFCALL(sym->type))
3297             {
3298
3299               /* if any registers used */
3300               if (sym->regsUsed)
3301                 {
3302                   /* save the registers used */
3303                   for (i = sym->regsUsed->size; i >= 0; i--)
3304                     {
3305                       if (bitVectBitValue (sym->regsUsed, i) ||
3306                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3307                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3308                     }
3309                 }
3310
3311             }
3312           else
3313             {
3314               /* this function has  a function call cannot
3315                  determines register usage so we will have to pop the
3316                  entire bank */
3317               if (options.parms_in_bank1) {
3318                   for (i = 7 ; i >= 0 ; i-- ) {
3319                       emitcode ("pop","%s",rb1regs[i]);
3320                   }
3321               }
3322               unsaveRBank (0, ic, FALSE);
3323             }
3324         }
3325         else
3326         {
3327             /* This ISR uses a non-zero bank.
3328              *
3329              * Restore any register banks saved by genFunction
3330              * in reverse order.
3331              */
3332             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3333             int ix;
3334           
3335             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3336             {
3337                 if (savedBanks & (1 << ix))
3338                 {
3339                     unsaveRBank(ix, NULL, FALSE);
3340                 }
3341             }
3342             
3343             if (options.useXstack)
3344             {
3345                 /* Restore bank AFTER calling unsaveRBank,
3346                  * since it can trash r0.
3347                  */
3348                 emitcode ("pop", "psw");
3349             }
3350         }
3351
3352       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3353         {
3354           if (options.stack10bit)
3355             {
3356               emitcode ("pop", DP2_RESULT_REG);
3357               emitcode ("pop", "dpx1");
3358               emitcode ("pop", "dph1");
3359               emitcode ("pop", "dpl1");
3360             }
3361           emitcode ("pop", "dps");
3362           emitcode ("pop", "dpx");
3363         }
3364       if (!inExcludeList ("dph"))
3365         emitcode ("pop", "dph");
3366       if (!inExcludeList ("dpl"))
3367         emitcode ("pop", "dpl");
3368       if (!inExcludeList ("b"))
3369         emitcode ("pop", "b");
3370       if (!inExcludeList ("acc"))
3371         emitcode ("pop", "acc");
3372
3373       /* if debug then send end of function */
3374       if (options.debug && currFunc) {
3375           _G.debugLine = 1;
3376           emitcode ("", "C$%s$%d$%d$%d ==.",
3377                     FileBaseName (ic->filename), currFunc->lastLine,
3378                     ic->level, ic->block);
3379           if (IS_STATIC (currFunc->etype))
3380             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3381           else
3382             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3383           _G.debugLine = 0;
3384         }
3385
3386       emitcode ("reti", "");
3387     }
3388   else
3389     {
3390       if (IFFUNC_CALLEESAVES(sym->type))
3391         {
3392           int i;
3393
3394           /* if any registers used */
3395           if (sym->regsUsed)
3396             {
3397               /* save the registers used */
3398               for (i = sym->regsUsed->size; i >= 0; i--)
3399                 {
3400                   if (bitVectBitValue (sym->regsUsed, i) ||
3401                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3402                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3403                 }
3404             }
3405
3406         }
3407
3408       /* if debug then send end of function */
3409       if (options.debug && currFunc)
3410         {
3411           _G.debugLine = 1;
3412           emitcode ("", "C$%s$%d$%d$%d ==.",
3413                     FileBaseName (ic->filename), currFunc->lastLine,
3414                     ic->level, ic->block);
3415           if (IS_STATIC (currFunc->etype))
3416             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3417           else
3418             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3419           _G.debugLine = 0;
3420         }
3421
3422       emitcode ("ret", "");
3423     }
3424
3425 }
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genJavaNativeRet - generate code for return JavaNative          */
3429 /*-----------------------------------------------------------------*/
3430 static void genJavaNativeRet(iCode *ic)
3431 {
3432     int i, size;
3433
3434     aopOp (IC_LEFT (ic), ic, FALSE, 
3435            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3436     size = AOP_SIZE (IC_LEFT (ic));
3437
3438     assert (size <= 4);
3439
3440     /* it is assigned to GPR0-R3 then push them */
3441     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3442         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3443         for (i = 0 ; i < size ; i++ ) {
3444             emitcode ("push","%s",
3445                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3446         }
3447         for (i = (size-1) ; i >= 0 ; i--) {
3448             emitcode ("pop","a%s",javaRet[i]);
3449         }
3450     } else {
3451         for (i = 0 ; i < size ; i++) 
3452             emitcode ("mov","%s,%s",javaRet[i],
3453                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3454     }
3455     for (i = size ; i < 4 ; i++ )
3456             emitcode ("mov","%s,#0",javaRet[i]);
3457     return;
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genRet - generate code for return statement                     */
3462 /*-----------------------------------------------------------------*/
3463 static void
3464 genRet (iCode * ic)
3465 {
3466   int size, offset = 0, pushed = 0;
3467
3468   D (emitcode (";", "genRet "););
3469
3470   /* if we have no return value then
3471      just generate the "ret" */
3472   if (!IC_LEFT (ic))
3473     goto jumpret;
3474
3475   /* if this is a JavaNative function then return 
3476      value in different register */
3477   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3478       genJavaNativeRet(ic);
3479       goto jumpret;
3480   }
3481   /* we have something to return then
3482      move the return value into place */
3483   aopOp (IC_LEFT (ic), ic, FALSE, 
3484          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3485   size = AOP_SIZE (IC_LEFT (ic));
3486
3487   _startLazyDPSEvaluation ();
3488   while (size--)
3489     {
3490       char *l;
3491       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3492         {
3493           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3494                       FALSE, TRUE, NULL);
3495           emitcode ("push", "%s", l);
3496           pushed++;
3497         }
3498       else
3499         {
3500           /* Since A is the last element of fReturn,
3501            * is is OK to clobber it in the aopGet.
3502            */
3503           l = aopGet (AOP (IC_LEFT (ic)), offset,
3504                       FALSE, FALSE, NULL);
3505           if (strcmp (fReturn[offset], l))
3506             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3507         }
3508     }
3509   _endLazyDPSEvaluation ();
3510
3511   if (pushed)
3512     {
3513       while (pushed)
3514         {
3515           pushed--;
3516           if (strcmp (fReturn[pushed], "a"))
3517             emitcode ("pop", fReturn[pushed]);
3518           else
3519             emitcode ("pop", "acc");
3520         }
3521     }
3522   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3523
3524 jumpret:
3525   /* generate a jump to the return label
3526      if the next is not the return statement */
3527   if (!(ic->next && ic->next->op == LABEL &&
3528         IC_LABEL (ic->next) == returnLabel))
3529
3530     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3531
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genLabel - generates a label                                    */
3536 /*-----------------------------------------------------------------*/
3537 static void
3538 genLabel (iCode * ic)
3539 {
3540   /* special case never generate */
3541   if (IC_LABEL (ic) == entryLabel)
3542     return;
3543
3544   D (emitcode (";", "genLabel ");
3545     );
3546
3547   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3548 }
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp                                      */
3552 /*-----------------------------------------------------------------*/
3553 static void
3554 genGoto (iCode * ic)
3555 {
3556   D (emitcode (";", "genGoto ");
3557     );
3558   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelBackwards: walks back through the iCode chain looking  */
3563 /* for the given label. Returns number of iCode instructions     */
3564 /* between that label and given ic.          */
3565 /* Returns zero if label not found.          */
3566 /*-----------------------------------------------------------------*/
3567 static int
3568 findLabelBackwards (iCode * ic, int key)
3569 {
3570   int count = 0;
3571
3572   while (ic->prev)
3573     {
3574       ic = ic->prev;
3575       count++;
3576
3577       /* If we have any pushes or pops, we cannot predict the distance.
3578          I don't like this at all, this should be dealt with in the 
3579          back-end */
3580       if (ic->op == IPUSH || ic->op == IPOP) {
3581         return 0;
3582       }
3583
3584       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3585         {
3586           /* printf("findLabelBackwards = %d\n", count); */
3587           return count;
3588         }
3589     }
3590
3591   return 0;
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* genPlusIncr :- does addition with increment if possible         */
3596 /*-----------------------------------------------------------------*/
3597 static bool
3598 genPlusIncr (iCode * ic)
3599 {
3600   unsigned int icount;
3601   unsigned int size = getDataSize (IC_RESULT (ic));
3602
3603   /* will try to generate an increment */
3604   /* if the right side is not a literal
3605      we cannot */
3606   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3607     return FALSE;
3608
3609   /* if the literal value of the right hand side
3610      is greater than 4 then it is not worth it */
3611   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3612     return FALSE;
3613
3614   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3615       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3616       while (icount--) {
3617           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3618       }
3619       return TRUE;
3620   }
3621   /* if increment 16 bits in register */
3622   if (
3623        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3624        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3625        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3626        (size > 1) &&
3627        (icount == 1))
3628     {
3629       symbol  *tlbl;
3630       int     emitTlbl;
3631       int     labelRange;
3632       char    *l;
3633
3634       /* If the next instruction is a goto and the goto target
3635        * is <= 5 instructions previous to this, we can generate
3636        * jumps straight to that target.
3637        */
3638       if (ic->next && ic->next->op == GOTO
3639           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3640           && labelRange <= 5)
3641         {
3642           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3643           tlbl = IC_LABEL (ic->next);
3644           emitTlbl = 0;
3645         }
3646       else
3647         {
3648           tlbl = newiTempLabel (NULL);
3649           emitTlbl = 1;
3650         }
3651         
3652       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3653       emitcode ("inc", "%s", l);
3654       
3655       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656           IS_AOP_PREG (IC_RESULT (ic)))
3657       {   
3658         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659       }
3660       else
3661       {
3662           emitcode ("clr", "a");
3663           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3664       }
3665
3666       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3667       emitcode ("inc", "%s", l);
3668       if (size > 2)
3669         {
3670             if (!strcmp(l, "acc"))
3671             {
3672                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3673             }
3674             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675                      IS_AOP_PREG (IC_RESULT (ic)))
3676             {
3677                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3678             }
3679             else
3680             {
3681                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3682             }
3683
3684             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3685             emitcode ("inc", "%s", l);
3686         }
3687       if (size > 3)
3688         {
3689             if (!strcmp(l, "acc"))
3690             {
3691                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3692             }
3693             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3694                      IS_AOP_PREG (IC_RESULT (ic)))
3695             {
3696                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3697             }
3698             else
3699             {
3700                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3701             }
3702
3703             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3704             emitcode ("inc", "%s", l);  }
3705
3706       if (emitTlbl)
3707         {
3708           emitcode ("", "!tlabeldef", tlbl->key + 100);
3709         }
3710       return TRUE;
3711     }
3712
3713   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3714       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3715       options.model == MODEL_FLAT24 ) {
3716
3717       switch (size) {
3718       case 3:
3719           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3720       case 2:
3721           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3722       case 1:
3723           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3724           break;
3725       }
3726       while (icount--) emitcode ("inc","dptr");      
3727       return TRUE;
3728   }
3729
3730   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3731       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3732       icount <= 5 ) {
3733       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3734       while (icount--) emitcode ("inc","dptr");
3735       emitcode ("mov","dps,#0");
3736       return TRUE;
3737   }
3738
3739   /* if the sizes are greater than 1 then we cannot */
3740   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741       AOP_SIZE (IC_LEFT (ic)) > 1)
3742     return FALSE;
3743
3744   /* we can if the aops of the left & result match or
3745      if they are in registers and the registers are the
3746      same */
3747   if (
3748        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3751     {
3752
3753       if (icount > 3)
3754         {
3755           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3756           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3757           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3758         }
3759       else
3760         {
3761
3762           _startLazyDPSEvaluation ();
3763           while (icount--)
3764             {
3765               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3766             }
3767           _endLazyDPSEvaluation ();
3768         }
3769
3770       return TRUE;
3771     }
3772
3773   return FALSE;
3774 }
3775
3776 /*-----------------------------------------------------------------*/
3777 /* outBitAcc - output a bit in acc                                 */
3778 /*-----------------------------------------------------------------*/
3779 static void
3780 outBitAcc (operand * result)
3781 {
3782   symbol *tlbl = newiTempLabel (NULL);
3783   /* if the result is a bit */
3784   if (AOP_TYPE (result) == AOP_CRY)
3785     {
3786       aopPut (AOP (result), "a", 0);
3787     }
3788   else
3789     {
3790       emitcode ("jz", "!tlabel", tlbl->key + 100);
3791       emitcode ("mov", "a,%s", one);
3792       emitcode ("", "!tlabeldef", tlbl->key + 100);
3793       outAcc (result);
3794     }
3795 }
3796
3797 /*-----------------------------------------------------------------*/
3798 /* genPlusBits - generates code for addition of two bits           */
3799 /*-----------------------------------------------------------------*/
3800 static void
3801 genPlusBits (iCode * ic)
3802 {
3803   D (emitcode (";", "genPlusBits "););
3804     
3805   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3806     {
3807       symbol *lbl = newiTempLabel (NULL);
3808       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810       emitcode ("cpl", "c");
3811       emitcode ("", "!tlabeldef", (lbl->key + 100));
3812       outBitC (IC_RESULT (ic));
3813     }
3814   else
3815     {
3816       emitcode ("clr", "a");
3817       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3818       emitcode ("rlc", "a");
3819       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3820       emitcode ("addc", "a,#0");
3821       outAcc (IC_RESULT (ic));
3822     }
3823 }
3824
3825 static void
3826 adjustArithmeticResult (iCode * ic)
3827 {
3828   if (opIsGptr (IC_RESULT (ic)) &&
3829       opIsGptr (IC_LEFT (ic)) &&
3830       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3831     {
3832       aopPut (AOP (IC_RESULT (ic)),
3833               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3834               GPTRSIZE - 1);
3835     }
3836
3837   if (opIsGptr (IC_RESULT (ic)) &&
3838       opIsGptr (IC_RIGHT (ic)) &&
3839       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3840     {
3841       aopPut (AOP (IC_RESULT (ic)),
3842             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3843               GPTRSIZE - 1);
3844     }
3845
3846   if (opIsGptr (IC_RESULT (ic)) &&
3847       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3848       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3849       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3850       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3851     {
3852       char buff[5];
3853       SNPRINTF (buff, sizeof(buff), 
3854                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3855       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3856     }
3857 }
3858
3859 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3860 // generates the result if possible. If result is generated, returns TRUE; otherwise
3861 // returns false and caller must deal with fact that result isn't aopOp'd.
3862 bool aopOp3(iCode * ic)
3863 {
3864     bool dp1InUse, dp2InUse;
3865     bool useDp2;
3866     
3867     // First, generate the right opcode. DPTR may be used if neither left nor result are
3868     // of type AOP_STR.
3869     
3870 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3871 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3872 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3873 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3874 //      );
3875 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3876 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3877 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3878 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3879 //      );
3880     
3881     // Right uses DPTR unless left or result is an AOP_STR; however,
3882     // if right is an AOP_STR, it must use DPTR regardless.
3883     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3884      && !AOP_IS_STR(IC_RIGHT(ic)))
3885     {
3886         useDp2 = TRUE;
3887     }
3888     else
3889     {
3890         useDp2 = FALSE;
3891     }
3892         
3893     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3894     
3895     // if the right used DPTR, left MUST use DPTR2.
3896     // if the right used DPTR2, left MUST use DPTR.
3897     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3898     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3899     // enabling us to assign DPTR to result.
3900      
3901     if (AOP_USESDPTR(IC_RIGHT(ic)))
3902     {
3903         useDp2 = TRUE;
3904     }
3905     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3906     {
3907         useDp2 = FALSE;
3908     }
3909     else
3910     {
3911         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3912         {
3913             useDp2 = TRUE;
3914         }
3915         else
3916         {
3917             useDp2 = FALSE;
3918         }
3919     }
3920
3921     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3922     
3923     // We've op'd the left & right. So, if left or right are the same operand as result, 
3924     // we know aopOp will succeed, and we can just do it & bail.
3925     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3926         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3927     {
3928 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3929         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3930         return TRUE;
3931     }
3932     
3933     // Note which dptrs are currently in use.
3934     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3935     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3936     
3937     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3938     // generate it.
3939     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3940     {
3941         return FALSE;
3942     }
3943     
3944     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3945     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3946     {
3947         return FALSE;
3948     }
3949     
3950     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3951     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3952     {
3953         return FALSE;
3954     }
3955
3956     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3957
3958     // Some sanity checking...
3959     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3960     {
3961         fprintf(stderr,
3962                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3963                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3964         emitcode(";", ">>> unexpected DPTR here.");
3965     }
3966     
3967     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3968     {
3969         fprintf(stderr,
3970                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3971                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3972         emitcode(";", ">>> unexpected DPTR2 here.");
3973     }    
3974     
3975     return TRUE;
3976 }
3977
3978 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3979 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3980 // will be set TRUE. The caller must then handle the case specially, noting
3981 // that the IC_RESULT operand is not aopOp'd.
3982 // 
3983 #define AOP_OP_3_NOFATAL(ic, rc) \
3984             do { rc = !aopOp3(ic); } while (0)
3985
3986 // aopOp the left & right operands of an ic.
3987 #define AOP_OP_2(ic) \
3988     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3989     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3990
3991 // convienience macro.
3992 #define AOP_SET_LOCALS(ic) \
3993     left = IC_LEFT(ic); \
3994     right = IC_RIGHT(ic); \
3995     result = IC_RESULT(ic);
3996
3997
3998 // Given an integer value of pushedSize bytes on the stack,
3999 // adjust it to be resultSize bytes, either by discarding
4000 // the most significant bytes or by zero-padding.
4001 //
4002 // On exit from this macro, pushedSize will have been adjusted to
4003 // equal resultSize, and ACC may be trashed.
4004 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4005       /* If the pushed data is bigger than the result,          \
4006        * simply discard unused bytes. Icky, but works.          \
4007        */                                                       \
4008       while (pushedSize > resultSize)                           \
4009       {                                                         \
4010           D (emitcode (";", "discarding unused result byte."););\
4011           emitcode ("pop", "acc");                              \
4012           pushedSize--;                                         \
4013       }                                                         \
4014       if (pushedSize < resultSize)                              \
4015       {                                                         \
4016           emitcode ("clr", "a");                                \
4017           /* Conversly, we haven't pushed enough here.          \
4018            * just zero-pad, and all is well.                    \
4019            */                                                   \
4020           while (pushedSize < resultSize)                       \
4021           {                                                     \
4022               emitcode("push", "acc");                          \
4023               pushedSize++;                                     \
4024           }                                                     \
4025       }                                                         \
4026       assert(pushedSize == resultSize);
4027
4028 /*-----------------------------------------------------------------*/
4029 /* genPlus - generates code for addition                           */
4030 /*-----------------------------------------------------------------*/
4031 static void
4032 genPlus (iCode * ic)
4033 {
4034   int size, offset = 0;
4035   bool pushResult;
4036   int rSize;
4037
4038   D (emitcode (";", "genPlus "););
4039
4040   /* special cases :- */
4041   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4042       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4043       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4044       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4045       if (size <= 9) {
4046           while (size--) emitcode ("inc","dptr");
4047       } else {
4048           emitcode ("mov","a,dpl");
4049           emitcode ("add","a,#!constbyte",size & 0xff);
4050           emitcode ("mov","dpl,a");
4051           emitcode ("mov","a,dph");
4052           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4053           emitcode ("mov","dph,a");
4054           emitcode ("mov","a,dpx");
4055           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4056           emitcode ("mov","dpx,a");
4057       }
4058       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4059       return ;
4060   }
4061   if ( IS_SYMOP(IC_LEFT(ic)) && 
4062        OP_SYMBOL(IC_LEFT(ic))->remat &&
4063        isOperandInFarSpace(IC_RIGHT(ic))) {
4064       operand *op = IC_RIGHT(ic);
4065       IC_RIGHT(ic) = IC_LEFT(ic);
4066       IC_LEFT(ic) = op;
4067   }
4068                 
4069   AOP_OP_3_NOFATAL (ic, pushResult);
4070     
4071   if (pushResult)
4072     {
4073       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4074     }
4075
4076   if (!pushResult)
4077     {
4078       /* if literal, literal on the right or
4079          if left requires ACC or right is already
4080          in ACC */
4081       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4082        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4083           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4084         {
4085           operand *t = IC_RIGHT (ic);
4086           IC_RIGHT (ic) = IC_LEFT (ic);
4087           IC_LEFT (ic) = t;
4088           emitcode (";", "Swapped plus args.");
4089         }
4090
4091       /* if both left & right are in bit
4092          space */
4093       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4094           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4095         {
4096           genPlusBits (ic);
4097           goto release;
4098         }
4099
4100       /* if left in bit space & right literal */
4101       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4102           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4103         {
4104           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4105           /* if result in bit space */
4106           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4107             {
4108               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4109                 emitcode ("cpl", "c");
4110               outBitC (IC_RESULT (ic));
4111             }
4112           else
4113             {
4114               size = getDataSize (IC_RESULT (ic));
4115               _startLazyDPSEvaluation ();
4116               while (size--)
4117                 {
4118                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4119                   emitcode ("addc", "a,#0");
4120                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4121                 }
4122               _endLazyDPSEvaluation ();
4123             }
4124           goto release;
4125         }
4126
4127       /* if I can do an increment instead
4128          of add then GOOD for ME */
4129       if (genPlusIncr (ic) == TRUE)
4130         {
4131           emitcode (";", "did genPlusIncr");
4132           goto release;
4133         }
4134
4135     }
4136   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4137
4138   _startLazyDPSEvaluation ();
4139   while (size--)
4140     {
4141       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4142         {
4143           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4144           if (offset == 0)
4145             emitcode ("add", "a,%s",
4146                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4147           else
4148             emitcode ("addc", "a,%s",
4149                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4150         }
4151       else
4152         {
4153           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4154           {
4155               /* right is going to use ACC or we would have taken the
4156                * above branch.
4157                */
4158               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4159        TR_AP("#3");
4160               D(emitcode(";", "+ AOP_ACC special case."););
4161               emitcode("xch", "a, %s", DP2_RESULT_REG);
4162           }
4163           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4164           if (offset == 0)
4165           {
4166             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4167             {
4168          TR_AP("#4");
4169                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4170             }
4171             else
4172             {
4173                 emitcode ("add", "a,%s",
4174                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4175                                   DP2_RESULT_REG));
4176             }
4177           }
4178           else
4179           {
4180             emitcode ("addc", "a,%s",
4181                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4182                           DP2_RESULT_REG));
4183           }
4184         }
4185       if (!pushResult)
4186         {
4187           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4188         }
4189       else
4190         {
4191           emitcode ("push", "acc");
4192         }
4193       offset++;
4194     }
4195   _endLazyDPSEvaluation ();
4196
4197   if (pushResult)
4198     {
4199       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4200
4201       size = getDataSize (IC_LEFT (ic));
4202       rSize = getDataSize (IC_RESULT (ic));
4203
4204       ADJUST_PUSHED_RESULT(size, rSize);
4205
4206       _startLazyDPSEvaluation ();
4207       while (size--)
4208         {
4209           emitcode ("pop", "acc");
4210           aopPut (AOP (IC_RESULT (ic)), "a", size);
4211         }
4212       _endLazyDPSEvaluation ();
4213     }
4214
4215   adjustArithmeticResult (ic);
4216
4217 release:
4218   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusDec :- does subtraction with deccrement if possible     */
4225 /*-----------------------------------------------------------------*/
4226 static bool
4227 genMinusDec (iCode * ic)
4228 {
4229   unsigned int icount;
4230   unsigned int size = getDataSize (IC_RESULT (ic));
4231
4232   /* will try to generate an increment */
4233   /* if the right side is not a literal
4234      we cannot */
4235   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4236     return FALSE;
4237
4238   /* if the literal value of the right hand side
4239      is greater than 4 then it is not worth it */
4240   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4241     return FALSE;
4242
4243   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4244       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4245       while (icount--) {
4246           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4247       }
4248       return TRUE;
4249   }
4250   /* if decrement 16 bits in register */
4251   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4252       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4253       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4254       (size > 1) &&
4255       (icount == 1))
4256     {
4257       symbol *tlbl;
4258       int    emitTlbl;
4259       int    labelRange;
4260       char   *l;
4261
4262       /* If the next instruction is a goto and the goto target
4263          * is <= 5 instructions previous to this, we can generate
4264          * jumps straight to that target.
4265        */
4266       if (ic->next && ic->next->op == GOTO
4267           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4268           && labelRange <= 5)
4269         {
4270           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4271           tlbl = IC_LABEL (ic->next);
4272           emitTlbl = 0;
4273         }
4274       else
4275         {
4276           tlbl = newiTempLabel (NULL);
4277           emitTlbl = 1;
4278         }
4279
4280       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4281       emitcode ("dec", "%s", l);
4282  
4283       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4284           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4285           IS_AOP_PREG (IC_RESULT (ic)))
4286       {     
4287           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4288       }
4289       else
4290       {
4291           emitcode ("mov", "a,#!constbyte",0xff);
4292           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4293       }
4294       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4295       emitcode ("dec", "%s", l);
4296       if (size > 2)
4297         {
4298             if (!strcmp(l, "acc"))
4299             {
4300                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4301             }
4302             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4303                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4304                      IS_AOP_PREG (IC_RESULT (ic)))
4305             {       
4306                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4307             }
4308             else
4309             {
4310                 emitcode ("mov", "a,#!constbyte",0xff);
4311                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4312             }
4313             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4314             emitcode ("dec", "%s", l);
4315         }
4316       if (size > 3)
4317         {
4318             if (!strcmp(l, "acc"))
4319             {
4320                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4321             }
4322             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4323                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4324                      IS_AOP_PREG (IC_RESULT (ic)))
4325             {       
4326                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4327             }
4328             else
4329             {
4330                 emitcode ("mov", "a,#!constbyte",0xff);
4331                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4332             }       
4333             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4334             emitcode ("dec", "%s", l);
4335         }
4336       if (emitTlbl)
4337         {
4338           emitcode ("", "!tlabeldef", tlbl->key + 100);
4339         }
4340       return TRUE;
4341     }
4342
4343   /* if the sizes are greater than 1 then we cannot */
4344   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345       AOP_SIZE (IC_LEFT (ic)) > 1)
4346     return FALSE;
4347
4348   /* we can if the aops of the left & result match or
4349      if they are in registers and the registers are the
4350      same */
4351   if (
4352        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4355     {
4356
4357       _startLazyDPSEvaluation ();
4358       while (icount--)
4359         {
4360           emitcode ("dec", "%s",
4361                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4362         }
4363       _endLazyDPSEvaluation ();
4364
4365       return TRUE;
4366     }
4367
4368   return FALSE;
4369 }
4370
4371 /*-----------------------------------------------------------------*/
4372 /* addSign - complete with sign                                    */
4373 /*-----------------------------------------------------------------*/
4374 static void
4375 addSign (operand * result, int offset, int sign)
4376 {
4377   int size = (getDataSize (result) - offset);
4378   if (size > 0)
4379     {
4380       _startLazyDPSEvaluation();
4381       if (sign)
4382         {
4383           emitcode ("rlc", "a");
4384           emitcode ("subb", "a,acc");
4385           while (size--)
4386           {
4387             aopPut (AOP (result), "a", offset++);
4388           }
4389         }
4390       else
4391       {
4392         while (size--)
4393         {
4394           aopPut (AOP (result), zero, offset++);
4395         }
4396       }
4397       _endLazyDPSEvaluation();
4398     }
4399 }
4400
4401 /*-----------------------------------------------------------------*/
4402 /* genMinusBits - generates code for subtraction  of two bits      */
4403 /*-----------------------------------------------------------------*/
4404 static void
4405 genMinusBits (iCode * ic)
4406 {
4407   symbol *lbl = newiTempLabel (NULL);
4408
4409   D (emitcode (";", "genMinusBits "););
4410
4411   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4412     {
4413       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415       emitcode ("cpl", "c");
4416       emitcode ("", "!tlabeldef", (lbl->key + 100));
4417       outBitC (IC_RESULT (ic));
4418     }
4419   else
4420     {
4421       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422       emitcode ("subb", "a,acc");
4423       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4424       emitcode ("inc", "a");
4425       emitcode ("", "!tlabeldef", (lbl->key + 100));
4426       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4427       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4428     }
4429 }
4430
4431 /*-----------------------------------------------------------------*/
4432 /* genMinus - generates code for subtraction                       */
4433 /*-----------------------------------------------------------------*/
4434 static void
4435 genMinus (iCode * ic)
4436 {
4437     int size, offset = 0;
4438     int rSize;
4439     long lit = 0L;
4440     bool pushResult;
4441
4442     D (emitcode (";", "genMinus "););
4443
4444     AOP_OP_3_NOFATAL(ic, pushResult);   
4445
4446     if (!pushResult)
4447     {
4448       /* special cases :- */
4449       /* if both left & right are in bit space */
4450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4451           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4452         {
4453           genMinusBits (ic);
4454           goto release;
4455         }
4456
4457       /* if I can do an decrement instead
4458          of subtract then GOOD for ME */
4459       if (genMinusDec (ic) == TRUE)
4460         goto release;
4461
4462     }
4463
4464   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4465
4466   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4467     {
4468       CLRC;
4469     }
4470   else
4471     {
4472       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4473       lit = -lit;
4474     }
4475
4476
4477   /* if literal, add a,#-lit, else normal subb */
4478   _startLazyDPSEvaluation ();
4479   while (size--) {
4480       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4481           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4482               emitcode ("mov","b,%s",
4483                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4484               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485               emitcode ("subb","a,b");
4486           } else {
4487               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4488               emitcode ("subb", "a,%s",
4489                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4490                                 DP2_RESULT_REG));
4491           }
4492       } else {
4493           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4494           /* first add without previous c */
4495           if (!offset) {
4496               if (!size && lit==-1) {
4497                   emitcode ("dec", "a");
4498               } else {
4499                   emitcode ("add", "a,#!constbyte",
4500                             (unsigned int) (lit & 0x0FFL));
4501               }
4502           } else {
4503               emitcode ("addc", "a,#!constbyte",
4504                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4505           }
4506       }
4507       
4508       if (pushResult) {
4509           emitcode ("push", "acc");
4510       } else {
4511           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4512       }
4513       offset++;
4514   }
4515   _endLazyDPSEvaluation ();
4516   
4517   if (pushResult)
4518     {
4519       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4520
4521       size = getDataSize (IC_LEFT (ic));
4522       rSize = getDataSize (IC_RESULT (ic));
4523
4524       ADJUST_PUSHED_RESULT(size, rSize);
4525
4526       _startLazyDPSEvaluation ();
4527       while (size--)
4528         {
4529           emitcode ("pop", "acc");
4530           aopPut (AOP (IC_RESULT (ic)), "a", size);
4531         }
4532       _endLazyDPSEvaluation ();
4533     }
4534
4535   adjustArithmeticResult (ic);
4536
4537 release:
4538   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4541 }
4542
4543
4544 /*-----------------------------------------------------------------*/
4545 /* genMultbits :- multiplication of bits                           */
4546 /*-----------------------------------------------------------------*/
4547 static void
4548 genMultbits (operand * left,
4549              operand * right,
4550              operand * result,
4551              iCode   * ic)
4552 {
4553   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4555   aopOp(result, ic, TRUE, FALSE);
4556   outBitC (result);
4557 }
4558
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4562 /*-----------------------------------------------------------------*/
4563 static void
4564 genMultOneByte (operand * left,
4565                 operand * right,
4566                 operand * result,
4567                 iCode   * ic)
4568 {
4569   sym_link *opetype = operandType (result);
4570   symbol *lbl;
4571
4572
4573   /* (if two literals: the value is computed before) */
4574   /* if one literal, literal on the right */
4575   if (AOP_TYPE (left) == AOP_LIT)
4576     {
4577       operand *t = right;
4578       right = left;
4579       left = t;
4580       emitcode (";", "swapped left and right");
4581     }
4582
4583   if (SPEC_USIGN(opetype)
4584       // ignore the sign of left and right, what else can we do?
4585       || (SPEC_USIGN(operandType(left)) && 
4586           SPEC_USIGN(operandType(right)))) {
4587     // just an unsigned 8*8=8/16 multiply
4588     //emitcode (";","unsigned");
4589     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4590     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4591     emitcode ("mul", "ab");
4592    
4593     _G.accInUse++; _G.bInUse++;
4594     aopOp(result, ic, TRUE, FALSE);
4595       
4596       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4597       {
4598           // this should never happen
4599           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4600                    AOP_SIZE(result), __FILE__, lineno);
4601           exit (1);
4602       }      
4603       
4604     aopPut (AOP (result), "a", 0);
4605     _G.accInUse--; _G.bInUse--;
4606     if (AOP_SIZE(result)==2) 
4607     {
4608       aopPut (AOP (result), "b", 1);
4609     }
4610     return;
4611   }
4612
4613   // we have to do a signed multiply
4614
4615   emitcode (";", "signed");
4616   emitcode ("clr", "F0"); // reset sign flag
4617   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4618
4619   lbl=newiTempLabel(NULL);
4620   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4621   // left side is negative, 8-bit two's complement, this fails for -128
4622   emitcode ("setb", "F0"); // set sign flag
4623   emitcode ("cpl", "a");
4624   emitcode ("inc", "a");
4625
4626   emitcode ("", "!tlabeldef", lbl->key+100);
4627
4628   /* if literal */
4629   if (AOP_TYPE(right)==AOP_LIT) {
4630     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4631     /* AND literal negative */
4632     if ((int) val < 0) {
4633       emitcode ("cpl", "F0"); // complement sign flag
4634       emitcode ("mov", "b,#!constbyte", -val);
4635     } else {
4636       emitcode ("mov", "b,#!constbyte", val);
4637     }
4638   } else {
4639     lbl=newiTempLabel(NULL);
4640     emitcode ("mov", "b,a");
4641     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4642     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4643     // right side is negative, 8-bit two's complement
4644     emitcode ("cpl", "F0"); // complement sign flag
4645     emitcode ("cpl", "a");
4646     emitcode ("inc", "a");
4647     emitcode ("", "!tlabeldef", lbl->key+100);
4648   }
4649   emitcode ("mul", "ab");
4650     
4651   _G.accInUse++;_G.bInUse++;
4652   aopOp(result, ic, TRUE, FALSE);
4653     
4654   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4655   {
4656     // this should never happen
4657       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4658                AOP_SIZE(result), __FILE__, lineno);
4659       exit (1);
4660   }    
4661     
4662   lbl=newiTempLabel(NULL);
4663   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4664   // only ONE op was negative, we have to do a 8/16-bit two's complement
4665   emitcode ("cpl", "a"); // lsb
4666   if (AOP_SIZE(result)==1) {
4667     emitcode ("inc", "a");
4668   } else {
4669     emitcode ("add", "a,#1");
4670     emitcode ("xch", "a,b");
4671     emitcode ("cpl", "a"); // msb
4672     emitcode ("addc", "a,#0");
4673     emitcode ("xch", "a,b");
4674   }
4675
4676   emitcode ("", "!tlabeldef", lbl->key+100);
4677   aopPut (AOP (result), "a", 0);
4678   _G.accInUse--;_G.bInUse--;
4679   if (AOP_SIZE(result)==2) {
4680     aopPut (AOP (result), "b", 1);
4681   }
4682 }
4683
4684 /*-----------------------------------------------------------------*/
4685 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4686 /*-----------------------------------------------------------------*/
4687 static void genMultTwoByte (operand *left, operand *right, 
4688                             operand *result, iCode *ic)
4689 {
4690         sym_link *retype = getSpec(operandType(right));
4691         sym_link *letype = getSpec(operandType(left));
4692         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4693         symbol *lbl;
4694
4695         if (AOP_TYPE (left) == AOP_LIT) {
4696                 operand *t = right;
4697                 right = left;
4698                 left = t;
4699         }
4700         /* save EA bit in F1 */
4701         lbl = newiTempLabel(NULL);
4702         emitcode ("setb","F1");
4703         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4704         emitcode ("clr","F1");
4705         emitcode("","!tlabeldef",lbl->key+100);
4706
4707         /* load up MB with right */
4708         if (!umult) {
4709                 emitcode("clr","F0");
4710                 if (AOP_TYPE(right) == AOP_LIT) {
4711                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4712                         if (val < 0) {
4713                                 emitcode("setb","F0");
4714                                 val = -val;
4715                         }
4716                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4717                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4718                 } else {
4719                         lbl = newiTempLabel(NULL);
4720                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4721                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4722                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4723                         emitcode ("xch", "a,b");
4724                         emitcode ("cpl","a");
4725                         emitcode ("add", "a,#1");
4726                         emitcode ("xch", "a,b");
4727                         emitcode ("cpl", "a"); // msb
4728                         emitcode ("addc", "a,#0");
4729                         emitcode ("setb","F0");
4730                         emitcode ("","!tlabeldef",lbl->key+100);
4731                         emitcode ("mov","mb,b");
4732                         emitcode ("mov","mb,a");
4733                 }
4734         } else {
4735                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4736                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4737         }
4738         /* load up MA with left */
4739         if (!umult) {
4740                 lbl = newiTempLabel(NULL);
4741                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4742                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4743                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4744                 emitcode ("xch", "a,b");
4745                 emitcode ("cpl","a");
4746                 emitcode ("add", "a,#1");
4747                 emitcode ("xch", "a,b");
4748                 emitcode ("cpl", "a"); // msb
4749                 emitcode ("addc","a,#0");
4750                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4751                 emitcode ("setb","F0");
4752                 emitcode ("","!tlabeldef",lbl->key+100);
4753                 emitcode ("mov","ma,b");
4754                 emitcode ("mov","ma,a");
4755         } else {
4756                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4757                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4758         }
4759         /* wait for multiplication to finish */
4760         lbl = newiTempLabel(NULL);
4761         emitcode("","!tlabeldef", lbl->key+100);
4762         emitcode("mov","a,mcnt1");
4763         emitcode("anl","a,#!constbyte",0x80);
4764         emitcode("jnz","!tlabel",lbl->key+100);
4765         
4766         freeAsmop (left, NULL, ic, TRUE);
4767         freeAsmop (right, NULL, ic,TRUE);
4768         aopOp(result, ic, TRUE, FALSE);
4769
4770         /* if unsigned then simple */   
4771         if (umult) {
4772                 emitcode ("mov","a,ma");
4773                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4774                 emitcode ("mov","a,ma");
4775                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4776                 aopPut(AOP(result),"ma",1);
4777                 aopPut(AOP(result),"ma",0);
4778         } else {
4779                 emitcode("push","ma");
4780                 emitcode("push","ma");
4781                 emitcode("push","ma");
4782                 MOVA("ma");
4783                 /* negate result if needed */
4784                 lbl = newiTempLabel(NULL);      
4785                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786                 emitcode("cpl","a");
4787                 emitcode("add","a,#1");
4788                 emitcode("","!tlabeldef", lbl->key+100);
4789                 if (AOP_TYPE(result) == AOP_ACC)
4790                 {
4791                     D(emitcode(";", "ACC special case."););
4792                     /* We know result is the only live aop, and 
4793                      * it's obviously not a DPTR2, so AP is available.
4794                      */
4795                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4796                 }
4797                 else
4798                 {
4799                     aopPut(AOP(result),"a",0);
4800                 }
4801             
4802                 emitcode("pop","acc");
4803                 lbl = newiTempLabel(NULL);      
4804                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4805                 emitcode("cpl","a");
4806                 emitcode("addc","a,#0");
4807                 emitcode("","!tlabeldef", lbl->key+100);
4808                 aopPut(AOP(result),"a",1);
4809                 emitcode("pop","acc");
4810                 if (AOP_SIZE(result) >= 3) {
4811                         lbl = newiTempLabel(NULL);      
4812                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4813                         emitcode("cpl","a");
4814                         emitcode("addc","a,#0");                        
4815                         emitcode("","!tlabeldef", lbl->key+100);
4816                         aopPut(AOP(result),"a",2);
4817                 }
4818                 emitcode("pop","acc");
4819                 if (AOP_SIZE(result) >= 4) {
4820                         lbl = newiTempLabel(NULL);      
4821                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4822                         emitcode("cpl","a");
4823                         emitcode("addc","a,#0");                        
4824                         emitcode("","!tlabeldef", lbl->key+100);
4825                         aopPut(AOP(result),"a",3);
4826                 }
4827                 if (AOP_TYPE(result) == AOP_ACC)
4828                 {
4829                     /* We stashed the result away above. */
4830                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4831                 }           
4832                 
4833         }
4834         freeAsmop (result, NULL, ic, TRUE);
4835
4836         /* restore EA bit in F1 */
4837         lbl = newiTempLabel(NULL);
4838         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4839         emitcode ("setb","EA");
4840         emitcode("","!tlabeldef",lbl->key+100);
4841         return ;
4842 }
4843
4844 /*-----------------------------------------------------------------*/
4845 /* genMult - generates code for multiplication                     */
4846 /*-----------------------------------------------------------------*/
4847 static void
4848 genMult (iCode * ic)
4849 {
4850   operand *left = IC_LEFT (ic);
4851   operand *right = IC_RIGHT (ic);
4852   operand *result = IC_RESULT (ic);
4853
4854   D (emitcode (";", "genMult "););
4855
4856   /* assign the amsops */
4857   AOP_OP_2 (ic);
4858
4859   /* special cases first */
4860   /* both are bits */
4861   if (AOP_TYPE (left) == AOP_CRY &&
4862       AOP_TYPE (right) == AOP_CRY)
4863     {
4864       genMultbits (left, right, result, ic);
4865       goto release;
4866     }
4867
4868   /* if both are of size == 1 */
4869   if (AOP_SIZE (left) == 1 &&
4870       AOP_SIZE (right) == 1)
4871     {
4872       genMultOneByte (left, right, result, ic);
4873       goto release;
4874     }
4875
4876   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4877           /* use the ds390 ARITHMETIC accel UNIT */
4878           genMultTwoByte (left, right, result, ic);
4879           return ;
4880   }
4881   /* should have been converted to function call */
4882   assert (0);
4883
4884 release:
4885   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887   freeAsmop (result, NULL, ic, TRUE);
4888 }
4889
4890 /*-----------------------------------------------------------------*/
4891 /* genDivbits :- division of bits                                  */
4892 /*-----------------------------------------------------------------*/
4893 static void
4894 genDivbits (operand * left,
4895             operand * right,
4896             operand * result,
4897             iCode   * ic)
4898 {
4899
4900   char *l;
4901
4902   /* the result must be bit */
4903   LOAD_AB_FOR_DIV (left, right, l);
4904   emitcode ("div", "ab");
4905   emitcode ("rrc", "a");
4906   aopOp(result, ic, TRUE, FALSE);
4907     
4908   aopPut (AOP (result), "c", 0);
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division                                  */
4913 /*-----------------------------------------------------------------*/
4914 static void
4915 genDivOneByte (operand * left,
4916                operand * right,
4917                operand * result,
4918                iCode   * ic)
4919 {
4920   sym_link *opetype = operandType (result);
4921   char *l;
4922   symbol *lbl;
4923   int size, offset;
4924
4925   offset = 1;
4926   /* signed or unsigned */
4927   if (SPEC_USIGN (opetype))
4928     {
4929         /* unsigned is easy */
4930         LOAD_AB_FOR_DIV (left, right, l);
4931         emitcode ("div", "ab");
4932
4933         _G.accInUse++;
4934         aopOp(result, ic, TRUE, FALSE);
4935         aopPut (AOP (result), "a", 0);
4936         _G.accInUse--;
4937
4938         size = AOP_SIZE (result) - 1;
4939         
4940         while (size--)
4941         {
4942             aopPut (AOP (result), zero, offset++);
4943         }
4944       return;
4945     }
4946
4947   /* signed is a little bit more difficult */
4948
4949   /* save the signs of the operands */
4950   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4951   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4952   emitcode ("push", "acc");     /* save it on the stack */
4953
4954   /* now sign adjust for both left & right */
4955   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4956   lbl = newiTempLabel (NULL);
4957   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4958   emitcode ("cpl", "a");
4959   emitcode ("inc", "a");
4960   emitcode ("", "!tlabeldef", (lbl->key + 100));
4961   emitcode ("mov", "b,a");
4962
4963   /* sign adjust left side */
4964   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4965
4966   lbl = newiTempLabel (NULL);
4967   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4968   emitcode ("cpl", "a");
4969   emitcode ("inc", "a");
4970   emitcode ("", "!tlabeldef", (lbl->key + 100));
4971
4972   /* now the division */
4973   emitcode ("nop", "; workaround for DS80C390 div bug.");
4974   emitcode ("div", "ab");
4975   /* we are interested in the lower order
4976      only */
4977   emitcode ("mov", "b,a");
4978   lbl = newiTempLabel (NULL);
4979   emitcode ("pop", "acc");
4980   /* if there was an over flow we don't
4981      adjust the sign of the result */
4982   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4983   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4984   CLRC;
4985   emitcode ("clr", "a");
4986   emitcode ("subb", "a,b");
4987   emitcode ("mov", "b,a");
4988   emitcode ("", "!tlabeldef", (lbl->key + 100));
4989
4990   /* now we are done */
4991   _G.accInUse++;     _G.bInUse++;
4992     aopOp(result, ic, TRUE, FALSE);
4993     
4994     aopPut (AOP (result), "b", 0);
4995     
4996     size = AOP_SIZE (result) - 1;
4997     
4998     if (size > 0)
4999     {
5000       emitcode ("mov", "c,b.7");
5001       emitcode ("subb", "a,acc");
5002     }
5003     while (size--)
5004     {
5005         aopPut (AOP (result), "a", offset++);
5006     }
5007     _G.accInUse--;     _G.bInUse--;
5008
5009 }
5010
5011 /*-----------------------------------------------------------------*/
5012 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5013 /*-----------------------------------------------------------------*/
5014 static void genDivTwoByte (operand *left, operand *right, 
5015                             operand *result, iCode *ic)
5016 {
5017         sym_link *retype = getSpec(operandType(right));
5018         sym_link *letype = getSpec(operandType(left));
5019         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5020         symbol *lbl;
5021
5022         /* save EA bit in F1 */
5023         lbl = newiTempLabel(NULL);
5024         emitcode ("setb","F1");
5025         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5026         emitcode ("clr","F1");
5027         emitcode("","!tlabeldef",lbl->key+100);
5028
5029         /* load up MA with left */
5030         if (!umult) {
5031                 emitcode("clr","F0");
5032                 lbl = newiTempLabel(NULL);
5033                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5034                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5035                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5036                 emitcode ("xch", "a,b");
5037                 emitcode ("cpl","a");
5038                 emitcode ("add", "a,#1");
5039                 emitcode ("xch", "a,b");
5040                 emitcode ("cpl", "a"); // msb
5041                 emitcode ("addc","a,#0");
5042                 emitcode ("setb","F0");
5043                 emitcode ("","!tlabeldef",lbl->key+100);
5044                 emitcode ("mov","ma,b");
5045                 emitcode ("mov","ma,a");
5046         } else {
5047                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5048                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5049         }
5050
5051         /* load up MB with right */
5052         if (!umult) {
5053                 if (AOP_TYPE(right) == AOP_LIT) {
5054                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5055                         if (val < 0) {
5056                                 lbl = newiTempLabel(NULL);
5057                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058                                 emitcode("setb","F0");
5059                                 emitcode ("","!tlabeldef",lbl->key+100);
5060                                 val = -val;
5061                         } 
5062                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5063                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5064                 } else {
5065                         lbl = newiTempLabel(NULL);
5066                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5067                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5069                         emitcode ("xch", "a,b");
5070                         emitcode ("cpl","a");
5071                         emitcode ("add", "a,#1");
5072                         emitcode ("xch", "a,b");
5073                         emitcode ("cpl", "a"); // msb
5074                         emitcode ("addc", "a,#0");
5075                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5076                         emitcode ("setb","F0");
5077                         emitcode ("","!tlabeldef",lbl->key+100);
5078                         emitcode ("mov","mb,b");
5079                         emitcode ("mov","mb,a");
5080                 }
5081         } else {
5082                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5083                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5084         }
5085
5086         /* wait for multiplication to finish */
5087         lbl = newiTempLabel(NULL);
5088         emitcode("","!tlabeldef", lbl->key+100);
5089         emitcode("mov","a,mcnt1");
5090         emitcode("anl","a,#!constbyte",0x80);
5091         emitcode("jnz","!tlabel",lbl->key+100);
5092         
5093         freeAsmop (left, NULL, ic, TRUE);
5094         freeAsmop (right, NULL, ic,TRUE);
5095         aopOp(result, ic, TRUE, FALSE);
5096
5097         /* if unsigned then simple */   
5098         if (umult) {
5099                 aopPut(AOP(result),"ma",1);
5100                 aopPut(AOP(result),"ma",0);
5101         } else {
5102                 emitcode("push","ma");
5103                 MOVA("ma");
5104                 /* negate result if needed */
5105                 lbl = newiTempLabel(NULL);      
5106                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5107                 emitcode("cpl","a");
5108                 emitcode("add","a,#1");
5109                 emitcode("","!tlabeldef", lbl->key+100);
5110                 aopPut(AOP(result),"a",0);
5111                 emitcode("pop","acc");
5112                 lbl = newiTempLabel(NULL);      
5113                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5114                 emitcode("cpl","a");
5115                 emitcode("addc","a,#0");
5116                 emitcode("","!tlabeldef", lbl->key+100);
5117                 aopPut(AOP(result),"a",1);
5118         }
5119         freeAsmop (result, NULL, ic, TRUE);
5120         /* restore EA bit in F1 */
5121         lbl = newiTempLabel(NULL);
5122         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5123         emitcode ("setb","EA");
5124         emitcode("","!tlabeldef",lbl->key+100);
5125         return ;
5126 }
5127
5128 /*-----------------------------------------------------------------*/
5129 /* genDiv - generates code for division                            */
5130 /*-----------------------------------------------------------------*/
5131 static void
5132 genDiv (iCode * ic)
5133 {
5134   operand *left = IC_LEFT (ic);
5135   operand *right = IC_RIGHT (ic);
5136   operand *result = IC_RESULT (ic);
5137
5138   D (emitcode (";", "genDiv "););
5139
5140   /* assign the amsops */
5141   AOP_OP_2 (ic);
5142
5143   /* special cases first */
5144   /* both are bits */
5145   if (AOP_TYPE (left) == AOP_CRY &&
5146       AOP_TYPE (right) == AOP_CRY)
5147     {
5148       genDivbits (left, right, result, ic);
5149       goto release;
5150     }
5151
5152   /* if both are of size == 1 */
5153   if (AOP_SIZE (left) == 1 &&
5154       AOP_SIZE (right) == 1)
5155     {
5156       genDivOneByte (left, right, result, ic);
5157       goto release;
5158     }
5159
5160   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5161           /* use the ds390 ARITHMETIC accel UNIT */
5162           genDivTwoByte (left, right, result, ic);
5163           return ;
5164   }
5165   /* should have been converted to function call */
5166   assert (0);
5167 release:
5168   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5169   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170   freeAsmop (result, NULL, ic, TRUE);
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genModbits :- modulus of bits                                   */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genModbits (operand * left,
5178             operand * right,
5179             operand * result,
5180             iCode   * ic)
5181 {
5182
5183   char *l;
5184
5185   /* the result must be bit */
5186   LOAD_AB_FOR_DIV (left, right, l);
5187   emitcode ("div", "ab");
5188   emitcode ("mov", "a,b");
5189   emitcode ("rrc", "a");
5190   aopOp(result, ic, TRUE, FALSE);
5191   aopPut (AOP (result), "c", 0);
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* genModOneByte : 8 bit modulus                                   */
5196 /*-----------------------------------------------------------------*/
5197 static void
5198 genModOneByte (operand * left,
5199                operand * right,
5200                operand * result,
5201                iCode   * ic)
5202 {
5203   sym_link *opetype = operandType (result);
5204   char *l;
5205   symbol *lbl;
5206
5207   /* signed or unsigned */
5208   if (SPEC_USIGN (opetype))
5209     {
5210       /* unsigned is easy */
5211       LOAD_AB_FOR_DIV (left, right, l);
5212       emitcode ("div", "ab");
5213       aopOp(result, ic, TRUE, FALSE);   
5214       aopPut (AOP (result), "b", 0);
5215       return;
5216     }
5217
5218   /* signed is a little bit more difficult */
5219
5220   /* save the signs of the operands */
5221   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5222
5223   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5224   emitcode ("push", "acc");     /* save it on the stack */
5225
5226   /* now sign adjust for both left & right */
5227   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5228
5229   lbl = newiTempLabel (NULL);
5230   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5231   emitcode ("cpl", "a");
5232   emitcode ("inc", "a");
5233   emitcode ("", "!tlabeldef", (lbl->key + 100));
5234   emitcode ("mov", "b,a");
5235
5236   /* sign adjust left side */
5237   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5238
5239   lbl = newiTempLabel (NULL);
5240   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5241   emitcode ("cpl", "a");
5242   emitcode ("inc", "a");
5243   emitcode ("", "!tlabeldef", (lbl->key + 100));
5244
5245   /* now the multiplication */
5246   emitcode ("nop", "; workaround for DS80C390 div bug.");
5247   emitcode ("div", "ab");
5248   /* we are interested in the lower order
5249      only */
5250   lbl = newiTempLabel (NULL);
5251   emitcode ("pop", "acc");
5252   /* if there was an over flow we don't
5253      adjust the sign of the result */
5254   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5255   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5256   CLRC;
5257   emitcode ("clr", "a");
5258   emitcode ("subb", "a,b");
5259   emitcode ("mov", "b,a");
5260   emitcode ("", "!tlabeldef", (lbl->key + 100));
5261   
5262   _G.bInUse++;
5263   /* now we are done */
5264   aopOp(result, ic, TRUE, FALSE);    
5265   aopPut (AOP (result), "b", 0);
5266   _G.bInUse--;
5267
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5272 /*-----------------------------------------------------------------*/
5273 static void genModTwoByte (operand *left, operand *right, 
5274                             operand *result, iCode *ic)
5275 {
5276         sym_link *retype = getSpec(operandType(right));
5277         sym_link *letype = getSpec(operandType(left));
5278         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5279         symbol *lbl;
5280
5281         /* load up MA with left */
5282         /* save EA bit in F1 */
5283         lbl = newiTempLabel(NULL);
5284         emitcode ("setb","F1");
5285         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5286         emitcode ("clr","F1");
5287         emitcode("","!tlabeldef",lbl->key+100);
5288
5289         if (!umult) {
5290                 lbl = newiTempLabel(NULL);
5291                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5294                 emitcode ("xch", "a,b");
5295                 emitcode ("cpl","a");
5296                 emitcode ("add", "a,#1");
5297                 emitcode ("xch", "a,b");
5298                 emitcode ("cpl", "a"); // msb
5299                 emitcode ("addc","a,#0");
5300                 emitcode ("","!tlabeldef",lbl->key+100);
5301                 emitcode ("mov","ma,b");
5302                 emitcode ("mov","ma,a");
5303         } else {
5304                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5305                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5306         }
5307
5308         /* load up MB with right */
5309         if (!umult) {
5310                 if (AOP_TYPE(right) == AOP_LIT) {
5311                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5312                         if (val < 0) {
5313                                 val = -val;
5314                         } 
5315                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5316                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5317                 } else {
5318                         lbl = newiTempLabel(NULL);
5319                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5320                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5321                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5322                         emitcode ("xch", "a,b");
5323                         emitcode ("cpl","a");
5324                         emitcode ("add", "a,#1");
5325                         emitcode ("xch", "a,b");
5326                         emitcode ("cpl", "a"); // msb
5327                         emitcode ("addc", "a,#0");
5328                         emitcode ("","!tlabeldef",lbl->key+100);
5329                         emitcode ("mov","mb,b");
5330                         emitcode ("mov","mb,a");
5331                 }
5332         } else {
5333                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5334                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5335         }
5336
5337         /* wait for multiplication to finish */
5338         lbl = newiTempLabel(NULL);
5339         emitcode("","!tlabeldef", lbl->key+100);
5340         emitcode("mov","a,mcnt1");
5341         emitcode("anl","a,#!constbyte",0x80);
5342         emitcode("jnz","!tlabel",lbl->key+100);
5343         
5344         freeAsmop (left, NULL, ic, TRUE);
5345         freeAsmop (right, NULL, ic,TRUE);
5346         aopOp(result, ic, TRUE, FALSE);
5347
5348         aopPut(AOP(result),"mb",1);
5349         aopPut(AOP(result),"mb",0);
5350         freeAsmop (result, NULL, ic, TRUE);
5351
5352         /* restore EA bit in F1 */
5353         lbl = newiTempLabel(NULL);
5354         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5355         emitcode ("setb","EA");
5356         emitcode("","!tlabeldef",lbl->key+100);
5357         return ;
5358 }
5359
5360 /*-----------------------------------------------------------------*/
5361 /* genMod - generates code for division                            */
5362 /*-----------------------------------------------------------------*/
5363 static void
5364 genMod (iCode * ic)
5365 {
5366   operand *left = IC_LEFT (ic);
5367   operand *right = IC_RIGHT (ic);
5368   operand *result = IC_RESULT (ic);
5369
5370   D (emitcode (";", "genMod "); );
5371
5372   /* assign the amsops */
5373   AOP_OP_2 (ic);
5374
5375   /* special cases first */
5376   /* both are bits */
5377   if (AOP_TYPE (left) == AOP_CRY &&
5378       AOP_TYPE (right) == AOP_CRY)
5379     {
5380       genModbits (left, right, result, ic);
5381       goto release;
5382     }
5383
5384   /* if both are of size == 1 */
5385   if (AOP_SIZE (left) == 1 &&
5386       AOP_SIZE (right) == 1)
5387     {
5388       genModOneByte (left, right, result, ic);
5389       goto release;
5390     }
5391
5392   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5393           /* use the ds390 ARITHMETIC accel UNIT */
5394           genModTwoByte (left, right, result, ic);
5395           return ;
5396   }
5397
5398   /* should have been converted to function call */
5399   assert (0);
5400
5401 release:
5402   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404   freeAsmop (result, NULL, ic, TRUE);
5405 }
5406
5407 /*-----------------------------------------------------------------*/
5408 /* genIfxJump :- will create a jump depending on the ifx           */
5409 /*-----------------------------------------------------------------*/
5410 static void
5411 genIfxJump (iCode * ic, char *jval)
5412 {
5413   symbol *jlbl;
5414   symbol *tlbl = newiTempLabel (NULL);
5415   char *inst;
5416
5417   D (emitcode (";", "genIfxJump"););
5418
5419   /* if true label then we jump if condition
5420      supplied is true */
5421   if (IC_TRUE (ic))
5422     {
5423       jlbl = IC_TRUE (ic);
5424       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5425                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5426     }
5427   else
5428     {
5429       /* false label is present */
5430       jlbl = IC_FALSE (ic);
5431       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5432                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5433     }
5434   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5435     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5436   else
5437     emitcode (inst, "!tlabel", tlbl->key + 100);
5438   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5439   emitcode ("", "!tlabeldef", tlbl->key + 100);
5440
5441   /* mark the icode as generated */
5442   ic->generated = 1;
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genCmp :- greater or less than comparison                       */
5447 /*-----------------------------------------------------------------*/
5448 static void
5449 genCmp (operand * left, operand * right,
5450         iCode * ic, iCode * ifx, int sign)
5451 {
5452   int size, offset = 0;
5453   unsigned long lit = 0L;
5454   operand *result;
5455
5456   D (emitcode (";", "genCmp"););
5457
5458   result = IC_RESULT (ic);
5459
5460   /* if left & right are bit variables */
5461   if (AOP_TYPE (left) == AOP_CRY &&
5462       AOP_TYPE (right) == AOP_CRY)
5463     {
5464       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5465       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5466     }
5467   else
5468     {
5469       /* subtract right from left if at the
5470          end the carry flag is set then we know that
5471          left is greater than right */
5472       size = max (AOP_SIZE (left), AOP_SIZE (right));
5473
5474       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5475       if ((size == 1) && !sign 
5476           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5477         {
5478           symbol *lbl = newiTempLabel (NULL);
5479           emitcode ("cjne", "%s,%s,!tlabel",
5480                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5481                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5482                     lbl->key + 100);
5483           emitcode ("", "!tlabeldef", lbl->key + 100);
5484         }
5485       else
5486         {
5487           if (AOP_TYPE (right) == AOP_LIT)
5488             {
5489               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5490               /* optimize if(x < 0) or if(x >= 0) */
5491               if (lit == 0L)
5492                 {
5493                   if (!sign)
5494                     {
5495                       CLRC;
5496                     }
5497                   else
5498                     {
5499                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5500
5501                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503
5504                       aopOp (result, ic, FALSE, FALSE);
5505
5506                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5507                         {
5508                           freeAsmop (result, NULL, ic, TRUE);
5509                           genIfxJump (ifx, "acc.7");
5510                           return;
5511                         }
5512                       else
5513                         {
5514                           emitcode ("rlc", "a");
5515                         }
5516                       goto release_freedLR;
5517                     }
5518                   goto release;
5519                 }
5520             }
5521           CLRC;
5522           while (size--)
5523             {
5524               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5525               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5526               // emitcode (";", "genCmp #2");
5527               if (sign && (size == 0))
5528                 {
5529                   // emitcode (";", "genCmp #3");
5530                   emitcode ("xrl", "a,#!constbyte",0x80);
5531                   if (AOP_TYPE (right) == AOP_LIT)
5532                     {
5533                       unsigned long lit = (unsigned long)
5534                       floatFromVal (AOP (right)->aopu.aop_lit);
5535                       // emitcode (";", "genCmp #3.1");
5536                       emitcode ("subb", "a,#!constbyte",
5537                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5538                     }
5539                   else
5540                     {
5541                       // emitcode (";", "genCmp #3.2");
5542                       saveAccWarn = 0;  
5543                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5544                       saveAccWarn = DEFAULT_ACC_WARNING;
5545                       emitcode ("xrl", "b,#!constbyte",0x80);
5546                       emitcode ("subb", "a,b");
5547                     }
5548                 }
5549               else
5550                 {
5551                   const char *s;
5552
5553                   // emitcode (";", "genCmp #4");
5554                   saveAccWarn = 0;
5555                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5556                   saveAccWarn = DEFAULT_ACC_WARNING;
5557
5558                   emitcode ("subb", "a,%s", s);
5559                 }
5560             }
5561         }
5562     }
5563
5564 release:
5565 /* Don't need the left & right operands any more; do need the result. */
5566   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568
5569   aopOp (result, ic, FALSE, FALSE);
5570
5571 release_freedLR:
5572
5573   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5574     {
5575       outBitC (result);
5576     }
5577   else
5578     {
5579       /* if the result is used in the next
5580          ifx conditional branch then generate
5581          code a little differently */
5582       if (ifx)
5583         {
5584           genIfxJump (ifx, "c");
5585         }
5586       else
5587         {
5588           outBitC (result);
5589         }
5590       /* leave the result in acc */
5591     }
5592   freeAsmop (result, NULL, ic, TRUE);
5593 }
5594
5595 /*-----------------------------------------------------------------*/
5596 /* genCmpGt :- greater than comparison                             */
5597 /*-----------------------------------------------------------------*/
5598 static void
5599 genCmpGt (iCode * ic, iCode * ifx)
5600 {
5601   operand *left, *right;
5602   sym_link *letype, *retype;
5603   int sign;
5604
5605   D (emitcode (";", "genCmpGt ");
5606     );
5607
5608   left = IC_LEFT (ic);
5609   right = IC_RIGHT (ic);
5610
5611   letype = getSpec (operandType (left));
5612   retype = getSpec (operandType (right));
5613   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5614
5615   /* assign the left & right amsops */
5616   AOP_OP_2 (ic);
5617
5618   genCmp (right, left, ic, ifx, sign);
5619 }
5620
5621 /*-----------------------------------------------------------------*/
5622 /* genCmpLt - less than comparisons                                */
5623 /*-----------------------------------------------------------------*/
5624 static void
5625 genCmpLt (iCode * ic, iCode * ifx)
5626 {
5627   operand *left, *right;
5628   sym_link *letype, *retype;
5629   int sign;
5630
5631   D (emitcode (";", "genCmpLt "););
5632
5633   left = IC_LEFT (ic);
5634   right = IC_RIGHT (ic);
5635
5636   letype = getSpec (operandType (left));
5637   retype = getSpec (operandType (right));
5638   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5639
5640   /* assign the left & right amsops */
5641   AOP_OP_2 (ic);
5642
5643   genCmp (left, right, ic, ifx, sign);
5644 }
5645
5646 /*-----------------------------------------------------------------*/
5647 /* gencjneshort - compare and jump if not equal                    */
5648 /*-----------------------------------------------------------------*/
5649 static void
5650 gencjneshort (operand * left, operand * right, symbol * lbl)
5651 {
5652   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5653   int offset = 0;
5654   unsigned long lit = 0L;
5655
5656   D (emitcode (";", "gencjneshort");
5657     );
5658
5659   /* if the left side is a literal or
5660      if the right is in a pointer register and left
5661      is not */
5662   if ((AOP_TYPE (left) == AOP_LIT) ||
5663       (AOP_TYPE (left) == AOP_IMMD) ||
5664       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5665     {
5666       operand *t = right;
5667       right = left;
5668       left = t;
5669     }
5670
5671   if (AOP_TYPE (right) == AOP_LIT)
5672     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5673
5674   if (opIsGptr (left) || opIsGptr (right))
5675     {
5676       /* We are comparing a generic pointer to something.
5677        * Exclude the generic type byte from the comparison.
5678        */
5679       size--;
5680       D (emitcode (";", "cjneshort: generic ptr special case."););
5681     }
5682
5683
5684   /* if the right side is a literal then anything goes */
5685   if (AOP_TYPE (right) == AOP_LIT &&
5686       AOP_TYPE (left) != AOP_DIR)
5687     {
5688       while (size--)
5689         {
5690           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5691           emitcode ("cjne", "a,%s,!tlabel",
5692                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5693                     lbl->key + 100);
5694           offset++;
5695         }
5696     }
5697
5698   /* if the right side is in a register or in direct space or
5699      if the left is a pointer register & right is not */
5700   else if (AOP_TYPE (right) == AOP_REG ||
5701            AOP_TYPE (right) == AOP_DIR ||
5702            AOP_TYPE (right) == AOP_LIT ||
5703            AOP_TYPE (right) == AOP_IMMD ||
5704            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5706     {
5707       while (size--)
5708         {
5709           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712             emitcode ("jnz", "!tlabel", lbl->key + 100);
5713           else
5714             emitcode ("cjne", "a,%s,!tlabel",
5715                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5716                       lbl->key + 100);
5717           offset++;
5718         }
5719     }
5720   else
5721     {
5722       /* right is a pointer reg need both a & b */
5723       while (size--)
5724         {
5725           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5726           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5727           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5728           offset++;
5729         }
5730     }
5731 }
5732
5733 /*-----------------------------------------------------------------*/
5734 /* gencjne - compare and jump if not equal                         */
5735 /*-----------------------------------------------------------------*/
5736 static void
5737 gencjne (operand * left, operand * right, symbol * lbl)
5738 {
5739   symbol *tlbl = newiTempLabel (NULL);
5740
5741   D (emitcode (";", "gencjne");
5742     );
5743
5744   gencjneshort (left, right, lbl);
5745
5746   emitcode ("mov", "a,%s", one);
5747   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5748   emitcode ("", "!tlabeldef", lbl->key + 100);
5749   emitcode ("clr", "a");
5750   emitcode ("", "!tlabeldef", tlbl->key + 100);
5751 }
5752
5753 /*-----------------------------------------------------------------*/
5754 /* genCmpEq - generates code for equal to                          */
5755 /*-----------------------------------------------------------------*/
5756 static void
5757 genCmpEq (iCode * ic, iCode * ifx)
5758 {
5759   operand *left, *right, *result;
5760
5761   D (emitcode (";", "genCmpEq ");
5762     );
5763
5764   AOP_OP_2 (ic);
5765   AOP_SET_LOCALS (ic);
5766
5767   /* if literal, literal on the right or
5768      if the right is in a pointer register and left
5769      is not */
5770   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5771       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5772     {
5773       operand *t = IC_RIGHT (ic);
5774       IC_RIGHT (ic) = IC_LEFT (ic);
5775       IC_LEFT (ic) = t;
5776     }
5777
5778   if (ifx &&                    /* !AOP_SIZE(result) */
5779       OP_SYMBOL (result) &&
5780       OP_SYMBOL (result)->regType == REG_CND)
5781     {
5782       symbol *tlbl;
5783       /* if they are both bit variables */
5784       if (AOP_TYPE (left) == AOP_CRY &&
5785           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5786         {
5787           if (AOP_TYPE (right) == AOP_LIT)
5788             {
5789               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5790               if (lit == 0L)
5791                 {
5792                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793                   emitcode ("cpl", "c");
5794                 }
5795               else if (lit == 1L)
5796                 {
5797                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5798                 }
5799               else
5800                 {
5801                   emitcode ("clr", "c");
5802                 }
5803               /* AOP_TYPE(right) == AOP_CRY */
5804             }
5805           else
5806             {
5807               symbol *lbl = newiTempLabel (NULL);
5808               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810               emitcode ("cpl", "c");
5811               emitcode ("", "!tlabeldef", (lbl->key + 100));
5812             }
5813           /* if true label then we jump if condition
5814              supplied is true */
5815           tlbl = newiTempLabel (NULL);
5816           if (IC_TRUE (ifx))
5817             {
5818               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5819               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5820             }
5821           else
5822             {
5823               emitcode ("jc", "!tlabel", tlbl->key + 100);
5824               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5825             }
5826           emitcode ("", "!tlabeldef", tlbl->key + 100);
5827         }
5828       else
5829         {
5830           tlbl = newiTempLabel (NULL);
5831           gencjneshort (left, right, tlbl);
5832           if (IC_TRUE (ifx))
5833             {
5834               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5835               emitcode ("", "!tlabeldef", tlbl->key + 100);
5836             }
5837           else
5838             {
5839               symbol *lbl = newiTempLabel (NULL);
5840               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5841               emitcode ("", "!tlabeldef", tlbl->key + 100);
5842               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5843               emitcode ("", "!tlabeldef", lbl->key + 100);
5844             }
5845         }
5846       /* mark the icode as generated */
5847       ifx->generated = 1;
5848
5849       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5851       return;
5852     }
5853
5854   /* if they are both bit variables */
5855   if (AOP_TYPE (left) == AOP_CRY &&
5856       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5857     {
5858       if (AOP_TYPE (right) == AOP_LIT)
5859         {
5860           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5861           if (lit == 0L)
5862             {
5863               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864               emitcode ("cpl", "c");
5865             }
5866           else if (lit == 1L)
5867             {
5868               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5869             }
5870           else
5871             {
5872               emitcode ("clr", "c");
5873             }
5874           /* AOP_TYPE(right) == AOP_CRY */
5875         }
5876       else
5877         {
5878           symbol *lbl = newiTempLabel (NULL);
5879           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5880           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5881           emitcode ("cpl", "c");
5882           emitcode ("", "!tlabeldef", (lbl->key + 100));
5883         }
5884
5885       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5887
5888       aopOp (result, ic, TRUE, FALSE);
5889
5890       /* c = 1 if egal */
5891       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5892         {
5893           outBitC (result);
5894           goto release;
5895         }
5896       if (ifx)
5897         {
5898           genIfxJump (ifx, "c");
5899           goto release;
5900         }
5901       /* if the result is used in an arithmetic operation
5902          then put the result in place */
5903       outBitC (result);
5904     }
5905   else
5906     {
5907       gencjne (left, right, newiTempLabel (NULL));
5908
5909       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5910       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5911
5912       aopOp (result, ic, TRUE, FALSE);
5913
5914       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5915         {
5916           aopPut (AOP (result), "a", 0);
5917           goto release;
5918         }
5919       if (ifx)
5920         {
5921           genIfxJump (ifx, "a");
5922           goto release;
5923         }
5924       /* if the result is used in an arithmetic operation
5925          then put the result in place */
5926       if (AOP_TYPE (result) != AOP_CRY)
5927         outAcc (result);
5928       /* leave the result in acc */
5929     }
5930
5931 release:
5932   freeAsmop (result, NULL, ic, TRUE);
5933 }
5934
5935 /*-----------------------------------------------------------------*/
5936 /* ifxForOp - returns the icode containing the ifx for operand     */
5937 /*-----------------------------------------------------------------*/
5938 static iCode *
5939 ifxForOp (operand * op, iCode * ic)
5940 {
5941   /* if true symbol then needs to be assigned */
5942   if (IS_TRUE_SYMOP (op))
5943     return NULL;
5944
5945   /* if this has register type condition and
5946      the next instruction is ifx with the same operand
5947      and live to of the operand is upto the ifx only then */
5948   if (ic->next &&
5949       ic->next->op == IFX &&
5950       IC_COND (ic->next)->key == op->key &&
5951       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5952     return ic->next;
5953
5954   return NULL;
5955 }
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use            */
5958 /*-----------------------------------------------------------------*/
5959 static iCode *
5960 hasInc (operand *op, iCode *ic, int osize)
5961 {
5962   sym_link *type = operandType(op);
5963   sym_link *retype = getSpec (type);
5964   iCode *lic = ic->next;
5965   int isize ;
5966   
5967   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968   if (!IS_SYMOP(op)) return NULL;
5969
5970   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971   if (IS_AGGREGATE(type->next)) return NULL;
5972   if (osize != (isize = getSize(type->next))) return NULL;
5973
5974   while (lic) {
5975       /* if operand of the form op = op + <sizeof *op> */
5976       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977           isOperandEqual(IC_RESULT(lic),op) && 
5978           isOperandLiteral(IC_RIGHT(lic)) &&
5979           operandLitValue(IC_RIGHT(lic)) == isize) {
5980           return lic;
5981       }
5982       /* if the operand used or deffed */
5983       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5984           return NULL;
5985       }
5986       /* if GOTO or IFX */
5987       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5988       lic = lic->next;
5989   }
5990   return NULL;
5991 }
5992
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation                                     */
5995 /*-----------------------------------------------------------------*/
5996 static void
5997 genAndOp (iCode * ic)
5998 {
5999   operand *left, *right, *result;
6000   symbol *tlbl;
6001
6002   D (emitcode (";", "genAndOp "););
6003
6004   /* note here that && operations that are in an
6005      if statement are taken away by backPatchLabels
6006      only those used in arthmetic operations remain */
6007   AOP_OP_2 (ic);
6008   AOP_SET_LOCALS (ic);
6009
6010   /* if both are bit variables */
6011   if (AOP_TYPE (left) == AOP_CRY &&
6012       AOP_TYPE (right) == AOP_CRY)
6013     {
6014       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6015       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6016       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018   
6019       aopOp (result,ic,FALSE, FALSE);
6020       outBitC (result);
6021     }
6022   else
6023     {
6024       tlbl = newiTempLabel (NULL);
6025       toBoolean (left);
6026       emitcode ("jz", "!tlabel", tlbl->key + 100);
6027       toBoolean (right);
6028       emitcode ("", "!tlabeldef", tlbl->key + 100);
6029       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031   
6032       aopOp (result,ic,FALSE, FALSE);
6033       outBitAcc (result);
6034     }
6035     freeAsmop (result, NULL, ic, TRUE);
6036 }
6037
6038
6039 /*-----------------------------------------------------------------*/
6040 /* genOrOp - for || operation                                      */
6041 /*-----------------------------------------------------------------*/
6042 static void
6043 genOrOp (iCode * ic)
6044 {
6045   operand *left, *right, *result;
6046   symbol *tlbl;
6047
6048   D (emitcode (";", "genOrOp "););
6049
6050   /* note here that || operations that are in an
6051      if statement are taken away by backPatchLabels
6052      only those used in arthmetic operations remain */
6053   AOP_OP_2 (ic);
6054   AOP_SET_LOCALS (ic);
6055
6056   /* if both are bit variables */
6057   if (AOP_TYPE (left) == AOP_CRY &&
6058       AOP_TYPE (right) == AOP_CRY)
6059     {
6060       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6061       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6062       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6064   
6065       aopOp (result,ic,FALSE, FALSE);
6066       
6067       outBitC (result);
6068     }
6069   else
6070     {
6071       tlbl = newiTempLabel (NULL);
6072       toBoolean (left);
6073       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6074       toBoolean (right);
6075       emitcode ("", "!tlabeldef", tlbl->key + 100);
6076       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6077       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6078   
6079       aopOp (result,ic,FALSE, FALSE);
6080       
6081       outBitAcc (result);
6082     }
6083
6084   freeAsmop (result, NULL, ic, TRUE);
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* isLiteralBit - test if lit == 2^n                               */
6089 /*-----------------------------------------------------------------*/
6090 static int
6091 isLiteralBit (unsigned long lit)
6092 {
6093   unsigned long pw[32] =
6094   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6095    0x100L, 0x200L, 0x400L, 0x800L,
6096    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6097    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6098    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6099    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6100    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6101   int idx;
6102
6103   for (idx = 0; idx < 32; idx++)
6104     if (lit == pw[idx])
6105       return idx + 1;
6106   return 0;
6107 }
6108
6109 /*-----------------------------------------------------------------*/
6110 /* continueIfTrue -                                                */
6111 /*-----------------------------------------------------------------*/
6112 static void
6113 continueIfTrue (iCode * ic)
6114 {
6115   if (IC_TRUE (ic))
6116     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6117   ic->generated = 1;
6118 }
6119
6120 /*-----------------------------------------------------------------*/
6121 /* jmpIfTrue -                                                     */
6122 /*-----------------------------------------------------------------*/
6123 static void
6124 jumpIfTrue (iCode * ic)
6125 {
6126   if (!IC_TRUE (ic))
6127     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6128   ic->generated = 1;
6129 }
6130
6131 /*-----------------------------------------------------------------*/
6132 /* jmpTrueOrFalse -                                                */
6133 /*-----------------------------------------------------------------*/
6134 static void
6135 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6136 {
6137   // ugly but optimized by peephole
6138   if (IC_TRUE (ic))
6139     {
6140       symbol *nlbl = newiTempLabel (NULL);
6141       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6142       emitcode ("", "!tlabeldef", tlbl->key + 100);
6143       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6144       emitcode ("", "!tlabeldef", nlbl->key + 100);
6145     }
6146   else
6147     {
6148       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6149       emitcode ("", "!tlabeldef", tlbl->key + 100);
6150     }
6151   ic->generated = 1;
6152 }
6153
6154 // Generate code to perform a bit-wise logic operation
6155 // on two operands in far space (assumed to already have been 
6156 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6157 // in far space. This requires pushing the result on the stack
6158 // then popping it into the result.
6159 static void
6160 genFarFarLogicOp(iCode *ic, char *logicOp)
6161 {
6162       int size, resultSize, compSize;
6163       int offset = 0;
6164       
6165       TR_AP("#5");
6166       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6167       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6168                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6169       
6170       _startLazyDPSEvaluation();
6171       for (size = compSize; (size--); offset++)
6172       {
6173           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6174           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6175           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6176           
6177           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6178           emitcode ("push", "acc");
6179       }
6180       _endLazyDPSEvaluation();
6181      
6182       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6183       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6184       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6185      
6186       resultSize = AOP_SIZE(IC_RESULT(ic));
6187
6188       ADJUST_PUSHED_RESULT(compSize, resultSize);
6189
6190       _startLazyDPSEvaluation();
6191       while (compSize--)
6192       {
6193           emitcode ("pop", "acc");
6194           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6195       }
6196       _endLazyDPSEvaluation();
6197       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6198 }
6199
6200
6201 /*-----------------------------------------------------------------*/
6202 /* genAnd  - code for and                                          */
6203 /*-----------------------------------------------------------------*/
6204 static void
6205 genAnd (iCode * ic, iCode * ifx)
6206 {
6207   operand *left, *right, *result;
6208   int size, offset = 0;
6209   unsigned long lit = 0L;
6210   int bytelit;
6211   char buff[10];
6212   bool pushResult;
6213
6214   D (emitcode (";", "genAnd "););
6215
6216   AOP_OP_3_NOFATAL (ic, pushResult);
6217   AOP_SET_LOCALS (ic);
6218
6219   if (pushResult)
6220   {
6221       genFarFarLogicOp(ic, "anl");
6222       return;
6223   }  
6224
6225 #ifdef DEBUG_TYPE
6226   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6227             AOP_TYPE (result),
6228             AOP_TYPE (left), AOP_TYPE (right));
6229   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6230             AOP_SIZE (result),
6231             AOP_SIZE (left), AOP_SIZE (right));
6232 #endif
6233
6234   /* if left is a literal & right is not then exchange them */
6235   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6236 #ifdef LOGIC_OPS_BROKEN      
6237     ||  AOP_NEEDSACC (left)
6238 #endif
6239     )
6240     {
6241       operand *tmp = right;
6242       right = left;
6243       left = tmp;
6244     }
6245
6246   /* if result = right then exchange them */
6247   if (sameRegs (AOP (result), AOP (right)))
6248     {
6249       operand *tmp = right;
6250       right = left;
6251       left = tmp;
6252     }
6253
6254   /* if right is bit then exchange them */
6255   if (AOP_TYPE (right) == AOP_CRY &&
6256       AOP_TYPE (left) != AOP_CRY)
6257     {
6258       operand *tmp = right;
6259       right = left;
6260       left = tmp;
6261     }
6262   if (AOP_TYPE (right) == AOP_LIT)
6263     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6264
6265   size = AOP_SIZE (result);
6266
6267   // if(bit & yy)
6268   // result = bit & yy;
6269   if (AOP_TYPE (left) == AOP_CRY)
6270     {
6271       // c = bit & literal;
6272       if (AOP_TYPE (right) == AOP_LIT)
6273         {
6274           if (lit & 1)
6275             {
6276               if (size && sameRegs (AOP (result), AOP (left)))
6277                 // no change
6278                 goto release;
6279               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6280             }
6281           else
6282             {
6283               // bit(result) = 0;
6284               if (size && (AOP_TYPE (result) == AOP_CRY))
6285                 {
6286                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6287                   goto release;
6288                 }
6289               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6290                 {
6291                   jumpIfTrue (ifx);
6292                   goto release;
6293                 }
6294               emitcode ("clr", "c");
6295             }
6296         }
6297       else
6298         {
6299           if (AOP_TYPE (right) == AOP_CRY)
6300             {
6301               // c = bit & bit;
6302               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6303               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6304             }
6305           else
6306             {
6307               // c = bit & val;
6308               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6309               // c = lsb
6310               emitcode ("rrc", "a");
6311               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6312             }
6313         }
6314       // bit = c
6315       // val = c
6316       if (size)
6317         outBitC (result);
6318       // if(bit & ...)
6319       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6320         genIfxJump (ifx, "c");
6321       goto release;
6322     }
6323
6324   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6325   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6326   if ((AOP_TYPE (right) == AOP_LIT) &&
6327       (AOP_TYPE (result) == AOP_CRY) &&
6328       (AOP_TYPE (left) != AOP_CRY))
6329     {
6330       int posbit = isLiteralBit (lit);
6331       /* left &  2^n */
6332       if (posbit)
6333         {
6334           posbit--;
6335           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6336           // bit = left & 2^n
6337           if (size)
6338             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6339           // if(left &  2^n)
6340           else
6341             {
6342               if (ifx)
6343                 {
6344                   SNPRINTF (buff, sizeof(buff), 
6345                             "acc.%d", posbit & 0x07);
6346                   genIfxJump (ifx, buff);
6347                 }
6348               else 
6349                   {
6350                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6351                   }
6352               goto release;
6353             }
6354         }
6355       else
6356         {
6357           symbol *tlbl = newiTempLabel (NULL);
6358           int sizel = AOP_SIZE (left);
6359           if (size)
6360             emitcode ("setb", "c");
6361           while (sizel--)
6362             {
6363               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6364                 {
6365                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6366                   // byte ==  2^n ?
6367                   if ((posbit = isLiteralBit (bytelit)) != 0)
6368                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6369                   else
6370                     {
6371                       if (bytelit != 0x0FFL)
6372                         emitcode ("anl", "a,%s",
6373                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6374                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6375                     }
6376                 }
6377               offset++;
6378             }
6379           // bit = left & literal
6380           if (size)
6381             {
6382               emitcode ("clr", "c");
6383               emitcode ("", "!tlabeldef", tlbl->key + 100);
6384             }
6385           // if(left & literal)
6386           else
6387             {
6388               if (ifx)
6389                 jmpTrueOrFalse (ifx, tlbl);
6390               goto release;
6391             }
6392         }
6393       outBitC (result);
6394       goto release;
6395     }
6396
6397   /* if left is same as result */
6398   if (sameRegs (AOP (result), AOP (left)))
6399     {
6400       for (; size--; offset++)
6401         {
6402           if (AOP_TYPE (right) == AOP_LIT)
6403             {
6404               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6405                 continue;
6406               else if (bytelit == 0)
6407                 aopPut (AOP (result), zero, offset);
6408               else if (IS_AOP_PREG (result))
6409                 {
6410                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6411                   emitcode ("anl", "a,%s",
6412                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6413                   aopPut (AOP (result), "a", offset);
6414                 }
6415               else
6416                 emitcode ("anl", "%s,%s",
6417                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6418                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6419             }
6420           else
6421             {
6422               if (AOP_TYPE (left) == AOP_ACC)
6423                 emitcode ("anl", "a,%s",
6424                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6425               else
6426                 {
6427                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6428                   if (IS_AOP_PREG (result))
6429                     {
6430                       emitcode ("anl", "a,%s",
6431                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6432                       aopPut (AOP (result), "a", offset);
6433                     }
6434                   else
6435                     emitcode ("anl", "%s,a",
6436                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6437                 }
6438             }
6439         }
6440     }
6441   else
6442     {
6443       // left & result in different registers
6444       if (AOP_TYPE (result) == AOP_CRY)
6445         {
6446           // result = bit
6447           // if(size), result in bit
6448           // if(!size && ifx), conditional oper: if(left & right)
6449           symbol *tlbl = newiTempLabel (NULL);
6450           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6451           if (size)
6452             emitcode ("setb", "c");
6453           while (sizer--)
6454             {
6455               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6456                 emitcode ("anl", "a,%s",
6457                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6458               } else {
6459                 if (AOP_TYPE(left)==AOP_ACC) {
6460                   emitcode("mov", "b,a");
6461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462                   emitcode("anl", "a,b");
6463                 }else {
6464                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6465                   emitcode ("anl", "a,%s",
6466                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6467                 }
6468               }
6469               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6470               offset++;
6471             }
6472           if (size)
6473             {
6474               CLRC;
6475               emitcode ("", "!tlabeldef", tlbl->key + 100);
6476               outBitC (result);
6477             }
6478           else if (ifx)
6479             jmpTrueOrFalse (ifx, tlbl);
6480         }
6481       else
6482         {
6483           for (; (size--); offset++)
6484             {
6485               // normal case
6486               // result = left & right
6487               if (AOP_TYPE (right) == AOP_LIT)
6488                 {
6489                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6490                     {
6491                       aopPut (AOP (result),
6492                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6493                               offset);
6494                       continue;
6495                     }
6496                   else if (bytelit == 0)
6497                     {
6498                       aopPut (AOP (result), zero, offset);
6499                       continue;
6500                     }
6501                   D (emitcode (";", "better literal AND."););
6502                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6503                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6504                                                     FALSE, FALSE, DP2_RESULT_REG));
6505
6506                 }
6507               else
6508                 {
6509                   // faster than result <- left, anl result,right
6510                   // and better if result is SFR
6511                   if (AOP_TYPE (left) == AOP_ACC)
6512                     {
6513                       emitcode ("anl", "a,%s", 
6514                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6515                     }
6516                   else
6517                     {
6518                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6519                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6520                       {
6521                           emitcode("mov", "b,a");
6522                           rOp = "b";
6523                       }
6524                         
6525                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6526                       emitcode ("anl", "a,%s", rOp);
6527                     }                   
6528                 }
6529               aopPut (AOP (result), "a", offset);
6530             }
6531         }
6532     }
6533
6534 release:
6535   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6536   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6537   freeAsmop (result, NULL, ic, TRUE);
6538 }
6539
6540
6541 /*-----------------------------------------------------------------*/
6542 /* genOr  - code for or                                            */
6543 /*-----------------------------------------------------------------*/
6544 static void
6545 genOr (iCode * ic, iCode * ifx)
6546 {
6547   operand *left, *right, *result;
6548   int size, offset = 0;
6549   unsigned long lit = 0L;
6550   bool     pushResult;
6551
6552   D (emitcode (";", "genOr "););
6553
6554   AOP_OP_3_NOFATAL (ic, pushResult);
6555   AOP_SET_LOCALS (ic);
6556
6557   if (pushResult)
6558   {
6559       genFarFarLogicOp(ic, "orl");
6560       return;
6561   }
6562
6563
6564 #ifdef DEBUG_TYPE
6565   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6566             AOP_TYPE (result),
6567             AOP_TYPE (left), AOP_TYPE (right));
6568   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6569             AOP_SIZE (result),
6570             AOP_SIZE (left), AOP_SIZE (right));
6571 #endif
6572
6573   /* if left is a literal & right is not then exchange them */
6574   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6575 #ifdef LOGIC_OPS_BROKEN
6576    || AOP_NEEDSACC (left) // I think this is a net loss now.
6577 #endif      
6578       )
6579     {
6580       operand *tmp = right;
6581       right = left;
6582       left = tmp;
6583     }
6584
6585   /* if result = right then exchange them */
6586   if (sameRegs (AOP (result), AOP (right)))
6587     {
6588       operand *tmp = right;
6589       right = left;
6590       left = tmp;
6591     }
6592
6593   /* if right is bit then exchange them */
6594   if (AOP_TYPE (right) == AOP_CRY &&
6595       AOP_TYPE (left) != AOP_CRY)
6596     {
6597       operand *tmp = right;
6598       right = left;
6599       left = tmp;
6600     }
6601   if (AOP_TYPE (right) == AOP_LIT)
6602     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6603
6604   size = AOP_SIZE (result);
6605
6606   // if(bit | yy)
6607   // xx = bit | yy;
6608   if (AOP_TYPE (left) == AOP_CRY)
6609     {
6610       if (AOP_TYPE (right) == AOP_LIT)
6611         {
6612           // c = bit & literal;
6613           if (lit)
6614             {
6615               // lit != 0 => result = 1
6616               if (AOP_TYPE (result) == AOP_CRY)
6617                 {
6618                   if (size)
6619                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6620                   else if (ifx)
6621                     continueIfTrue (ifx);
6622                   goto release;
6623                 }
6624               emitcode ("setb", "c");
6625             }
6626           else
6627             {
6628               // lit == 0 => result = left
6629               if (size && sameRegs (AOP (result), AOP (left)))
6630                 goto release;
6631               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6632             }
6633         }
6634       else
6635         {
6636           if (AOP_TYPE (right) == AOP_CRY)
6637             {
6638               // c = bit | bit;
6639               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6640               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6641             }
6642           else
6643             {
6644               // c = bit | val;
6645               symbol *tlbl = newiTempLabel (NULL);
6646               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6647                 emitcode ("setb", "c");
6648               emitcode ("jb", "%s,!tlabel",
6649                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6650               toBoolean (right);
6651               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6652               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6653                 {
6654                   jmpTrueOrFalse (ifx, tlbl);
6655                   goto release;
6656                 }
6657               else
6658                 {
6659                   CLRC;
6660                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6661                 }
6662             }
6663         }
6664       // bit = c
6665       // val = c
6666       if (size)
6667         outBitC (result);
6668       // if(bit | ...)
6669       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6670            genIfxJump (ifx, "c");
6671       goto release;
6672     }
6673
6674   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6675   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6676   if ((AOP_TYPE (right) == AOP_LIT) &&
6677       (AOP_TYPE (result) == AOP_CRY) &&
6678       (AOP_TYPE (left) != AOP_CRY))
6679     {
6680       if (lit)
6681         {
6682           // result = 1
6683           if (size)
6684             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6685           else
6686             continueIfTrue (ifx);
6687           goto release;
6688         }
6689       else
6690         {
6691           // lit = 0, result = boolean(left)
6692           if (size)
6693             emitcode ("setb", "c");
6694           toBoolean (right);
6695           if (size)
6696             {
6697               symbol *tlbl = newiTempLabel (NULL);
6698               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6699               CLRC;
6700               emitcode ("", "!tlabeldef", tlbl->key + 100);
6701             }
6702           else
6703             {
6704               genIfxJump (ifx, "a");
6705               goto release;
6706             }
6707         }
6708       outBitC (result);
6709       goto release;
6710     }
6711
6712   /* if left is same as result */
6713   if (sameRegs (AOP (result), AOP (left)))
6714     {
6715       for (; size--; offset++)
6716         {
6717           if (AOP_TYPE (right) == AOP_LIT)
6718             {
6719               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6720                 {
6721                   continue;
6722                 }
6723               else
6724                 {
6725                   if (IS_AOP_PREG (left))
6726                     {
6727                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6728                       emitcode ("orl", "a,%s",
6729                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6730                       aopPut (AOP (result), "a", offset);
6731                     }
6732                   else
6733                     {
6734                       emitcode ("orl", "%s,%s",
6735                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6736                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6737                     }
6738                 }
6739             }
6740           else
6741             {
6742               if (AOP_TYPE (left) == AOP_ACC)
6743                 {
6744                   emitcode ("orl", "a,%s",
6745                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6746                 }
6747               else
6748                 {
6749                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6750                   if (IS_AOP_PREG (left))
6751                     {
6752                       emitcode ("orl", "a,%s", 
6753                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6754                       aopPut (AOP (result), "a", offset);
6755                     }
6756                   else
6757                     {
6758                       emitcode ("orl", "%s,a",
6759                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6760                     }
6761                 }
6762             }
6763         }
6764     }
6765   else
6766     {
6767       // left & result in different registers
6768       if (AOP_TYPE (result) == AOP_CRY)
6769         {
6770           // result = bit
6771           // if(size), result in bit
6772           // if(!size && ifx), conditional oper: if(left | right)
6773           symbol *tlbl = newiTempLabel (NULL);
6774           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6775           if (size)
6776             emitcode ("setb", "c");
6777           while (sizer--)
6778             {
6779               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6780                 emitcode ("orl", "a,%s",
6781                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6782               } else {
6783                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6784                 emitcode ("orl", "a,%s",
6785                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6786               }
6787               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6788               offset++;
6789             }
6790           if (size)
6791             {
6792               CLRC;
6793               emitcode ("", "!tlabeldef", tlbl->key + 100);
6794               outBitC (result);
6795             }
6796           else if (ifx)
6797             jmpTrueOrFalse (ifx, tlbl);
6798         }
6799       else
6800         {
6801             _startLazyDPSEvaluation();
6802           for (; (size--); offset++)
6803             {
6804               // normal case
6805               // result = left & right
6806               if (AOP_TYPE (right) == AOP_LIT)
6807                 {
6808                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6809                     {
6810                       aopPut (AOP (result),
6811                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6812                               offset);
6813                       continue;
6814                     }
6815                   D (emitcode (";", "better literal OR."););
6816                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817                   emitcode ("orl", "a, %s",
6818                             aopGet (AOP (right), offset,
6819                                     FALSE, FALSE, DP2_RESULT_REG));
6820
6821                 }
6822               else
6823                 {
6824                   // faster than result <- left, anl result,right
6825                   // and better if result is SFR
6826                   if (AOP_TYPE (left) == AOP_ACC)
6827                     {
6828                       emitcode ("orl", "a,%s",
6829                                 aopGet (AOP (right), offset,
6830                                         FALSE, FALSE, DP2_RESULT_REG));
6831                     }
6832                   else
6833                     {
6834                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6835                         
6836                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6837                       {
6838                           emitcode("mov", "b,a");
6839                           rOp = "b";
6840                       }
6841                         
6842                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6843                       emitcode ("orl", "a,%s", rOp);
6844                     }
6845                 }
6846               aopPut (AOP (result), "a", offset);
6847             }
6848             _endLazyDPSEvaluation();
6849         }
6850     }
6851
6852 release:
6853   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6855   freeAsmop (result, NULL, ic, TRUE);
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* genXor - code for xclusive or                                   */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 genXor (iCode * ic, iCode * ifx)
6863 {
6864   operand *left, *right, *result;
6865   int size, offset = 0;
6866   unsigned long lit = 0L;
6867   bool pushResult;
6868
6869   D (emitcode (";", "genXor "););
6870
6871   AOP_OP_3_NOFATAL (ic, pushResult);
6872   AOP_SET_LOCALS (ic);
6873
6874   if (pushResult)
6875   {
6876       genFarFarLogicOp(ic, "xrl");
6877       return;
6878   }  
6879
6880 #ifdef DEBUG_TYPE
6881   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6882             AOP_TYPE (result),
6883             AOP_TYPE (left), AOP_TYPE (right));
6884   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6885             AOP_SIZE (result),
6886             AOP_SIZE (left), AOP_SIZE (right));
6887 #endif
6888
6889   /* if left is a literal & right is not ||
6890      if left needs acc & right does not */
6891   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6892 #ifdef LOGIC_OPS_BROKEN      
6893       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6894 #endif
6895      )
6896     {
6897       operand *tmp = right;
6898       right = left;
6899       left = tmp;
6900     }
6901
6902   /* if result = right then exchange them */
6903   if (sameRegs (AOP (result), AOP (right)))
6904     {
6905       operand *tmp = right;
6906       right = left;
6907       left = tmp;
6908     }
6909
6910   /* if right is bit then exchange them */
6911   if (AOP_TYPE (right) == AOP_CRY &&
6912       AOP_TYPE (left) != AOP_CRY)
6913     {
6914       operand *tmp = right;
6915       right = left;
6916       left = tmp;
6917     }
6918   if (AOP_TYPE (right) == AOP_LIT)
6919     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6920
6921   size = AOP_SIZE (result);
6922
6923   // if(bit ^ yy)
6924   // xx = bit ^ yy;
6925   if (AOP_TYPE (left) == AOP_CRY)
6926     {
6927       if (AOP_TYPE (right) == AOP_LIT)
6928         {
6929           // c = bit & literal;
6930           if (lit >> 1)
6931             {
6932               // lit>>1  != 0 => result = 1
6933               if (AOP_TYPE (result) == AOP_CRY)
6934                 {
6935                   if (size)
6936                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6937                   else if (ifx)
6938                     continueIfTrue (ifx);
6939                   goto release;
6940                 }
6941               emitcode ("setb", "c");
6942             }
6943           else
6944             {
6945               // lit == (0 or 1)
6946               if (lit == 0)
6947                 {
6948                   // lit == 0, result = left
6949                   if (size && sameRegs (AOP (result), AOP (left)))
6950                     goto release;
6951                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6952                 }
6953               else
6954                 {
6955                   // lit == 1, result = not(left)
6956                   if (size && sameRegs (AOP (result), AOP (left)))
6957                     {
6958                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6959                       goto release;
6960                     }
6961                   else
6962                     {
6963                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964                       emitcode ("cpl", "c");
6965                     }
6966                 }
6967             }
6968
6969         }
6970       else
6971         {
6972           // right != literal
6973           symbol *tlbl = newiTempLabel (NULL);
6974           if (AOP_TYPE (right) == AOP_CRY)
6975             {
6976               // c = bit ^ bit;
6977               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6978             }
6979           else
6980             {
6981               int sizer = AOP_SIZE (right);
6982               // c = bit ^ val
6983               // if val>>1 != 0, result = 1
6984               emitcode ("setb", "c");
6985               while (sizer)
6986                 {
6987                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6988                   if (sizer == 1)
6989                     // test the msb of the lsb
6990                     emitcode ("anl", "a,#!constbyte",0xfe);
6991                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6992                   sizer--;
6993                 }
6994               // val = (0,1)
6995               emitcode ("rrc", "a");
6996             }
6997           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6998           emitcode ("cpl", "c");
6999           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7000         }
7001       // bit = c
7002       // val = c
7003       if (size)
7004         outBitC (result);
7005       // if(bit | ...)
7006       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7007         genIfxJump (ifx, "c");
7008       goto release;
7009     }
7010
7011   if (sameRegs (AOP (result), AOP (left)))
7012     {
7013       /* if left is same as result */
7014       for (; size--; offset++)
7015         {
7016           if (AOP_TYPE (right) == AOP_LIT)
7017             {
7018               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7019                 continue;
7020               else if (IS_AOP_PREG (left))
7021                 {
7022                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7023                   emitcode ("xrl", "a,%s",
7024                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7025                   aopPut (AOP (result), "a", offset);
7026                 }
7027               else
7028                 emitcode ("xrl", "%s,%s",
7029                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7030                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7031             }
7032           else
7033             {
7034               if (AOP_TYPE (left) == AOP_ACC)
7035                 emitcode ("xrl", "a,%s",
7036                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7037               else
7038                 {
7039                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7040                   if (IS_AOP_PREG (left))
7041                     {
7042                       emitcode ("xrl", "a,%s",
7043                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7044                       aopPut (AOP (result), "a", offset);
7045                     }
7046                   else
7047                     emitcode ("xrl", "%s,a",
7048                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7049                 }
7050             }
7051         }
7052     }
7053   else
7054     {
7055       // left & result in different registers
7056       if (AOP_TYPE (result) == AOP_CRY)
7057         {
7058           // result = bit
7059           // if(size), result in bit
7060           // if(!size && ifx), conditional oper: if(left ^ right)
7061           symbol *tlbl = newiTempLabel (NULL);
7062           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7063                   
7064           if (size)
7065             emitcode ("setb", "c");
7066           while (sizer--)
7067             {
7068               if ((AOP_TYPE (right) == AOP_LIT) &&
7069                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7070                 {
7071                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7072                 }
7073               else
7074                 {
7075                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7076                     emitcode ("xrl", "a,%s",
7077                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7078                   } else {
7079                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7080                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7081                       {
7082                           emitcode("mov", "b,a");
7083                           rOp = "b";
7084                       }
7085                         
7086                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7087                       emitcode ("xrl", "a,%s", rOp);                  
7088                   }
7089                 }
7090               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7091               offset++;
7092             }
7093           if (size)
7094             {
7095               CLRC;
7096               emitcode ("", "!tlabeldef", tlbl->key + 100);
7097               outBitC (result);
7098             }
7099           else if (ifx)
7100             jmpTrueOrFalse (ifx, tlbl);
7101         }
7102       else
7103         {
7104         for (; (size--); offset++)
7105           {
7106             // normal case
7107             // result = left & right
7108             if (AOP_TYPE (right) == AOP_LIT)
7109               {
7110                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7111                   {
7112                     aopPut (AOP (result),
7113                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7114                             offset);
7115                     continue;
7116                   }
7117                 D (emitcode (";", "better literal XOR."););
7118                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7119                 emitcode ("xrl", "a, %s",
7120                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7121               }
7122             else
7123               {
7124                 // faster than result <- left, anl result,right
7125                 // and better if result is SFR
7126                 if (AOP_TYPE (left) == AOP_ACC)
7127                   {
7128                     emitcode ("xrl", "a,%s",
7129                               aopGet (AOP (right), offset,
7130                                       FALSE, FALSE, DP2_RESULT_REG));
7131                   }
7132                 else
7133                   {
7134                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7136                       {
7137                           emitcode("mov", "b,a");
7138                           rOp = "b";
7139                       }
7140                         
7141                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142                       emitcode ("xrl", "a,%s", rOp);
7143                   }
7144               }
7145             aopPut (AOP (result), "a", offset);
7146           }
7147         }
7148         
7149     }
7150
7151 release:
7152   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7153   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7154   freeAsmop (result, NULL, ic, TRUE);
7155 }
7156
7157 /*-----------------------------------------------------------------*/
7158 /* genInline - write the inline code out                           */
7159 /*-----------------------------------------------------------------*/
7160 static void
7161 genInline (iCode * ic)
7162 {
7163   char *buffer, *bp, *bp1;
7164
7165   D (emitcode (";", "genInline "); );
7166
7167   _G.inLine += (!options.asmpeep);
7168
7169   buffer = Safe_strdup(IC_INLINE(ic));
7170   bp = buffer;
7171   bp1 = buffer;
7172
7173   /* emit each line as a code */
7174   while (*bp)
7175     {
7176       if (*bp == '\n')
7177         {
7178           *bp++ = '\0';
7179           emitcode (bp1, "");
7180           bp1 = bp;
7181         }
7182       else
7183         {
7184           if (*bp == ':')
7185             {
7186               bp++;
7187               *bp = '\0';
7188               bp++;
7189               emitcode (bp1, "");
7190               bp1 = bp;
7191             }
7192           else
7193             bp++;
7194         }
7195     }
7196   if (bp1 != bp)
7197     emitcode (bp1, "");
7198   /*     emitcode("",buffer); */
7199   _G.inLine -= (!options.asmpeep);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genRRC - rotate right with carry                                */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genRRC (iCode * ic)
7207 {
7208   operand *left, *result;
7209   int     size, offset;
7210
7211   D (emitcode (";", "genRRC "););
7212
7213   /* rotate right with carry */
7214   left = IC_LEFT (ic);
7215   result = IC_RESULT (ic);
7216   aopOp (left, ic, FALSE, FALSE);
7217   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7218
7219   /* move it to the result */
7220   size = AOP_SIZE (result);
7221   offset = size - 1;
7222   CLRC;
7223
7224   _startLazyDPSEvaluation ();
7225   while (size--)
7226     {
7227       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7228       emitcode ("rrc", "a");
7229       if (AOP_SIZE (result) > 1)
7230         aopPut (AOP (result), "a", offset--);
7231     }
7232   _endLazyDPSEvaluation ();
7233
7234   /* now we need to put the carry into the
7235      highest order byte of the result */
7236   if (AOP_SIZE (result) > 1)
7237     {
7238       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7239     }
7240   emitcode ("mov", "acc.7,c");
7241   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7242   freeAsmop (left, NULL, ic, TRUE);
7243   freeAsmop (result, NULL, ic, TRUE);
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* genRLC - generate code for rotate left with carry               */
7248 /*-----------------------------------------------------------------*/
7249 static void
7250 genRLC (iCode * ic)
7251 {
7252   operand *left, *result;
7253   int size, offset;
7254   char *l;
7255
7256   D (emitcode (";", "genRLC "););
7257
7258   /* rotate right with carry */
7259   left = IC_LEFT (ic);
7260   result = IC_RESULT (ic);
7261   aopOp (left, ic, FALSE, FALSE);
7262   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7263
7264   /* move it to the result */
7265   size = AOP_SIZE (result);
7266   offset = 0;
7267   if (size--)
7268     {
7269       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7270       MOVA (l);
7271       emitcode ("add", "a,acc");
7272       if (AOP_SIZE (result) > 1)
7273         {
7274           aopPut (AOP (result), "a", offset++);
7275         }
7276
7277       _startLazyDPSEvaluation ();
7278       while (size--)
7279         {
7280           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7281           MOVA (l);
7282           emitcode ("rlc", "a");
7283           if (AOP_SIZE (result) > 1)
7284             aopPut (AOP (result), "a", offset++);
7285         }
7286       _endLazyDPSEvaluation ();
7287     }
7288   /* now we need to put the carry into the
7289      highest order byte of the result */
7290   if (AOP_SIZE (result) > 1)
7291     {
7292       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7293       MOVA (l);
7294     }
7295   emitcode ("mov", "acc.0,c");
7296   aopPut (AOP (result), "a", 0);
7297   freeAsmop (left, NULL, ic, TRUE);
7298   freeAsmop (result, NULL, ic, TRUE);
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* genGetHbit - generates code get highest order bit               */
7303 /*-----------------------------------------------------------------*/
7304 static void
7305 genGetHbit (iCode * ic)
7306 {
7307   operand *left, *result;
7308   left = IC_LEFT (ic);
7309   result = IC_RESULT (ic);
7310   aopOp (left, ic, FALSE, FALSE);
7311   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7312
7313   D (emitcode (";", "genGetHbit "););
7314
7315   /* get the highest order byte into a */
7316   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7317   if (AOP_TYPE (result) == AOP_CRY)
7318     {
7319       emitcode ("rlc", "a");
7320       outBitC (result);
7321     }
7322   else
7323     {
7324       emitcode ("rl", "a");
7325       emitcode ("anl", "a,#1");
7326       outAcc (result);
7327     }
7328
7329
7330   freeAsmop (left, NULL, ic, TRUE);
7331   freeAsmop (result, NULL, ic, TRUE);
7332 }
7333
7334 /*-----------------------------------------------------------------*/
7335 /* genSwap - generates code to swap nibbles or bytes               */
7336 /*-----------------------------------------------------------------*/
7337 static void
7338 genSwap (iCode * ic)
7339 {
7340   operand *left, *result;
7341
7342   D(emitcode (";     genSwap",""));
7343
7344   left = IC_LEFT (ic);
7345   result = IC_RESULT (ic);
7346   aopOp (left, ic, FALSE, FALSE);
7347   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7348   
7349   _startLazyDPSEvaluation ();
7350   switch (AOP_SIZE (left))
7351     {
7352     case 1: /* swap nibbles in byte */
7353       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7354       emitcode ("swap", "a");
7355       aopPut (AOP (result), "a", 0);
7356       break;
7357     case 2: /* swap bytes in word */
7358       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7359         {
7360           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7361           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7362           aopPut (AOP (result), "a", 1);
7363         }
7364       else if (operandsEqu (left, result))
7365         {
7366           char * reg = "a";
7367           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7368           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7369             {
7370               emitcode ("mov", "b,a");
7371               reg = "b";
7372               _G.bInUse=1;
7373             }
7374           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7375           aopPut (AOP (result), reg, 1);
7376           _G.bInUse=0;
7377         }
7378       else
7379         {
7380           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7381           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7382         }
7383       break;
7384     default:
7385       wassertl(FALSE, "unsupported SWAP operand size");
7386     }
7387   _endLazyDPSEvaluation ();
7388   
7389   freeAsmop (left, NULL, ic, TRUE);
7390   freeAsmop (result, NULL, ic, TRUE);
7391 }
7392
7393 /*-----------------------------------------------------------------*/
7394 /* AccRol - rotate left accumulator by known count                 */
7395 /*-----------------------------------------------------------------*/
7396 static void
7397 AccRol (int shCount)
7398 {
7399   shCount &= 0x0007;            // shCount : 0..7
7400
7401   switch (shCount)
7402     {
7403     case 0:
7404       break;
7405     case 1:
7406       emitcode ("rl", "a");
7407       break;
7408     case 2:
7409       emitcode ("rl", "a");
7410       emitcode ("rl", "a");
7411       break;
7412     case 3:
7413       emitcode ("swap", "a");
7414       emitcode ("rr", "a");
7415       break;
7416     case 4:
7417       emitcode ("swap", "a");
7418       break;
7419     case 5:
7420       emitcode ("swap", "a");
7421       emitcode ("rl", "a");
7422       break;
7423     case 6:
7424       emitcode ("rr", "a");
7425       emitcode ("rr", "a");
7426       break;
7427     case 7:
7428       emitcode ("rr", "a");
7429       break;
7430     }
7431 }
7432
7433 /*-----------------------------------------------------------------*/
7434 /* AccLsh - left shift accumulator by known count                  */
7435 /*-----------------------------------------------------------------*/
7436 static void
7437 AccLsh (int shCount)
7438 {
7439   if (shCount != 0)
7440     {
7441       if (shCount == 1)
7442         emitcode ("add", "a,acc");
7443       else if (shCount == 2)
7444         {
7445           emitcode ("add", "a,acc");
7446           emitcode ("add", "a,acc");
7447         }
7448       else
7449         {
7450           /* rotate left accumulator */
7451           AccRol (shCount);
7452           /* and kill the lower order bits */
7453           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7454         }
7455     }
7456 }
7457
7458 /*-----------------------------------------------------------------*/
7459 /* AccRsh - right shift accumulator by known count                 */
7460 /*-----------------------------------------------------------------*/
7461 static void
7462 AccRsh (int shCount)
7463 {
7464   if (shCount != 0)
7465     {
7466       if (shCount == 1)
7467         {
7468           CLRC;
7469           emitcode ("rrc", "a");
7470         }
7471       else
7472         {
7473           /* rotate right accumulator */
7474           AccRol (8 - shCount);
7475           /* and kill the higher order bits */
7476           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7477         }
7478     }
7479 }
7480
7481 #ifdef BETTER_LITERAL_SHIFT
7482 /*-----------------------------------------------------------------*/
7483 /* AccSRsh - signed right shift accumulator by known count                 */
7484 /*-----------------------------------------------------------------*/
7485 static void
7486 AccSRsh (int shCount)
7487 {
7488   symbol *tlbl;
7489   if (shCount != 0)
7490     {
7491       if (shCount == 1)
7492         {
7493           emitcode ("mov", "c,acc.7");
7494           emitcode ("rrc", "a");
7495         }
7496       else if (shCount == 2)
7497         {
7498           emitcode ("mov", "c,acc.7");
7499           emitcode ("rrc", "a");
7500           emitcode ("mov", "c,acc.7");
7501           emitcode ("rrc", "a");
7502         }
7503       else
7504         {
7505           tlbl = newiTempLabel (NULL);
7506           /* rotate right accumulator */
7507           AccRol (8 - shCount);
7508           /* and kill the higher order bits */
7509           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7510           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7511           emitcode ("orl", "a,#!constbyte",
7512                     (unsigned char) ~SRMask[shCount]);
7513           emitcode ("", "!tlabeldef", tlbl->key + 100);
7514         }
7515     }
7516 }
7517 #endif
7518
7519 #ifdef BETTER_LITERAL_SHIFT
7520 /*-----------------------------------------------------------------*/
7521 /* shiftR1Left2Result - shift right one byte from left to result   */
7522 /*-----------------------------------------------------------------*/
7523 static void
7524 shiftR1Left2Result (operand * left, int offl,
7525                     operand * result, int offr,
7526                     int shCount, int sign)
7527 {
7528   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7529   /* shift right accumulator */
7530   if (sign)
7531     AccSRsh (shCount);
7532   else
7533     AccRsh (shCount);
7534   aopPut (AOP (result), "a", offr);
7535 }
7536 #endif
7537
7538 #ifdef BETTER_LITERAL_SHIFT
7539 /*-----------------------------------------------------------------*/
7540 /* shiftL1Left2Result - shift left one byte from left to result    */
7541 /*-----------------------------------------------------------------*/
7542 static void
7543 shiftL1Left2Result (operand * left, int offl,
7544                     operand * result, int offr, int shCount)
7545 {
7546   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7547   /* shift left accumulator */
7548   AccLsh (shCount);
7549   aopPut (AOP (result), "a", offr);
7550 }
7551 #endif
7552
7553 #ifdef BETTER_LITERAL_SHIFT
7554 /*-----------------------------------------------------------------*/
7555 /* movLeft2Result - move byte from left to result                  */
7556 /*-----------------------------------------------------------------*/
7557 static void
7558 movLeft2Result (operand * left, int offl,
7559                 operand * result, int offr, int sign)
7560 {
7561   char *l;
7562   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7563   {
7564       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7565
7566       if (*l == '@' && (IS_AOP_PREG (result)))
7567       {
7568           emitcode ("mov", "a,%s", l);
7569           aopPut (AOP (result), "a", offr);
7570       }
7571       else
7572       {
7573           if (!sign)
7574           {
7575             aopPut (AOP (result), l, offr);
7576           }
7577           else
7578             {
7579               /* MSB sign in acc.7 ! */
7580               if (getDataSize (left) == offl + 1)
7581                 {
7582                   emitcode ("mov", "a,%s", l);
7583                   aopPut (AOP (result), "a", offr);
7584                 }
7585             }
7586       }
7587   }
7588 }
7589 #endif
7590
7591 #ifdef BETTER_LITERAL_SHIFT
7592 /*-----------------------------------------------------------------*/
7593 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7594 /*-----------------------------------------------------------------*/
7595 static void
7596 AccAXRrl1 (char *x)
7597 {
7598   emitcode ("rrc", "a");
7599   emitcode ("xch", "a,%s", x);
7600   emitcode ("rrc", "a");
7601   emitcode ("xch", "a,%s", x);
7602 }
7603 #endif
7604
7605 #ifdef BETTER_LITERAL_SHIFT
7606 //REMOVE ME!!!
7607 /*-----------------------------------------------------------------*/
7608 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7609 /*-----------------------------------------------------------------*/
7610 static void
7611 AccAXLrl1 (char *x)
7612 {
7613   emitcode ("xch", "a,%s", x);
7614   emitcode ("rlc", "a");
7615   emitcode ("xch", "a,%s", x);
7616   emitcode ("rlc", "a");
7617 }
7618 #endif
7619
7620 #ifdef BETTER_LITERAL_SHIFT
7621 /*-----------------------------------------------------------------*/
7622 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7623 /*-----------------------------------------------------------------*/
7624 static void
7625 AccAXLsh1 (char *x)
7626 {
7627   emitcode ("xch", "a,%s", x);
7628   emitcode ("add", "a,acc");
7629   emitcode ("xch", "a,%s", x);
7630   emitcode ("rlc", "a");
7631 }
7632 #endif
7633
7634 #ifdef BETTER_LITERAL_SHIFT
7635 /*-----------------------------------------------------------------*/
7636 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7637 /*-----------------------------------------------------------------*/
7638 static void
7639 AccAXLsh (char *x, int shCount)
7640 {
7641   switch (shCount)
7642     {
7643     case 0:
7644       break;
7645     case 1:
7646       AccAXLsh1 (x);
7647       break;
7648     case 2:
7649       AccAXLsh1 (x);
7650       AccAXLsh1 (x);
7651       break;
7652     case 3:
7653     case 4:
7654     case 5:                     // AAAAABBB:CCCCCDDD
7655
7656       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7657
7658       emitcode ("anl", "a,#!constbyte",
7659                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7660
7661       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7662
7663       AccRol (shCount);         // DDDCCCCC:BBB00000
7664
7665       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7666
7667       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7668
7669       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7670
7671       emitcode ("anl", "a,#!constbyte",
7672                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7673
7674       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7675
7676       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7677
7678       break;
7679     case 6:                     // AAAAAABB:CCCCCCDD
7680       emitcode ("anl", "a,#!constbyte",
7681                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7682       emitcode ("mov", "c,acc.0");      // c = B
7683       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7684 #if 0
7685       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7686       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7687 #else
7688       emitcode("rrc","a"); 
7689       emitcode("xch","a,%s", x); 
7690       emitcode("rrc","a"); 
7691       emitcode("mov","c,acc.0"); //<< get correct bit 
7692       emitcode("xch","a,%s", x); 
7693
7694       emitcode("rrc","a"); 
7695       emitcode("xch","a,%s", x); 
7696       emitcode("rrc","a"); 
7697       emitcode("xch","a,%s", x); 
7698 #endif
7699       break;
7700     case 7:                     // a:x <<= 7
7701
7702       emitcode ("anl", "a,#!constbyte",
7703                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7704
7705       emitcode ("mov", "c,acc.0");      // c = B
7706
7707       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7708
7709       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7710
7711       break;
7712     default:
7713       break;
7714     }
7715 }
7716 #endif
7717
7718 #ifdef BETTER_LITERAL_SHIFT
7719 //REMOVE ME!!!
7720 /*-----------------------------------------------------------------*/
7721 /* AccAXRsh - right shift a:x known count (0..7)                   */
7722 /*-----------------------------------------------------------------*/
7723 static void
7724 AccAXRsh (char *x, int shCount)
7725 {
7726   switch (shCount)
7727     {
7728     case 0:
7729       break;
7730     case 1:
7731       CLRC;
7732       AccAXRrl1 (x);            // 0->a:x
7733
7734       break;
7735     case 2:
7736       CLRC;
7737       AccAXRrl1 (x);            // 0->a:x
7738
7739       CLRC;
7740       AccAXRrl1 (x);            // 0->a:x
7741
7742       break;
7743     case 3:
7744     case 4:
7745     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7746
7747       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7748
7749       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7750
7751       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7752
7753       emitcode ("anl", "a,#!constbyte",
7754                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7755
7756       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7757
7758       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7759
7760       emitcode ("anl", "a,#!constbyte",
7761                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7762
7763       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7764
7765       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7766
7767       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7768
7769       break;
7770     case 6:                     // AABBBBBB:CCDDDDDD
7771
7772       emitcode ("mov", "c,acc.7");
7773       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7774
7775       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7776
7777       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7778
7779       emitcode ("anl", "a,#!constbyte",
7780                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7781
7782       break;
7783     case 7:                     // ABBBBBBB:CDDDDDDD
7784
7785       emitcode ("mov", "c,acc.7");      // c = A
7786
7787       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7788
7789       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7790
7791       emitcode ("anl", "a,#!constbyte",
7792                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7793
7794       break;
7795     default:
7796       break;
7797     }
7798 }
7799 #endif
7800
7801 #ifdef BETTER_LITERAL_SHIFT
7802 /*-----------------------------------------------------------------*/
7803 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7804 /*-----------------------------------------------------------------*/
7805 static void
7806 AccAXRshS (char *x, int shCount)
7807 {
7808   symbol *tlbl;
7809   switch (shCount)
7810     {
7811     case 0:
7812       break;
7813     case 1:
7814       emitcode ("mov", "c,acc.7");
7815       AccAXRrl1 (x);            // s->a:x
7816
7817       break;
7818     case 2:
7819       emitcode ("mov", "c,acc.7");
7820       AccAXRrl1 (x);            // s->a:x
7821
7822       emitcode ("mov", "c,acc.7");
7823       AccAXRrl1 (x);            // s->a:x
7824
7825       break;
7826     case 3:
7827     case 4:
7828     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7829
7830       tlbl = newiTempLabel (NULL);
7831       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7832
7833       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7834
7835       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7836
7837       emitcode ("anl", "a,#!constbyte",
7838                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7839
7840       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7841
7842       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7843
7844       emitcode ("anl", "a,#!constbyte",
7845                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7846
7847       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7848
7849       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7850
7851       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7852
7853       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7854       emitcode ("orl", "a,#!constbyte",
7855                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7856
7857       emitcode ("", "!tlabeldef", tlbl->key + 100);
7858       break;                    // SSSSAAAA:BBBCCCCC
7859
7860     case 6:                     // AABBBBBB:CCDDDDDD
7861
7862       tlbl = newiTempLabel (NULL);
7863       emitcode ("mov", "c,acc.7");
7864       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7865
7866       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7867
7868       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7869
7870       emitcode ("anl", "a,#!constbyte",
7871                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7872
7873       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7874       emitcode ("orl", "a,#!constbyte",
7875                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7876
7877       emitcode ("", "!tlabeldef", tlbl->key + 100);
7878       break;
7879     case 7:                     // ABBBBBBB:CDDDDDDD
7880
7881       tlbl = newiTempLabel (NULL);
7882       emitcode ("mov", "c,acc.7");      // c = A
7883
7884       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7885
7886       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7887
7888       emitcode ("anl", "a,#!constbyte",
7889                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7890
7891       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7892       emitcode ("orl", "a,#!constbyte",
7893                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7894
7895       emitcode ("", "!tlabeldef", tlbl->key + 100);
7896       break;
7897     default:
7898       break;
7899     }
7900 }
7901 #endif
7902
7903 #ifdef BETTER_LITERAL_SHIFT
7904 static void
7905 _loadLeftIntoAx(char    **lsb, 
7906                 operand *left, 
7907                 operand *result,
7908                 int     offl,
7909                 int     offr)
7910 {
7911   // Get the initial value from left into a pair of registers.
7912   // MSB must be in A, LSB can be any register.
7913   //
7914   // If the result is held in registers, it is an optimization
7915   // if the LSB can be held in the register which will hold the,
7916   // result LSB since this saves us from having to copy it into
7917   // the result following AccAXLsh.
7918   //
7919   // If the result is addressed indirectly, this is not a gain.
7920   if (AOP_NEEDSACC(result))
7921   {
7922        char *leftByte;
7923        
7924        _startLazyDPSEvaluation();
7925       if (AOP_TYPE(left) == AOP_DPTR2)
7926        {
7927            // Get MSB in A.
7928            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7929            // get LSB in DP2_RESULT_REG.
7930            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7931            assert(!strcmp(leftByte, DP2_RESULT_REG));
7932        }
7933        else
7934        {
7935            // get LSB into DP2_RESULT_REG
7936            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7937            if (strcmp(leftByte, DP2_RESULT_REG))
7938            {
7939                TR_AP("#7");
7940                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7941            }
7942            // And MSB in A.
7943            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7944            assert(strcmp(leftByte, DP2_RESULT_REG));
7945            MOVA(leftByte);
7946        }
7947        _endLazyDPSEvaluation();
7948        *lsb = DP2_RESULT_REG;
7949   }
7950   else
7951   {
7952       if (sameRegs (AOP (result), AOP (left)) &&
7953         ((offl + MSB16) == offr))
7954       {
7955           /* don't crash result[offr] */
7956           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7957           emitcode ("xch", "a,%s", 
7958                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7959       }
7960       else
7961       {
7962           movLeft2Result (left, offl, result, offr, 0);
7963           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7964       }
7965       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7966       assert(strcmp(*lsb,"a"));      
7967   }
7968 }
7969
7970 static void
7971 _storeAxResults(char    *lsb,
7972                 operand *result,
7973                 int     offr)
7974 {
7975   _startLazyDPSEvaluation();
7976   if (AOP_NEEDSACC(result))
7977   {
7978       /* We have to explicitly update the result LSB.
7979        */
7980       emitcode("xch","a,%s", lsb);
7981       aopPut(AOP(result), "a", offr);
7982       emitcode("mov","a,%s", lsb);
7983   }
7984   if (getDataSize (result) > 1)
7985   {
7986       aopPut (AOP (result), "a", offr + MSB16);
7987   }
7988   _endLazyDPSEvaluation();
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* shiftL2Left2Result - shift left two bytes from left to result   */
7993 /*-----------------------------------------------------------------*/
7994 static void
7995 shiftL2Left2Result (operand * left, int offl,
7996                     operand * result, int offr, int shCount)
7997 {
7998   char *lsb;
7999
8000   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8001   
8002   AccAXLsh (lsb, shCount);
8003   
8004   _storeAxResults(lsb, result, offr);
8005 }
8006 #endif
8007
8008 #ifdef BETTER_LITERAL_SHIFT
8009 /*-----------------------------------------------------------------*/
8010 /* shiftR2Left2Result - shift right two bytes from left to result  */
8011 /*-----------------------------------------------------------------*/
8012 static void
8013 shiftR2Left2Result (operand * left, int offl,
8014                     operand * result, int offr,
8015                     int shCount, int sign)
8016 {
8017   char *lsb;
8018   
8019   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8020   
8021   /* a:x >> shCount (x = lsb(result)) */
8022   if (sign)
8023   {
8024      AccAXRshS(lsb, shCount);
8025   }
8026   else
8027   {
8028     AccAXRsh(lsb, shCount);
8029   }
8030   
8031   _storeAxResults(lsb, result, offr);
8032 }
8033 #endif
8034
8035 /*-----------------------------------------------------------------*/
8036 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8037 /*-----------------------------------------------------------------*/
8038 static void
8039 shiftLLeftOrResult (operand * left, int offl,
8040                     operand * result, int offr, int shCount)
8041 {
8042   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8043   /* shift left accumulator */
8044   AccLsh (shCount);
8045   /* or with result */
8046   emitcode ("orl", "a,%s",
8047             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8048   /* back to result */
8049   aopPut (AOP (result), "a", offr);
8050 }
8051
8052 #if 0
8053 //REMOVE ME!!!
8054 /*-----------------------------------------------------------------*/
8055 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8056 /*-----------------------------------------------------------------*/
8057 static void
8058 shiftRLeftOrResult (operand * left, int offl,
8059                     operand * result, int offr, int shCount)
8060 {
8061   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8062   /* shift right accumulator */
8063   AccRsh (shCount);
8064   /* or with result */
8065   emitcode ("orl", "a,%s",
8066             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8067   /* back to result */
8068   aopPut (AOP (result), "a", offr);
8069 }
8070 #endif
8071
8072 #ifdef BETTER_LITERAL_SHIFT
8073 /*-----------------------------------------------------------------*/
8074 /* genlshOne - left shift a one byte quantity by known count       */
8075 /*-----------------------------------------------------------------*/
8076 static void
8077 genlshOne (operand * result, operand * left, int shCount)
8078 {
8079   D (emitcode (";", "genlshOne "););
8080   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8081 }
8082 #endif
8083
8084 #ifdef BETTER_LITERAL_SHIFT
8085 /*-----------------------------------------------------------------*/
8086 /* genlshTwo - left shift two bytes by known amount != 0           */
8087 /*-----------------------------------------------------------------*/
8088 static void
8089 genlshTwo (operand * result, operand * left, int shCount)
8090 {
8091   int size;
8092
8093   D (emitcode (";", "genlshTwo "););
8094
8095   size = getDataSize (result);
8096
8097   /* if shCount >= 8 */
8098   if (shCount >= 8)
8099   {
8100       shCount -= 8;
8101
8102       _startLazyDPSEvaluation();
8103
8104       if (size > 1)
8105         {
8106           if (shCount)
8107           {
8108             _endLazyDPSEvaluation();
8109             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8110             aopPut (AOP (result), zero, LSB);       
8111           }
8112           else
8113           {
8114             movLeft2Result (left, LSB, result, MSB16, 0);
8115             aopPut (AOP (result), zero, LSB);
8116             _endLazyDPSEvaluation();
8117           }
8118         }
8119         else
8120         {
8121           aopPut (AOP (result), zero, LSB);
8122           _endLazyDPSEvaluation();
8123         }
8124   }
8125
8126   /*  1 <= shCount <= 7 */
8127   else
8128     {
8129       if (size == 1)
8130       {
8131         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8132       }
8133       else
8134       {
8135         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8136       }
8137     }
8138 }
8139 #endif
8140
8141 #if 0
8142 //REMOVE ME!!!
8143 /*-----------------------------------------------------------------*/
8144 /* shiftLLong - shift left one long from left to result            */
8145 /* offl = LSB or MSB16                                             */
8146 /*-----------------------------------------------------------------*/
8147 static void
8148 shiftLLong (operand * left, operand * result, int offr)
8149 {
8150   char *l;
8151   int size = AOP_SIZE (result);
8152
8153   if (size >= LSB + offr)
8154     {
8155       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8156       MOVA (l);
8157       emitcode ("add", "a,acc");
8158       if (sameRegs (AOP (left), AOP (result)) &&
8159           size >= MSB16 + offr && offr != LSB)
8160         emitcode ("xch", "a,%s",
8161                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8162       else
8163         aopPut (AOP (result), "a", LSB + offr);
8164     }
8165
8166   if (size >= MSB16 + offr)
8167     {
8168       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8169         {
8170           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8171         }
8172       emitcode ("rlc", "a");
8173       if (sameRegs (AOP (left), AOP (result)) &&
8174           size >= MSB24 + offr && offr != LSB)
8175         emitcode ("xch", "a,%s",
8176                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8177       else
8178         aopPut (AOP (result), "a", MSB16 + offr);
8179     }
8180
8181   if (size >= MSB24 + offr)
8182     {
8183       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8184         {
8185           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8186         }
8187       emitcode ("rlc", "a");
8188       if (sameRegs (AOP (left), AOP (result)) &&
8189           size >= MSB32 + offr && offr != LSB)
8190         emitcode ("xch", "a,%s",
8191                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8192       else
8193         aopPut (AOP (result), "a", MSB24 + offr);
8194     }
8195
8196   if (size > MSB32 + offr)
8197     {
8198       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8199         {
8200           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8201         }
8202       emitcode ("rlc", "a");
8203       aopPut (AOP (result), "a", MSB32 + offr);
8204     }
8205   if (offr != LSB)
8206     aopPut (AOP (result), zero, LSB);
8207 }
8208 #endif
8209
8210 #if 0
8211 //REMOVE ME!!!
8212 /*-----------------------------------------------------------------*/
8213 /* genlshFour - shift four byte by a known amount != 0             */
8214 /*-----------------------------------------------------------------*/
8215 static void
8216 genlshFour (operand * result, operand * left, int shCount)
8217 {
8218   int size;
8219
8220   D (emitcode (";", "genlshFour ");
8221     );
8222
8223   size = AOP_SIZE (result);
8224
8225   /* if shifting more that 3 bytes */
8226   if (shCount >= 24)
8227     {
8228       shCount -= 24;
8229       if (shCount)
8230         /* lowest order of left goes to the highest
8231            order of the destination */
8232         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8233       else
8234         movLeft2Result (left, LSB, result, MSB32, 0);
8235       aopPut (AOP (result), zero, LSB);
8236       aopPut (AOP (result), zero, MSB16);
8237       aopPut (AOP (result), zero, MSB24);
8238       return;
8239     }
8240
8241   /* more than two bytes */
8242   else if (shCount >= 16)
8243     {
8244       /* lower order two bytes goes to higher order two bytes */
8245       shCount -= 16;
8246       /* if some more remaining */
8247       if (shCount)
8248         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8249       else
8250         {
8251           movLeft2Result (left, MSB16, result, MSB32, 0);
8252           movLeft2Result (left, LSB, result, MSB24, 0);
8253         }
8254       aopPut (AOP (result), zero, MSB16);
8255       aopPut (AOP (result), zero, LSB);
8256       return;
8257     }
8258
8259   /* if more than 1 byte */
8260   else if (shCount >= 8)
8261     {
8262       /* lower order three bytes goes to higher order  three bytes */
8263       shCount -= 8;
8264       if (size == 2)
8265         {
8266           if (shCount)
8267             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8268           else
8269             movLeft2Result (left, LSB, result, MSB16, 0);
8270         }
8271       else
8272         {                       /* size = 4 */
8273           if (shCount == 0)
8274             {
8275               movLeft2Result (left, MSB24, result, MSB32, 0);
8276               movLeft2Result (left, MSB16, result, MSB24, 0);
8277               movLeft2Result (left, LSB, result, MSB16, 0);
8278               aopPut (AOP (result), zero, LSB);
8279             }
8280           else if (shCount == 1)
8281             shiftLLong (left, result, MSB16);
8282           else
8283             {
8284               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8285               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8286               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8287               aopPut (AOP (result), zero, LSB);
8288             }
8289         }
8290     }
8291
8292   /* 1 <= shCount <= 7 */
8293   else if (shCount <= 2)
8294     {
8295       shiftLLong (left, result, LSB);
8296       if (shCount == 2)
8297         shiftLLong (result, result, LSB);
8298     }
8299   /* 3 <= shCount <= 7, optimize */
8300   else
8301     {
8302       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8303       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8304       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8305     }
8306 }
8307 #endif
8308
8309 #ifdef BETTER_LITERAL_SHIFT
8310 /*-----------------------------------------------------------------*/
8311 /* genLeftShiftLiteral - left shifting by known count              */
8312 /*-----------------------------------------------------------------*/
8313 static bool
8314 genLeftShiftLiteral (operand * left,
8315                      operand * right,
8316                      operand * result,
8317                      iCode * ic)
8318 {
8319   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8320   int size;
8321
8322   size = getSize (operandType (result));
8323
8324   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8325
8326   /* We only handle certain easy cases so far. */
8327   if ((shCount != 0)
8328    && (shCount < (size * 8))
8329    && (size != 1)
8330    && (size != 2))
8331   {
8332       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8333       return FALSE;
8334   }
8335
8336   freeAsmop (right, NULL, ic, TRUE);
8337
8338   aopOp(left, ic, FALSE, FALSE);
8339   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8340
8341 #if 0 // debug spew
8342   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8343   {
8344         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8345         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8346         {
8347            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8348         }
8349   }
8350   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8351   {
8352         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8353         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8354         {
8355            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8356         }       
8357   }  
8358 #endif
8359   
8360 #if VIEW_SIZE
8361   emitcode ("; shift left ", "result %d, left %d", size,
8362             AOP_SIZE (left));
8363 #endif
8364
8365   /* I suppose that the left size >= result size */
8366   if (shCount == 0)
8367   {
8368         _startLazyDPSEvaluation();
8369         while (size--)
8370         {
8371           movLeft2Result (left, size, result, size, 0);
8372         }
8373         _endLazyDPSEvaluation();
8374   }
8375   else if (shCount >= (size * 8))
8376   {
8377     _startLazyDPSEvaluation();
8378     while (size--)
8379     {
8380       aopPut (AOP (result), zero, size);
8381     }
8382     _endLazyDPSEvaluation();
8383   }
8384   else
8385   {
8386       switch (size)
8387         {
8388         case 1:
8389           genlshOne (result, left, shCount);
8390           break;
8391
8392         case 2:
8393           genlshTwo (result, left, shCount);
8394           break;
8395 #if 0
8396         case 4:
8397           genlshFour (result, left, shCount);
8398           break;
8399 #endif
8400         default:
8401           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8402           break;
8403         }
8404     }
8405   freeAsmop (left, NULL, ic, TRUE);
8406   freeAsmop (result, NULL, ic, TRUE);
8407   return TRUE;
8408 }
8409 #endif
8410
8411 /*-----------------------------------------------------------------*/
8412 /* genLeftShift - generates code for left shifting                 */
8413 /*-----------------------------------------------------------------*/
8414 static void
8415 genLeftShift (iCode * ic)
8416 {
8417   operand *left, *right, *result;
8418   int size, offset;
8419   char *l;
8420   symbol *tlbl, *tlbl1;
8421
8422   D (emitcode (";", "genLeftShift "););
8423
8424   right = IC_RIGHT (ic);
8425   left = IC_LEFT (ic);
8426   result = IC_RESULT (ic);
8427
8428   aopOp (right, ic, FALSE, FALSE);
8429
8430
8431 #ifdef BETTER_LITERAL_SHIFT
8432   /* if the shift count is known then do it
8433      as efficiently as possible */
8434   if (AOP_TYPE (right) == AOP_LIT)
8435     {
8436       if (genLeftShiftLiteral (left, right, result, ic))
8437       {
8438         return;
8439       }
8440     }
8441 #endif
8442
8443   /* shift count is unknown then we have to form
8444      a loop get the loop count in B : Note: we take
8445      only the lower order byte since shifting
8446      more that 32 bits make no sense anyway, ( the
8447      largest size of an object can be only 32 bits ) */
8448
8449   if (AOP_TYPE (right) == AOP_LIT)
8450   {
8451       /* Really should be handled by genLeftShiftLiteral,
8452        * but since I'm too lazy to fix that today, at least we can make
8453        * some small improvement.
8454        */
8455        emitcode("mov", "b,#!constbyte",
8456                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8457   }
8458   else
8459   {
8460       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8461       emitcode ("inc", "b");
8462   }
8463   freeAsmop (right, NULL, ic, TRUE);
8464   aopOp (left, ic, FALSE, FALSE);
8465   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8466
8467   /* now move the left to the result if they are not the
8468      same */
8469   if (!sameRegs (AOP (left), AOP (result)) &&
8470       AOP_SIZE (result) > 1)
8471     {
8472
8473       size = AOP_SIZE (result);
8474       offset = 0;
8475       _startLazyDPSEvaluation ();
8476       while (size--)
8477         {
8478           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8479           if (*l == '@' && (IS_AOP_PREG (result)))
8480             {
8481
8482               emitcode ("mov", "a,%s", l);
8483               aopPut (AOP (result), "a", offset);
8484             }
8485           else
8486             aopPut (AOP (result), l, offset);
8487           offset++;
8488         }
8489       _endLazyDPSEvaluation ();
8490     }
8491
8492   tlbl = newiTempLabel (NULL);
8493   size = AOP_SIZE (result);
8494   offset = 0;
8495   tlbl1 = newiTempLabel (NULL);
8496
8497   /* if it is only one byte then */
8498   if (size == 1)
8499     {
8500       symbol *tlbl1 = newiTempLabel (NULL);
8501
8502       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8503       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8504       emitcode ("", "!tlabeldef", tlbl->key + 100);
8505       emitcode ("add", "a,acc");
8506       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8507       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8508       aopPut (AOP (result), "a", 0);
8509       goto release;
8510     }
8511
8512   reAdjustPreg (AOP (result));
8513
8514   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8515   emitcode ("", "!tlabeldef", tlbl->key + 100);
8516   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8517   emitcode ("add", "a,acc");
8518   aopPut (AOP (result), "a", offset++);
8519   _startLazyDPSEvaluation ();
8520   while (--size)
8521     {
8522       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8523       emitcode ("rlc", "a");
8524       aopPut (AOP (result), "a", offset++);
8525     }
8526   _endLazyDPSEvaluation ();
8527   reAdjustPreg (AOP (result));
8528
8529   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8530   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8531 release:
8532   freeAsmop (left, NULL, ic, TRUE);
8533   freeAsmop (result, NULL, ic, TRUE);
8534 }
8535
8536 #ifdef BETTER_LITERAL_SHIFT
8537 /*-----------------------------------------------------------------*/
8538 /* genrshOne - right shift a one byte quantity by known count      */
8539 /*-----------------------------------------------------------------*/
8540 static void
8541 genrshOne (operand * result, operand * left,
8542            int shCount, int sign)
8543 {
8544   D (emitcode (";", "genrshOne"););
8545   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8546 }
8547 #endif
8548
8549 #ifdef BETTER_LITERAL_SHIFT
8550 /*-----------------------------------------------------------------*/
8551 /* genrshTwo - right shift two bytes by known amount != 0          */
8552 /*-----------------------------------------------------------------*/
8553 static void
8554 genrshTwo (operand * result, operand * left,
8555            int shCount, int sign)
8556 {
8557   D (emitcode (";", "genrshTwo"););
8558
8559   /* if shCount >= 8 */
8560   if (shCount >= 8)
8561     {
8562       shCount -= 8;
8563       _startLazyDPSEvaluation();
8564       if (shCount)
8565       {
8566         shiftR1Left2Result (left, MSB16, result, LSB,
8567                             shCount, sign);
8568       }                     
8569       else
8570       {
8571         movLeft2Result (left, MSB16, result, LSB, sign);
8572       }
8573       addSign (result, MSB16, sign);
8574       _endLazyDPSEvaluation();
8575     }
8576
8577   /*  1 <= shCount <= 7 */
8578   else
8579   {
8580     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8581   }
8582 }
8583 #endif
8584
8585 /*-----------------------------------------------------------------*/
8586 /* shiftRLong - shift right one long from left to result           */
8587 /* offl = LSB or MSB16                                             */
8588 /*-----------------------------------------------------------------*/
8589 static void
8590 shiftRLong (operand * left, int offl,
8591             operand * result, int sign)
8592 {
8593   int isSameRegs=sameRegs(AOP(left),AOP(result));
8594
8595   if (isSameRegs && offl>1) {
8596     // we are in big trouble, but this shouldn't happen
8597     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8598   }
8599
8600   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8601   
8602   if (offl==MSB16) {
8603     // shift is > 8
8604     if (sign) {
8605       emitcode ("rlc", "a");
8606       emitcode ("subb", "a,acc");
8607       emitcode ("xch", "a,%s",
8608                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8609     } else {
8610       aopPut (AOP(result), zero, MSB32);
8611     }
8612   }
8613
8614   if (!sign) {
8615     emitcode ("clr", "c");
8616   } else {
8617     emitcode ("mov", "c,acc.7");
8618   }
8619
8620   emitcode ("rrc", "a");
8621
8622   if (isSameRegs && offl==MSB16) {
8623     emitcode ("xch",
8624               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8625   } else {
8626     aopPut (AOP (result), "a", MSB32);
8627     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8628   }
8629
8630   emitcode ("rrc", "a");
8631   if (isSameRegs && offl==1) {
8632     emitcode ("xch", "a,%s",
8633               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8634   } else {
8635     aopPut (AOP (result), "a", MSB24);
8636     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8637   }
8638   emitcode ("rrc", "a");
8639   aopPut (AOP (result), "a", MSB16 - offl);
8640
8641   if (offl == LSB)
8642     {
8643       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8644       emitcode ("rrc", "a");
8645       aopPut (AOP (result), "a", LSB);
8646     }
8647 }
8648
8649 /*-----------------------------------------------------------------*/
8650 /* genrshFour - shift four byte by a known amount != 0             */
8651 /*-----------------------------------------------------------------*/
8652 static void
8653 genrshFour (operand * result, operand * left,
8654             int shCount, int sign)
8655 {
8656   D (emitcode (";", "genrshFour"););
8657
8658   /* if shifting more that 3 bytes */
8659   if (shCount >= 24)
8660     {
8661       shCount -= 24;
8662       _startLazyDPSEvaluation();
8663       if (shCount)
8664         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8665       else
8666         movLeft2Result (left, MSB32, result, LSB, sign);
8667       addSign (result, MSB16, sign);
8668       _endLazyDPSEvaluation();
8669     }
8670   else if (shCount >= 16)
8671     {
8672       shCount -= 16;
8673       _startLazyDPSEvaluation();
8674       if (shCount)
8675         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8676       else
8677         {
8678           movLeft2Result (left, MSB24, result, LSB, 0);
8679           movLeft2Result (left, MSB32, result, MSB16, sign);
8680         }
8681       addSign (result, MSB24, sign);
8682       _endLazyDPSEvaluation();
8683     }
8684   else if (shCount >= 8)
8685     {
8686       shCount -= 8;
8687       _startLazyDPSEvaluation();
8688       if (shCount == 1)
8689         {
8690             shiftRLong (left, MSB16, result, sign);
8691         }
8692       else if (shCount == 0)
8693         {
8694           movLeft2Result (left, MSB16, result, LSB, 0);
8695           movLeft2Result (left, MSB24, result, MSB16, 0);
8696           movLeft2Result (left, MSB32, result, MSB24, sign);
8697           addSign (result, MSB32, sign);
8698         }
8699       else
8700         {
8701           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8702           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8703           /* the last shift is signed */
8704           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8705           addSign (result, MSB32, sign);
8706         }
8707         _endLazyDPSEvaluation();
8708     }
8709   else
8710     {   
8711         /* 1 <= shCount <= 7 */
8712       if (shCount <= 2)
8713         {
8714           shiftRLong (left, LSB, result, sign);
8715           if (shCount == 2)
8716             shiftRLong (result, LSB, result, sign);
8717         }
8718       else
8719         {
8720           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8721           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8722           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8723         }
8724     }
8725 }
8726
8727 #ifdef BETTER_LITERAL_SHIFT
8728 /*-----------------------------------------------------------------*/
8729 /* genRightShiftLiteral - right shifting by known count            */
8730 /*-----------------------------------------------------------------*/
8731 static bool
8732 genRightShiftLiteral (operand * left,
8733                       operand * right,
8734                       operand * result,
8735                       iCode * ic,
8736                       int sign)
8737 {
8738   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8739   int size;
8740
8741   size = getSize (operandType (result));
8742
8743   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8744
8745   /* We only handle certain easy cases so far. */
8746   if ((shCount != 0)
8747    && (shCount < (size * 8))
8748    && (size != 1)
8749    && (size != 2)
8750    && (size != 4))
8751   {
8752       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8753       return FALSE;
8754   }
8755
8756   freeAsmop (right, NULL, ic, TRUE);
8757
8758   aopOp (left, ic, FALSE, FALSE);
8759   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8760
8761 #if VIEW_SIZE
8762   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8763             AOP_SIZE (left));
8764 #endif
8765
8766   /* test the LEFT size !!! */
8767
8768   /* I suppose that the left size >= result size */
8769   if (shCount == 0)
8770   {
8771       size = getDataSize (result);
8772       _startLazyDPSEvaluation();
8773       while (size--)
8774       {
8775         movLeft2Result (left, size, result, size, 0);
8776       }
8777       _endLazyDPSEvaluation();
8778   }
8779   else if (shCount >= (size * 8))
8780     {
8781       if (sign)
8782       {
8783         /* get sign in acc.7 */
8784         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8785       }
8786       addSign (result, LSB, sign);
8787     }
8788   else
8789     {
8790       switch (size)
8791         {
8792         case 1:
8793           genrshOne (result, left, shCount, sign);
8794           break;
8795
8796         case 2:
8797           genrshTwo (result, left, shCount, sign);
8798           break;
8799 #if 1
8800         case 4:
8801           genrshFour (result, left, shCount, sign);
8802           break;
8803 #endif    
8804         default:
8805           break;
8806         }
8807     }
8808   freeAsmop (left, NULL, ic, TRUE);
8809   freeAsmop (result, NULL, ic, TRUE);
8810   
8811   return TRUE;
8812 }
8813 #endif
8814
8815 /*-----------------------------------------------------------------*/
8816 /* genSignedRightShift - right shift of signed number              */
8817 /*-----------------------------------------------------------------*/
8818 static void
8819 genSignedRightShift (iCode * ic)
8820 {
8821   operand *right, *left, *result;
8822   int size, offset;
8823   char *l;
8824   symbol *tlbl, *tlbl1;
8825
8826   D (emitcode (";", "genSignedRightShift "););
8827
8828   /* we do it the hard way put the shift count in b
8829      and loop thru preserving the sign */
8830
8831   right = IC_RIGHT (ic);
8832   left = IC_LEFT (ic);
8833   result = IC_RESULT (ic);
8834
8835   aopOp (right, ic, FALSE, FALSE);
8836
8837 #ifdef BETTER_LITERAL_SHIFT
8838   if (AOP_TYPE (right) == AOP_LIT)
8839     {
8840       if (genRightShiftLiteral (left, right, result, ic, 1))
8841       {
8842         return;
8843       }
8844     }
8845 #endif
8846   /* shift count is unknown then we have to form
8847      a loop get the loop count in B : Note: we take
8848      only the lower order byte since shifting
8849      more that 32 bits make no sense anyway, ( the
8850      largest size of an object can be only 32 bits ) */
8851
8852   if (AOP_TYPE (right) == AOP_LIT)
8853   {
8854       /* Really should be handled by genRightShiftLiteral,
8855        * but since I'm too lazy to fix that today, at least we can make
8856        * some small improvement.
8857        */
8858        emitcode("mov", "b,#!constbyte",
8859                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8860   }
8861   else
8862   {
8863         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8864         emitcode ("inc", "b");
8865   }
8866   freeAsmop (right, NULL, ic, TRUE);
8867   aopOp (left, ic, FALSE, FALSE);
8868   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8869
8870   /* now move the left to the result if they are not the
8871      same */
8872   if (!sameRegs (AOP (left), AOP (result)) &&
8873       AOP_SIZE (result) > 1)
8874     {
8875
8876       size = AOP_SIZE (result);
8877       offset = 0;
8878       _startLazyDPSEvaluation ();
8879       while (size--)
8880         {
8881           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8882           if (*l == '@' && IS_AOP_PREG (result))
8883             {
8884
8885               emitcode ("mov", "a,%s", l);
8886               aopPut (AOP (result), "a", offset);
8887             }
8888           else
8889             aopPut (AOP (result), l, offset);
8890           offset++;
8891         }
8892       _endLazyDPSEvaluation ();
8893     }
8894
8895   /* mov the highest order bit to OVR */
8896   tlbl = newiTempLabel (NULL);
8897   tlbl1 = newiTempLabel (NULL);
8898
8899   size = AOP_SIZE (result);
8900   offset = size - 1;
8901   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8902   emitcode ("rlc", "a");
8903   emitcode ("mov", "ov,c");
8904   /* if it is only one byte then */
8905   if (size == 1)
8906     {
8907       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8908       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8909       emitcode ("", "!tlabeldef", tlbl->key + 100);
8910       emitcode ("mov", "c,ov");
8911       emitcode ("rrc", "a");
8912       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8914       aopPut (AOP (result), "a", 0);
8915       goto release;
8916     }
8917
8918   reAdjustPreg (AOP (result));
8919   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8920   emitcode ("", "!tlabeldef", tlbl->key + 100);
8921   emitcode ("mov", "c,ov");
8922   _startLazyDPSEvaluation ();
8923   while (size--)
8924     {
8925       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8926       emitcode ("rrc", "a");
8927       aopPut (AOP (result), "a", offset--);
8928     }
8929   _endLazyDPSEvaluation ();
8930   reAdjustPreg (AOP (result));
8931   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8932   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8933
8934 release:
8935   freeAsmop (left, NULL, ic, TRUE);
8936   freeAsmop (result, NULL, ic, TRUE);
8937 }
8938
8939 /*-----------------------------------------------------------------*/
8940 /* genRightShift - generate code for right shifting                */
8941 /*-----------------------------------------------------------------*/
8942 static void
8943 genRightShift (iCode * ic)
8944 {
8945   operand *right, *left, *result;
8946   sym_link *retype;
8947   int size, offset;
8948   char *l;
8949   symbol *tlbl, *tlbl1;
8950
8951   D (emitcode (";", "genRightShift "););
8952
8953   /* if signed then we do it the hard way preserve the
8954      sign bit moving it inwards */
8955   retype = getSpec (operandType (IC_RESULT (ic)));
8956
8957   if (!SPEC_USIGN (retype))
8958     {
8959       genSignedRightShift (ic);
8960       return;
8961     }
8962
8963   /* signed & unsigned types are treated the same : i.e. the
8964      signed is NOT propagated inwards : quoting from the
8965      ANSI - standard : "for E1 >> E2, is equivalent to division
8966      by 2**E2 if unsigned or if it has a non-negative value,
8967      otherwise the result is implementation defined ", MY definition
8968      is that the sign does not get propagated */
8969
8970   right = IC_RIGHT (ic);
8971   left = IC_LEFT (ic);
8972   result = IC_RESULT (ic);
8973
8974   aopOp (right, ic, FALSE, FALSE);
8975
8976 #ifdef BETTER_LITERAL_SHIFT
8977   /* if the shift count is known then do it
8978      as efficiently as possible */
8979   if (AOP_TYPE (right) == AOP_LIT)
8980     {
8981       if (genRightShiftLiteral (left, right, result, ic, 0))
8982       {
8983         return;
8984       }
8985     }
8986 #endif
8987
8988   /* shift count is unknown then we have to form
8989      a loop get the loop count in B : Note: we take
8990      only the lower order byte since shifting
8991      more that 32 bits make no sense anyway, ( the
8992      largest size of an object can be only 32 bits ) */
8993   
8994   if (AOP_TYPE (right) == AOP_LIT)
8995   {
8996       /* Really should be handled by genRightShiftLiteral,
8997        * but since I'm too lazy to fix that today, at least we can make
8998        * some small improvement.
8999        */
9000        emitcode("mov", "b,#!constbyte",
9001                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9002   }
9003   else
9004   {
9005       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9006       emitcode ("inc", "b");
9007   }
9008   freeAsmop (right, NULL, ic, TRUE);
9009   aopOp (left, ic, FALSE, FALSE);
9010   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9011
9012   /* now move the left to the result if they are not the
9013      same */
9014   if (!sameRegs (AOP (left), AOP (result)) &&
9015       AOP_SIZE (result) > 1)
9016     {
9017
9018       size = AOP_SIZE (result);
9019       offset = 0;
9020       _startLazyDPSEvaluation ();
9021       while (size--)
9022         {
9023           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9024           if (*l == '@' && IS_AOP_PREG (result))
9025             {
9026
9027               emitcode ("mov", "a,%s", l);
9028               aopPut (AOP (result), "a", offset);
9029             }
9030           else
9031             aopPut (AOP (result), l, offset);
9032           offset++;
9033         }
9034       _endLazyDPSEvaluation ();
9035     }
9036
9037   tlbl = newiTempLabel (NULL);
9038   tlbl1 = newiTempLabel (NULL);
9039   size = AOP_SIZE (result);
9040   offset = size - 1;
9041
9042   /* if it is only one byte then */
9043   if (size == 1)
9044     {
9045       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9046       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9047       emitcode ("", "!tlabeldef", tlbl->key + 100);
9048       CLRC;
9049       emitcode ("rrc", "a");
9050       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9051       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9052       aopPut (AOP (result), "a", 0);
9053       goto release;
9054     }
9055
9056   reAdjustPreg (AOP (result));
9057   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9058   emitcode ("", "!tlabeldef", tlbl->key + 100);
9059   CLRC;
9060   _startLazyDPSEvaluation ();
9061   while (size--)
9062     {
9063       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9064       emitcode ("rrc", "a");
9065       aopPut (AOP (result), "a", offset--);
9066     }
9067   _endLazyDPSEvaluation ();
9068   reAdjustPreg (AOP (result));
9069
9070   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9071   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9072
9073 release:
9074   freeAsmop (left, NULL, ic, TRUE);
9075   freeAsmop (result, NULL, ic, TRUE);
9076 }
9077
9078
9079 /*-----------------------------------------------------------------*/
9080 /* emitPtrByteGet - emits code to get a byte into A through a      */
9081 /*                  pointer register (R0, R1, or DPTR). The        */
9082 /*                  original value of A can be preserved in B.     */
9083 /*-----------------------------------------------------------------*/
9084 static void
9085 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9086 {
9087   switch (p_type)
9088     {
9089     case IPOINTER:
9090     case POINTER:
9091       if (preserveAinB)
9092         emitcode ("mov", "b,a");
9093       emitcode ("mov", "a,@%s", rname);
9094       break;
9095
9096     case PPOINTER:
9097       if (preserveAinB)
9098         emitcode ("mov", "b,a");
9099       emitcode ("movx", "a,@%s", rname);
9100       break;
9101       
9102     case FPOINTER:
9103       if (preserveAinB)
9104         emitcode ("mov", "b,a");
9105       emitcode ("movx", "a,@dptr");
9106       break;
9107
9108     case CPOINTER:
9109       if (preserveAinB)
9110         emitcode ("mov", "b,a");
9111       emitcode ("clr", "a");
9112       emitcode ("movc", "a,@a+dptr");
9113       break;
9114
9115     case GPOINTER:
9116       if (preserveAinB)
9117         {
9118           emitcode ("push", "b");
9119           emitcode ("push", "acc");
9120         }
9121       emitcode ("lcall", "__gptrget");
9122       if (preserveAinB)
9123         emitcode ("pop", "b");
9124       break;
9125     }
9126 }
9127
9128 /*-----------------------------------------------------------------*/
9129 /* emitPtrByteSet - emits code to set a byte from src through a    */
9130 /*                  pointer register (R0, R1, or DPTR).            */
9131 /*-----------------------------------------------------------------*/
9132 static void
9133 emitPtrByteSet (char *rname, int p_type, char *src)
9134 {
9135   switch (p_type)
9136     {
9137     case IPOINTER:
9138     case POINTER:
9139       if (*src=='@')
9140         {
9141           MOVA (src);
9142           emitcode ("mov", "@%s,a", rname);
9143         }
9144       else
9145         emitcode ("mov", "@%s,%s", rname, src);
9146       break;
9147
9148     case PPOINTER:
9149       MOVA (src);
9150       emitcode ("movx", "@%s,a", rname);
9151       break;
9152       
9153     case FPOINTER:
9154       MOVA (src);
9155       emitcode ("movx", "@dptr,a");
9156       break;
9157
9158     case GPOINTER:
9159       MOVA (src);
9160       emitcode ("lcall", "__gptrput");
9161       break;
9162     }
9163 }
9164
9165 /*-----------------------------------------------------------------*/
9166 /* genUnpackBits - generates code for unpacking bits               */
9167 /*-----------------------------------------------------------------*/
9168 static void
9169 genUnpackBits (operand * result, char *rname, int ptype)
9170 {
9171   int offset = 0;       /* result byte offset */
9172   int rsize;            /* result size */
9173   int rlen = 0;         /* remaining bitfield length */
9174   sym_link *etype;      /* bitfield type information */
9175   int blen;             /* bitfield length */
9176   int bstr;             /* bitfield starting bit within byte */
9177
9178   D(emitcode (";     genUnpackBits",""));
9179
9180   etype = getSpec (operandType (result));
9181   rsize = getSize (operandType (result));
9182   blen = SPEC_BLEN (etype);
9183   bstr = SPEC_BSTR (etype);
9184
9185   /* If the bitfield length is less than a byte */
9186   if (blen < 8)
9187     {
9188       emitPtrByteGet (rname, ptype, FALSE);
9189       AccRsh (bstr);
9190       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9191       aopPut (AOP (result), "a", offset++);
9192       goto finish;
9193     }
9194
9195   /* Bit field did not fit in a byte. Copy all
9196      but the partial byte at the end.  */
9197   for (rlen=blen;rlen>=8;rlen-=8)
9198     {
9199       emitPtrByteGet (rname, ptype, FALSE);
9200       aopPut (AOP (result), "a", offset++);
9201       if (rlen>8)
9202         emitcode ("inc", "%s", rname);
9203     }
9204
9205   /* Handle the partial byte at the end */
9206   if (rlen)
9207     {
9208       emitPtrByteGet (rname, ptype, FALSE);
9209       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9210       aopPut (AOP (result), "a", offset++);
9211     }
9212
9213 finish:
9214   if (offset < rsize)
9215     {
9216       rsize -= offset;
9217       while (rsize--)
9218         aopPut (AOP (result), zero, offset++);
9219     }
9220 }
9221
9222
9223 /*-----------------------------------------------------------------*/
9224 /* genDataPointerGet - generates code when ptr offset is known     */
9225 /*-----------------------------------------------------------------*/
9226 static void
9227 genDataPointerGet (operand * left,
9228                    operand * result,
9229                    iCode * ic)
9230 {
9231   char *l;
9232   char buff[256];
9233   int size, offset = 0;
9234   aopOp (result, ic, TRUE, FALSE);
9235
9236   /* get the string representation of the name */
9237   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9238   size = AOP_SIZE (result);
9239   _startLazyDPSEvaluation ();
9240   while (size--)
9241     {
9242         if (offset)
9243         {
9244             SNPRINTF (buff, sizeof(buff), 
9245                       "(%s + %d)", l + 1, offset);
9246         }
9247         else
9248         {
9249             SNPRINTF (buff, sizeof(buff), 
9250                       "%s", l + 1);
9251         }
9252       aopPut (AOP (result), buff, offset++);
9253     }
9254   _endLazyDPSEvaluation ();
9255
9256   freeAsmop (left, NULL, ic, TRUE);
9257   freeAsmop (result, NULL, ic, TRUE);
9258 }
9259
9260 /*-----------------------------------------------------------------*/
9261 /* genNearPointerGet - emitcode for near pointer fetch             */
9262 /*-----------------------------------------------------------------*/
9263 static void
9264 genNearPointerGet (operand * left,
9265                    operand * result,
9266                    iCode * ic,
9267                    iCode *pi)
9268 {
9269   asmop *aop = NULL;
9270   regs *preg;
9271   char *rname;
9272   sym_link *rtype, *retype, *letype;
9273   sym_link *ltype = operandType (left);
9274   char buff[80];
9275
9276   rtype = operandType (result);
9277   retype = getSpec (rtype);
9278   letype = getSpec (ltype);
9279
9280   aopOp (left, ic, FALSE, FALSE);
9281
9282   /* if left is rematerialisable and
9283      result is not bit variable type and
9284      the left is pointer to data space i.e
9285      lower 128 bytes of space */
9286   if (AOP_TYPE (left) == AOP_IMMD &&
9287       !IS_BITVAR (retype) &&
9288       !IS_BITVAR (letype) &&
9289       DCL_TYPE (ltype) == POINTER)
9290     {
9291       genDataPointerGet (left, result, ic);
9292       return;
9293     }
9294
9295   /* if the value is already in a pointer register
9296      then don't need anything more */
9297   if (!AOP_INPREG (AOP (left)))
9298     {
9299       /* otherwise get a free pointer register */
9300       aop = newAsmop (0);
9301       preg = getFreePtr (ic, &aop, FALSE);
9302       emitcode ("mov", "%s,%s",
9303                 preg->name,
9304                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9305       rname = preg->name;
9306     }
9307   else
9308     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9309
9310   freeAsmop (left, NULL, ic, TRUE);
9311   aopOp (result, ic, FALSE, FALSE);
9312
9313   /* if bitfield then unpack the bits */
9314   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9315     genUnpackBits (result, rname, POINTER);
9316   else
9317     {
9318       /* we have can just get the values */
9319       int size = AOP_SIZE (result);
9320       int offset = 0;
9321
9322       while (size--)
9323         {
9324           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9325             {
9326
9327               emitcode ("mov", "a,@%s", rname);
9328               aopPut (AOP (result), "a", offset);
9329             }
9330           else
9331             {
9332               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9333               aopPut (AOP (result), buff, offset);
9334             }
9335           offset++;
9336           if (size || pi)
9337             {
9338                 emitcode ("inc", "%s", rname);
9339             }
9340         }
9341     }
9342
9343   /* now some housekeeping stuff */
9344   if (aop)
9345     {
9346       /* we had to allocate for this iCode */
9347       if (pi) { /* post increment present */
9348         aopPut(AOP ( left ),rname,0);
9349       }
9350       freeAsmop (NULL, aop, ic, TRUE);
9351     }
9352   else
9353     {
9354       /* we did not allocate which means left
9355          already in a pointer register, then
9356          if size > 0 && this could be used again
9357          we have to point it back to where it
9358          belongs */
9359       if (AOP_SIZE (result) > 1 &&
9360           !OP_SYMBOL (left)->remat &&
9361           (OP_SYMBOL (left)->liveTo > ic->seq ||
9362            ic->depth) &&
9363           !pi)
9364         {
9365           int size = AOP_SIZE (result) - 1;
9366           while (size--)
9367             emitcode ("dec", "%s", rname);
9368         }
9369     }
9370
9371   /* done */
9372   freeAsmop (result, NULL, ic, TRUE);
9373   if (pi) pi->generated = 1;
9374 }
9375
9376 /*-----------------------------------------------------------------*/
9377 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9378 /*-----------------------------------------------------------------*/
9379 static void
9380 genPagedPointerGet (operand * left,
9381                     operand * result,
9382                     iCode * ic,
9383                     iCode * pi)
9384 {
9385   asmop *aop = NULL;
9386   regs *preg;
9387   char *rname;
9388   sym_link *rtype, *retype, *letype;
9389
9390   rtype = operandType (result);
9391   retype = getSpec (rtype);
9392   letype = getSpec (operandType (left));
9393   aopOp (left, ic, FALSE, FALSE);
9394
9395   /* if the value is already in a pointer register
9396      then don't need anything more */
9397   if (!AOP_INPREG (AOP (left)))
9398     {
9399       /* otherwise get a free pointer register */
9400       aop = newAsmop (0);
9401       preg = getFreePtr (ic, &aop, FALSE);
9402       emitcode ("mov", "%s,%s",
9403                 preg->name,
9404                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9405       rname = preg->name;
9406     }
9407   else
9408     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9409
9410   freeAsmop (left, NULL, ic, TRUE);
9411   aopOp (result, ic, FALSE, FALSE);
9412
9413   /* if bitfield then unpack the bits */
9414   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9415     genUnpackBits (result, rname, PPOINTER);
9416   else
9417     {
9418       /* we have can just get the values */
9419       int size = AOP_SIZE (result);
9420       int offset = 0;
9421
9422       while (size--)
9423         {
9424
9425           emitcode ("movx", "a,@%s", rname);
9426           aopPut (AOP (result), "a", offset);
9427
9428           offset++;
9429
9430           if (size || pi)
9431             emitcode ("inc", "%s", rname);
9432         }
9433     }
9434
9435   /* now some housekeeping stuff */
9436   if (aop)
9437     {
9438       /* we had to allocate for this iCode */
9439       if (pi) aopPut ( AOP (left), rname, 0);
9440       freeAsmop (NULL, aop, ic, TRUE);
9441     }
9442   else
9443     {
9444       /* we did not allocate which means left
9445          already in a pointer register, then
9446          if size > 0 && this could be used again
9447          we have to point it back to where it
9448          belongs */
9449       if (AOP_SIZE (result) > 1 &&
9450           !OP_SYMBOL (left)->remat &&
9451           (OP_SYMBOL (left)->liveTo > ic->seq ||
9452            ic->depth) &&
9453           !pi)
9454         {
9455           int size = AOP_SIZE (result) - 1;
9456           while (size--)
9457             emitcode ("dec", "%s", rname);
9458         }
9459     }
9460
9461   /* done */
9462   freeAsmop (result, NULL, ic, TRUE);
9463   if (pi) pi->generated = 1;
9464 }
9465
9466 /*-----------------------------------------------------------------*/
9467 /* genFarPointerGet - gget value from far space                    */
9468 /*-----------------------------------------------------------------*/
9469 static void
9470 genFarPointerGet (operand * left,
9471                   operand * result, iCode * ic, iCode *pi)
9472 {
9473     int size, offset, dopi=1;
9474   sym_link *retype = getSpec (operandType (result));
9475   sym_link *letype = getSpec (operandType (left));
9476   D (emitcode (";", "genFarPointerGet"););
9477
9478   aopOp (left, ic, FALSE, FALSE);
9479
9480   /* if the operand is already in dptr
9481      then we do nothing else we move the value to dptr */
9482   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9483     {
9484       /* if this is remateriazable */
9485       if (AOP_TYPE (left) == AOP_IMMD)
9486         {
9487           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9488         }
9489       else
9490         {
9491           /* we need to get it byte by byte */
9492           _startLazyDPSEvaluation ();
9493           if (AOP_TYPE (left) != AOP_DPTR)
9494             {
9495               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9496               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9497               if (options.model == MODEL_FLAT24)
9498                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9499             }
9500           else
9501             {
9502               /* We need to generate a load to DPTR indirect through DPTR. */
9503               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9504               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9505               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9506               if (options.model == MODEL_FLAT24)
9507                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9508               emitcode ("pop", "dph");
9509               emitcode ("pop", "dpl");
9510               dopi =0;
9511             }
9512           _endLazyDPSEvaluation ();
9513         }
9514     }
9515   /* so dptr know contains the address */
9516   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9517
9518   /* if bit then unpack */
9519   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9520       if (AOP_INDPTRn(left)) {
9521           genSetDPTR(AOP(left)->aopu.dptr);
9522       }
9523       genUnpackBits (result, "dptr", FPOINTER);
9524       if (AOP_INDPTRn(left)) {
9525           genSetDPTR(0);
9526       }
9527   } else
9528     {
9529       size = AOP_SIZE (result);
9530       offset = 0;
9531
9532       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9533           while (size--) {
9534               genSetDPTR(AOP(left)->aopu.dptr);
9535               emitcode ("movx", "a,@dptr");
9536               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9537                   emitcode ("inc", "dptr");
9538               genSetDPTR (0);
9539               aopPut (AOP (result), "a", offset++);
9540           }
9541       } else {
9542           _startLazyDPSEvaluation ();
9543           while (size--) {
9544               if (AOP_INDPTRn(left)) {
9545                   genSetDPTR(AOP(left)->aopu.dptr);
9546               } else {
9547                   genSetDPTR (0);
9548               }
9549               _flushLazyDPS ();
9550               
9551               emitcode ("movx", "a,@dptr");
9552               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9553                   emitcode ("inc", "dptr");
9554               
9555               aopPut (AOP (result), "a", offset++);
9556           }
9557           _endLazyDPSEvaluation ();
9558       }
9559     }
9560   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9561       if (!AOP_INDPTRn(left)) {
9562           _startLazyDPSEvaluation ();
9563           aopPut ( AOP (left), "dpl", 0);
9564           aopPut ( AOP (left), "dph", 1);
9565           if (options.model == MODEL_FLAT24)
9566               aopPut ( AOP (left), "dpx", 2);
9567           _endLazyDPSEvaluation ();
9568       }
9569     pi->generated = 1;
9570   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9571              AOP_SIZE(result) > 1 &&
9572              IS_SYMOP(left) &&
9573              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9574       
9575       size = AOP_SIZE (result) - 1;
9576       if (AOP_INDPTRn(left)) {
9577           genSetDPTR(AOP(left)->aopu.dptr);
9578       }
9579       while (size--) emitcode ("lcall","__decdptr");
9580       if (AOP_INDPTRn(left)) {
9581           genSetDPTR(0);
9582       }
9583   }
9584
9585   freeAsmop (left, NULL, ic, TRUE);
9586   freeAsmop (result, NULL, ic, TRUE);
9587 }
9588
9589 /*-----------------------------------------------------------------*/
9590 /* genCodePointerGet - get value from code space                  */
9591 /*-----------------------------------------------------------------*/
9592 static void
9593 genCodePointerGet (operand * left,
9594                     operand * result, iCode * ic, iCode *pi)
9595 {
9596   int size, offset, dopi=1;
9597   sym_link *retype = getSpec (operandType (result));
9598
9599   aopOp (left, ic, FALSE, FALSE);
9600
9601   /* if the operand is already in dptr
9602      then we do nothing else we move the value to dptr */
9603   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9604     {
9605       /* if this is remateriazable */
9606       if (AOP_TYPE (left) == AOP_IMMD)
9607         {
9608           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9609         }
9610       else
9611         {                       /* we need to get it byte by byte */
9612           _startLazyDPSEvaluation ();
9613           if (AOP_TYPE (left) != AOP_DPTR)
9614             {
9615               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9616               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9617               if (options.model == MODEL_FLAT24)
9618                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9619             }
9620           else
9621             {
9622               /* We need to generate a load to DPTR indirect through DPTR. */
9623               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9624               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9625               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9626               if (options.model == MODEL_FLAT24)
9627                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9628               emitcode ("pop", "dph");
9629               emitcode ("pop", "dpl");
9630               dopi=0;
9631             }
9632           _endLazyDPSEvaluation ();
9633         }
9634     }
9635   /* so dptr know contains the address */
9636   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9637
9638   /* if bit then unpack */
9639   if (IS_BITVAR (retype)) {
9640       if (AOP_INDPTRn(left)) {
9641           genSetDPTR(AOP(left)->aopu.dptr);
9642       }
9643       genUnpackBits (result, "dptr", CPOINTER);
9644       if (AOP_INDPTRn(left)) {
9645           genSetDPTR(0);
9646       }
9647   } else
9648     {
9649       size = AOP_SIZE (result);
9650       offset = 0;
9651       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9652           while (size--) {
9653               genSetDPTR(AOP(left)->aopu.dptr);
9654               emitcode ("clr", "a");
9655               emitcode ("movc", "a,@a+dptr");
9656               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9657                   emitcode ("inc", "dptr");
9658               genSetDPTR (0);
9659               aopPut (AOP (result), "a", offset++);
9660           }
9661       } else {
9662           _startLazyDPSEvaluation ();
9663           while (size--)
9664               {
9665                   if (AOP_INDPTRn(left)) {
9666                       genSetDPTR(AOP(left)->aopu.dptr);
9667                   } else {
9668                       genSetDPTR (0);
9669                   }
9670                   _flushLazyDPS ();
9671                   
9672                   emitcode ("clr", "a");
9673                   emitcode ("movc", "a,@a+dptr");
9674                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9675                       emitcode ("inc", "dptr");
9676                   aopPut (AOP (result), "a", offset++);
9677               }
9678           _endLazyDPSEvaluation ();
9679       }
9680     }
9681   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9682       if (!AOP_INDPTRn(left)) {
9683           _startLazyDPSEvaluation ();
9684           
9685           aopPut ( AOP (left), "dpl", 0);
9686           aopPut ( AOP (left), "dph", 1);
9687           if (options.model == MODEL_FLAT24)
9688               aopPut ( AOP (left), "dpx", 2);
9689
9690           _endLazyDPSEvaluation ();
9691       }
9692       pi->generated = 1;
9693   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9694              AOP_SIZE(result) > 1 &&
9695              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9696       
9697       size = AOP_SIZE (result) - 1;
9698       if (AOP_INDPTRn(left)) {
9699           genSetDPTR(AOP(left)->aopu.dptr);
9700       }
9701       while (size--) emitcode ("lcall","__decdptr");
9702       if (AOP_INDPTRn(left)) {
9703           genSetDPTR(0);
9704       }
9705   }
9706   
9707   freeAsmop (left, NULL, ic, TRUE);
9708   freeAsmop (result, NULL, ic, TRUE);
9709 }
9710
9711 /*-----------------------------------------------------------------*/
9712 /* genGenPointerGet - gget value from generic pointer space        */
9713 /*-----------------------------------------------------------------*/
9714 static void
9715 genGenPointerGet (operand * left,
9716                   operand * result, iCode * ic, iCode * pi)
9717 {
9718   int size, offset;
9719   sym_link *retype = getSpec (operandType (result));
9720   sym_link *letype = getSpec (operandType (left));
9721
9722   D (emitcode (";", "genGenPointerGet "); );
9723
9724   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9725
9726   /* if the operand is already in dptr
9727      then we do nothing else we move the value to dptr */
9728   if (AOP_TYPE (left) != AOP_STR)
9729     {
9730       /* if this is remateriazable */
9731       if (AOP_TYPE (left) == AOP_IMMD)
9732         {
9733           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9734           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9735             {
9736                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9737             }
9738             else
9739             {
9740                 emitcode ("mov", "b,#%d", pointerCode (retype));
9741             }
9742         }
9743       else
9744         {                       /* we need to get it byte by byte */
9745             _startLazyDPSEvaluation ();
9746             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9747             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9748             if (options.model == MODEL_FLAT24) {
9749                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9750                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9751             } else {
9752                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9753             }
9754             _endLazyDPSEvaluation ();
9755         }
9756     }
9757
9758   /* so dptr-b now contains the address */
9759   _G.bInUse++;
9760   aopOp (result, ic, FALSE, TRUE);
9761   _G.bInUse--;
9762
9763   /* if bit then unpack */
9764   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9765   {
9766     genUnpackBits (result, "dptr", GPOINTER);
9767   }
9768   else
9769     {
9770         size = AOP_SIZE (result);
9771         offset = 0;
9772
9773         while (size--)
9774         {
9775             if (size)
9776             {
9777                 // Get two bytes at a time, results in _AP & A.
9778                 // dptr will be incremented ONCE by __gptrgetWord.
9779                 //
9780                 // Note: any change here must be coordinated
9781                 // with the implementation of __gptrgetWord
9782                 // in device/lib/_gptrget.c
9783                 emitcode ("lcall", "__gptrgetWord");
9784                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9785                 aopPut (AOP (result), "a", offset++);
9786                 size--;
9787             }
9788             else
9789             {
9790                 // Only one byte to get.
9791                 emitcode ("lcall", "__gptrget");
9792                 aopPut (AOP (result), "a", offset++);
9793             }
9794             
9795             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9796             {
9797                 emitcode ("inc", "dptr");
9798             }
9799         }
9800     }
9801
9802   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9803     _startLazyDPSEvaluation ();
9804       
9805     aopPut ( AOP (left), "dpl", 0);
9806     aopPut ( AOP (left), "dph", 1);
9807     if (options.model == MODEL_FLAT24) {
9808         aopPut ( AOP (left), "dpx", 2);
9809         aopPut ( AOP (left), "b", 3);   
9810     } else  aopPut ( AOP (left), "b", 2);       
9811     
9812     _endLazyDPSEvaluation ();
9813       
9814     pi->generated = 1;
9815   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9816              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9817       
9818       size = AOP_SIZE (result) - 1;
9819       while (size--) emitcode ("lcall","__decdptr");
9820   }
9821
9822   freeAsmop (left, NULL, ic, TRUE);
9823   freeAsmop (result, NULL, ic, TRUE);
9824 }
9825
9826 /*-----------------------------------------------------------------*/
9827 /* genPointerGet - generate code for pointer get                   */
9828 /*-----------------------------------------------------------------*/
9829 static void
9830 genPointerGet (iCode * ic, iCode *pi)
9831 {
9832   operand *left, *result;
9833   sym_link *type, *etype;
9834   int p_type;
9835
9836   D (emitcode (";", "genPointerGet ");
9837     );
9838
9839   left = IC_LEFT (ic);
9840   result = IC_RESULT (ic);
9841
9842   /* depending on the type of pointer we need to
9843      move it to the correct pointer register */
9844   type = operandType (left);
9845   etype = getSpec (type);
9846   /* if left is of type of pointer then it is simple */
9847   if (IS_PTR (type) && !IS_FUNC (type->next))
9848     p_type = DCL_TYPE (type);
9849   else
9850     {
9851       /* we have to go by the storage class */
9852       p_type = PTR_TYPE (SPEC_OCLS (etype));
9853     }
9854   /* special case when cast remat */
9855   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9856       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9857           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9858           type = operandType (left);
9859           p_type = DCL_TYPE (type);
9860   }
9861   /* now that we have the pointer type we assign
9862      the pointer values */
9863   switch (p_type)
9864     {
9865
9866     case POINTER:
9867     case IPOINTER:
9868       genNearPointerGet (left, result, ic, pi);
9869       break;
9870
9871     case PPOINTER:
9872       genPagedPointerGet (left, result, ic, pi);
9873       break;
9874
9875     case FPOINTER:
9876       genFarPointerGet (left, result, ic, pi);
9877       break;
9878
9879     case CPOINTER:
9880       genCodePointerGet (left, result, ic, pi);
9881       break;
9882
9883     case GPOINTER:
9884       genGenPointerGet (left, result, ic, pi);
9885       break;
9886     }
9887
9888 }
9889
9890 /*-----------------------------------------------------------------*/
9891 /* genPackBits - generates code for packed bit storage             */
9892 /*-----------------------------------------------------------------*/
9893 static void
9894 genPackBits (sym_link * etype,
9895              operand * right,
9896              char *rname, int p_type)
9897 {
9898   int offset = 0;       /* source byte offset */
9899   int rlen = 0;         /* remaining bitfield length */
9900   int blen;             /* bitfield length */
9901   int bstr;             /* bitfield starting bit within byte */
9902   int litval;           /* source literal value (if AOP_LIT) */
9903   unsigned char mask;   /* bitmask within current byte */
9904
9905   D(emitcode (";     genPackBits",""));
9906
9907   blen = SPEC_BLEN (etype);
9908   bstr = SPEC_BSTR (etype);
9909
9910   /* If the bitfield length is less than a byte */
9911   if (blen < 8)
9912     {
9913       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9914               (unsigned char) (0xFF >> (8 - bstr)));
9915
9916       if (AOP_TYPE (right) == AOP_LIT)
9917         {
9918           /* Case with a bitfield length <8 and literal source
9919           */
9920           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9921           litval <<= bstr;
9922           litval &= (~mask) & 0xff;
9923           emitPtrByteGet (rname, p_type, FALSE);
9924           if ((mask|litval)!=0xff)
9925             emitcode ("anl","a,#!constbyte", mask);
9926           if (litval)
9927             emitcode ("orl","a,#!constbyte", litval);
9928         }
9929       else
9930         {
9931           if ((blen==1) && (p_type!=GPOINTER))
9932             {
9933               /* Case with a bitfield length == 1 and no generic pointer
9934               */
9935               if (AOP_TYPE (right) == AOP_CRY)
9936                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9937               else
9938                 {
9939                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9940                   emitcode ("rrc","a");
9941                 }
9942               emitPtrByteGet (rname, p_type, FALSE);
9943               emitcode ("mov","acc.%d,c",bstr);
9944             }
9945           else
9946             {
9947               /* Case with a bitfield length < 8 and arbitrary source
9948               */
9949               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9950               /* shift and mask source value */
9951               AccLsh (bstr);
9952               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9953
9954               /* transfer A to B and get next byte */
9955               emitPtrByteGet (rname, p_type, TRUE);
9956
9957               emitcode ("anl", "a,#!constbyte", mask);
9958               emitcode ("orl", "a,b");
9959               if (p_type == GPOINTER)
9960                 emitcode ("pop", "b");
9961            }
9962         }
9963
9964       emitPtrByteSet (rname, p_type, "a");
9965       return;
9966     }
9967
9968   /* Bit length is greater than 7 bits. In this case, copy  */
9969   /* all except the partial byte at the end                 */
9970   for (rlen=blen;rlen>=8;rlen-=8)
9971     {
9972       emitPtrByteSet (rname, p_type, 
9973                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9974       if (rlen>8)
9975         emitcode ("inc", "%s", rname);
9976     }
9977
9978   /* If there was a partial byte at the end */
9979   if (rlen)
9980     {
9981       mask = (((unsigned char) -1 << rlen) & 0xff);
9982       
9983       if (AOP_TYPE (right) == AOP_LIT)
9984         {
9985           /* Case with partial byte and literal source
9986           */
9987           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9988           litval >>= (blen-rlen);
9989           litval &= (~mask) & 0xff;
9990           emitPtrByteGet (rname, p_type, FALSE);
9991           if ((mask|litval)!=0xff)
9992             emitcode ("anl","a,#!constbyte", mask);
9993           if (litval)
9994             emitcode ("orl","a,#!constbyte", litval);
9995         }
9996       else
9997         {
9998           /* Case with partial byte and arbitrary source
9999           */
10000           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10001           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10002
10003           /* transfer A to B and get next byte */
10004           emitPtrByteGet (rname, p_type, TRUE);
10005
10006           emitcode ("anl", "a,#!constbyte", mask);
10007           emitcode ("orl", "a,b");
10008           if (p_type == GPOINTER)
10009             emitcode ("pop", "b");
10010         }
10011       emitPtrByteSet (rname, p_type, "a");
10012     }
10013
10014 }
10015
10016
10017 /*-----------------------------------------------------------------*/
10018 /* genDataPointerSet - remat pointer to data space                 */
10019 /*-----------------------------------------------------------------*/
10020 static void
10021 genDataPointerSet (operand * right,
10022                    operand * result,
10023                    iCode * ic)
10024 {
10025   int size, offset = 0;
10026   char *l, buff[256];
10027
10028   aopOp (right, ic, FALSE, FALSE);
10029
10030   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10031   size = AOP_SIZE (right);
10032   while (size--)
10033     {
10034       if (offset)
10035         {
10036             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10037         }
10038       else
10039         {
10040             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10041         }
10042         
10043       emitcode ("mov", "%s,%s", buff,
10044                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10045     }
10046
10047   freeAsmop (right, NULL, ic, TRUE);
10048   freeAsmop (result, NULL, ic, TRUE);
10049 }
10050
10051 /*-----------------------------------------------------------------*/
10052 /* genNearPointerSet - emitcode for near pointer put                */
10053 /*-----------------------------------------------------------------*/
10054 static void
10055 genNearPointerSet (operand * right,
10056                    operand * result,
10057                    iCode * ic,
10058                    iCode * pi)
10059 {
10060   asmop *aop = NULL;
10061   char *rname, *l;
10062   sym_link *retype, *letype;
10063   sym_link *ptype = operandType (result);
10064
10065   retype = getSpec (operandType (right));
10066   letype = getSpec (ptype);
10067
10068   aopOp (result, ic, FALSE, FALSE);
10069
10070   /* if the result is rematerializable &
10071      in data space & not a bit variable */
10072   if (AOP_TYPE (result) == AOP_IMMD &&
10073       DCL_TYPE (ptype) == POINTER &&
10074       !IS_BITVAR (retype) &&
10075       !IS_BITVAR (letype))
10076     {
10077       genDataPointerSet (right, result, ic);
10078       return;
10079     }
10080
10081   /* if the value is already in a pointer register
10082      then don't need anything more */
10083   if (!AOP_INPREG (AOP (result)))
10084     {
10085       /* otherwise get a free pointer register */
10086       regs *preg;
10087         
10088       aop = newAsmop (0);
10089       preg = getFreePtr (ic, &aop, FALSE);
10090       emitcode ("mov", "%s,%s",
10091                 preg->name,
10092                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10093       rname = preg->name;
10094     }
10095   else
10096     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10097
10098   aopOp (right, ic, FALSE, FALSE);
10099
10100   /* if bitfield then unpack the bits */
10101   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10102     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10103   else
10104     {
10105       /* we have can just get the values */
10106       int size = AOP_SIZE (right);
10107       int offset = 0;
10108
10109       while (size--)
10110         {
10111           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10112           if (*l == '@')
10113             {
10114               MOVA (l);
10115               emitcode ("mov", "@%s,a", rname);
10116             }
10117           else
10118             emitcode ("mov", "@%s,%s", rname, l);
10119           if (size || pi)
10120             emitcode ("inc", "%s", rname);
10121           offset++;
10122         }
10123     }
10124
10125   /* now some housekeeping stuff */
10126   if (aop)
10127     {
10128       /* we had to allocate for this iCode */
10129       if (pi) aopPut (AOP (result),rname,0);
10130       freeAsmop (NULL, aop, ic, TRUE);
10131     }
10132   else
10133     {
10134       /* we did not allocate which means left
10135          already in a pointer register, then
10136          if size > 0 && this could be used again
10137          we have to point it back to where it
10138          belongs */
10139       if (AOP_SIZE (right) > 1 &&
10140           !OP_SYMBOL (result)->remat &&
10141           (OP_SYMBOL (result)->liveTo > ic->seq ||
10142            ic->depth) &&
10143           !pi)
10144         {
10145           int size = AOP_SIZE (right) - 1;
10146           while (size--)
10147             emitcode ("dec", "%s", rname);
10148         }
10149     }
10150
10151   /* done */
10152   if (pi) pi->generated = 1;
10153   freeAsmop (result, NULL, ic, TRUE);
10154   freeAsmop (right, NULL, ic, TRUE);
10155
10156
10157 }
10158
10159 /*-----------------------------------------------------------------*/
10160 /* genPagedPointerSet - emitcode for Paged pointer put             */
10161 /*-----------------------------------------------------------------*/
10162 static void
10163 genPagedPointerSet (operand * right,
10164                     operand * result,
10165                     iCode * ic,
10166                     iCode *pi)
10167 {
10168   asmop *aop = NULL;
10169   char *rname;
10170   sym_link *retype, *letype;
10171
10172   retype = getSpec (operandType (right));
10173   letype = getSpec (operandType (result));
10174
10175   aopOp (result, ic, FALSE, FALSE);
10176
10177   /* if the value is already in a pointer register
10178      then don't need anything more */
10179   if (!AOP_INPREG (AOP (result)))
10180     {
10181       /* otherwise get a free pointer register */
10182       regs *preg;
10183         
10184       aop = newAsmop (0);
10185       preg = getFreePtr (ic, &aop, FALSE);
10186       emitcode ("mov", "%s,%s",
10187                 preg->name,
10188                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10189       rname = preg->name;
10190     }
10191   else
10192     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10193
10194   aopOp (right, ic, FALSE, FALSE);
10195
10196   /* if bitfield then unpack the bits */
10197   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10198     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10199   else
10200     {
10201       /* we have can just get the values */
10202       int size = AOP_SIZE (right);
10203       int offset = 0;
10204
10205       while (size--)
10206         {
10207           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10208
10209           emitcode ("movx", "@%s,a", rname);
10210
10211           if (size || pi)
10212             emitcode ("inc", "%s", rname);
10213
10214           offset++;
10215         }
10216     }
10217
10218   /* now some housekeeping stuff */
10219   if (aop)
10220     {
10221       if (pi) aopPut (AOP (result),rname,0);
10222       /* we had to allocate for this iCode */
10223       freeAsmop (NULL, aop, ic, TRUE);
10224     }
10225   else
10226     {
10227       /* we did not allocate which means left
10228          already in a pointer register, then
10229          if size > 0 && this could be used again
10230          we have to point it back to where it
10231          belongs */
10232       if (AOP_SIZE (right) > 1 &&
10233           !OP_SYMBOL (result)->remat &&
10234           (OP_SYMBOL (result)->liveTo > ic->seq ||
10235            ic->depth) &&
10236           !pi)
10237         {
10238           int size = AOP_SIZE (right) - 1;
10239           while (size--)
10240             emitcode ("dec", "%s", rname);
10241         }
10242     }
10243
10244   /* done */
10245   if (pi) pi->generated = 1;
10246   freeAsmop (result, NULL, ic, TRUE);
10247   freeAsmop (right, NULL, ic, TRUE);
10248
10249
10250 }
10251
10252 /*-----------------------------------------------------------------*/
10253 /* genFarPointerSet - set value from far space                     */
10254 /*-----------------------------------------------------------------*/
10255 static void
10256 genFarPointerSet (operand * right,
10257                   operand * result, iCode * ic, iCode *pi)
10258 {
10259   int size, offset, dopi=1;
10260   sym_link *retype = getSpec (operandType (right));
10261   sym_link *letype = getSpec (operandType (result));
10262
10263   aopOp (result, ic, FALSE, FALSE);
10264
10265   /* if the operand is already in dptr
10266      then we do nothing else we move the value to dptr */
10267   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10268     {
10269       /* if this is remateriazable */
10270       if (AOP_TYPE (result) == AOP_IMMD)
10271         emitcode ("mov", "dptr,%s", 
10272                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10273       else
10274         {
10275           /* we need to get it byte by byte */
10276           _startLazyDPSEvaluation ();
10277           if (AOP_TYPE (result) != AOP_DPTR)
10278             {
10279               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10280               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10281               if (options.model == MODEL_FLAT24)
10282                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10283             }
10284           else
10285             {
10286               /* We need to generate a load to DPTR indirect through DPTR. */
10287               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10288                 
10289               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10290               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10291               if (options.model == MODEL_FLAT24)
10292                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10293               emitcode ("pop", "dph");
10294               emitcode ("pop", "dpl");
10295               dopi=0;
10296             }
10297           _endLazyDPSEvaluation ();
10298         }
10299     }
10300   /* so dptr know contains the address */
10301   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10302
10303   /* if bit then unpack */
10304   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10305       if (AOP_INDPTRn(result)) {
10306           genSetDPTR(AOP(result)->aopu.dptr);
10307       }
10308       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10309       if (AOP_INDPTRn(result)) {
10310           genSetDPTR(0);
10311       }
10312   } else {
10313       size = AOP_SIZE (right);
10314       offset = 0;
10315       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10316           while (size--) {
10317               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10318               
10319               genSetDPTR(AOP(result)->aopu.dptr);
10320               emitcode ("movx", "@dptr,a");
10321               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10322                   emitcode ("inc", "dptr");
10323               genSetDPTR (0);
10324           }
10325       } else {
10326           _startLazyDPSEvaluation ();
10327           while (size--) {
10328               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10329               
10330               if (AOP_INDPTRn(result)) {
10331                   genSetDPTR(AOP(result)->aopu.dptr);
10332               } else {
10333                   genSetDPTR (0);
10334               }
10335               _flushLazyDPS ();
10336               
10337               emitcode ("movx", "@dptr,a");
10338               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10339                   emitcode ("inc", "dptr");
10340           }
10341           _endLazyDPSEvaluation ();
10342       }
10343   }
10344   
10345   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10346       if (!AOP_INDPTRn(result)) {
10347           _startLazyDPSEvaluation ();
10348           
10349           aopPut (AOP(result),"dpl",0);
10350           aopPut (AOP(result),"dph",1);
10351           if (options.model == MODEL_FLAT24)
10352               aopPut (AOP(result),"dpx",2);
10353
10354           _endLazyDPSEvaluation ();
10355       }
10356       pi->generated=1;
10357   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10358              AOP_SIZE(right) > 1 &&
10359              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10360       
10361       size = AOP_SIZE (right) - 1;
10362       if (AOP_INDPTRn(result)) {
10363           genSetDPTR(AOP(result)->aopu.dptr);
10364       } 
10365       while (size--) emitcode ("lcall","__decdptr");
10366       if (AOP_INDPTRn(result)) {
10367           genSetDPTR(0);
10368       }
10369   }
10370   freeAsmop (result, NULL, ic, TRUE);
10371   freeAsmop (right, NULL, ic, TRUE);
10372 }
10373
10374 /*-----------------------------------------------------------------*/
10375 /* genGenPointerSet - set value from generic pointer space         */
10376 /*-----------------------------------------------------------------*/
10377 static void
10378 genGenPointerSet (operand * right,
10379                   operand * result, iCode * ic, iCode *pi)
10380 {
10381   int size, offset;
10382   sym_link *retype = getSpec (operandType (right));
10383   sym_link *letype = getSpec (operandType (result));
10384
10385   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10386
10387   /* if the operand is already in dptr
10388      then we do nothing else we move the value to dptr */
10389   if (AOP_TYPE (result) != AOP_STR)
10390     {
10391       _startLazyDPSEvaluation ();
10392       /* if this is remateriazable */
10393       if (AOP_TYPE (result) == AOP_IMMD)
10394         {
10395           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10396           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10397           {
10398               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10399           }
10400           else
10401           {
10402               emitcode ("mov", 
10403                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10404           }
10405         }
10406       else
10407         {                       /* we need to get it byte by byte */
10408           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10409           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10410           if (options.model == MODEL_FLAT24) {
10411             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10412             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10413           } else {
10414             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10415           }
10416         }
10417       _endLazyDPSEvaluation ();
10418     }
10419   /* so dptr + b now contains the address */
10420   _G.bInUse++;
10421   aopOp (right, ic, FALSE, TRUE);
10422   _G.bInUse--;
10423     
10424
10425   /* if bit then unpack */
10426   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10427     {
10428         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10429     }
10430   else
10431     {
10432         size = AOP_SIZE (right);
10433         offset = 0;
10434
10435         _startLazyDPSEvaluation ();
10436         while (size--)
10437         {
10438             if (size)
10439             {
10440                 // Set two bytes at a time, passed in _AP & A.
10441                 // dptr will be incremented ONCE by __gptrputWord.
10442                 //
10443                 // Note: any change here must be coordinated
10444                 // with the implementation of __gptrputWord
10445                 // in device/lib/_gptrput.c
10446                 emitcode("mov", "_ap, %s", 
10447                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10448                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10449                 
10450                 genSetDPTR (0);
10451                 _flushLazyDPS ();
10452                 emitcode ("lcall", "__gptrputWord");
10453                 size--;
10454             }
10455             else
10456             {
10457                 // Only one byte to put.
10458                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10459
10460                 genSetDPTR (0);
10461                 _flushLazyDPS ();               
10462                 emitcode ("lcall", "__gptrput");
10463             }
10464             
10465             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10466             {
10467                 emitcode ("inc", "dptr");
10468             }
10469         }
10470         _endLazyDPSEvaluation ();
10471     }
10472
10473   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10474       _startLazyDPSEvaluation ();
10475       
10476       aopPut (AOP(result),"dpl",0);
10477       aopPut (AOP(result),"dph",1);
10478       if (options.model == MODEL_FLAT24) {
10479           aopPut (AOP(result),"dpx",2);
10480           aopPut (AOP(result),"b",3);
10481       } else {
10482           aopPut (AOP(result),"b",2);
10483       }
10484       _endLazyDPSEvaluation ();
10485       
10486       pi->generated=1;
10487   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10488              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10489       
10490       size = AOP_SIZE (right) - 1;
10491       while (size--) emitcode ("lcall","__decdptr");
10492   }
10493   freeAsmop (result, NULL, ic, TRUE);
10494   freeAsmop (right, NULL, ic, TRUE);
10495 }
10496
10497 /*-----------------------------------------------------------------*/
10498 /* genPointerSet - stores the value into a pointer location        */
10499 /*-----------------------------------------------------------------*/
10500 static void
10501 genPointerSet (iCode * ic, iCode *pi)
10502 {
10503   operand *right, *result;
10504   sym_link *type, *etype;
10505   int p_type;
10506
10507   D (emitcode (";", "genPointerSet "););
10508
10509   right = IC_RIGHT (ic);
10510   result = IC_RESULT (ic);
10511
10512   /* depending on the type of pointer we need to
10513      move it to the correct pointer register */
10514   type = operandType (result);
10515   etype = getSpec (type);
10516   /* if left is of type of pointer then it is simple */
10517   if (IS_PTR (type) && !IS_FUNC (type->next))
10518     {
10519       p_type = DCL_TYPE (type);
10520     }
10521   else
10522     {
10523       /* we have to go by the storage class */
10524       p_type = PTR_TYPE (SPEC_OCLS (etype));
10525     }
10526   /* special case when cast remat */
10527   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10528       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10529           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10530           type = operandType (result);
10531           p_type = DCL_TYPE (type);
10532   }
10533
10534   /* now that we have the pointer type we assign
10535      the pointer values */
10536   switch (p_type)
10537     {
10538
10539     case POINTER:
10540     case IPOINTER:
10541       genNearPointerSet (right, result, ic, pi);
10542       break;
10543
10544     case PPOINTER:
10545       genPagedPointerSet (right, result, ic, pi);
10546       break;
10547
10548     case FPOINTER:
10549       genFarPointerSet (right, result, ic, pi);
10550       break;
10551
10552     case GPOINTER:
10553       genGenPointerSet (right, result, ic, pi);
10554       break;
10555
10556     default:
10557       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10558               "genPointerSet: illegal pointer type");
10559     }
10560
10561 }
10562
10563 /*-----------------------------------------------------------------*/
10564 /* genIfx - generate code for Ifx statement                        */
10565 /*-----------------------------------------------------------------*/
10566 static void
10567 genIfx (iCode * ic, iCode * popIc)
10568 {
10569   operand *cond = IC_COND (ic);
10570   int isbit = 0;
10571
10572   D (emitcode (";", "genIfx "););
10573
10574   aopOp (cond, ic, FALSE, FALSE);
10575
10576   /* get the value into acc */
10577   if (AOP_TYPE (cond) != AOP_CRY)
10578     {
10579         toBoolean (cond);
10580     }
10581   else
10582     {
10583         isbit = 1;
10584     }
10585     
10586   /* the result is now in the accumulator */
10587   freeAsmop (cond, NULL, ic, TRUE);
10588
10589   /* if there was something to be popped then do it */
10590   if (popIc)
10591     genIpop (popIc);
10592
10593   /* if the condition is  a bit variable */
10594   if (isbit && IS_ITEMP (cond) &&
10595       SPIL_LOC (cond))
10596     {
10597         genIfxJump (ic, SPIL_LOC (cond)->rname);
10598     }
10599   else if (isbit && !IS_ITEMP (cond))
10600     {
10601         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10602     }
10603   else
10604     {
10605         genIfxJump (ic, "a");
10606     }
10607
10608   ic->generated = 1;
10609 }
10610
10611 /*-----------------------------------------------------------------*/
10612 /* genAddrOf - generates code for address of                       */
10613 /*-----------------------------------------------------------------*/
10614 static void
10615 genAddrOf (iCode * ic)
10616 {
10617   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10618   int size, offset;
10619
10620   D (emitcode (";", "genAddrOf ");
10621     );
10622
10623   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10624
10625   /* if the operand is on the stack then we
10626      need to get the stack offset of this
10627      variable */
10628   if (sym->onStack) {
10629       
10630       /* if 10 bit stack */
10631       if (options.stack10bit) {
10632           char buff[10];
10633           int  offset;
10634           
10635           tsprintf(buff, sizeof(buff), 
10636                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10637           /* if it has an offset then we need to compute it */
10638 /*        emitcode ("subb", "a,#!constbyte", */
10639 /*                  -((sym->stack < 0) ? */
10640 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10641 /*                    ((short) sym->stack)) & 0xff); */
10642 /*        emitcode ("mov","b,a"); */
10643 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10644 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10645 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10646           if (sym->stack) {
10647               emitcode ("mov", "a,_bpx");
10648               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10649                                              ((char) (sym->stack - _G.nRegsSaved)) :
10650                                              ((char) sym->stack )) & 0xff);
10651               emitcode ("mov", "b,a");
10652               emitcode ("mov", "a,_bpx+1");
10653               
10654               offset = (((sym->stack < 0) ? 
10655                          ((short) (sym->stack - _G.nRegsSaved)) :
10656                          ((short) sym->stack )) >> 8) & 0xff;
10657           
10658               emitcode ("addc","a,#!constbyte", offset);
10659
10660               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10661               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10662               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10663           } else {
10664               /* we can just move _bp */
10665               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10666               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10667               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10668           }       
10669       } else {
10670           /* if it has an offset then we need to compute it */
10671           if (sym->stack) {
10672               emitcode ("mov", "a,_bp");
10673               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10674               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10675           } else {
10676               /* we can just move _bp */
10677               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10678           }
10679           /* fill the result with zero */
10680           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10681           
10682           
10683           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10684               fprintf (stderr,
10685                        "*** warning: pointer to stack var truncated.\n");
10686           }
10687
10688           offset = 1;
10689           while (size--) {
10690               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10691           }      
10692       }
10693       goto release;
10694   }
10695
10696   /* object not on stack then we need the name */
10697   size = AOP_SIZE (IC_RESULT (ic));
10698   offset = 0;
10699
10700   while (size--)
10701     {
10702       char s[SDCC_NAME_MAX];
10703       if (offset) {
10704           switch (offset) {
10705           case 1:
10706               tsprintf(s, sizeof(s), "#!his",sym->rname);
10707               break;
10708           case 2:
10709               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10710               break;
10711           case 3:
10712               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10713               break;
10714           default: /* should not need this (just in case) */
10715               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10716                        sym->rname,
10717                        offset * 8);
10718           }
10719       } 
10720       else
10721       {
10722           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10723       }
10724         
10725       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10726     }
10727
10728 release:
10729   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10730
10731 }
10732
10733 #if 0 // obsolete, and buggy for != xdata
10734 /*-----------------------------------------------------------------*/
10735 /* genArrayInit - generates code for address of                       */
10736 /*-----------------------------------------------------------------*/
10737 static void
10738 genArrayInit (iCode * ic)
10739 {
10740     literalList *iLoop;
10741     int         ix, count;
10742     int         elementSize = 0, eIndex;
10743     unsigned    val, lastVal;
10744     sym_link    *type;
10745     operand     *left=IC_LEFT(ic);
10746     
10747     D (emitcode (";", "genArrayInit "););
10748
10749     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10750     
10751     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10752     {
10753         // Load immediate value into DPTR.
10754         emitcode("mov", "dptr, %s",
10755              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10756     }
10757     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10758     {
10759 #if 0
10760       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10761               "Unexpected operand to genArrayInit.\n");
10762       exit(1);
10763 #else
10764       // a regression because of SDCCcse.c:1.52
10765       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10766       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10767       if (options.model == MODEL_FLAT24)
10768         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10769 #endif
10770     }
10771     
10772     type = operandType(IC_LEFT(ic));
10773     
10774     if (type && type->next)
10775     {
10776         elementSize = getSize(type->next);
10777     }
10778     else
10779     {
10780         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10781                                 "can't determine element size in genArrayInit.\n");
10782         exit(1);
10783     }
10784     
10785     iLoop = IC_ARRAYILIST(ic);
10786     lastVal = 0xffff;
10787     
10788     while (iLoop)
10789     {
10790         bool firstpass = TRUE;
10791         
10792         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10793                  iLoop->count, (int)iLoop->literalValue, elementSize);
10794         
10795         ix = iLoop->count;
10796         
10797         while (ix)
10798         {
10799             symbol *tlbl = NULL;
10800             
10801             count = ix > 256 ? 256 : ix;
10802             
10803             if (count > 1)
10804             {
10805                 tlbl = newiTempLabel (NULL);
10806                 if (firstpass || (count & 0xff))
10807                 {
10808                     emitcode("mov", "b, #!constbyte", count & 0xff);
10809                 }
10810                 
10811                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10812             }
10813             
10814             firstpass = FALSE;
10815                 
10816             for (eIndex = 0; eIndex < elementSize; eIndex++)
10817             {
10818                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10819                 if (val != lastVal)
10820                 {
10821                     emitcode("mov", "a, #!constbyte", val);
10822                     lastVal = val;
10823                 }
10824                 
10825                 emitcode("movx", "@dptr, a");
10826                 emitcode("inc", "dptr");
10827             }
10828             
10829             if (count > 1)
10830             {
10831                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10832             }
10833             
10834             ix -= count;
10835         }
10836         
10837         iLoop = iLoop->next;
10838     }
10839     
10840     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10841 }
10842 #endif
10843
10844 /*-----------------------------------------------------------------*/
10845 /* genFarFarAssign - assignment when both are in far space         */
10846 /*-----------------------------------------------------------------*/
10847 static void
10848 genFarFarAssign (operand * result, operand * right, iCode * ic)
10849 {
10850   int size = AOP_SIZE (right);
10851   int offset = 0;
10852   symbol *rSym = NULL;
10853
10854   if (size == 1)
10855   {
10856       /* quick & easy case. */
10857       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10858       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10859       freeAsmop (right, NULL, ic, FALSE);
10860       /* now assign DPTR to result */
10861       _G.accInUse++;
10862       aopOp(result, ic, FALSE, FALSE);
10863       _G.accInUse--;
10864       aopPut(AOP(result), "a", 0);
10865       freeAsmop(result, NULL, ic, FALSE);
10866       return;
10867   }
10868   
10869   /* See if we've got an underlying symbol to abuse. */
10870   if (IS_SYMOP(result) && OP_SYMBOL(result))
10871   {
10872       if (IS_TRUE_SYMOP(result))
10873       {
10874           rSym = OP_SYMBOL(result);
10875       }
10876       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10877       {
10878           rSym = OP_SYMBOL(result)->usl.spillLoc;
10879       }
10880   }
10881              
10882   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10883   {
10884       /* We can use the '390 auto-toggle feature to good effect here. */
10885       
10886       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10887       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10888       emitcode ("mov", "dptr,#%s", rSym->rname); 
10889       /* DP2 = result, DP1 = right, DP1 is current. */
10890       while (size)
10891       {
10892           emitcode("movx", "a,@dptr");
10893           emitcode("movx", "@dptr,a");
10894           if (--size)
10895           {
10896                emitcode("inc", "dptr");
10897                emitcode("inc", "dptr");
10898           }
10899       }
10900       emitcode("mov", "dps,#0");
10901       freeAsmop (right, NULL, ic, FALSE);
10902 #if 0
10903 some alternative code for processors without auto-toggle
10904 no time to test now, so later well put in...kpb
10905         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10906         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10907         emitcode ("mov", "dptr,#%s", rSym->rname); 
10908         /* DP2 = result, DP1 = right, DP1 is current. */
10909         while (size)
10910         {
10911           --size;
10912           emitcode("movx", "a,@dptr");
10913           if (size)
10914             emitcode("inc", "dptr");
10915           emitcode("inc", "dps");
10916           emitcode("movx", "@dptr,a");
10917           if (size)
10918             emitcode("inc", "dptr");
10919           emitcode("inc", "dps");
10920         }
10921         emitcode("mov", "dps,#0");
10922         freeAsmop (right, NULL, ic, FALSE);
10923 #endif
10924   }
10925   else
10926   {
10927       D (emitcode (";", "genFarFarAssign"););
10928       aopOp (result, ic, TRUE, TRUE);
10929
10930       _startLazyDPSEvaluation ();
10931       
10932       while (size--)
10933         {
10934           aopPut (AOP (result),
10935                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10936           offset++;
10937         }
10938       _endLazyDPSEvaluation ();
10939       freeAsmop (result, NULL, ic, FALSE);
10940       freeAsmop (right, NULL, ic, FALSE);
10941   }
10942 }
10943
10944 /*-----------------------------------------------------------------*/
10945 /* genAssign - generate code for assignment                        */
10946 /*-----------------------------------------------------------------*/
10947 static void
10948 genAssign (iCode * ic)
10949 {
10950   operand *result, *right;
10951   int size, offset;
10952   unsigned long lit = 0L;
10953
10954   D (emitcode (";", "genAssign ");
10955     );
10956
10957   result = IC_RESULT (ic);
10958   right = IC_RIGHT (ic);
10959
10960   /* if they are the same */
10961   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10962     return;
10963
10964   aopOp (right, ic, FALSE, FALSE);
10965
10966   emitcode (";", "genAssign: resultIsFar = %s",
10967             isOperandInFarSpace (result) ?
10968             "TRUE" : "FALSE");
10969
10970   /* special case both in far space */
10971   if ((AOP_TYPE (right) == AOP_DPTR ||
10972        AOP_TYPE (right) == AOP_DPTR2) &&
10973   /* IS_TRUE_SYMOP(result)       && */
10974       isOperandInFarSpace (result))
10975     {
10976       genFarFarAssign (result, right, ic);
10977       return;
10978     }
10979
10980   aopOp (result, ic, TRUE, FALSE);
10981
10982   /* if they are the same registers */
10983   if (sameRegs (AOP (right), AOP (result)))
10984     goto release;
10985
10986   /* if the result is a bit */
10987   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10988     {
10989       /* if the right size is a literal then
10990          we know what the value is */
10991       if (AOP_TYPE (right) == AOP_LIT)
10992         {
10993           if (((int) operandLitValue (right)))
10994             aopPut (AOP (result), one, 0);
10995           else
10996             aopPut (AOP (result), zero, 0);
10997           goto release;
10998         }
10999
11000       /* the right is also a bit variable */
11001       if (AOP_TYPE (right) == AOP_CRY)
11002         {
11003           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11004           aopPut (AOP (result), "c", 0);
11005           goto release;
11006         }
11007
11008       /* we need to or */
11009       toBoolean (right);
11010       aopPut (AOP (result), "a", 0);
11011       goto release;
11012     }
11013
11014   /* bit variables done */
11015   /* general case */
11016   size = AOP_SIZE (result);
11017   offset = 0;
11018   if (AOP_TYPE (right) == AOP_LIT)
11019     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11020
11021   if ((size > 1) &&
11022       (AOP_TYPE (result) != AOP_REG) &&
11023       (AOP_TYPE (right) == AOP_LIT) &&
11024       !IS_FLOAT (operandType (right)))
11025     {
11026       _startLazyDPSEvaluation ();
11027       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11028         {
11029           aopPut (AOP (result),
11030                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11031                   offset);
11032           offset++;
11033           size--;
11034         }
11035       /* And now fill the rest with zeros. */
11036       if (size)
11037         {
11038           emitcode ("clr", "a");
11039         }
11040       while (size--)
11041         {
11042           aopPut (AOP (result), "a", offset++);
11043         }
11044       _endLazyDPSEvaluation ();
11045     }
11046   else
11047     {
11048       _startLazyDPSEvaluation ();
11049       while (size--)
11050         {
11051           aopPut (AOP (result),
11052                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11053                   offset);
11054           offset++;
11055         }
11056       _endLazyDPSEvaluation ();
11057     }
11058
11059 release:
11060   freeAsmop (right, NULL, ic, FALSE);
11061   freeAsmop (result, NULL, ic, TRUE);
11062 }
11063
11064 /*-----------------------------------------------------------------*/
11065 /* genJumpTab - generates code for jump table                      */
11066 /*-----------------------------------------------------------------*/
11067 static void
11068 genJumpTab (iCode * ic)
11069 {
11070   symbol *jtab;
11071   char *l;
11072
11073   D (emitcode (";", "genJumpTab ");
11074     );
11075
11076   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11077   /* get the condition into accumulator */
11078   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11079   MOVA (l);
11080   /* multiply by four! */
11081   emitcode ("add", "a,acc");
11082   emitcode ("add", "a,acc");
11083   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11084
11085   jtab = newiTempLabel (NULL);
11086   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11087   emitcode ("jmp", "@a+dptr");
11088   emitcode ("", "!tlabeldef", jtab->key + 100);
11089   /* now generate the jump labels */
11090   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11091        jtab = setNextItem (IC_JTLABELS (ic)))
11092     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11093
11094 }
11095
11096 /*-----------------------------------------------------------------*/
11097 /* genCast - gen code for casting                                  */
11098 /*-----------------------------------------------------------------*/
11099 static void
11100 genCast (iCode * ic)
11101 {
11102   operand *result = IC_RESULT (ic);
11103   sym_link *ctype = operandType (IC_LEFT (ic));
11104   sym_link *rtype = operandType (IC_RIGHT (ic));
11105   operand *right = IC_RIGHT (ic);
11106   int size, offset;
11107
11108   D (emitcode (";", "genCast "););
11109
11110   /* if they are equivalent then do nothing */
11111   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11112     return;
11113
11114   aopOp (right, ic, FALSE, FALSE);
11115   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11116
11117   /* if the result is a bit */
11118   if (IS_BITVAR (OP_SYMBOL (result)->type)
11119       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11120     {
11121       /* if the right size is a literal then
11122          we know what the value is */
11123       if (AOP_TYPE (right) == AOP_LIT)
11124         {
11125           if (((int) operandLitValue (right)))
11126             aopPut (AOP (result), one, 0);
11127           else
11128             aopPut (AOP (result), zero, 0);
11129
11130           goto release;
11131         }
11132
11133       /* the right is also a bit variable */
11134       if (AOP_TYPE (right) == AOP_CRY)
11135         {
11136           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11137           aopPut (AOP (result), "c", 0);
11138           goto release;
11139         }
11140
11141       /* we need to or */
11142       toBoolean (right);
11143       aopPut (AOP (result), "a", 0);
11144       goto release;
11145     }
11146
11147   /* if they are the same size : or less */
11148   if (AOP_SIZE (result) <= AOP_SIZE (right))
11149     {
11150
11151       /* if they are in the same place */
11152       if (sameRegs (AOP (right), AOP (result)))
11153         goto release;
11154
11155       /* if they in different places then copy */
11156       size = AOP_SIZE (result);
11157       offset = 0;
11158       _startLazyDPSEvaluation ();
11159       while (size--)
11160         {
11161           aopPut (AOP (result),
11162                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11163                   offset);
11164           offset++;
11165         }
11166       _endLazyDPSEvaluation ();
11167       goto release;
11168     }
11169
11170
11171   /* if the result is of type pointer */
11172   if (IS_PTR (ctype))
11173     {
11174
11175       int p_type;
11176       sym_link *type = operandType (right);
11177
11178       /* pointer to generic pointer */
11179       if (IS_GENPTR (ctype))
11180         {
11181           if (IS_PTR (type))
11182             {
11183               p_type = DCL_TYPE (type);
11184             }
11185           else
11186             {
11187 #if OLD_CAST_BEHAVIOR
11188               /* KV: we are converting a non-pointer type to
11189                * a generic pointer. This (ifdef'd out) code
11190                * says that the resulting generic pointer
11191                * should have the same class as the storage
11192                * location of the non-pointer variable.
11193                *
11194                * For example, converting an int (which happens
11195                * to be stored in DATA space) to a pointer results
11196                * in a DATA generic pointer; if the original int
11197                * in XDATA space, so will be the resulting pointer.
11198                *
11199                * I don't like that behavior, and thus this change:
11200                * all such conversions will be forced to XDATA and
11201                * throw a warning. If you want some non-XDATA
11202                * type, or you want to suppress the warning, you
11203                * must go through an intermediate cast, like so:
11204                *
11205                * char _generic *gp = (char _xdata *)(intVar);
11206                */
11207               sym_link *etype = getSpec (type);
11208
11209               /* we have to go by the storage class */
11210               if (SPEC_OCLS (etype) != generic)
11211                 {
11212                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11213                 }
11214               else
11215 #endif
11216                 {
11217                   /* Converting unknown class (i.e. register variable)
11218                    * to generic pointer. This is not good, but
11219                    * we'll make a guess (and throw a warning).
11220                    */
11221                   p_type = FPOINTER;
11222                   werror (W_INT_TO_GEN_PTR_CAST);
11223                 }
11224             }
11225
11226           /* the first two bytes are known */
11227           size = GPTRSIZE - 1;
11228           offset = 0;
11229           _startLazyDPSEvaluation ();
11230           while (size--)
11231             {
11232               aopPut (AOP (result),
11233                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11234                       offset);
11235               offset++;
11236             }
11237           _endLazyDPSEvaluation ();
11238
11239           /* the last byte depending on type */
11240             {
11241                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11242                 char gpValStr[10];
11243             
11244                 if (gpVal == -1)
11245                 {
11246                     // pointerTypeToGPByte will have bitched.
11247                     exit(1);
11248                 }
11249             
11250                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11251                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11252             }
11253           goto release;
11254         }
11255
11256       /* just copy the pointers */
11257       size = AOP_SIZE (result);
11258       offset = 0;
11259       _startLazyDPSEvaluation ();
11260       while (size--)
11261         {
11262           aopPut (AOP (result),
11263                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11264                   offset);
11265           offset++;
11266         }
11267       _endLazyDPSEvaluation ();
11268       goto release;
11269     }
11270
11271   /* so we now know that the size of destination is greater
11272      than the size of the source */
11273   /* we move to result for the size of source */
11274   size = AOP_SIZE (right);
11275   offset = 0;
11276   _startLazyDPSEvaluation ();
11277   while (size--)
11278     {
11279       aopPut (AOP (result),
11280               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11281               offset);
11282       offset++;
11283     }
11284   _endLazyDPSEvaluation ();
11285
11286   /* now depending on the sign of the source && destination */
11287   size = AOP_SIZE (result) - AOP_SIZE (right);
11288   /* if unsigned or not an integral type */
11289   /* also, if the source is a bit, we don't need to sign extend, because
11290    * it can't possibly have set the sign bit.
11291    */
11292   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11293     {
11294       while (size--)
11295         {
11296           aopPut (AOP (result), zero, offset++);
11297         }
11298     }
11299   else
11300     {
11301       /* we need to extend the sign :{ */
11302       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11303                         FALSE, FALSE, NULL));
11304       emitcode ("rlc", "a");
11305       emitcode ("subb", "a,acc");
11306       while (size--)
11307         aopPut (AOP (result), "a", offset++);
11308     }
11309
11310   /* we are done hurray !!!! */
11311
11312 release:
11313   freeAsmop (right, NULL, ic, TRUE);
11314   freeAsmop (result, NULL, ic, TRUE);
11315
11316 }
11317
11318 /*-----------------------------------------------------------------*/
11319 /* genDjnz - generate decrement & jump if not zero instrucion      */
11320 /*-----------------------------------------------------------------*/
11321 static int
11322 genDjnz (iCode * ic, iCode * ifx)
11323 {
11324   symbol *lbl, *lbl1;
11325   if (!ifx)
11326     return 0;
11327
11328   /* if the if condition has a false label
11329      then we cannot save */
11330   if (IC_FALSE (ifx))
11331     return 0;
11332
11333   /* if the minus is not of the form
11334      a = a - 1 */
11335   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11336       !IS_OP_LITERAL (IC_RIGHT (ic)))
11337     return 0;
11338
11339   if (operandLitValue (IC_RIGHT (ic)) != 1)
11340     return 0;
11341
11342   /* if the size of this greater than one then no
11343      saving */
11344   if (getSize (operandType (IC_RESULT (ic))) > 1)
11345     return 0;
11346
11347   /* otherwise we can save BIG */
11348   D(emitcode(";", "genDjnz"););
11349
11350   lbl = newiTempLabel (NULL);
11351   lbl1 = newiTempLabel (NULL);
11352
11353   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11354
11355   if (AOP_NEEDSACC(IC_RESULT(ic)))
11356   {
11357       /* If the result is accessed indirectly via
11358        * the accumulator, we must explicitly write
11359        * it back after the decrement.
11360        */
11361       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11362       
11363       if (strcmp(rByte, "a"))
11364       {
11365            /* Something is hopelessly wrong */
11366            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11367                    __FILE__, __LINE__);
11368            /* We can just give up; the generated code will be inefficient,
11369             * but what the hey.
11370             */
11371            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11372            return 0;
11373       }
11374       emitcode ("dec", "%s", rByte);
11375       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11376       emitcode ("jnz", "!tlabel", lbl->key + 100);
11377   }
11378   else if (IS_AOP_PREG (IC_RESULT (ic)))
11379     {
11380       emitcode ("dec", "%s",
11381                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11382       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11383       emitcode ("jnz", "!tlabel", lbl->key + 100);
11384     }
11385   else
11386     {
11387       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11388                 lbl->key + 100);
11389     }
11390   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11391   emitcode ("", "!tlabeldef", lbl->key + 100);
11392   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11393   emitcode ("", "!tlabeldef", lbl1->key + 100);
11394
11395   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11396   ifx->generated = 1;
11397   return 1;
11398 }
11399
11400 /*-----------------------------------------------------------------*/
11401 /* genReceive - generate code for a receive iCode                  */
11402 /*-----------------------------------------------------------------*/
11403 static void
11404 genReceive (iCode * ic)
11405 {
11406     int size = getSize (operandType (IC_RESULT (ic)));
11407     int offset = 0;
11408     int rb1off ;
11409     
11410     D (emitcode (";", "genReceive "););
11411
11412     if (ic->argreg == 1) 
11413     {
11414         /* first parameter */
11415         if (AOP_IS_STR(IC_RESULT(ic)))
11416         {
11417             /* Nothing to do: it's already in the proper place. */
11418             return;
11419         }
11420         else
11421         {
11422             bool useDp2;
11423             
11424             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11425                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11426                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11427             
11428             _G.accInUse++;
11429             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11430             _G.accInUse--; 
11431             
11432             /* Sanity checking... */
11433             if (AOP_USESDPTR(IC_RESULT(ic)))
11434             {
11435                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11436                         "genReceive got unexpected DPTR.");
11437             }
11438             assignResultValue (IC_RESULT (ic));
11439         }
11440     } 
11441     else 
11442     { 
11443         /* second receive onwards */
11444         /* this gets a little tricky since unused recevies will be
11445          eliminated, we have saved the reg in the type field . and
11446          we use that to figure out which register to use */
11447         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11448         rb1off = ic->argreg;
11449         while (size--) 
11450         {
11451             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11452         }
11453     }
11454     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11455 }
11456
11457 /*-----------------------------------------------------------------*/
11458 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11459 /*-----------------------------------------------------------------*/
11460 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11461 {
11462     operand *from , *to , *count;
11463     symbol *lbl;
11464     bitVect *rsave;
11465     int i;
11466
11467     /* we know it has to be 3 parameters */
11468     assert (nparms == 3);
11469     
11470     rsave = newBitVect(16);
11471     /* save DPTR if it needs to be saved */
11472     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11473             if (bitVectBitValue(ic->rMask,i))
11474                     rsave = bitVectSetBit(rsave,i);
11475     }
11476     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11477                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11478     savermask(rsave);
11479     
11480     to = parms[0];
11481     from = parms[1];
11482     count = parms[2];
11483
11484     aopOp (from, ic->next, FALSE, FALSE);
11485
11486     /* get from into DPTR1 */
11487     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11488     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11489     if (options.model == MODEL_FLAT24) {
11490         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11491     }
11492
11493     freeAsmop (from, NULL, ic, FALSE);
11494     aopOp (to, ic, FALSE, FALSE);
11495     /* get "to" into DPTR */
11496     /* if the operand is already in dptr
11497        then we do nothing else we move the value to dptr */
11498     if (AOP_TYPE (to) != AOP_STR) {
11499         /* if already in DPTR then we need to push */
11500         if (AOP_TYPE(to) == AOP_DPTR) {
11501             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11502             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11503             if (options.model == MODEL_FLAT24)
11504                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11505             emitcode ("pop", "dph");
11506             emitcode ("pop", "dpl");        
11507         } else {
11508             _startLazyDPSEvaluation ();
11509             /* if this is remateriazable */
11510             if (AOP_TYPE (to) == AOP_IMMD) {
11511                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11512             } else {                    /* we need to get it byte by byte */
11513                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11514                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11515                 if (options.model == MODEL_FLAT24) {
11516                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11517                 }
11518             }
11519             _endLazyDPSEvaluation ();
11520         }
11521     }
11522     freeAsmop (to, NULL, ic, FALSE);
11523     _G.dptrInUse = _G.dptr1InUse = 1;
11524     aopOp (count, ic->next->next, FALSE,FALSE);
11525     lbl =newiTempLabel(NULL);
11526
11527     /* now for the actual copy */
11528     if (AOP_TYPE(count) == AOP_LIT && 
11529         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11530         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11531         if (fromc) {
11532             emitcode ("lcall","__bi_memcpyc2x_s");
11533         } else {
11534             emitcode ("lcall","__bi_memcpyx2x_s");
11535         }
11536         freeAsmop (count, NULL, ic, FALSE);
11537     } else {
11538         symbol *lbl1 = newiTempLabel(NULL);
11539         
11540         emitcode (";"," Auto increment but no djnz");
11541         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11542         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11543         freeAsmop (count, NULL, ic, FALSE);
11544         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11545         emitcode ("","!tlabeldef",lbl->key+100);
11546         if (fromc) {
11547             emitcode ("clr","a");
11548             emitcode ("movc", "a,@a+dptr");
11549         } else 
11550             emitcode ("movx", "a,@dptr");
11551         emitcode ("movx", "@dptr,a");
11552         emitcode ("inc", "dptr");
11553         emitcode ("inc", "dptr");
11554         emitcode ("mov","a,b");
11555         emitcode ("orl","a,_ap");
11556         emitcode ("jz","!tlabel",lbl1->key+100);
11557         emitcode ("mov","a,_ap");
11558         emitcode ("add","a,#!constbyte",0xFF);
11559         emitcode ("mov","_ap,a");
11560         emitcode ("mov","a,b");
11561         emitcode ("addc","a,#!constbyte",0xFF);
11562         emitcode ("mov","b,a");
11563         emitcode ("sjmp","!tlabel",lbl->key+100);
11564         emitcode ("","!tlabeldef",lbl1->key+100);
11565     }
11566     emitcode ("mov", "dps,#0"); 
11567     _G.dptrInUse = _G.dptr1InUse = 0;
11568     unsavermask(rsave);
11569
11570 }
11571
11572 /*-----------------------------------------------------------------*/
11573 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11574 /*-----------------------------------------------------------------*/
11575 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11576 {
11577     operand *from , *to , *count;
11578     symbol *lbl,*lbl2;
11579     bitVect *rsave;
11580     int i;
11581
11582     /* we know it has to be 3 parameters */
11583     assert (nparms == 3);
11584     
11585     rsave = newBitVect(16);
11586     /* save DPTR if it needs to be saved */
11587     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11588             if (bitVectBitValue(ic->rMask,i))
11589                     rsave = bitVectSetBit(rsave,i);
11590     }
11591     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11592                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11593     savermask(rsave);
11594     
11595     to = parms[0];
11596     from = parms[1];
11597     count = parms[2];
11598
11599     aopOp (from, ic->next, FALSE, FALSE);
11600
11601     /* get from into DPTR1 */
11602     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11603     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11604     if (options.model == MODEL_FLAT24) {
11605         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11606     }
11607
11608     freeAsmop (from, NULL, ic, FALSE);
11609     aopOp (to, ic, FALSE, FALSE);
11610     /* get "to" into DPTR */
11611     /* if the operand is already in dptr
11612        then we do nothing else we move the value to dptr */
11613     if (AOP_TYPE (to) != AOP_STR) {
11614         /* if already in DPTR then we need to push */
11615         if (AOP_TYPE(to) == AOP_DPTR) {
11616             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11617             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11618             if (options.model == MODEL_FLAT24)
11619                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11620             emitcode ("pop", "dph");
11621             emitcode ("pop", "dpl");        
11622         } else {
11623             _startLazyDPSEvaluation ();
11624             /* if this is remateriazable */
11625             if (AOP_TYPE (to) == AOP_IMMD) {
11626                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11627             } else {                    /* we need to get it byte by byte */
11628                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11629                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11630                 if (options.model == MODEL_FLAT24) {
11631                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11632                 }
11633             }
11634             _endLazyDPSEvaluation ();
11635         }
11636     }
11637     freeAsmop (to, NULL, ic, FALSE);
11638     _G.dptrInUse = _G.dptr1InUse = 1;
11639     aopOp (count, ic->next->next, FALSE,FALSE);
11640     lbl =newiTempLabel(NULL);
11641     lbl2 =newiTempLabel(NULL);
11642
11643     /* now for the actual compare */
11644     if (AOP_TYPE(count) == AOP_LIT && 
11645         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11646         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11647         if (fromc)
11648             emitcode("lcall","__bi_memcmpc2x_s");
11649         else
11650             emitcode("lcall","__bi_memcmpx2x_s");
11651         freeAsmop (count, NULL, ic, FALSE);
11652         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11653         aopPut(AOP(IC_RESULT(ic)),"a",0);
11654         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11655     } else {
11656         symbol *lbl1 = newiTempLabel(NULL);
11657
11658         emitcode("push","ar0");         
11659         emitcode (";"," Auto increment but no djnz");
11660         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11661         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11662         freeAsmop (count, NULL, ic, FALSE);
11663         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11664         emitcode ("","!tlabeldef",lbl->key+100);
11665         if (fromc) {
11666             emitcode ("clr","a");
11667             emitcode ("movc", "a,@a+dptr");
11668         } else 
11669             emitcode ("movx", "a,@dptr");
11670         emitcode ("mov","r0,a");
11671         emitcode ("movx", "a,@dptr");
11672         emitcode ("clr","c");
11673         emitcode ("subb","a,r0");
11674         emitcode ("jnz","!tlabel",lbl2->key+100);
11675         emitcode ("inc", "dptr");
11676         emitcode ("inc", "dptr");
11677         emitcode ("mov","a,b");
11678         emitcode ("orl","a,_ap");
11679         emitcode ("jz","!tlabel",lbl1->key+100);
11680         emitcode ("mov","a,_ap");
11681         emitcode ("add","a,#!constbyte",0xFF);
11682         emitcode ("mov","_ap,a");
11683         emitcode ("mov","a,b");
11684         emitcode ("addc","a,#!constbyte",0xFF);
11685         emitcode ("mov","b,a");
11686         emitcode ("sjmp","!tlabel",lbl->key+100);
11687         emitcode ("","!tlabeldef",lbl1->key+100);
11688         emitcode ("clr","a");
11689         emitcode ("","!tlabeldef",lbl2->key+100);
11690         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11691         aopPut(AOP(IC_RESULT(ic)),"a",0);
11692         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11693         emitcode("pop","ar0");
11694         emitcode ("mov", "dps,#0");      
11695     }
11696     _G.dptrInUse = _G.dptr1InUse = 0;
11697     unsavermask(rsave);
11698
11699 }
11700
11701 /*-----------------------------------------------------------------*/
11702 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11703 /* port, first parameter output area second parameter pointer to   */
11704 /* port third parameter count                                      */
11705 /*-----------------------------------------------------------------*/
11706 static void genInp( iCode *ic, int nparms, operand **parms)
11707 {
11708     operand *from , *to , *count;
11709     symbol *lbl;
11710     bitVect *rsave;
11711     int i;
11712
11713     /* we know it has to be 3 parameters */
11714     assert (nparms == 3);
11715     
11716     rsave = newBitVect(16);
11717     /* save DPTR if it needs to be saved */
11718     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11719             if (bitVectBitValue(ic->rMask,i))
11720                     rsave = bitVectSetBit(rsave,i);
11721     }
11722     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11723                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11724     savermask(rsave);
11725     
11726     to = parms[0];
11727     from = parms[1];
11728     count = parms[2];
11729
11730     aopOp (from, ic->next, FALSE, FALSE);
11731
11732     /* get from into DPTR1 */
11733     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11734     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11735     if (options.model == MODEL_FLAT24) {
11736         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11737     }
11738
11739     freeAsmop (from, NULL, ic, FALSE);
11740     aopOp (to, ic, FALSE, FALSE);
11741     /* get "to" into DPTR */
11742     /* if the operand is already in dptr
11743        then we do nothing else we move the value to dptr */
11744     if (AOP_TYPE (to) != AOP_STR) {
11745         /* if already in DPTR then we need to push */
11746         if (AOP_TYPE(to) == AOP_DPTR) {
11747             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11748             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11749             if (options.model == MODEL_FLAT24)
11750                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11751             emitcode ("pop", "dph");
11752             emitcode ("pop", "dpl");        
11753         } else {
11754             _startLazyDPSEvaluation ();
11755             /* if this is remateriazable */
11756             if (AOP_TYPE (to) == AOP_IMMD) {
11757                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11758             } else {                    /* we need to get it byte by byte */
11759                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11760                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11761                 if (options.model == MODEL_FLAT24) {
11762                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11763                 }
11764             }
11765             _endLazyDPSEvaluation ();
11766         }
11767     }
11768     freeAsmop (to, NULL, ic, FALSE);
11769
11770     _G.dptrInUse = _G.dptr1InUse = 1;
11771     aopOp (count, ic->next->next, FALSE,FALSE);
11772     lbl =newiTempLabel(NULL);
11773
11774     /* now for the actual copy */
11775     if (AOP_TYPE(count) == AOP_LIT && 
11776         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11777         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11778         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11779         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11780         freeAsmop (count, NULL, ic, FALSE);
11781         emitcode ("","!tlabeldef",lbl->key+100);
11782         emitcode ("movx", "a,@dptr");   /* read data from port */
11783         emitcode ("dec","dps");         /* switch to DPTR */
11784         emitcode ("movx", "@dptr,a");   /* save into location */
11785         emitcode ("inc", "dptr");       /* point to next area */
11786         emitcode ("inc","dps");         /* switch to DPTR2 */
11787         emitcode ("djnz","b,!tlabel",lbl->key+100);
11788     } else {
11789         symbol *lbl1 = newiTempLabel(NULL);
11790         
11791         emitcode (";"," Auto increment but no djnz");
11792         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11793         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11794         freeAsmop (count, NULL, ic, FALSE);
11795         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11796         emitcode ("","!tlabeldef",lbl->key+100);
11797         emitcode ("movx", "a,@dptr");
11798         emitcode ("dec","dps");         /* switch to DPTR */
11799         emitcode ("movx", "@dptr,a");
11800         emitcode ("inc", "dptr");
11801         emitcode ("inc","dps");         /* switch to DPTR2 */
11802 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11803 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11804         emitcode ("mov","a,b");
11805         emitcode ("orl","a,_ap");
11806         emitcode ("jz","!tlabel",lbl1->key+100);
11807         emitcode ("mov","a,_ap");
11808         emitcode ("add","a,#!constbyte",0xFF);
11809         emitcode ("mov","_ap,a");
11810         emitcode ("mov","a,b");
11811         emitcode ("addc","a,#!constbyte",0xFF);
11812         emitcode ("mov","b,a");
11813         emitcode ("sjmp","!tlabel",lbl->key+100);
11814         emitcode ("","!tlabeldef",lbl1->key+100);
11815     }
11816     emitcode ("mov", "dps,#0"); 
11817     _G.dptrInUse = _G.dptr1InUse = 0;
11818     unsavermask(rsave);
11819
11820 }
11821
11822 /*-----------------------------------------------------------------*/
11823 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11824 /* port, first parameter output area second parameter pointer to   */
11825 /* port third parameter count                                      */
11826 /*-----------------------------------------------------------------*/
11827 static void genOutp( iCode *ic, int nparms, operand **parms)
11828 {
11829     operand *from , *to , *count;
11830     symbol *lbl;
11831     bitVect *rsave;
11832     int i;
11833
11834     /* we know it has to be 3 parameters */
11835     assert (nparms == 3);
11836     
11837     rsave = newBitVect(16);
11838     /* save DPTR if it needs to be saved */
11839     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11840             if (bitVectBitValue(ic->rMask,i))
11841                     rsave = bitVectSetBit(rsave,i);
11842     }
11843     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11844                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11845     savermask(rsave);
11846     
11847     to = parms[0];
11848     from = parms[1];
11849     count = parms[2];
11850
11851     aopOp (from, ic->next, FALSE, FALSE);
11852
11853     /* get from into DPTR1 */
11854     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11855     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11856     if (options.model == MODEL_FLAT24) {
11857         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11858     }
11859
11860     freeAsmop (from, NULL, ic, FALSE);
11861     aopOp (to, ic, FALSE, FALSE);
11862     /* get "to" into DPTR */
11863     /* if the operand is already in dptr
11864        then we do nothing else we move the value to dptr */
11865     if (AOP_TYPE (to) != AOP_STR) {
11866         /* if already in DPTR then we need to push */
11867         if (AOP_TYPE(to) == AOP_DPTR) {
11868             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11869             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11870             if (options.model == MODEL_FLAT24)
11871                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11872             emitcode ("pop", "dph");
11873             emitcode ("pop", "dpl");        
11874         } else {
11875             _startLazyDPSEvaluation ();
11876             /* if this is remateriazable */
11877             if (AOP_TYPE (to) == AOP_IMMD) {
11878                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11879             } else {                    /* we need to get it byte by byte */
11880                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11881                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11882                 if (options.model == MODEL_FLAT24) {
11883                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11884                 }
11885             }
11886             _endLazyDPSEvaluation ();
11887         }
11888     }
11889     freeAsmop (to, NULL, ic, FALSE);
11890
11891     _G.dptrInUse = _G.dptr1InUse = 1;
11892     aopOp (count, ic->next->next, FALSE,FALSE);
11893     lbl =newiTempLabel(NULL);
11894
11895     /* now for the actual copy */
11896     if (AOP_TYPE(count) == AOP_LIT && 
11897         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11898         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11899         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11900         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11901         emitcode ("","!tlabeldef",lbl->key+100);
11902         emitcode ("movx", "a,@dptr");   /* read data from port */
11903         emitcode ("inc","dps");         /* switch to DPTR2 */
11904         emitcode ("movx", "@dptr,a");   /* save into location */
11905         emitcode ("inc", "dptr");       /* point to next area */
11906         emitcode ("dec","dps");         /* switch to DPTR */
11907         emitcode ("djnz","b,!tlabel",lbl->key+100);
11908         freeAsmop (count, NULL, ic, FALSE);
11909     } else {
11910         symbol *lbl1 = newiTempLabel(NULL);
11911         
11912         emitcode (";"," Auto increment but no djnz");
11913         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11914         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11915         freeAsmop (count, NULL, ic, FALSE);
11916         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11917         emitcode ("","!tlabeldef",lbl->key+100);
11918         emitcode ("movx", "a,@dptr");
11919         emitcode ("inc", "dptr");
11920         emitcode ("inc","dps");         /* switch to DPTR2 */
11921         emitcode ("movx", "@dptr,a");
11922         emitcode ("dec","dps");         /* switch to DPTR */
11923         emitcode ("mov","a,b");
11924         emitcode ("orl","a,_ap");
11925         emitcode ("jz","!tlabel",lbl1->key+100);
11926         emitcode ("mov","a,_ap");
11927         emitcode ("add","a,#!constbyte",0xFF);
11928         emitcode ("mov","_ap,a");
11929         emitcode ("mov","a,b");
11930         emitcode ("addc","a,#!constbyte",0xFF);
11931         emitcode ("mov","b,a");
11932         emitcode ("sjmp","!tlabel",lbl->key+100);
11933         emitcode ("","!tlabeldef",lbl1->key+100);
11934     }
11935     emitcode ("mov", "dps,#0"); 
11936     _G.dptrInUse = _G.dptr1InUse = 0;
11937     unsavermask(rsave);
11938
11939 }
11940
11941 /*-----------------------------------------------------------------*/
11942 /* genSwapW - swap lower & high order bytes                        */
11943 /*-----------------------------------------------------------------*/
11944 static void genSwapW(iCode *ic, int nparms, operand **parms)
11945 {
11946     operand *dest;
11947     operand *src;
11948     assert (nparms==1);
11949
11950     src = parms[0];
11951     dest=IC_RESULT(ic);
11952
11953     assert(getSize(operandType(src))==2);
11954
11955     aopOp (src, ic, FALSE, FALSE);
11956     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11957     _G.accInUse++;
11958     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11959     _G.accInUse--;
11960     freeAsmop (src, NULL, ic, FALSE);
11961     
11962     aopOp (dest,ic, FALSE, FALSE);
11963     aopPut(AOP(dest),"b",0);
11964     aopPut(AOP(dest),"a",1);
11965     freeAsmop (dest, NULL, ic, FALSE);    
11966 }
11967
11968 /*-----------------------------------------------------------------*/
11969 /* genMemsetX - gencode for memSetX data                           */
11970 /*-----------------------------------------------------------------*/
11971 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11972 {
11973     operand *to , *val , *count;
11974     symbol *lbl;
11975     char *l;
11976     int i;
11977     bitVect *rsave;
11978
11979     /* we know it has to be 3 parameters */
11980     assert (nparms == 3);
11981     
11982     to = parms[0];
11983     val = parms[1];
11984     count = parms[2];
11985         
11986     /* save DPTR if it needs to be saved */
11987     rsave = newBitVect(16);
11988     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11989             if (bitVectBitValue(ic->rMask,i))
11990                     rsave = bitVectSetBit(rsave,i);
11991     }
11992     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11993                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11994     savermask(rsave);
11995
11996     aopOp (to, ic, FALSE, FALSE);
11997     /* get "to" into DPTR */
11998     /* if the operand is already in dptr
11999        then we do nothing else we move the value to dptr */
12000     if (AOP_TYPE (to) != AOP_STR) {
12001         /* if already in DPTR then we need to push */
12002         if (AOP_TYPE(to) == AOP_DPTR) {
12003             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12004             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12005             if (options.model == MODEL_FLAT24)
12006                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12007             emitcode ("pop", "dph");
12008             emitcode ("pop", "dpl");        
12009         } else {
12010             _startLazyDPSEvaluation ();
12011             /* if this is remateriazable */
12012             if (AOP_TYPE (to) == AOP_IMMD) {
12013                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12014             } else {                    /* we need to get it byte by byte */
12015                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12016                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12017                 if (options.model == MODEL_FLAT24) {
12018                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12019                 }
12020             }
12021             _endLazyDPSEvaluation ();
12022         }
12023     }
12024     freeAsmop (to, NULL, ic, FALSE);
12025
12026     aopOp (val, ic->next->next, FALSE,FALSE);
12027     aopOp (count, ic->next->next, FALSE,FALSE);    
12028     lbl =newiTempLabel(NULL);
12029     /* now for the actual copy */
12030     if (AOP_TYPE(count) == AOP_LIT && 
12031         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12032         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12033         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12034         MOVA(l);
12035         emitcode ("","!tlabeldef",lbl->key+100);
12036         emitcode ("movx", "@dptr,a");
12037         emitcode ("inc", "dptr");
12038         emitcode ("djnz","b,!tlabel",lbl->key+100);
12039     } else {
12040         symbol *lbl1 = newiTempLabel(NULL);
12041         
12042         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12043         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12044         emitcode ("","!tlabeldef",lbl->key+100);
12045         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12046         emitcode ("movx", "@dptr,a");
12047         emitcode ("inc", "dptr");
12048         emitcode ("mov","a,b");
12049         emitcode ("orl","a,_ap");
12050         emitcode ("jz","!tlabel",lbl1->key+100);
12051         emitcode ("mov","a,_ap");
12052         emitcode ("add","a,#!constbyte",0xFF);
12053         emitcode ("mov","_ap,a");
12054         emitcode ("mov","a,b");
12055         emitcode ("addc","a,#!constbyte",0xFF);
12056         emitcode ("mov","b,a");
12057         emitcode ("sjmp","!tlabel",lbl->key+100);
12058         emitcode ("","!tlabeldef",lbl1->key+100);
12059     }
12060     freeAsmop (count, NULL, ic, FALSE);
12061     unsavermask(rsave);
12062 }
12063
12064 /*-----------------------------------------------------------------*/
12065 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12066 /*-----------------------------------------------------------------*/
12067 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12068 {
12069         bitVect *rsave ;
12070         operand *pnum, *result;
12071         int i;
12072     
12073         assert (nparms==1);
12074         /* save registers that need to be saved */
12075         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12076                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12077     
12078         pnum = parms[0]; 
12079         aopOp (pnum, ic, FALSE, FALSE);
12080         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12081         freeAsmop (pnum, NULL, ic, FALSE);
12082         emitcode ("lcall","NatLib_LoadPrimitive");
12083         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12084         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12085             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12086                 for (i = (size-1) ; i >= 0 ; i-- ) {
12087                         emitcode ("push","a%s",javaRet[i]);
12088                 }
12089                 for (i=0; i < size ; i++ ) {
12090                         emitcode ("pop","a%s",
12091                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12092                 }
12093         } else {
12094                 for (i = 0 ; i < size ; i++ ) {
12095                         aopPut(AOP(result),javaRet[i],i);
12096                 }
12097         }    
12098         freeAsmop (result, NULL, ic, FALSE);
12099         unsavermask(rsave);
12100 }
12101
12102 /*-----------------------------------------------------------------*/
12103 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12104 /*-----------------------------------------------------------------*/
12105 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12106 {
12107         bitVect *rsave ;
12108         operand *pnum, *result;
12109         int size = 3;
12110         int i;
12111     
12112         assert (nparms==1);
12113         /* save registers that need to be saved */
12114         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12115                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12116     
12117         pnum = parms[0]; 
12118         aopOp (pnum, ic, FALSE, FALSE);
12119         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12120         freeAsmop (pnum, NULL, ic, FALSE);
12121         emitcode ("lcall","NatLib_LoadPointer");
12122         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12123         if (AOP_TYPE(result)!=AOP_STR) {
12124                 for (i = 0 ; i < size ; i++ ) {
12125                         aopPut(AOP(result),fReturn[i],i);
12126                 }
12127         }    
12128         freeAsmop (result, NULL, ic, FALSE);
12129         unsavermask(rsave);
12130 }
12131
12132 /*-----------------------------------------------------------------*/
12133 /* genNatLibInstallStateBlock -                                    */
12134 /*-----------------------------------------------------------------*/
12135 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12136                                        operand **parms, const char *name)
12137 {
12138         bitVect *rsave ;
12139         operand *psb, *handle;
12140         assert (nparms==2);
12141
12142         /* save registers that need to be saved */
12143         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12144                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12145         psb = parms[0];
12146         handle = parms[1];
12147
12148         /* put pointer to state block into DPTR1 */
12149         aopOp (psb, ic, FALSE, FALSE);
12150         if (AOP_TYPE (psb) == AOP_IMMD) {
12151                 emitcode ("mov","dps,#1");
12152                 emitcode ("mov", "dptr,%s",
12153                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12154                 emitcode ("mov","dps,#0");
12155         } else {
12156                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12157                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12158                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12159         }
12160         freeAsmop (psb, NULL, ic, FALSE);
12161
12162         /* put libraryID into DPTR */
12163         emitcode ("mov","dptr,#LibraryID");
12164
12165         /* put handle into r3:r2 */
12166         aopOp (handle, ic, FALSE, FALSE);
12167         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12168                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12169                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12170                 emitcode ("pop","ar3");
12171                 emitcode ("pop","ar2");
12172         } else {        
12173                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12174                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12175         }
12176         freeAsmop (psb, NULL, ic, FALSE);
12177
12178         /* make the call */
12179         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12180
12181         /* put return value into place*/
12182         _G.accInUse++;
12183         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12184         _G.accInUse--;
12185         aopPut(AOP(IC_RESULT(ic)),"a",0);
12186         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12187         unsavermask(rsave);
12188 }
12189
12190 /*-----------------------------------------------------------------*/
12191 /* genNatLibRemoveStateBlock -                                     */
12192 /*-----------------------------------------------------------------*/
12193 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12194 {
12195         bitVect *rsave ;
12196
12197         assert(nparms==0);
12198
12199         /* save registers that need to be saved */
12200         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12201                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12202
12203         /* put libraryID into DPTR */
12204         emitcode ("mov","dptr,#LibraryID");
12205         /* make the call */
12206         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12207         unsavermask(rsave);
12208 }
12209
12210 /*-----------------------------------------------------------------*/
12211 /* genNatLibGetStateBlock -                                        */
12212 /*-----------------------------------------------------------------*/
12213 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12214                                    operand **parms,const char *name)
12215 {
12216         bitVect *rsave ;
12217         symbol *lbl = newiTempLabel(NULL);
12218         
12219         assert(nparms==0);
12220         /* save registers that need to be saved */
12221         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12222                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12223
12224         /* put libraryID into DPTR */
12225         emitcode ("mov","dptr,#LibraryID");
12226         /* make the call */
12227         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12228         emitcode ("jnz","!tlabel",lbl->key+100);
12229
12230         /* put return value into place */
12231         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12232         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12233                 emitcode ("push","ar3");
12234                 emitcode ("push","ar2");
12235                 emitcode ("pop","%s",
12236                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12237                 emitcode ("pop","%s",
12238                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12239         } else {
12240                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12241                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12242         }
12243         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12244         emitcode ("","!tlabeldef",lbl->key+100);
12245         unsavermask(rsave);
12246 }
12247
12248 /*-----------------------------------------------------------------*/
12249 /* genMMMalloc -                                                   */
12250 /*-----------------------------------------------------------------*/
12251 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12252                          int size, const char *name)
12253 {
12254         bitVect *rsave ;
12255         operand *bsize;
12256         symbol *rsym;
12257         symbol *lbl = newiTempLabel(NULL);
12258
12259         assert (nparms == 1);
12260         /* save registers that need to be saved */
12261         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12262                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12263         
12264         bsize=parms[0];
12265         aopOp (bsize,ic,FALSE,FALSE);
12266
12267         /* put the size in R4-R2 */
12268         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12269                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12270                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12271                 if (size==3) {
12272                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12273                         emitcode("pop","ar4");
12274                 }
12275                 emitcode("pop","ar3");
12276                 emitcode("pop","ar2");          
12277         } else {
12278                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12279                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12280                 if (size==3) {
12281                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12282                 }
12283         }
12284         freeAsmop (bsize, NULL, ic, FALSE);
12285
12286         /* make the call */
12287         emitcode ("lcall","MM_%s",name);
12288         emitcode ("jz","!tlabel",lbl->key+100);
12289         emitcode ("mov","r2,#!constbyte",0xff);
12290         emitcode ("mov","r3,#!constbyte",0xff);
12291         emitcode ("","!tlabeldef",lbl->key+100);
12292         /* we don't care about the pointer : we just save the handle */
12293         rsym = OP_SYMBOL(IC_RESULT(ic));
12294         if (rsym->liveFrom != rsym->liveTo) {
12295                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12296                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12297                         emitcode ("push","ar3");
12298                         emitcode ("push","ar2");
12299                         emitcode ("pop","%s",
12300                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12301                         emitcode ("pop","%s",
12302                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12303                 } else {
12304                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12305                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12306                 }
12307                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12308         }
12309         unsavermask(rsave);
12310 }
12311
12312 /*-----------------------------------------------------------------*/
12313 /* genMMDeref -                                                    */
12314 /*-----------------------------------------------------------------*/
12315 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12316 {
12317         bitVect *rsave ;
12318         operand *handle;
12319
12320         assert (nparms == 1);
12321         /* save registers that need to be saved */
12322         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12323                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12324         
12325         handle=parms[0];
12326         aopOp (handle,ic,FALSE,FALSE);
12327
12328         /* put the size in R4-R2 */
12329         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12330                 emitcode("push","%s",
12331                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12332                 emitcode("push","%s",
12333                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12334                 emitcode("pop","ar3");
12335                 emitcode("pop","ar2");          
12336         } else {
12337                 emitcode ("mov","r2,%s",
12338                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12339                 emitcode ("mov","r3,%s",
12340                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12341         }
12342         freeAsmop (handle, NULL, ic, FALSE);
12343
12344         /* make the call */
12345         emitcode ("lcall","MM_Deref");
12346         
12347         {
12348                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12349                 if (rsym->liveFrom != rsym->liveTo) {                   
12350                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12351                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12352                             _startLazyDPSEvaluation ();
12353                             
12354                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12355                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12356                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12357
12358                             _endLazyDPSEvaluation ();
12359                             
12360                         }
12361                 }
12362         }
12363         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12364         unsavermask(rsave);
12365 }
12366
12367 /*-----------------------------------------------------------------*/
12368 /* genMMUnrestrictedPersist -                                      */
12369 /*-----------------------------------------------------------------*/
12370 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12371 {
12372         bitVect *rsave ;
12373         operand *handle;
12374
12375         assert (nparms == 1);
12376         /* save registers that need to be saved */
12377         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12378                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12379         
12380         handle=parms[0];
12381         aopOp (handle,ic,FALSE,FALSE);
12382
12383         /* put the size in R3-R2 */
12384         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12385                 emitcode("push","%s",
12386                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12387                 emitcode("push","%s",
12388                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12389                 emitcode("pop","ar3");
12390                 emitcode("pop","ar2");          
12391         } else {
12392                 emitcode ("mov","r2,%s",
12393                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12394                 emitcode ("mov","r3,%s",
12395                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12396         }
12397         freeAsmop (handle, NULL, ic, FALSE);
12398
12399         /* make the call */
12400         emitcode ("lcall","MM_UnrestrictedPersist");
12401
12402         {
12403                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12404                 if (rsym->liveFrom != rsym->liveTo) {   
12405                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12406                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12407                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12408                 }
12409         }
12410         unsavermask(rsave);
12411 }
12412
12413 /*-----------------------------------------------------------------*/
12414 /* genSystemExecJavaProcess -                                      */
12415 /*-----------------------------------------------------------------*/
12416 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12417 {
12418         bitVect *rsave ;
12419         operand *handle, *pp;
12420
12421         assert (nparms==2);
12422         /* save registers that need to be saved */
12423         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12424                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12425         
12426         pp = parms[0];
12427         handle = parms[1];
12428         
12429         /* put the handle in R3-R2 */
12430         aopOp (handle,ic,FALSE,FALSE);
12431         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12432                 emitcode("push","%s",
12433                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12434                 emitcode("push","%s",
12435                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12436                 emitcode("pop","ar3");
12437                 emitcode("pop","ar2");          
12438         } else {
12439                 emitcode ("mov","r2,%s",
12440                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12441                 emitcode ("mov","r3,%s",
12442                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12443         }
12444         freeAsmop (handle, NULL, ic, FALSE);
12445         
12446         /* put pointer in DPTR */
12447         aopOp (pp,ic,FALSE,FALSE);
12448         if (AOP_TYPE(pp) == AOP_IMMD) {
12449                 emitcode ("mov", "dptr,%s",
12450                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12451         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12452                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12453                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12454                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12455         }
12456         freeAsmop (handle, NULL, ic, FALSE);
12457
12458         /* make the call */
12459         emitcode ("lcall","System_ExecJavaProcess");
12460         
12461         /* put result in place */
12462         {
12463                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12464                 if (rsym->liveFrom != rsym->liveTo) {   
12465                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12466                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12467                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12468                 }
12469         }
12470         
12471         unsavermask(rsave);
12472 }
12473
12474 /*-----------------------------------------------------------------*/
12475 /* genSystemRTCRegisters -                                         */
12476 /*-----------------------------------------------------------------*/
12477 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12478                                   char *name)
12479 {
12480         bitVect *rsave ;
12481         operand *pp;
12482
12483         assert (nparms==1);
12484         /* save registers that need to be saved */
12485         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12486                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12487         
12488         pp=parms[0];
12489         /* put pointer in DPTR */
12490         aopOp (pp,ic,FALSE,FALSE);
12491         if (AOP_TYPE (pp) == AOP_IMMD) {
12492                 emitcode ("mov","dps,#1");
12493                 emitcode ("mov", "dptr,%s", 
12494                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12495                 emitcode ("mov","dps,#0");
12496         } else {
12497                 emitcode ("mov","dpl1,%s",
12498                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12499                 emitcode ("mov","dph1,%s",
12500                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12501                 emitcode ("mov","dpx1,%s",
12502                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12503         }
12504         freeAsmop (pp, NULL, ic, FALSE);
12505
12506         /* make the call */
12507         emitcode ("lcall","System_%sRTCRegisters",name);
12508
12509         unsavermask(rsave);
12510 }
12511
12512 /*-----------------------------------------------------------------*/
12513 /* genSystemThreadSleep -                                          */
12514 /*-----------------------------------------------------------------*/
12515 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12516 {
12517         bitVect *rsave ;
12518         operand *to, *s;
12519
12520         assert (nparms==1);
12521         /* save registers that need to be saved */
12522         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12523                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12524
12525         to = parms[0];
12526         aopOp(to,ic,FALSE,FALSE);
12527         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12528             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12529                 emitcode ("push","%s",
12530                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12531                 emitcode ("push","%s",
12532                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12533                 emitcode ("push","%s",
12534                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12535                 emitcode ("push","%s",
12536                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12537                 emitcode ("pop","ar3");
12538                 emitcode ("pop","ar2");
12539                 emitcode ("pop","ar1");
12540                 emitcode ("pop","ar0");
12541         } else {
12542                 emitcode ("mov","r0,%s",
12543                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12544                 emitcode ("mov","r1,%s",
12545                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12546                 emitcode ("mov","r2,%s",
12547                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12548                 emitcode ("mov","r3,%s",
12549                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12550         }
12551         freeAsmop (to, NULL, ic, FALSE);
12552
12553         /* suspend in acc */
12554         s = parms[1];
12555         aopOp(s,ic,FALSE,FALSE);
12556         emitcode ("mov","a,%s",
12557                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12558         freeAsmop (s, NULL, ic, FALSE);
12559
12560         /* make the call */
12561         emitcode ("lcall","System_%s",name);
12562
12563         unsavermask(rsave);
12564 }
12565
12566 /*-----------------------------------------------------------------*/
12567 /* genSystemThreadResume -                                         */
12568 /*-----------------------------------------------------------------*/
12569 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12570 {
12571         bitVect *rsave ;
12572         operand *tid,*pid;
12573
12574         assert (nparms==2);
12575         /* save registers that need to be saved */
12576         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12577                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12578         
12579         tid = parms[0];
12580         pid = parms[1];
12581         
12582         /* PID in R0 */
12583         aopOp(pid,ic,FALSE,FALSE);
12584         emitcode ("mov","r0,%s",
12585                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12586         freeAsmop (pid, NULL, ic, FALSE);
12587         
12588         /* tid into ACC */
12589         aopOp(tid,ic,FALSE,FALSE);
12590         emitcode ("mov","a,%s",
12591                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12592         freeAsmop (tid, NULL, ic, FALSE);
12593         
12594         emitcode ("lcall","System_ThreadResume");
12595
12596         /* put result into place */
12597         {
12598                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12599                 if (rsym->liveFrom != rsym->liveTo) {   
12600                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12601                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12602                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12603                 }
12604         }
12605         unsavermask(rsave);
12606 }
12607
12608 /*-----------------------------------------------------------------*/
12609 /* genSystemProcessResume -                                        */
12610 /*-----------------------------------------------------------------*/
12611 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12612 {
12613         bitVect *rsave ;
12614         operand *pid;
12615
12616         assert (nparms==1);
12617         /* save registers that need to be saved */
12618         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12619                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12620         
12621         pid = parms[0];
12622         
12623         /* pid into ACC */
12624         aopOp(pid,ic,FALSE,FALSE);
12625         emitcode ("mov","a,%s",
12626                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12627         freeAsmop (pid, NULL, ic, FALSE);
12628         
12629         emitcode ("lcall","System_ProcessResume");
12630
12631         unsavermask(rsave);
12632 }
12633
12634 /*-----------------------------------------------------------------*/
12635 /* genSystem -                                                     */
12636 /*-----------------------------------------------------------------*/
12637 static void genSystem (iCode *ic,int nparms,char *name)
12638 {
12639         assert(nparms == 0);
12640
12641         emitcode ("lcall","System_%s",name);
12642 }
12643
12644 /*-----------------------------------------------------------------*/
12645 /* genSystemPoll -                                                  */
12646 /*-----------------------------------------------------------------*/
12647 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12648 {
12649         bitVect *rsave ;
12650         operand *fp;
12651
12652         assert (nparms==1);
12653         /* save registers that need to be saved */
12654         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12655                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12656
12657         fp = parms[0];
12658         aopOp (fp,ic,FALSE,FALSE);
12659         if (AOP_TYPE (fp) == AOP_IMMD) {
12660                 emitcode ("mov", "dptr,%s", 
12661                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12662         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12663                 emitcode ("mov","dpl,%s",
12664                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12665                 emitcode ("mov","dph,%s",
12666                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12667                 emitcode ("mov","dpx,%s",
12668                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12669         }
12670         freeAsmop (fp, NULL, ic, FALSE);
12671
12672         emitcode ("lcall","System_%sPoll",name);
12673
12674         /* put result into place */
12675         {
12676                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12677                 if (rsym->liveFrom != rsym->liveTo) {   
12678                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12679                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12680                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12681                 }
12682         }
12683         unsavermask(rsave);
12684 }
12685
12686 /*-----------------------------------------------------------------*/
12687 /* genSystemGetCurrentID -                                         */
12688 /*-----------------------------------------------------------------*/
12689 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12690 {
12691         assert (nparms==0);
12692
12693         emitcode ("lcall","System_GetCurrent%sId",name);
12694         /* put result into place */
12695         {
12696                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12697                 if (rsym->liveFrom != rsym->liveTo) {   
12698                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12699                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12700                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12701                 }
12702         }
12703 }
12704
12705 /*-----------------------------------------------------------------*/
12706 /* genDummyRead - generate code for dummy read of volatiles        */
12707 /*-----------------------------------------------------------------*/
12708 static void
12709 genDummyRead (iCode * ic)
12710 {
12711   operand *right;
12712   int size, offset;
12713
12714   D(emitcode(";     genDummyRead",""));
12715
12716   right = IC_RIGHT (ic);
12717
12718   aopOp (right, ic, FALSE, FALSE);
12719
12720   /* if the result is a bit */
12721   if (AOP_TYPE (right) == AOP_CRY)
12722     {
12723       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12724       goto release;
12725     }
12726
12727   /* bit variables done */
12728   /* general case */
12729   size = AOP_SIZE (right);
12730   offset = 0;
12731   while (size--)
12732     {
12733       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12734       offset++;
12735     }
12736
12737 release:
12738   freeAsmop (right, NULL, ic, TRUE);
12739 }
12740
12741 /*-----------------------------------------------------------------*/
12742 /* genCritical - generate code for start of a critical sequence    */
12743 /*-----------------------------------------------------------------*/
12744 static void
12745 genCritical (iCode *ic)
12746 {
12747   symbol *tlbl = newiTempLabel (NULL);
12748
12749   D(emitcode(";     genCritical",""));
12750   
12751   if (IC_RESULT (ic))
12752     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12753
12754   emitcode ("setb", "c");
12755   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12756   emitcode ("clr", "c");
12757   emitcode ("", "%05d$:", (tlbl->key + 100));
12758
12759   if (IC_RESULT (ic))
12760     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12761   else
12762     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12763
12764   if (IC_RESULT (ic))
12765     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12766 }
12767
12768 /*-----------------------------------------------------------------*/
12769 /* genEndCritical - generate code for end of a critical sequence   */
12770 /*-----------------------------------------------------------------*/
12771 static void
12772 genEndCritical (iCode *ic)
12773 {
12774   D(emitcode(";     genEndCritical",""));
12775   
12776   if (IC_RIGHT (ic))
12777     {
12778       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12779       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12780         {
12781           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12782           emitcode ("mov", "ea,c");
12783         }
12784       else
12785         {
12786           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12787           emitcode ("rrc", "a");
12788           emitcode ("mov", "ea,c");
12789         }
12790       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12791     }
12792   else
12793     {
12794       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12795       emitcode ("mov", "ea,c");
12796     }
12797 }
12798
12799
12800
12801 /*-----------------------------------------------------------------*/
12802 /* genBuiltIn - calls the appropriate function to  generating code */
12803 /* for a built in function                                         */
12804 /*-----------------------------------------------------------------*/
12805 static void genBuiltIn (iCode *ic)
12806 {
12807         operand *bi_parms[MAX_BUILTIN_ARGS];
12808         int nbi_parms;
12809         iCode *bi_iCode;
12810         symbol *bif;
12811
12812         /* get all the arguments for a built in function */
12813         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12814
12815         /* which function is it */
12816         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12817         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12818                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12819         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12820                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12821         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12822                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12823         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12824                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12825         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12826                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12827         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12828                 genInp(bi_iCode,nbi_parms,bi_parms);
12829         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12830                 genOutp(bi_iCode,nbi_parms,bi_parms);
12831         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12832                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12833                 /* JavaNative builtIns */               
12834         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12835                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12836         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12837                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12838         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12839                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12840         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12841                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12842         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12843                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12844         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12845                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12846         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12847                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12848         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12849                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12850         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12851                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12852         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12853                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12854         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12855                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12856         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12857                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12858         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12859                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12860         } else if (strcmp(bif->name,"MM_Free")==0) {
12861                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12862         } else if (strcmp(bif->name,"MM_Deref")==0) {
12863                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12864         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12865                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12866         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12867                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12868         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12869                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12870         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12871                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12872         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12873                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12874         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12875                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12876         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12877                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12878         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12879                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12880         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12881                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12882         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12883                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12884         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12885                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12886         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12887                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12888         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12889                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12890         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12891                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12892         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12893                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12894         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12895                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12896         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12897                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12898         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12899                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12900         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12901                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12902         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12903                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12904         } else {
12905                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12906                 return ;
12907         }
12908         return ;    
12909 }
12910
12911 /*-----------------------------------------------------------------*/
12912 /* gen390Code - generate code for Dallas 390 based controllers     */
12913 /*-----------------------------------------------------------------*/
12914 void
12915 gen390Code (iCode * lic)
12916 {
12917   iCode *ic;
12918   int cln = 0;
12919
12920   lineHead = lineCurr = NULL;
12921   dptrn[1][0] = "dpl1";
12922   dptrn[1][1] = "dph1";
12923   dptrn[1][2] = "dpx1";
12924   
12925   if (options.model == MODEL_FLAT24) {
12926     fReturnSizeDS390 = 5;
12927     fReturn = fReturn24;
12928   } else {
12929     fReturnSizeDS390 = 4;
12930     fReturn = fReturn16;
12931     options.stack10bit=0;
12932   }
12933 #if 1
12934   /* print the allocation information */
12935   if (allocInfo && currFunc)
12936     printAllocInfo (currFunc, codeOutFile);
12937 #endif
12938   /* if debug information required */
12939   if (options.debug && currFunc)
12940     {
12941       debugFile->writeFunction(currFunc);
12942       _G.debugLine = 1;
12943       if (IS_STATIC (currFunc->etype))
12944         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12945       else
12946         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12947       _G.debugLine = 0;
12948     }
12949   /* stack pointer name */
12950   if (options.useXstack)
12951     spname = "_spx";
12952   else
12953     spname = "sp";
12954
12955
12956   for (ic = lic; ic; ic = ic->next)
12957     {
12958
12959       if (ic->lineno && cln != ic->lineno)
12960         {
12961           if (options.debug)
12962             {
12963               _G.debugLine = 1;
12964               emitcode ("", "C$%s$%d$%d$%d ==.",
12965                         FileBaseName (ic->filename), ic->lineno,
12966                         ic->level, ic->block);
12967               _G.debugLine = 0;
12968             }
12969           if (!options.noCcodeInAsm) {
12970             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12971                       printCLine(ic->filename, ic->lineno));
12972           }
12973           cln = ic->lineno;
12974         }
12975       if (options.iCodeInAsm) {
12976         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12977       }
12978       /* if the result is marked as
12979          spilt and rematerializable or code for
12980          this has already been generated then
12981          do nothing */
12982       if (resultRemat (ic) || ic->generated)
12983         continue;
12984
12985       /* depending on the operation */
12986       switch (ic->op)
12987         {
12988         case '!':
12989           genNot (ic);
12990           break;
12991
12992         case '~':
12993           genCpl (ic);
12994           break;
12995
12996         case UNARYMINUS:
12997           genUminus (ic);
12998           break;
12999
13000         case IPUSH:
13001           genIpush (ic);
13002           break;
13003
13004         case IPOP:
13005           /* IPOP happens only when trying to restore a
13006              spilt live range, if there is an ifx statement
13007              following this pop then the if statement might
13008              be using some of the registers being popped which
13009              would destory the contents of the register so
13010              we need to check for this condition and handle it */
13011           if (ic->next &&
13012               ic->next->op == IFX &&
13013               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13014             genIfx (ic->next, ic);
13015           else
13016             genIpop (ic);
13017           break;
13018
13019         case CALL:
13020           genCall (ic);
13021           break;
13022
13023         case PCALL:
13024           genPcall (ic);
13025           break;
13026
13027         case FUNCTION:
13028           genFunction (ic);
13029           break;
13030
13031         case ENDFUNCTION:
13032           genEndFunction (ic);
13033           break;
13034
13035         case RETURN:
13036           genRet (ic);
13037           break;
13038
13039         case LABEL:
13040           genLabel (ic);
13041           break;
13042
13043         case GOTO:
13044           genGoto (ic);
13045           break;
13046
13047         case '+':
13048           genPlus (ic);
13049           break;
13050
13051         case '-':
13052           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13053             genMinus (ic);
13054           break;
13055
13056         case '*':
13057           genMult (ic);
13058           break;
13059
13060         case '/':
13061           genDiv (ic);
13062           break;
13063
13064         case '%':
13065           genMod (ic);
13066           break;
13067
13068         case '>':
13069           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13070           break;
13071
13072         case '<':
13073           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13074           break;
13075
13076         case LE_OP:
13077         case GE_OP:
13078         case NE_OP:
13079
13080           /* note these two are xlated by algebraic equivalence
13081              during parsing SDCC.y */
13082           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13083                   "got '>=' or '<=' shouldn't have come here");
13084           break;
13085
13086         case EQ_OP:
13087           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13088           break;
13089
13090         case AND_OP:
13091           genAndOp (ic);
13092           break;
13093
13094         case OR_OP:
13095           genOrOp (ic);
13096           break;
13097
13098         case '^':
13099           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13100           break;
13101
13102         case '|':
13103           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13104           break;
13105
13106         case BITWISEAND:
13107           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13108           break;
13109
13110         case INLINEASM:
13111           genInline (ic);
13112           break;
13113
13114         case RRC:
13115           genRRC (ic);
13116           break;
13117
13118         case RLC:
13119           genRLC (ic);
13120           break;
13121
13122         case GETHBIT:
13123           genGetHbit (ic);
13124           break;
13125
13126         case LEFT_OP:
13127           genLeftShift (ic);
13128           break;
13129
13130         case RIGHT_OP:
13131           genRightShift (ic);
13132           break;
13133
13134         case GET_VALUE_AT_ADDRESS:
13135           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13136           break;
13137
13138         case '=':
13139           if (POINTER_SET (ic))
13140             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13141           else
13142             genAssign (ic);
13143           break;
13144
13145         case IFX:
13146           genIfx (ic, NULL);
13147           break;
13148
13149         case ADDRESS_OF:
13150           genAddrOf (ic);
13151           break;
13152
13153         case JUMPTABLE:
13154           genJumpTab (ic);
13155           break;
13156
13157         case CAST:
13158           genCast (ic);
13159           break;
13160
13161         case RECEIVE:
13162           genReceive (ic);
13163           break;
13164
13165         case SEND:
13166           if (ic->builtinSEND) genBuiltIn(ic);
13167           else addSet (&_G.sendSet, ic);
13168           break;
13169
13170         case DUMMY_READ_VOLATILE:
13171           genDummyRead (ic);
13172           break;
13173
13174         case CRITICAL:
13175           genCritical (ic);
13176           break;
13177
13178         case ENDCRITICAL:
13179           genEndCritical (ic);
13180           break;
13181         
13182         case SWAP:
13183           genSwap (ic);
13184           break;
13185           
13186 #if 0 // obsolete, and buggy for != xdata
13187         case ARRAYINIT:
13188             genArrayInit(ic);
13189             break;
13190 #endif
13191             
13192         default:
13193           ic = ic;
13194         }
13195     }
13196
13197
13198   /* now we are ready to call the
13199      peep hole optimizer */
13200   if (!options.nopeep)
13201     peepHole (&lineHead);
13202
13203   /* now do the actual printing */
13204   printLine (lineHead, codeOutFile);
13205   return;
13206 }