* src/SDCCopt.c (killDeadCode): change iCode type to DUMMY_READ_VOLATILE
[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               else
6391                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6392               goto release;
6393             }
6394         }
6395       outBitC (result);
6396       goto release;
6397     }
6398
6399   /* if left is same as result */
6400   if (sameRegs (AOP (result), AOP (left)))
6401     {
6402       for (; size--; offset++)
6403         {
6404           if (AOP_TYPE (right) == AOP_LIT)
6405             {
6406               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6407                 continue;
6408               else if (bytelit == 0)
6409                 aopPut (AOP (result), zero, offset);
6410               else if (IS_AOP_PREG (result))
6411                 {
6412                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6413                   emitcode ("anl", "a,%s",
6414                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6415                   aopPut (AOP (result), "a", offset);
6416                 }
6417               else
6418                 emitcode ("anl", "%s,%s",
6419                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6420                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421             }
6422           else
6423             {
6424               if (AOP_TYPE (left) == AOP_ACC)
6425                 emitcode ("anl", "a,%s",
6426                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6427               else
6428                 {
6429                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6430                   if (IS_AOP_PREG (result))
6431                     {
6432                       emitcode ("anl", "a,%s",
6433                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6434                       aopPut (AOP (result), "a", offset);
6435                     }
6436                   else
6437                     emitcode ("anl", "%s,a",
6438                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6439                 }
6440             }
6441         }
6442     }
6443   else
6444     {
6445       // left & result in different registers
6446       if (AOP_TYPE (result) == AOP_CRY)
6447         {
6448           // result = bit
6449           // if(size), result in bit
6450           // if(!size && ifx), conditional oper: if(left & right)
6451           symbol *tlbl = newiTempLabel (NULL);
6452           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6453           if (size)
6454             emitcode ("setb", "c");
6455           while (sizer--)
6456             {
6457               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6458                 emitcode ("anl", "a,%s",
6459                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6460               } else {
6461                 if (AOP_TYPE(left)==AOP_ACC) {
6462                   emitcode("mov", "b,a");
6463                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6464                   emitcode("anl", "a,b");
6465                 }else {
6466                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6467                   emitcode ("anl", "a,%s",
6468                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6469                 }
6470               }
6471               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6472               offset++;
6473             }
6474           if (size)
6475             {
6476               CLRC;
6477               emitcode ("", "!tlabeldef", tlbl->key + 100);
6478               outBitC (result);
6479             }
6480           else if (ifx)
6481             jmpTrueOrFalse (ifx, tlbl);
6482           else
6483             emitcode ("", "!tlabeldef", tlbl->key + 100);
6484         }
6485       else
6486         {
6487           for (; (size--); offset++)
6488             {
6489               // normal case
6490               // result = left & right
6491               if (AOP_TYPE (right) == AOP_LIT)
6492                 {
6493                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6494                     {
6495                       aopPut (AOP (result),
6496                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6497                               offset);
6498                       continue;
6499                     }
6500                   else if (bytelit == 0)
6501                     {
6502                       aopPut (AOP (result), zero, offset);
6503                       continue;
6504                     }
6505                   D (emitcode (";", "better literal AND."););
6506                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6507                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6508                                                     FALSE, FALSE, DP2_RESULT_REG));
6509
6510                 }
6511               else
6512                 {
6513                   // faster than result <- left, anl result,right
6514                   // and better if result is SFR
6515                   if (AOP_TYPE (left) == AOP_ACC)
6516                     {
6517                       emitcode ("anl", "a,%s", 
6518                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6519                     }
6520                   else
6521                     {
6522                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6523                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6524                       {
6525                           emitcode("mov", "b,a");
6526                           rOp = "b";
6527                       }
6528                         
6529                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6530                       emitcode ("anl", "a,%s", rOp);
6531                     }                   
6532                 }
6533               aopPut (AOP (result), "a", offset);
6534             }
6535         }
6536     }
6537
6538 release:
6539   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6540   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6541   freeAsmop (result, NULL, ic, TRUE);
6542 }
6543
6544
6545 /*-----------------------------------------------------------------*/
6546 /* genOr  - code for or                                            */
6547 /*-----------------------------------------------------------------*/
6548 static void
6549 genOr (iCode * ic, iCode * ifx)
6550 {
6551   operand *left, *right, *result;
6552   int size, offset = 0;
6553   unsigned long lit = 0L;
6554   bool     pushResult;
6555
6556   D (emitcode (";", "genOr "););
6557
6558   AOP_OP_3_NOFATAL (ic, pushResult);
6559   AOP_SET_LOCALS (ic);
6560
6561   if (pushResult)
6562   {
6563       genFarFarLogicOp(ic, "orl");
6564       return;
6565   }
6566
6567
6568 #ifdef DEBUG_TYPE
6569   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6570             AOP_TYPE (result),
6571             AOP_TYPE (left), AOP_TYPE (right));
6572   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6573             AOP_SIZE (result),
6574             AOP_SIZE (left), AOP_SIZE (right));
6575 #endif
6576
6577   /* if left is a literal & right is not then exchange them */
6578   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6579 #ifdef LOGIC_OPS_BROKEN
6580    || AOP_NEEDSACC (left) // I think this is a net loss now.
6581 #endif      
6582       )
6583     {
6584       operand *tmp = right;
6585       right = left;
6586       left = tmp;
6587     }
6588
6589   /* if result = right then exchange them */
6590   if (sameRegs (AOP (result), AOP (right)))
6591     {
6592       operand *tmp = right;
6593       right = left;
6594       left = tmp;
6595     }
6596
6597   /* if right is bit then exchange them */
6598   if (AOP_TYPE (right) == AOP_CRY &&
6599       AOP_TYPE (left) != AOP_CRY)
6600     {
6601       operand *tmp = right;
6602       right = left;
6603       left = tmp;
6604     }
6605   if (AOP_TYPE (right) == AOP_LIT)
6606     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6607
6608   size = AOP_SIZE (result);
6609
6610   // if(bit | yy)
6611   // xx = bit | yy;
6612   if (AOP_TYPE (left) == AOP_CRY)
6613     {
6614       if (AOP_TYPE (right) == AOP_LIT)
6615         {
6616           // c = bit & literal;
6617           if (lit)
6618             {
6619               // lit != 0 => result = 1
6620               if (AOP_TYPE (result) == AOP_CRY)
6621                 {
6622                   if (size)
6623                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6624                   else if (ifx)
6625                     continueIfTrue (ifx);
6626                   goto release;
6627                 }
6628               emitcode ("setb", "c");
6629             }
6630           else
6631             {
6632               // lit == 0 => result = left
6633               if (size && sameRegs (AOP (result), AOP (left)))
6634                 goto release;
6635               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6636             }
6637         }
6638       else
6639         {
6640           if (AOP_TYPE (right) == AOP_CRY)
6641             {
6642               // c = bit | bit;
6643               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6644               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6645             }
6646           else
6647             {
6648               // c = bit | val;
6649               symbol *tlbl = newiTempLabel (NULL);
6650               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6651                 emitcode ("setb", "c");
6652               emitcode ("jb", "%s,!tlabel",
6653                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6654               toBoolean (right);
6655               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6656               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6657                 {
6658                   jmpTrueOrFalse (ifx, tlbl);
6659                   goto release;
6660                 }
6661               else
6662                 {
6663                   CLRC;
6664                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6665                 }
6666             }
6667         }
6668       // bit = c
6669       // val = c
6670       if (size)
6671         outBitC (result);
6672       // if(bit | ...)
6673       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6674            genIfxJump (ifx, "c");
6675       goto release;
6676     }
6677
6678   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6679   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6680   if ((AOP_TYPE (right) == AOP_LIT) &&
6681       (AOP_TYPE (result) == AOP_CRY) &&
6682       (AOP_TYPE (left) != AOP_CRY))
6683     {
6684       if (lit)
6685         {
6686           // result = 1
6687           if (size)
6688             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6689           else
6690             continueIfTrue (ifx);
6691           goto release;
6692         }
6693       else
6694         {
6695           // lit = 0, result = boolean(left)
6696           if (size)
6697             emitcode ("setb", "c");
6698           toBoolean (right);
6699           if (size)
6700             {
6701               symbol *tlbl = newiTempLabel (NULL);
6702               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6703               CLRC;
6704               emitcode ("", "!tlabeldef", tlbl->key + 100);
6705             }
6706           else
6707             {
6708               genIfxJump (ifx, "a");
6709               goto release;
6710             }
6711         }
6712       outBitC (result);
6713       goto release;
6714     }
6715
6716   /* if left is same as result */
6717   if (sameRegs (AOP (result), AOP (left)))
6718     {
6719       for (; size--; offset++)
6720         {
6721           if (AOP_TYPE (right) == AOP_LIT)
6722             {
6723               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6724                 {
6725                   continue;
6726                 }
6727               else
6728                 {
6729                   if (IS_AOP_PREG (left))
6730                     {
6731                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6732                       emitcode ("orl", "a,%s",
6733                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6734                       aopPut (AOP (result), "a", offset);
6735                     }
6736                   else
6737                     {
6738                       emitcode ("orl", "%s,%s",
6739                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6740                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6741                     }
6742                 }
6743             }
6744           else
6745             {
6746               if (AOP_TYPE (left) == AOP_ACC)
6747                 {
6748                   emitcode ("orl", "a,%s",
6749                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6750                 }
6751               else
6752                 {
6753                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6754                   if (IS_AOP_PREG (left))
6755                     {
6756                       emitcode ("orl", "a,%s", 
6757                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6758                       aopPut (AOP (result), "a", offset);
6759                     }
6760                   else
6761                     {
6762                       emitcode ("orl", "%s,a",
6763                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6764                     }
6765                 }
6766             }
6767         }
6768     }
6769   else
6770     {
6771       // left & result in different registers
6772       if (AOP_TYPE (result) == AOP_CRY)
6773         {
6774           // result = bit
6775           // if(size), result in bit
6776           // if(!size && ifx), conditional oper: if(left | right)
6777           symbol *tlbl = newiTempLabel (NULL);
6778           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6779           if (size)
6780             emitcode ("setb", "c");
6781           while (sizer--)
6782             {
6783               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6784                 emitcode ("orl", "a,%s",
6785                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6786               } else {
6787                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6788                 emitcode ("orl", "a,%s",
6789                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6790               }
6791               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6792               offset++;
6793             }
6794           if (size)
6795             {
6796               CLRC;
6797               emitcode ("", "!tlabeldef", tlbl->key + 100);
6798               outBitC (result);
6799             }
6800           else if (ifx)
6801             jmpTrueOrFalse (ifx, tlbl);
6802           else
6803             emitcode ("", "!tlabeldef", tlbl->key + 100);
6804         }
6805       else
6806         {
6807             _startLazyDPSEvaluation();
6808           for (; (size--); offset++)
6809             {
6810               // normal case
6811               // result = left & right
6812               if (AOP_TYPE (right) == AOP_LIT)
6813                 {
6814                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6815                     {
6816                       aopPut (AOP (result),
6817                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6818                               offset);
6819                       continue;
6820                     }
6821                   D (emitcode (";", "better literal OR."););
6822                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6823                   emitcode ("orl", "a, %s",
6824                             aopGet (AOP (right), offset,
6825                                     FALSE, FALSE, DP2_RESULT_REG));
6826
6827                 }
6828               else
6829                 {
6830                   // faster than result <- left, anl result,right
6831                   // and better if result is SFR
6832                   if (AOP_TYPE (left) == AOP_ACC)
6833                     {
6834                       emitcode ("orl", "a,%s",
6835                                 aopGet (AOP (right), offset,
6836                                         FALSE, FALSE, DP2_RESULT_REG));
6837                     }
6838                   else
6839                     {
6840                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6841                         
6842                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6843                       {
6844                           emitcode("mov", "b,a");
6845                           rOp = "b";
6846                       }
6847                         
6848                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6849                       emitcode ("orl", "a,%s", rOp);
6850                     }
6851                 }
6852               aopPut (AOP (result), "a", offset);
6853             }
6854             _endLazyDPSEvaluation();
6855         }
6856     }
6857
6858 release:
6859   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6860   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6861   freeAsmop (result, NULL, ic, TRUE);
6862 }
6863
6864 /*-----------------------------------------------------------------*/
6865 /* genXor - code for xclusive or                                   */
6866 /*-----------------------------------------------------------------*/
6867 static void
6868 genXor (iCode * ic, iCode * ifx)
6869 {
6870   operand *left, *right, *result;
6871   int size, offset = 0;
6872   unsigned long lit = 0L;
6873   bool pushResult;
6874
6875   D (emitcode (";", "genXor "););
6876
6877   AOP_OP_3_NOFATAL (ic, pushResult);
6878   AOP_SET_LOCALS (ic);
6879
6880   if (pushResult)
6881   {
6882       genFarFarLogicOp(ic, "xrl");
6883       return;
6884   }  
6885
6886 #ifdef DEBUG_TYPE
6887   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6888             AOP_TYPE (result),
6889             AOP_TYPE (left), AOP_TYPE (right));
6890   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6891             AOP_SIZE (result),
6892             AOP_SIZE (left), AOP_SIZE (right));
6893 #endif
6894
6895   /* if left is a literal & right is not ||
6896      if left needs acc & right does not */
6897   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6898 #ifdef LOGIC_OPS_BROKEN      
6899       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6900 #endif
6901      )
6902     {
6903       operand *tmp = right;
6904       right = left;
6905       left = tmp;
6906     }
6907
6908   /* if result = right then exchange them */
6909   if (sameRegs (AOP (result), AOP (right)))
6910     {
6911       operand *tmp = right;
6912       right = left;
6913       left = tmp;
6914     }
6915
6916   /* if right is bit then exchange them */
6917   if (AOP_TYPE (right) == AOP_CRY &&
6918       AOP_TYPE (left) != AOP_CRY)
6919     {
6920       operand *tmp = right;
6921       right = left;
6922       left = tmp;
6923     }
6924   if (AOP_TYPE (right) == AOP_LIT)
6925     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6926
6927   size = AOP_SIZE (result);
6928
6929   // if(bit ^ yy)
6930   // xx = bit ^ yy;
6931   if (AOP_TYPE (left) == AOP_CRY)
6932     {
6933       if (AOP_TYPE (right) == AOP_LIT)
6934         {
6935           // c = bit & literal;
6936           if (lit >> 1)
6937             {
6938               // lit>>1  != 0 => result = 1
6939               if (AOP_TYPE (result) == AOP_CRY)
6940                 {
6941                   if (size)
6942                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6943                   else if (ifx)
6944                     continueIfTrue (ifx);
6945                   goto release;
6946                 }
6947               emitcode ("setb", "c");
6948             }
6949           else
6950             {
6951               // lit == (0 or 1)
6952               if (lit == 0)
6953                 {
6954                   // lit == 0, result = left
6955                   if (size && sameRegs (AOP (result), AOP (left)))
6956                     goto release;
6957                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6958                 }
6959               else
6960                 {
6961                   // lit == 1, result = not(left)
6962                   if (size && sameRegs (AOP (result), AOP (left)))
6963                     {
6964                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6965                       goto release;
6966                     }
6967                   else
6968                     {
6969                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6970                       emitcode ("cpl", "c");
6971                     }
6972                 }
6973             }
6974
6975         }
6976       else
6977         {
6978           // right != literal
6979           symbol *tlbl = newiTempLabel (NULL);
6980           if (AOP_TYPE (right) == AOP_CRY)
6981             {
6982               // c = bit ^ bit;
6983               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6984             }
6985           else
6986             {
6987               int sizer = AOP_SIZE (right);
6988               // c = bit ^ val
6989               // if val>>1 != 0, result = 1
6990               emitcode ("setb", "c");
6991               while (sizer)
6992                 {
6993                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6994                   if (sizer == 1)
6995                     // test the msb of the lsb
6996                     emitcode ("anl", "a,#!constbyte",0xfe);
6997                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6998                   sizer--;
6999                 }
7000               // val = (0,1)
7001               emitcode ("rrc", "a");
7002             }
7003           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7004           emitcode ("cpl", "c");
7005           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7006         }
7007       // bit = c
7008       // val = c
7009       if (size)
7010         outBitC (result);
7011       // if(bit | ...)
7012       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7013         genIfxJump (ifx, "c");
7014       goto release;
7015     }
7016
7017   if (sameRegs (AOP (result), AOP (left)))
7018     {
7019       /* if left is same as result */
7020       for (; size--; offset++)
7021         {
7022           if (AOP_TYPE (right) == AOP_LIT)
7023             {
7024               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7025                 continue;
7026               else if (IS_AOP_PREG (left))
7027                 {
7028                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7029                   emitcode ("xrl", "a,%s",
7030                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7031                   aopPut (AOP (result), "a", offset);
7032                 }
7033               else
7034                 emitcode ("xrl", "%s,%s",
7035                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7036                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7037             }
7038           else
7039             {
7040               if (AOP_TYPE (left) == AOP_ACC)
7041                 emitcode ("xrl", "a,%s",
7042                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7043               else
7044                 {
7045                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7046                   if (IS_AOP_PREG (left))
7047                     {
7048                       emitcode ("xrl", "a,%s",
7049                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7050                       aopPut (AOP (result), "a", offset);
7051                     }
7052                   else
7053                     emitcode ("xrl", "%s,a",
7054                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7055                 }
7056             }
7057         }
7058     }
7059   else
7060     {
7061       // left & result in different registers
7062       if (AOP_TYPE (result) == AOP_CRY)
7063         {
7064           // result = bit
7065           // if(size), result in bit
7066           // if(!size && ifx), conditional oper: if(left ^ right)
7067           symbol *tlbl = newiTempLabel (NULL);
7068           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7069                   
7070           if (size)
7071             emitcode ("setb", "c");
7072           while (sizer--)
7073             {
7074               if ((AOP_TYPE (right) == AOP_LIT) &&
7075                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7076                 {
7077                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7078                 }
7079               else
7080                 {
7081                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7082                     emitcode ("xrl", "a,%s",
7083                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7084                   } else {
7085                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7086                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7087                       {
7088                           emitcode("mov", "b,a");
7089                           rOp = "b";
7090                       }
7091                         
7092                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7093                       emitcode ("xrl", "a,%s", rOp);                  
7094                   }
7095                 }
7096               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7097               offset++;
7098             }
7099           if (size)
7100             {
7101               CLRC;
7102               emitcode ("", "!tlabeldef", tlbl->key + 100);
7103               outBitC (result);
7104             }
7105           else if (ifx)
7106             jmpTrueOrFalse (ifx, tlbl);
7107         }
7108       else
7109         {
7110         for (; (size--); offset++)
7111           {
7112             // normal case
7113             // result = left & right
7114             if (AOP_TYPE (right) == AOP_LIT)
7115               {
7116                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7117                   {
7118                     aopPut (AOP (result),
7119                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7120                             offset);
7121                     continue;
7122                   }
7123                 D (emitcode (";", "better literal XOR."););
7124                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7125                 emitcode ("xrl", "a, %s",
7126                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7127               }
7128             else
7129               {
7130                 // faster than result <- left, anl result,right
7131                 // and better if result is SFR
7132                 if (AOP_TYPE (left) == AOP_ACC)
7133                   {
7134                     emitcode ("xrl", "a,%s",
7135                               aopGet (AOP (right), offset,
7136                                       FALSE, FALSE, DP2_RESULT_REG));
7137                   }
7138                 else
7139                   {
7140                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7141                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7142                       {
7143                           emitcode("mov", "b,a");
7144                           rOp = "b";
7145                       }
7146                         
7147                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7148                       emitcode ("xrl", "a,%s", rOp);
7149                   }
7150               }
7151             aopPut (AOP (result), "a", offset);
7152           }
7153         }
7154         
7155     }
7156
7157 release:
7158   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7159   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7160   freeAsmop (result, NULL, ic, TRUE);
7161 }
7162
7163 /*-----------------------------------------------------------------*/
7164 /* genInline - write the inline code out                           */
7165 /*-----------------------------------------------------------------*/
7166 static void
7167 genInline (iCode * ic)
7168 {
7169   char *buffer, *bp, *bp1;
7170
7171   D (emitcode (";", "genInline "); );
7172
7173   _G.inLine += (!options.asmpeep);
7174
7175   buffer = Safe_strdup(IC_INLINE(ic));
7176   bp = buffer;
7177   bp1 = buffer;
7178
7179   /* emit each line as a code */
7180   while (*bp)
7181     {
7182       if (*bp == '\n')
7183         {
7184           *bp++ = '\0';
7185           emitcode (bp1, "");
7186           bp1 = bp;
7187         }
7188       else
7189         {
7190           if (*bp == ':')
7191             {
7192               bp++;
7193               *bp = '\0';
7194               bp++;
7195               emitcode (bp1, "");
7196               bp1 = bp;
7197             }
7198           else
7199             bp++;
7200         }
7201     }
7202   if (bp1 != bp)
7203     emitcode (bp1, "");
7204   /*     emitcode("",buffer); */
7205   _G.inLine -= (!options.asmpeep);
7206 }
7207
7208 /*-----------------------------------------------------------------*/
7209 /* genRRC - rotate right with carry                                */
7210 /*-----------------------------------------------------------------*/
7211 static void
7212 genRRC (iCode * ic)
7213 {
7214   operand *left, *result;
7215   int     size, offset;
7216
7217   D (emitcode (";", "genRRC "););
7218
7219   /* rotate right with carry */
7220   left = IC_LEFT (ic);
7221   result = IC_RESULT (ic);
7222   aopOp (left, ic, FALSE, FALSE);
7223   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7224
7225   /* move it to the result */
7226   size = AOP_SIZE (result);
7227   offset = size - 1;
7228   CLRC;
7229
7230   _startLazyDPSEvaluation ();
7231   while (size--)
7232     {
7233       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7234       emitcode ("rrc", "a");
7235       if (AOP_SIZE (result) > 1)
7236         aopPut (AOP (result), "a", offset--);
7237     }
7238   _endLazyDPSEvaluation ();
7239
7240   /* now we need to put the carry into the
7241      highest order byte of the result */
7242   if (AOP_SIZE (result) > 1)
7243     {
7244       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7245     }
7246   emitcode ("mov", "acc.7,c");
7247   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7248   freeAsmop (left, NULL, ic, TRUE);
7249   freeAsmop (result, NULL, ic, TRUE);
7250 }
7251
7252 /*-----------------------------------------------------------------*/
7253 /* genRLC - generate code for rotate left with carry               */
7254 /*-----------------------------------------------------------------*/
7255 static void
7256 genRLC (iCode * ic)
7257 {
7258   operand *left, *result;
7259   int size, offset;
7260   char *l;
7261
7262   D (emitcode (";", "genRLC "););
7263
7264   /* rotate right with carry */
7265   left = IC_LEFT (ic);
7266   result = IC_RESULT (ic);
7267   aopOp (left, ic, FALSE, FALSE);
7268   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7269
7270   /* move it to the result */
7271   size = AOP_SIZE (result);
7272   offset = 0;
7273   if (size--)
7274     {
7275       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7276       MOVA (l);
7277       emitcode ("add", "a,acc");
7278       if (AOP_SIZE (result) > 1)
7279         {
7280           aopPut (AOP (result), "a", offset++);
7281         }
7282
7283       _startLazyDPSEvaluation ();
7284       while (size--)
7285         {
7286           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7287           MOVA (l);
7288           emitcode ("rlc", "a");
7289           if (AOP_SIZE (result) > 1)
7290             aopPut (AOP (result), "a", offset++);
7291         }
7292       _endLazyDPSEvaluation ();
7293     }
7294   /* now we need to put the carry into the
7295      highest order byte of the result */
7296   if (AOP_SIZE (result) > 1)
7297     {
7298       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7299       MOVA (l);
7300     }
7301   emitcode ("mov", "acc.0,c");
7302   aopPut (AOP (result), "a", 0);
7303   freeAsmop (left, NULL, ic, TRUE);
7304   freeAsmop (result, NULL, ic, TRUE);
7305 }
7306
7307 /*-----------------------------------------------------------------*/
7308 /* genGetHbit - generates code get highest order bit               */
7309 /*-----------------------------------------------------------------*/
7310 static void
7311 genGetHbit (iCode * ic)
7312 {
7313   operand *left, *result;
7314   left = IC_LEFT (ic);
7315   result = IC_RESULT (ic);
7316   aopOp (left, ic, FALSE, FALSE);
7317   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7318
7319   D (emitcode (";", "genGetHbit "););
7320
7321   /* get the highest order byte into a */
7322   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7323   if (AOP_TYPE (result) == AOP_CRY)
7324     {
7325       emitcode ("rlc", "a");
7326       outBitC (result);
7327     }
7328   else
7329     {
7330       emitcode ("rl", "a");
7331       emitcode ("anl", "a,#1");
7332       outAcc (result);
7333     }
7334
7335
7336   freeAsmop (left, NULL, ic, TRUE);
7337   freeAsmop (result, NULL, ic, TRUE);
7338 }
7339
7340 /*-----------------------------------------------------------------*/
7341 /* genSwap - generates code to swap nibbles or bytes               */
7342 /*-----------------------------------------------------------------*/
7343 static void
7344 genSwap (iCode * ic)
7345 {
7346   operand *left, *result;
7347
7348   D(emitcode (";     genSwap",""));
7349
7350   left = IC_LEFT (ic);
7351   result = IC_RESULT (ic);
7352   aopOp (left, ic, FALSE, FALSE);
7353   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7354   
7355   _startLazyDPSEvaluation ();
7356   switch (AOP_SIZE (left))
7357     {
7358     case 1: /* swap nibbles in byte */
7359       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7360       emitcode ("swap", "a");
7361       aopPut (AOP (result), "a", 0);
7362       break;
7363     case 2: /* swap bytes in word */
7364       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7365         {
7366           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7367           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7368           aopPut (AOP (result), "a", 1);
7369         }
7370       else if (operandsEqu (left, result))
7371         {
7372           char * reg = "a";
7373           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7374           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7375             {
7376               emitcode ("mov", "b,a");
7377               reg = "b";
7378               _G.bInUse=1;
7379             }
7380           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7381           aopPut (AOP (result), reg, 1);
7382           _G.bInUse=0;
7383         }
7384       else
7385         {
7386           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7387           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7388         }
7389       break;
7390     default:
7391       wassertl(FALSE, "unsupported SWAP operand size");
7392     }
7393   _endLazyDPSEvaluation ();
7394   
7395   freeAsmop (left, NULL, ic, TRUE);
7396   freeAsmop (result, NULL, ic, TRUE);
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* AccRol - rotate left accumulator by known count                 */
7401 /*-----------------------------------------------------------------*/
7402 static void
7403 AccRol (int shCount)
7404 {
7405   shCount &= 0x0007;            // shCount : 0..7
7406
7407   switch (shCount)
7408     {
7409     case 0:
7410       break;
7411     case 1:
7412       emitcode ("rl", "a");
7413       break;
7414     case 2:
7415       emitcode ("rl", "a");
7416       emitcode ("rl", "a");
7417       break;
7418     case 3:
7419       emitcode ("swap", "a");
7420       emitcode ("rr", "a");
7421       break;
7422     case 4:
7423       emitcode ("swap", "a");
7424       break;
7425     case 5:
7426       emitcode ("swap", "a");
7427       emitcode ("rl", "a");
7428       break;
7429     case 6:
7430       emitcode ("rr", "a");
7431       emitcode ("rr", "a");
7432       break;
7433     case 7:
7434       emitcode ("rr", "a");
7435       break;
7436     }
7437 }
7438
7439 /*-----------------------------------------------------------------*/
7440 /* AccLsh - left shift accumulator by known count                  */
7441 /*-----------------------------------------------------------------*/
7442 static void
7443 AccLsh (int shCount)
7444 {
7445   if (shCount != 0)
7446     {
7447       if (shCount == 1)
7448         emitcode ("add", "a,acc");
7449       else if (shCount == 2)
7450         {
7451           emitcode ("add", "a,acc");
7452           emitcode ("add", "a,acc");
7453         }
7454       else
7455         {
7456           /* rotate left accumulator */
7457           AccRol (shCount);
7458           /* and kill the lower order bits */
7459           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7460         }
7461     }
7462 }
7463
7464 /*-----------------------------------------------------------------*/
7465 /* AccRsh - right shift accumulator by known count                 */
7466 /*-----------------------------------------------------------------*/
7467 static void
7468 AccRsh (int shCount)
7469 {
7470   if (shCount != 0)
7471     {
7472       if (shCount == 1)
7473         {
7474           CLRC;
7475           emitcode ("rrc", "a");
7476         }
7477       else
7478         {
7479           /* rotate right accumulator */
7480           AccRol (8 - shCount);
7481           /* and kill the higher order bits */
7482           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7483         }
7484     }
7485 }
7486
7487 #ifdef BETTER_LITERAL_SHIFT
7488 /*-----------------------------------------------------------------*/
7489 /* AccSRsh - signed right shift accumulator by known count                 */
7490 /*-----------------------------------------------------------------*/
7491 static void
7492 AccSRsh (int shCount)
7493 {
7494   symbol *tlbl;
7495   if (shCount != 0)
7496     {
7497       if (shCount == 1)
7498         {
7499           emitcode ("mov", "c,acc.7");
7500           emitcode ("rrc", "a");
7501         }
7502       else if (shCount == 2)
7503         {
7504           emitcode ("mov", "c,acc.7");
7505           emitcode ("rrc", "a");
7506           emitcode ("mov", "c,acc.7");
7507           emitcode ("rrc", "a");
7508         }
7509       else
7510         {
7511           tlbl = newiTempLabel (NULL);
7512           /* rotate right accumulator */
7513           AccRol (8 - shCount);
7514           /* and kill the higher order bits */
7515           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7516           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7517           emitcode ("orl", "a,#!constbyte",
7518                     (unsigned char) ~SRMask[shCount]);
7519           emitcode ("", "!tlabeldef", tlbl->key + 100);
7520         }
7521     }
7522 }
7523 #endif
7524
7525 #ifdef BETTER_LITERAL_SHIFT
7526 /*-----------------------------------------------------------------*/
7527 /* shiftR1Left2Result - shift right one byte from left to result   */
7528 /*-----------------------------------------------------------------*/
7529 static void
7530 shiftR1Left2Result (operand * left, int offl,
7531                     operand * result, int offr,
7532                     int shCount, int sign)
7533 {
7534   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7535   /* shift right accumulator */
7536   if (sign)
7537     AccSRsh (shCount);
7538   else
7539     AccRsh (shCount);
7540   aopPut (AOP (result), "a", offr);
7541 }
7542 #endif
7543
7544 #ifdef BETTER_LITERAL_SHIFT
7545 /*-----------------------------------------------------------------*/
7546 /* shiftL1Left2Result - shift left one byte from left to result    */
7547 /*-----------------------------------------------------------------*/
7548 static void
7549 shiftL1Left2Result (operand * left, int offl,
7550                     operand * result, int offr, int shCount)
7551 {
7552   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7553   /* shift left accumulator */
7554   AccLsh (shCount);
7555   aopPut (AOP (result), "a", offr);
7556 }
7557 #endif
7558
7559 #ifdef BETTER_LITERAL_SHIFT
7560 /*-----------------------------------------------------------------*/
7561 /* movLeft2Result - move byte from left to result                  */
7562 /*-----------------------------------------------------------------*/
7563 static void
7564 movLeft2Result (operand * left, int offl,
7565                 operand * result, int offr, int sign)
7566 {
7567   char *l;
7568   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7569   {
7570       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7571
7572       if (*l == '@' && (IS_AOP_PREG (result)))
7573       {
7574           emitcode ("mov", "a,%s", l);
7575           aopPut (AOP (result), "a", offr);
7576       }
7577       else
7578       {
7579           if (!sign)
7580           {
7581             aopPut (AOP (result), l, offr);
7582           }
7583           else
7584             {
7585               /* MSB sign in acc.7 ! */
7586               if (getDataSize (left) == offl + 1)
7587                 {
7588                   emitcode ("mov", "a,%s", l);
7589                   aopPut (AOP (result), "a", offr);
7590                 }
7591             }
7592       }
7593   }
7594 }
7595 #endif
7596
7597 #ifdef BETTER_LITERAL_SHIFT
7598 /*-----------------------------------------------------------------*/
7599 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7600 /*-----------------------------------------------------------------*/
7601 static void
7602 AccAXRrl1 (char *x)
7603 {
7604   emitcode ("rrc", "a");
7605   emitcode ("xch", "a,%s", x);
7606   emitcode ("rrc", "a");
7607   emitcode ("xch", "a,%s", x);
7608 }
7609 #endif
7610
7611 #ifdef BETTER_LITERAL_SHIFT
7612 //REMOVE ME!!!
7613 /*-----------------------------------------------------------------*/
7614 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7615 /*-----------------------------------------------------------------*/
7616 static void
7617 AccAXLrl1 (char *x)
7618 {
7619   emitcode ("xch", "a,%s", x);
7620   emitcode ("rlc", "a");
7621   emitcode ("xch", "a,%s", x);
7622   emitcode ("rlc", "a");
7623 }
7624 #endif
7625
7626 #ifdef BETTER_LITERAL_SHIFT
7627 /*-----------------------------------------------------------------*/
7628 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7629 /*-----------------------------------------------------------------*/
7630 static void
7631 AccAXLsh1 (char *x)
7632 {
7633   emitcode ("xch", "a,%s", x);
7634   emitcode ("add", "a,acc");
7635   emitcode ("xch", "a,%s", x);
7636   emitcode ("rlc", "a");
7637 }
7638 #endif
7639
7640 #ifdef BETTER_LITERAL_SHIFT
7641 /*-----------------------------------------------------------------*/
7642 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7643 /*-----------------------------------------------------------------*/
7644 static void
7645 AccAXLsh (char *x, int shCount)
7646 {
7647   switch (shCount)
7648     {
7649     case 0:
7650       break;
7651     case 1:
7652       AccAXLsh1 (x);
7653       break;
7654     case 2:
7655       AccAXLsh1 (x);
7656       AccAXLsh1 (x);
7657       break;
7658     case 3:
7659     case 4:
7660     case 5:                     // AAAAABBB:CCCCCDDD
7661
7662       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7663
7664       emitcode ("anl", "a,#!constbyte",
7665                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7666
7667       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7668
7669       AccRol (shCount);         // DDDCCCCC:BBB00000
7670
7671       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7672
7673       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7674
7675       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7676
7677       emitcode ("anl", "a,#!constbyte",
7678                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7679
7680       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7681
7682       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7683
7684       break;
7685     case 6:                     // AAAAAABB:CCCCCCDD
7686       emitcode ("anl", "a,#!constbyte",
7687                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7688       emitcode ("mov", "c,acc.0");      // c = B
7689       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7690 #if 0
7691       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7692       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7693 #else
7694       emitcode("rrc","a"); 
7695       emitcode("xch","a,%s", x); 
7696       emitcode("rrc","a"); 
7697       emitcode("mov","c,acc.0"); //<< get correct bit 
7698       emitcode("xch","a,%s", x); 
7699
7700       emitcode("rrc","a"); 
7701       emitcode("xch","a,%s", x); 
7702       emitcode("rrc","a"); 
7703       emitcode("xch","a,%s", x); 
7704 #endif
7705       break;
7706     case 7:                     // a:x <<= 7
7707
7708       emitcode ("anl", "a,#!constbyte",
7709                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7710
7711       emitcode ("mov", "c,acc.0");      // c = B
7712
7713       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7714
7715       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7716
7717       break;
7718     default:
7719       break;
7720     }
7721 }
7722 #endif
7723
7724 #ifdef BETTER_LITERAL_SHIFT
7725 //REMOVE ME!!!
7726 /*-----------------------------------------------------------------*/
7727 /* AccAXRsh - right shift a:x known count (0..7)                   */
7728 /*-----------------------------------------------------------------*/
7729 static void
7730 AccAXRsh (char *x, int shCount)
7731 {
7732   switch (shCount)
7733     {
7734     case 0:
7735       break;
7736     case 1:
7737       CLRC;
7738       AccAXRrl1 (x);            // 0->a:x
7739
7740       break;
7741     case 2:
7742       CLRC;
7743       AccAXRrl1 (x);            // 0->a:x
7744
7745       CLRC;
7746       AccAXRrl1 (x);            // 0->a:x
7747
7748       break;
7749     case 3:
7750     case 4:
7751     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7752
7753       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7754
7755       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7756
7757       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7758
7759       emitcode ("anl", "a,#!constbyte",
7760                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7761
7762       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7763
7764       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7765
7766       emitcode ("anl", "a,#!constbyte",
7767                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7768
7769       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7770
7771       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7772
7773       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7774
7775       break;
7776     case 6:                     // AABBBBBB:CCDDDDDD
7777
7778       emitcode ("mov", "c,acc.7");
7779       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7780
7781       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7782
7783       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7787
7788       break;
7789     case 7:                     // ABBBBBBB:CDDDDDDD
7790
7791       emitcode ("mov", "c,acc.7");      // c = A
7792
7793       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7794
7795       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7796
7797       emitcode ("anl", "a,#!constbyte",
7798                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7799
7800       break;
7801     default:
7802       break;
7803     }
7804 }
7805 #endif
7806
7807 #ifdef BETTER_LITERAL_SHIFT
7808 /*-----------------------------------------------------------------*/
7809 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7810 /*-----------------------------------------------------------------*/
7811 static void
7812 AccAXRshS (char *x, int shCount)
7813 {
7814   symbol *tlbl;
7815   switch (shCount)
7816     {
7817     case 0:
7818       break;
7819     case 1:
7820       emitcode ("mov", "c,acc.7");
7821       AccAXRrl1 (x);            // s->a:x
7822
7823       break;
7824     case 2:
7825       emitcode ("mov", "c,acc.7");
7826       AccAXRrl1 (x);            // s->a:x
7827
7828       emitcode ("mov", "c,acc.7");
7829       AccAXRrl1 (x);            // s->a:x
7830
7831       break;
7832     case 3:
7833     case 4:
7834     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7835
7836       tlbl = newiTempLabel (NULL);
7837       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7838
7839       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7840
7841       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7842
7843       emitcode ("anl", "a,#!constbyte",
7844                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7845
7846       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7847
7848       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7849
7850       emitcode ("anl", "a,#!constbyte",
7851                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7852
7853       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7854
7855       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7856
7857       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7858
7859       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7860       emitcode ("orl", "a,#!constbyte",
7861                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7862
7863       emitcode ("", "!tlabeldef", tlbl->key + 100);
7864       break;                    // SSSSAAAA:BBBCCCCC
7865
7866     case 6:                     // AABBBBBB:CCDDDDDD
7867
7868       tlbl = newiTempLabel (NULL);
7869       emitcode ("mov", "c,acc.7");
7870       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7871
7872       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7873
7874       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7875
7876       emitcode ("anl", "a,#!constbyte",
7877                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7878
7879       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7880       emitcode ("orl", "a,#!constbyte",
7881                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7882
7883       emitcode ("", "!tlabeldef", tlbl->key + 100);
7884       break;
7885     case 7:                     // ABBBBBBB:CDDDDDDD
7886
7887       tlbl = newiTempLabel (NULL);
7888       emitcode ("mov", "c,acc.7");      // c = A
7889
7890       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7891
7892       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7893
7894       emitcode ("anl", "a,#!constbyte",
7895                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7896
7897       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7898       emitcode ("orl", "a,#!constbyte",
7899                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7900
7901       emitcode ("", "!tlabeldef", tlbl->key + 100);
7902       break;
7903     default:
7904       break;
7905     }
7906 }
7907 #endif
7908
7909 #ifdef BETTER_LITERAL_SHIFT
7910 static void
7911 _loadLeftIntoAx(char    **lsb, 
7912                 operand *left, 
7913                 operand *result,
7914                 int     offl,
7915                 int     offr)
7916 {
7917   // Get the initial value from left into a pair of registers.
7918   // MSB must be in A, LSB can be any register.
7919   //
7920   // If the result is held in registers, it is an optimization
7921   // if the LSB can be held in the register which will hold the,
7922   // result LSB since this saves us from having to copy it into
7923   // the result following AccAXLsh.
7924   //
7925   // If the result is addressed indirectly, this is not a gain.
7926   if (AOP_NEEDSACC(result))
7927   {
7928        char *leftByte;
7929        
7930        _startLazyDPSEvaluation();
7931       if (AOP_TYPE(left) == AOP_DPTR2)
7932        {
7933            // Get MSB in A.
7934            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7935            // get LSB in DP2_RESULT_REG.
7936            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7937            assert(!strcmp(leftByte, DP2_RESULT_REG));
7938        }
7939        else
7940        {
7941            // get LSB into DP2_RESULT_REG
7942            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7943            if (strcmp(leftByte, DP2_RESULT_REG))
7944            {
7945                TR_AP("#7");
7946                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7947            }
7948            // And MSB in A.
7949            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7950            assert(strcmp(leftByte, DP2_RESULT_REG));
7951            MOVA(leftByte);
7952        }
7953        _endLazyDPSEvaluation();
7954        *lsb = DP2_RESULT_REG;
7955   }
7956   else
7957   {
7958       if (sameRegs (AOP (result), AOP (left)) &&
7959         ((offl + MSB16) == offr))
7960       {
7961           /* don't crash result[offr] */
7962           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7963           emitcode ("xch", "a,%s", 
7964                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7965       }
7966       else
7967       {
7968           movLeft2Result (left, offl, result, offr, 0);
7969           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7970       }
7971       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7972       assert(strcmp(*lsb,"a"));      
7973   }
7974 }
7975
7976 static void
7977 _storeAxResults(char    *lsb,
7978                 operand *result,
7979                 int     offr)
7980 {
7981   _startLazyDPSEvaluation();
7982   if (AOP_NEEDSACC(result))
7983   {
7984       /* We have to explicitly update the result LSB.
7985        */
7986       emitcode("xch","a,%s", lsb);
7987       aopPut(AOP(result), "a", offr);
7988       emitcode("mov","a,%s", lsb);
7989   }
7990   if (getDataSize (result) > 1)
7991   {
7992       aopPut (AOP (result), "a", offr + MSB16);
7993   }
7994   _endLazyDPSEvaluation();
7995 }
7996
7997 /*-----------------------------------------------------------------*/
7998 /* shiftL2Left2Result - shift left two bytes from left to result   */
7999 /*-----------------------------------------------------------------*/
8000 static void
8001 shiftL2Left2Result (operand * left, int offl,
8002                     operand * result, int offr, int shCount)
8003 {
8004   char *lsb;
8005
8006   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8007   
8008   AccAXLsh (lsb, shCount);
8009   
8010   _storeAxResults(lsb, result, offr);
8011 }
8012 #endif
8013
8014 #ifdef BETTER_LITERAL_SHIFT
8015 /*-----------------------------------------------------------------*/
8016 /* shiftR2Left2Result - shift right two bytes from left to result  */
8017 /*-----------------------------------------------------------------*/
8018 static void
8019 shiftR2Left2Result (operand * left, int offl,
8020                     operand * result, int offr,
8021                     int shCount, int sign)
8022 {
8023   char *lsb;
8024   
8025   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8026   
8027   /* a:x >> shCount (x = lsb(result)) */
8028   if (sign)
8029   {
8030      AccAXRshS(lsb, shCount);
8031   }
8032   else
8033   {
8034     AccAXRsh(lsb, shCount);
8035   }
8036   
8037   _storeAxResults(lsb, result, offr);
8038 }
8039 #endif
8040
8041 /*-----------------------------------------------------------------*/
8042 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 shiftLLeftOrResult (operand * left, int offl,
8046                     operand * result, int offr, int shCount)
8047 {
8048   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8049   /* shift left accumulator */
8050   AccLsh (shCount);
8051   /* or with result */
8052   emitcode ("orl", "a,%s",
8053             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8054   /* back to result */
8055   aopPut (AOP (result), "a", offr);
8056 }
8057
8058 #if 0
8059 //REMOVE ME!!!
8060 /*-----------------------------------------------------------------*/
8061 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8062 /*-----------------------------------------------------------------*/
8063 static void
8064 shiftRLeftOrResult (operand * left, int offl,
8065                     operand * result, int offr, int shCount)
8066 {
8067   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8068   /* shift right accumulator */
8069   AccRsh (shCount);
8070   /* or with result */
8071   emitcode ("orl", "a,%s",
8072             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8073   /* back to result */
8074   aopPut (AOP (result), "a", offr);
8075 }
8076 #endif
8077
8078 #ifdef BETTER_LITERAL_SHIFT
8079 /*-----------------------------------------------------------------*/
8080 /* genlshOne - left shift a one byte quantity by known count       */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 genlshOne (operand * result, operand * left, int shCount)
8084 {
8085   D (emitcode (";", "genlshOne "););
8086   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8087 }
8088 #endif
8089
8090 #ifdef BETTER_LITERAL_SHIFT
8091 /*-----------------------------------------------------------------*/
8092 /* genlshTwo - left shift two bytes by known amount != 0           */
8093 /*-----------------------------------------------------------------*/
8094 static void
8095 genlshTwo (operand * result, operand * left, int shCount)
8096 {
8097   int size;
8098
8099   D (emitcode (";", "genlshTwo "););
8100
8101   size = getDataSize (result);
8102
8103   /* if shCount >= 8 */
8104   if (shCount >= 8)
8105   {
8106       shCount -= 8;
8107
8108       _startLazyDPSEvaluation();
8109
8110       if (size > 1)
8111         {
8112           if (shCount)
8113           {
8114             _endLazyDPSEvaluation();
8115             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8116             aopPut (AOP (result), zero, LSB);       
8117           }
8118           else
8119           {
8120             movLeft2Result (left, LSB, result, MSB16, 0);
8121             aopPut (AOP (result), zero, LSB);
8122             _endLazyDPSEvaluation();
8123           }
8124         }
8125         else
8126         {
8127           aopPut (AOP (result), zero, LSB);
8128           _endLazyDPSEvaluation();
8129         }
8130   }
8131
8132   /*  1 <= shCount <= 7 */
8133   else
8134     {
8135       if (size == 1)
8136       {
8137         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8138       }
8139       else
8140       {
8141         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8142       }
8143     }
8144 }
8145 #endif
8146
8147 #if 0
8148 //REMOVE ME!!!
8149 /*-----------------------------------------------------------------*/
8150 /* shiftLLong - shift left one long from left to result            */
8151 /* offl = LSB or MSB16                                             */
8152 /*-----------------------------------------------------------------*/
8153 static void
8154 shiftLLong (operand * left, operand * result, int offr)
8155 {
8156   char *l;
8157   int size = AOP_SIZE (result);
8158
8159   if (size >= LSB + offr)
8160     {
8161       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8162       MOVA (l);
8163       emitcode ("add", "a,acc");
8164       if (sameRegs (AOP (left), AOP (result)) &&
8165           size >= MSB16 + offr && offr != LSB)
8166         emitcode ("xch", "a,%s",
8167                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8168       else
8169         aopPut (AOP (result), "a", LSB + offr);
8170     }
8171
8172   if (size >= MSB16 + offr)
8173     {
8174       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8175         {
8176           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8177         }
8178       emitcode ("rlc", "a");
8179       if (sameRegs (AOP (left), AOP (result)) &&
8180           size >= MSB24 + offr && offr != LSB)
8181         emitcode ("xch", "a,%s",
8182                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8183       else
8184         aopPut (AOP (result), "a", MSB16 + offr);
8185     }
8186
8187   if (size >= MSB24 + offr)
8188     {
8189       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8190         {
8191           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8192         }
8193       emitcode ("rlc", "a");
8194       if (sameRegs (AOP (left), AOP (result)) &&
8195           size >= MSB32 + offr && offr != LSB)
8196         emitcode ("xch", "a,%s",
8197                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8198       else
8199         aopPut (AOP (result), "a", MSB24 + offr);
8200     }
8201
8202   if (size > MSB32 + offr)
8203     {
8204       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8205         {
8206           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8207         }
8208       emitcode ("rlc", "a");
8209       aopPut (AOP (result), "a", MSB32 + offr);
8210     }
8211   if (offr != LSB)
8212     aopPut (AOP (result), zero, LSB);
8213 }
8214 #endif
8215
8216 #if 0
8217 //REMOVE ME!!!
8218 /*-----------------------------------------------------------------*/
8219 /* genlshFour - shift four byte by a known amount != 0             */
8220 /*-----------------------------------------------------------------*/
8221 static void
8222 genlshFour (operand * result, operand * left, int shCount)
8223 {
8224   int size;
8225
8226   D (emitcode (";", "genlshFour ");
8227     );
8228
8229   size = AOP_SIZE (result);
8230
8231   /* if shifting more that 3 bytes */
8232   if (shCount >= 24)
8233     {
8234       shCount -= 24;
8235       if (shCount)
8236         /* lowest order of left goes to the highest
8237            order of the destination */
8238         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8239       else
8240         movLeft2Result (left, LSB, result, MSB32, 0);
8241       aopPut (AOP (result), zero, LSB);
8242       aopPut (AOP (result), zero, MSB16);
8243       aopPut (AOP (result), zero, MSB24);
8244       return;
8245     }
8246
8247   /* more than two bytes */
8248   else if (shCount >= 16)
8249     {
8250       /* lower order two bytes goes to higher order two bytes */
8251       shCount -= 16;
8252       /* if some more remaining */
8253       if (shCount)
8254         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8255       else
8256         {
8257           movLeft2Result (left, MSB16, result, MSB32, 0);
8258           movLeft2Result (left, LSB, result, MSB24, 0);
8259         }
8260       aopPut (AOP (result), zero, MSB16);
8261       aopPut (AOP (result), zero, LSB);
8262       return;
8263     }
8264
8265   /* if more than 1 byte */
8266   else if (shCount >= 8)
8267     {
8268       /* lower order three bytes goes to higher order  three bytes */
8269       shCount -= 8;
8270       if (size == 2)
8271         {
8272           if (shCount)
8273             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8274           else
8275             movLeft2Result (left, LSB, result, MSB16, 0);
8276         }
8277       else
8278         {                       /* size = 4 */
8279           if (shCount == 0)
8280             {
8281               movLeft2Result (left, MSB24, result, MSB32, 0);
8282               movLeft2Result (left, MSB16, result, MSB24, 0);
8283               movLeft2Result (left, LSB, result, MSB16, 0);
8284               aopPut (AOP (result), zero, LSB);
8285             }
8286           else if (shCount == 1)
8287             shiftLLong (left, result, MSB16);
8288           else
8289             {
8290               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8291               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8292               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8293               aopPut (AOP (result), zero, LSB);
8294             }
8295         }
8296     }
8297
8298   /* 1 <= shCount <= 7 */
8299   else if (shCount <= 2)
8300     {
8301       shiftLLong (left, result, LSB);
8302       if (shCount == 2)
8303         shiftLLong (result, result, LSB);
8304     }
8305   /* 3 <= shCount <= 7, optimize */
8306   else
8307     {
8308       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8309       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8310       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8311     }
8312 }
8313 #endif
8314
8315 #ifdef BETTER_LITERAL_SHIFT
8316 /*-----------------------------------------------------------------*/
8317 /* genLeftShiftLiteral - left shifting by known count              */
8318 /*-----------------------------------------------------------------*/
8319 static bool
8320 genLeftShiftLiteral (operand * left,
8321                      operand * right,
8322                      operand * result,
8323                      iCode * ic)
8324 {
8325   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8326   int size;
8327
8328   size = getSize (operandType (result));
8329
8330   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8331
8332   /* We only handle certain easy cases so far. */
8333   if ((shCount != 0)
8334    && (shCount < (size * 8))
8335    && (size != 1)
8336    && (size != 2))
8337   {
8338       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8339       return FALSE;
8340   }
8341
8342   freeAsmop (right, NULL, ic, TRUE);
8343
8344   aopOp(left, ic, FALSE, FALSE);
8345   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8346
8347 #if 0 // debug spew
8348   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8349   {
8350         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8351         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8352         {
8353            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8354         }
8355   }
8356   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8357   {
8358         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8359         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8360         {
8361            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8362         }       
8363   }  
8364 #endif
8365   
8366 #if VIEW_SIZE
8367   emitcode ("; shift left ", "result %d, left %d", size,
8368             AOP_SIZE (left));
8369 #endif
8370
8371   /* I suppose that the left size >= result size */
8372   if (shCount == 0)
8373   {
8374         _startLazyDPSEvaluation();
8375         while (size--)
8376         {
8377           movLeft2Result (left, size, result, size, 0);
8378         }
8379         _endLazyDPSEvaluation();
8380   }
8381   else if (shCount >= (size * 8))
8382   {
8383     _startLazyDPSEvaluation();
8384     while (size--)
8385     {
8386       aopPut (AOP (result), zero, size);
8387     }
8388     _endLazyDPSEvaluation();
8389   }
8390   else
8391   {
8392       switch (size)
8393         {
8394         case 1:
8395           genlshOne (result, left, shCount);
8396           break;
8397
8398         case 2:
8399           genlshTwo (result, left, shCount);
8400           break;
8401 #if 0
8402         case 4:
8403           genlshFour (result, left, shCount);
8404           break;
8405 #endif
8406         default:
8407           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8408           break;
8409         }
8410     }
8411   freeAsmop (left, NULL, ic, TRUE);
8412   freeAsmop (result, NULL, ic, TRUE);
8413   return TRUE;
8414 }
8415 #endif
8416
8417 /*-----------------------------------------------------------------*/
8418 /* genLeftShift - generates code for left shifting                 */
8419 /*-----------------------------------------------------------------*/
8420 static void
8421 genLeftShift (iCode * ic)
8422 {
8423   operand *left, *right, *result;
8424   int size, offset;
8425   char *l;
8426   symbol *tlbl, *tlbl1;
8427
8428   D (emitcode (";", "genLeftShift "););
8429
8430   right = IC_RIGHT (ic);
8431   left = IC_LEFT (ic);
8432   result = IC_RESULT (ic);
8433
8434   aopOp (right, ic, FALSE, FALSE);
8435
8436
8437 #ifdef BETTER_LITERAL_SHIFT
8438   /* if the shift count is known then do it
8439      as efficiently as possible */
8440   if (AOP_TYPE (right) == AOP_LIT)
8441     {
8442       if (genLeftShiftLiteral (left, right, result, ic))
8443       {
8444         return;
8445       }
8446     }
8447 #endif
8448
8449   /* shift count is unknown then we have to form
8450      a loop get the loop count in B : Note: we take
8451      only the lower order byte since shifting
8452      more that 32 bits make no sense anyway, ( the
8453      largest size of an object can be only 32 bits ) */
8454
8455   if (AOP_TYPE (right) == AOP_LIT)
8456   {
8457       /* Really should be handled by genLeftShiftLiteral,
8458        * but since I'm too lazy to fix that today, at least we can make
8459        * some small improvement.
8460        */
8461        emitcode("mov", "b,#!constbyte",
8462                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8463   }
8464   else
8465   {
8466       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8467       emitcode ("inc", "b");
8468   }
8469   freeAsmop (right, NULL, ic, TRUE);
8470   aopOp (left, ic, FALSE, FALSE);
8471   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8472
8473   /* now move the left to the result if they are not the
8474      same */
8475   if (!sameRegs (AOP (left), AOP (result)) &&
8476       AOP_SIZE (result) > 1)
8477     {
8478
8479       size = AOP_SIZE (result);
8480       offset = 0;
8481       _startLazyDPSEvaluation ();
8482       while (size--)
8483         {
8484           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8485           if (*l == '@' && (IS_AOP_PREG (result)))
8486             {
8487
8488               emitcode ("mov", "a,%s", l);
8489               aopPut (AOP (result), "a", offset);
8490             }
8491           else
8492             aopPut (AOP (result), l, offset);
8493           offset++;
8494         }
8495       _endLazyDPSEvaluation ();
8496     }
8497
8498   tlbl = newiTempLabel (NULL);
8499   size = AOP_SIZE (result);
8500   offset = 0;
8501   tlbl1 = newiTempLabel (NULL);
8502
8503   /* if it is only one byte then */
8504   if (size == 1)
8505     {
8506       symbol *tlbl1 = newiTempLabel (NULL);
8507
8508       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8509       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8510       emitcode ("", "!tlabeldef", tlbl->key + 100);
8511       emitcode ("add", "a,acc");
8512       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8513       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8514       aopPut (AOP (result), "a", 0);
8515       goto release;
8516     }
8517
8518   reAdjustPreg (AOP (result));
8519
8520   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8521   emitcode ("", "!tlabeldef", tlbl->key + 100);
8522   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8523   emitcode ("add", "a,acc");
8524   aopPut (AOP (result), "a", offset++);
8525   _startLazyDPSEvaluation ();
8526   while (--size)
8527     {
8528       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8529       emitcode ("rlc", "a");
8530       aopPut (AOP (result), "a", offset++);
8531     }
8532   _endLazyDPSEvaluation ();
8533   reAdjustPreg (AOP (result));
8534
8535   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8536   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8537 release:
8538   freeAsmop (left, NULL, ic, TRUE);
8539   freeAsmop (result, NULL, ic, TRUE);
8540 }
8541
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /*-----------------------------------------------------------------*/
8544 /* genrshOne - right shift a one byte quantity by known count      */
8545 /*-----------------------------------------------------------------*/
8546 static void
8547 genrshOne (operand * result, operand * left,
8548            int shCount, int sign)
8549 {
8550   D (emitcode (";", "genrshOne"););
8551   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8552 }
8553 #endif
8554
8555 #ifdef BETTER_LITERAL_SHIFT
8556 /*-----------------------------------------------------------------*/
8557 /* genrshTwo - right shift two bytes by known amount != 0          */
8558 /*-----------------------------------------------------------------*/
8559 static void
8560 genrshTwo (operand * result, operand * left,
8561            int shCount, int sign)
8562 {
8563   D (emitcode (";", "genrshTwo"););
8564
8565   /* if shCount >= 8 */
8566   if (shCount >= 8)
8567     {
8568       shCount -= 8;
8569       _startLazyDPSEvaluation();
8570       if (shCount)
8571       {
8572         shiftR1Left2Result (left, MSB16, result, LSB,
8573                             shCount, sign);
8574       }                     
8575       else
8576       {
8577         movLeft2Result (left, MSB16, result, LSB, sign);
8578       }
8579       addSign (result, MSB16, sign);
8580       _endLazyDPSEvaluation();
8581     }
8582
8583   /*  1 <= shCount <= 7 */
8584   else
8585   {
8586     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8587   }
8588 }
8589 #endif
8590
8591 /*-----------------------------------------------------------------*/
8592 /* shiftRLong - shift right one long from left to result           */
8593 /* offl = LSB or MSB16                                             */
8594 /*-----------------------------------------------------------------*/
8595 static void
8596 shiftRLong (operand * left, int offl,
8597             operand * result, int sign)
8598 {
8599   int isSameRegs=sameRegs(AOP(left),AOP(result));
8600
8601   if (isSameRegs && offl>1) {
8602     // we are in big trouble, but this shouldn't happen
8603     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8604   }
8605
8606   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8607   
8608   if (offl==MSB16) {
8609     // shift is > 8
8610     if (sign) {
8611       emitcode ("rlc", "a");
8612       emitcode ("subb", "a,acc");
8613       emitcode ("xch", "a,%s",
8614                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8615     } else {
8616       aopPut (AOP(result), zero, MSB32);
8617     }
8618   }
8619
8620   if (!sign) {
8621     emitcode ("clr", "c");
8622   } else {
8623     emitcode ("mov", "c,acc.7");
8624   }
8625
8626   emitcode ("rrc", "a");
8627
8628   if (isSameRegs && offl==MSB16) {
8629     emitcode ("xch",
8630               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8631   } else {
8632     aopPut (AOP (result), "a", MSB32);
8633     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8634   }
8635
8636   emitcode ("rrc", "a");
8637   if (isSameRegs && offl==1) {
8638     emitcode ("xch", "a,%s",
8639               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8640   } else {
8641     aopPut (AOP (result), "a", MSB24);
8642     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8643   }
8644   emitcode ("rrc", "a");
8645   aopPut (AOP (result), "a", MSB16 - offl);
8646
8647   if (offl == LSB)
8648     {
8649       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8650       emitcode ("rrc", "a");
8651       aopPut (AOP (result), "a", LSB);
8652     }
8653 }
8654
8655 /*-----------------------------------------------------------------*/
8656 /* genrshFour - shift four byte by a known amount != 0             */
8657 /*-----------------------------------------------------------------*/
8658 static void
8659 genrshFour (operand * result, operand * left,
8660             int shCount, int sign)
8661 {
8662   D (emitcode (";", "genrshFour"););
8663
8664   /* if shifting more that 3 bytes */
8665   if (shCount >= 24)
8666     {
8667       shCount -= 24;
8668       _startLazyDPSEvaluation();
8669       if (shCount)
8670         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8671       else
8672         movLeft2Result (left, MSB32, result, LSB, sign);
8673       addSign (result, MSB16, sign);
8674       _endLazyDPSEvaluation();
8675     }
8676   else if (shCount >= 16)
8677     {
8678       shCount -= 16;
8679       _startLazyDPSEvaluation();
8680       if (shCount)
8681         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8682       else
8683         {
8684           movLeft2Result (left, MSB24, result, LSB, 0);
8685           movLeft2Result (left, MSB32, result, MSB16, sign);
8686         }
8687       addSign (result, MSB24, sign);
8688       _endLazyDPSEvaluation();
8689     }
8690   else if (shCount >= 8)
8691     {
8692       shCount -= 8;
8693       _startLazyDPSEvaluation();
8694       if (shCount == 1)
8695         {
8696             shiftRLong (left, MSB16, result, sign);
8697         }
8698       else if (shCount == 0)
8699         {
8700           movLeft2Result (left, MSB16, result, LSB, 0);
8701           movLeft2Result (left, MSB24, result, MSB16, 0);
8702           movLeft2Result (left, MSB32, result, MSB24, sign);
8703           addSign (result, MSB32, sign);
8704         }
8705       else
8706         {
8707           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8708           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8709           /* the last shift is signed */
8710           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8711           addSign (result, MSB32, sign);
8712         }
8713         _endLazyDPSEvaluation();
8714     }
8715   else
8716     {   
8717         /* 1 <= shCount <= 7 */
8718       if (shCount <= 2)
8719         {
8720           shiftRLong (left, LSB, result, sign);
8721           if (shCount == 2)
8722             shiftRLong (result, LSB, result, sign);
8723         }
8724       else
8725         {
8726           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8727           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8728           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8729         }
8730     }
8731 }
8732
8733 #ifdef BETTER_LITERAL_SHIFT
8734 /*-----------------------------------------------------------------*/
8735 /* genRightShiftLiteral - right shifting by known count            */
8736 /*-----------------------------------------------------------------*/
8737 static bool
8738 genRightShiftLiteral (operand * left,
8739                       operand * right,
8740                       operand * result,
8741                       iCode * ic,
8742                       int sign)
8743 {
8744   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8745   int size;
8746
8747   size = getSize (operandType (result));
8748
8749   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8750
8751   /* We only handle certain easy cases so far. */
8752   if ((shCount != 0)
8753    && (shCount < (size * 8))
8754    && (size != 1)
8755    && (size != 2)
8756    && (size != 4))
8757   {
8758       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8759       return FALSE;
8760   }
8761
8762   freeAsmop (right, NULL, ic, TRUE);
8763
8764   aopOp (left, ic, FALSE, FALSE);
8765   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8766
8767 #if VIEW_SIZE
8768   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8769             AOP_SIZE (left));
8770 #endif
8771
8772   /* test the LEFT size !!! */
8773
8774   /* I suppose that the left size >= result size */
8775   if (shCount == 0)
8776   {
8777       size = getDataSize (result);
8778       _startLazyDPSEvaluation();
8779       while (size--)
8780       {
8781         movLeft2Result (left, size, result, size, 0);
8782       }
8783       _endLazyDPSEvaluation();
8784   }
8785   else if (shCount >= (size * 8))
8786     {
8787       if (sign)
8788       {
8789         /* get sign in acc.7 */
8790         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8791       }
8792       addSign (result, LSB, sign);
8793     }
8794   else
8795     {
8796       switch (size)
8797         {
8798         case 1:
8799           genrshOne (result, left, shCount, sign);
8800           break;
8801
8802         case 2:
8803           genrshTwo (result, left, shCount, sign);
8804           break;
8805 #if 1
8806         case 4:
8807           genrshFour (result, left, shCount, sign);
8808           break;
8809 #endif    
8810         default:
8811           break;
8812         }
8813     }
8814   freeAsmop (left, NULL, ic, TRUE);
8815   freeAsmop (result, NULL, ic, TRUE);
8816   
8817   return TRUE;
8818 }
8819 #endif
8820
8821 /*-----------------------------------------------------------------*/
8822 /* genSignedRightShift - right shift of signed number              */
8823 /*-----------------------------------------------------------------*/
8824 static void
8825 genSignedRightShift (iCode * ic)
8826 {
8827   operand *right, *left, *result;
8828   int size, offset;
8829   char *l;
8830   symbol *tlbl, *tlbl1;
8831
8832   D (emitcode (";", "genSignedRightShift "););
8833
8834   /* we do it the hard way put the shift count in b
8835      and loop thru preserving the sign */
8836
8837   right = IC_RIGHT (ic);
8838   left = IC_LEFT (ic);
8839   result = IC_RESULT (ic);
8840
8841   aopOp (right, ic, FALSE, FALSE);
8842
8843 #ifdef BETTER_LITERAL_SHIFT
8844   if (AOP_TYPE (right) == AOP_LIT)
8845     {
8846       if (genRightShiftLiteral (left, right, result, ic, 1))
8847       {
8848         return;
8849       }
8850     }
8851 #endif
8852   /* shift count is unknown then we have to form
8853      a loop get the loop count in B : Note: we take
8854      only the lower order byte since shifting
8855      more that 32 bits make no sense anyway, ( the
8856      largest size of an object can be only 32 bits ) */
8857
8858   if (AOP_TYPE (right) == AOP_LIT)
8859   {
8860       /* Really should be handled by genRightShiftLiteral,
8861        * but since I'm too lazy to fix that today, at least we can make
8862        * some small improvement.
8863        */
8864        emitcode("mov", "b,#!constbyte",
8865                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8866   }
8867   else
8868   {
8869         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8870         emitcode ("inc", "b");
8871   }
8872   freeAsmop (right, NULL, ic, TRUE);
8873   aopOp (left, ic, FALSE, FALSE);
8874   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8875
8876   /* now move the left to the result if they are not the
8877      same */
8878   if (!sameRegs (AOP (left), AOP (result)) &&
8879       AOP_SIZE (result) > 1)
8880     {
8881
8882       size = AOP_SIZE (result);
8883       offset = 0;
8884       _startLazyDPSEvaluation ();
8885       while (size--)
8886         {
8887           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8888           if (*l == '@' && IS_AOP_PREG (result))
8889             {
8890
8891               emitcode ("mov", "a,%s", l);
8892               aopPut (AOP (result), "a", offset);
8893             }
8894           else
8895             aopPut (AOP (result), l, offset);
8896           offset++;
8897         }
8898       _endLazyDPSEvaluation ();
8899     }
8900
8901   /* mov the highest order bit to OVR */
8902   tlbl = newiTempLabel (NULL);
8903   tlbl1 = newiTempLabel (NULL);
8904
8905   size = AOP_SIZE (result);
8906   offset = size - 1;
8907   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8908   emitcode ("rlc", "a");
8909   emitcode ("mov", "ov,c");
8910   /* if it is only one byte then */
8911   if (size == 1)
8912     {
8913       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8914       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8915       emitcode ("", "!tlabeldef", tlbl->key + 100);
8916       emitcode ("mov", "c,ov");
8917       emitcode ("rrc", "a");
8918       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8920       aopPut (AOP (result), "a", 0);
8921       goto release;
8922     }
8923
8924   reAdjustPreg (AOP (result));
8925   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926   emitcode ("", "!tlabeldef", tlbl->key + 100);
8927   emitcode ("mov", "c,ov");
8928   _startLazyDPSEvaluation ();
8929   while (size--)
8930     {
8931       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8932       emitcode ("rrc", "a");
8933       aopPut (AOP (result), "a", offset--);
8934     }
8935   _endLazyDPSEvaluation ();
8936   reAdjustPreg (AOP (result));
8937   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8938   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8939
8940 release:
8941   freeAsmop (left, NULL, ic, TRUE);
8942   freeAsmop (result, NULL, ic, TRUE);
8943 }
8944
8945 /*-----------------------------------------------------------------*/
8946 /* genRightShift - generate code for right shifting                */
8947 /*-----------------------------------------------------------------*/
8948 static void
8949 genRightShift (iCode * ic)
8950 {
8951   operand *right, *left, *result;
8952   sym_link *retype;
8953   int size, offset;
8954   char *l;
8955   symbol *tlbl, *tlbl1;
8956
8957   D (emitcode (";", "genRightShift "););
8958
8959   /* if signed then we do it the hard way preserve the
8960      sign bit moving it inwards */
8961   retype = getSpec (operandType (IC_RESULT (ic)));
8962
8963   if (!SPEC_USIGN (retype))
8964     {
8965       genSignedRightShift (ic);
8966       return;
8967     }
8968
8969   /* signed & unsigned types are treated the same : i.e. the
8970      signed is NOT propagated inwards : quoting from the
8971      ANSI - standard : "for E1 >> E2, is equivalent to division
8972      by 2**E2 if unsigned or if it has a non-negative value,
8973      otherwise the result is implementation defined ", MY definition
8974      is that the sign does not get propagated */
8975
8976   right = IC_RIGHT (ic);
8977   left = IC_LEFT (ic);
8978   result = IC_RESULT (ic);
8979
8980   aopOp (right, ic, FALSE, FALSE);
8981
8982 #ifdef BETTER_LITERAL_SHIFT
8983   /* if the shift count is known then do it
8984      as efficiently as possible */
8985   if (AOP_TYPE (right) == AOP_LIT)
8986     {
8987       if (genRightShiftLiteral (left, right, result, ic, 0))
8988       {
8989         return;
8990       }
8991     }
8992 #endif
8993
8994   /* shift count is unknown then we have to form
8995      a loop get the loop count in B : Note: we take
8996      only the lower order byte since shifting
8997      more that 32 bits make no sense anyway, ( the
8998      largest size of an object can be only 32 bits ) */
8999   
9000   if (AOP_TYPE (right) == AOP_LIT)
9001   {
9002       /* Really should be handled by genRightShiftLiteral,
9003        * but since I'm too lazy to fix that today, at least we can make
9004        * some small improvement.
9005        */
9006        emitcode("mov", "b,#!constbyte",
9007                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9008   }
9009   else
9010   {
9011       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9012       emitcode ("inc", "b");
9013   }
9014   freeAsmop (right, NULL, ic, TRUE);
9015   aopOp (left, ic, FALSE, FALSE);
9016   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9017
9018   /* now move the left to the result if they are not the
9019      same */
9020   if (!sameRegs (AOP (left), AOP (result)) &&
9021       AOP_SIZE (result) > 1)
9022     {
9023
9024       size = AOP_SIZE (result);
9025       offset = 0;
9026       _startLazyDPSEvaluation ();
9027       while (size--)
9028         {
9029           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9030           if (*l == '@' && IS_AOP_PREG (result))
9031             {
9032
9033               emitcode ("mov", "a,%s", l);
9034               aopPut (AOP (result), "a", offset);
9035             }
9036           else
9037             aopPut (AOP (result), l, offset);
9038           offset++;
9039         }
9040       _endLazyDPSEvaluation ();
9041     }
9042
9043   tlbl = newiTempLabel (NULL);
9044   tlbl1 = newiTempLabel (NULL);
9045   size = AOP_SIZE (result);
9046   offset = size - 1;
9047
9048   /* if it is only one byte then */
9049   if (size == 1)
9050     {
9051       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9052       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9053       emitcode ("", "!tlabeldef", tlbl->key + 100);
9054       CLRC;
9055       emitcode ("rrc", "a");
9056       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9057       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9058       aopPut (AOP (result), "a", 0);
9059       goto release;
9060     }
9061
9062   reAdjustPreg (AOP (result));
9063   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9064   emitcode ("", "!tlabeldef", tlbl->key + 100);
9065   CLRC;
9066   _startLazyDPSEvaluation ();
9067   while (size--)
9068     {
9069       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9070       emitcode ("rrc", "a");
9071       aopPut (AOP (result), "a", offset--);
9072     }
9073   _endLazyDPSEvaluation ();
9074   reAdjustPreg (AOP (result));
9075
9076   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9077   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9078
9079 release:
9080   freeAsmop (left, NULL, ic, TRUE);
9081   freeAsmop (result, NULL, ic, TRUE);
9082 }
9083
9084
9085 /*-----------------------------------------------------------------*/
9086 /* emitPtrByteGet - emits code to get a byte into A through a      */
9087 /*                  pointer register (R0, R1, or DPTR). The        */
9088 /*                  original value of A can be preserved in B.     */
9089 /*-----------------------------------------------------------------*/
9090 static void
9091 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9092 {
9093   switch (p_type)
9094     {
9095     case IPOINTER:
9096     case POINTER:
9097       if (preserveAinB)
9098         emitcode ("mov", "b,a");
9099       emitcode ("mov", "a,@%s", rname);
9100       break;
9101
9102     case PPOINTER:
9103       if (preserveAinB)
9104         emitcode ("mov", "b,a");
9105       emitcode ("movx", "a,@%s", rname);
9106       break;
9107       
9108     case FPOINTER:
9109       if (preserveAinB)
9110         emitcode ("mov", "b,a");
9111       emitcode ("movx", "a,@dptr");
9112       break;
9113
9114     case CPOINTER:
9115       if (preserveAinB)
9116         emitcode ("mov", "b,a");
9117       emitcode ("clr", "a");
9118       emitcode ("movc", "a,@a+dptr");
9119       break;
9120
9121     case GPOINTER:
9122       if (preserveAinB)
9123         {
9124           emitcode ("push", "b");
9125           emitcode ("push", "acc");
9126         }
9127       emitcode ("lcall", "__gptrget");
9128       if (preserveAinB)
9129         emitcode ("pop", "b");
9130       break;
9131     }
9132 }
9133
9134 /*-----------------------------------------------------------------*/
9135 /* emitPtrByteSet - emits code to set a byte from src through a    */
9136 /*                  pointer register (R0, R1, or DPTR).            */
9137 /*-----------------------------------------------------------------*/
9138 static void
9139 emitPtrByteSet (char *rname, int p_type, char *src)
9140 {
9141   switch (p_type)
9142     {
9143     case IPOINTER:
9144     case POINTER:
9145       if (*src=='@')
9146         {
9147           MOVA (src);
9148           emitcode ("mov", "@%s,a", rname);
9149         }
9150       else
9151         emitcode ("mov", "@%s,%s", rname, src);
9152       break;
9153
9154     case PPOINTER:
9155       MOVA (src);
9156       emitcode ("movx", "@%s,a", rname);
9157       break;
9158       
9159     case FPOINTER:
9160       MOVA (src);
9161       emitcode ("movx", "@dptr,a");
9162       break;
9163
9164     case GPOINTER:
9165       MOVA (src);
9166       emitcode ("lcall", "__gptrput");
9167       break;
9168     }
9169 }
9170
9171 /*-----------------------------------------------------------------*/
9172 /* genUnpackBits - generates code for unpacking bits               */
9173 /*-----------------------------------------------------------------*/
9174 static void
9175 genUnpackBits (operand * result, char *rname, int ptype)
9176 {
9177   int offset = 0;       /* result byte offset */
9178   int rsize;            /* result size */
9179   int rlen = 0;         /* remaining bitfield length */
9180   sym_link *etype;      /* bitfield type information */
9181   int blen;             /* bitfield length */
9182   int bstr;             /* bitfield starting bit within byte */
9183
9184   D(emitcode (";     genUnpackBits",""));
9185
9186   etype = getSpec (operandType (result));
9187   rsize = getSize (operandType (result));
9188   blen = SPEC_BLEN (etype);
9189   bstr = SPEC_BSTR (etype);
9190
9191   /* If the bitfield length is less than a byte */
9192   if (blen < 8)
9193     {
9194       emitPtrByteGet (rname, ptype, FALSE);
9195       AccRsh (bstr);
9196       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9197       aopPut (AOP (result), "a", offset++);
9198       goto finish;
9199     }
9200
9201   /* Bit field did not fit in a byte. Copy all
9202      but the partial byte at the end.  */
9203   for (rlen=blen;rlen>=8;rlen-=8)
9204     {
9205       emitPtrByteGet (rname, ptype, FALSE);
9206       aopPut (AOP (result), "a", offset++);
9207       if (rlen>8)
9208         emitcode ("inc", "%s", rname);
9209     }
9210
9211   /* Handle the partial byte at the end */
9212   if (rlen)
9213     {
9214       emitPtrByteGet (rname, ptype, FALSE);
9215       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9216       aopPut (AOP (result), "a", offset++);
9217     }
9218
9219 finish:
9220   if (offset < rsize)
9221     {
9222       rsize -= offset;
9223       while (rsize--)
9224         aopPut (AOP (result), zero, offset++);
9225     }
9226 }
9227
9228
9229 /*-----------------------------------------------------------------*/
9230 /* genDataPointerGet - generates code when ptr offset is known     */
9231 /*-----------------------------------------------------------------*/
9232 static void
9233 genDataPointerGet (operand * left,
9234                    operand * result,
9235                    iCode * ic)
9236 {
9237   char *l;
9238   char buff[256];
9239   int size, offset = 0;
9240   aopOp (result, ic, TRUE, FALSE);
9241
9242   /* get the string representation of the name */
9243   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9244   size = AOP_SIZE (result);
9245   _startLazyDPSEvaluation ();
9246   while (size--)
9247     {
9248         if (offset)
9249         {
9250             SNPRINTF (buff, sizeof(buff), 
9251                       "(%s + %d)", l + 1, offset);
9252         }
9253         else
9254         {
9255             SNPRINTF (buff, sizeof(buff), 
9256                       "%s", l + 1);
9257         }
9258       aopPut (AOP (result), buff, offset++);
9259     }
9260   _endLazyDPSEvaluation ();
9261
9262   freeAsmop (left, NULL, ic, TRUE);
9263   freeAsmop (result, NULL, ic, TRUE);
9264 }
9265
9266 /*-----------------------------------------------------------------*/
9267 /* genNearPointerGet - emitcode for near pointer fetch             */
9268 /*-----------------------------------------------------------------*/
9269 static void
9270 genNearPointerGet (operand * left,
9271                    operand * result,
9272                    iCode * ic,
9273                    iCode *pi)
9274 {
9275   asmop *aop = NULL;
9276   regs *preg;
9277   char *rname;
9278   sym_link *rtype, *retype, *letype;
9279   sym_link *ltype = operandType (left);
9280   char buff[80];
9281
9282   rtype = operandType (result);
9283   retype = getSpec (rtype);
9284   letype = getSpec (ltype);
9285
9286   aopOp (left, ic, FALSE, FALSE);
9287
9288   /* if left is rematerialisable and
9289      result is not bit variable type and
9290      the left is pointer to data space i.e
9291      lower 128 bytes of space */
9292   if (AOP_TYPE (left) == AOP_IMMD &&
9293       !IS_BITVAR (retype) &&
9294       !IS_BITVAR (letype) &&
9295       DCL_TYPE (ltype) == POINTER)
9296     {
9297       genDataPointerGet (left, result, ic);
9298       return;
9299     }
9300
9301   /* if the value is already in a pointer register
9302      then don't need anything more */
9303   if (!AOP_INPREG (AOP (left)))
9304     {
9305       /* otherwise get a free pointer register */
9306       aop = newAsmop (0);
9307       preg = getFreePtr (ic, &aop, FALSE);
9308       emitcode ("mov", "%s,%s",
9309                 preg->name,
9310                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9311       rname = preg->name;
9312     }
9313   else
9314     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9315
9316   freeAsmop (left, NULL, ic, TRUE);
9317   aopOp (result, ic, FALSE, FALSE);
9318
9319   /* if bitfield then unpack the bits */
9320   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9321     genUnpackBits (result, rname, POINTER);
9322   else
9323     {
9324       /* we have can just get the values */
9325       int size = AOP_SIZE (result);
9326       int offset = 0;
9327
9328       while (size--)
9329         {
9330           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9331             {
9332
9333               emitcode ("mov", "a,@%s", rname);
9334               aopPut (AOP (result), "a", offset);
9335             }
9336           else
9337             {
9338               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9339               aopPut (AOP (result), buff, offset);
9340             }
9341           offset++;
9342           if (size || pi)
9343             {
9344                 emitcode ("inc", "%s", rname);
9345             }
9346         }
9347     }
9348
9349   /* now some housekeeping stuff */
9350   if (aop)
9351     {
9352       /* we had to allocate for this iCode */
9353       if (pi) { /* post increment present */
9354         aopPut(AOP ( left ),rname,0);
9355       }
9356       freeAsmop (NULL, aop, ic, TRUE);
9357     }
9358   else
9359     {
9360       /* we did not allocate which means left
9361          already in a pointer register, then
9362          if size > 0 && this could be used again
9363          we have to point it back to where it
9364          belongs */
9365       if (AOP_SIZE (result) > 1 &&
9366           !OP_SYMBOL (left)->remat &&
9367           (OP_SYMBOL (left)->liveTo > ic->seq ||
9368            ic->depth) &&
9369           !pi)
9370         {
9371           int size = AOP_SIZE (result) - 1;
9372           while (size--)
9373             emitcode ("dec", "%s", rname);
9374         }
9375     }
9376
9377   /* done */
9378   freeAsmop (result, NULL, ic, TRUE);
9379   if (pi) pi->generated = 1;
9380 }
9381
9382 /*-----------------------------------------------------------------*/
9383 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9384 /*-----------------------------------------------------------------*/
9385 static void
9386 genPagedPointerGet (operand * left,
9387                     operand * result,
9388                     iCode * ic,
9389                     iCode * pi)
9390 {
9391   asmop *aop = NULL;
9392   regs *preg;
9393   char *rname;
9394   sym_link *rtype, *retype, *letype;
9395
9396   rtype = operandType (result);
9397   retype = getSpec (rtype);
9398   letype = getSpec (operandType (left));
9399   aopOp (left, ic, FALSE, FALSE);
9400
9401   /* if the value is already in a pointer register
9402      then don't need anything more */
9403   if (!AOP_INPREG (AOP (left)))
9404     {
9405       /* otherwise get a free pointer register */
9406       aop = newAsmop (0);
9407       preg = getFreePtr (ic, &aop, FALSE);
9408       emitcode ("mov", "%s,%s",
9409                 preg->name,
9410                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9411       rname = preg->name;
9412     }
9413   else
9414     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9415
9416   freeAsmop (left, NULL, ic, TRUE);
9417   aopOp (result, ic, FALSE, FALSE);
9418
9419   /* if bitfield then unpack the bits */
9420   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9421     genUnpackBits (result, rname, PPOINTER);
9422   else
9423     {
9424       /* we have can just get the values */
9425       int size = AOP_SIZE (result);
9426       int offset = 0;
9427
9428       while (size--)
9429         {
9430
9431           emitcode ("movx", "a,@%s", rname);
9432           aopPut (AOP (result), "a", offset);
9433
9434           offset++;
9435
9436           if (size || pi)
9437             emitcode ("inc", "%s", rname);
9438         }
9439     }
9440
9441   /* now some housekeeping stuff */
9442   if (aop)
9443     {
9444       /* we had to allocate for this iCode */
9445       if (pi) aopPut ( AOP (left), rname, 0);
9446       freeAsmop (NULL, aop, ic, TRUE);
9447     }
9448   else
9449     {
9450       /* we did not allocate which means left
9451          already in a pointer register, then
9452          if size > 0 && this could be used again
9453          we have to point it back to where it
9454          belongs */
9455       if (AOP_SIZE (result) > 1 &&
9456           !OP_SYMBOL (left)->remat &&
9457           (OP_SYMBOL (left)->liveTo > ic->seq ||
9458            ic->depth) &&
9459           !pi)
9460         {
9461           int size = AOP_SIZE (result) - 1;
9462           while (size--)
9463             emitcode ("dec", "%s", rname);
9464         }
9465     }
9466
9467   /* done */
9468   freeAsmop (result, NULL, ic, TRUE);
9469   if (pi) pi->generated = 1;
9470 }
9471
9472 /*-----------------------------------------------------------------*/
9473 /* genFarPointerGet - gget value from far space                    */
9474 /*-----------------------------------------------------------------*/
9475 static void
9476 genFarPointerGet (operand * left,
9477                   operand * result, iCode * ic, iCode *pi)
9478 {
9479     int size, offset, dopi=1;
9480   sym_link *retype = getSpec (operandType (result));
9481   sym_link *letype = getSpec (operandType (left));
9482   D (emitcode (";", "genFarPointerGet"););
9483
9484   aopOp (left, ic, FALSE, FALSE);
9485
9486   /* if the operand is already in dptr
9487      then we do nothing else we move the value to dptr */
9488   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9489     {
9490       /* if this is remateriazable */
9491       if (AOP_TYPE (left) == AOP_IMMD)
9492         {
9493           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9494         }
9495       else
9496         {
9497           /* we need to get it byte by byte */
9498           _startLazyDPSEvaluation ();
9499           if (AOP_TYPE (left) != AOP_DPTR)
9500             {
9501               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9502               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9503               if (options.model == MODEL_FLAT24)
9504                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9505             }
9506           else
9507             {
9508               /* We need to generate a load to DPTR indirect through DPTR. */
9509               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9510               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9511               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9512               if (options.model == MODEL_FLAT24)
9513                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9514               emitcode ("pop", "dph");
9515               emitcode ("pop", "dpl");
9516               dopi =0;
9517             }
9518           _endLazyDPSEvaluation ();
9519         }
9520     }
9521   /* so dptr know contains the address */
9522   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9523
9524   /* if bit then unpack */
9525   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9526       if (AOP_INDPTRn(left)) {
9527           genSetDPTR(AOP(left)->aopu.dptr);
9528       }
9529       genUnpackBits (result, "dptr", FPOINTER);
9530       if (AOP_INDPTRn(left)) {
9531           genSetDPTR(0);
9532       }
9533   } else
9534     {
9535       size = AOP_SIZE (result);
9536       offset = 0;
9537
9538       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9539           while (size--) {
9540               genSetDPTR(AOP(left)->aopu.dptr);
9541               emitcode ("movx", "a,@dptr");
9542               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9543                   emitcode ("inc", "dptr");
9544               genSetDPTR (0);
9545               aopPut (AOP (result), "a", offset++);
9546           }
9547       } else {
9548           _startLazyDPSEvaluation ();
9549           while (size--) {
9550               if (AOP_INDPTRn(left)) {
9551                   genSetDPTR(AOP(left)->aopu.dptr);
9552               } else {
9553                   genSetDPTR (0);
9554               }
9555               _flushLazyDPS ();
9556               
9557               emitcode ("movx", "a,@dptr");
9558               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9559                   emitcode ("inc", "dptr");
9560               
9561               aopPut (AOP (result), "a", offset++);
9562           }
9563           _endLazyDPSEvaluation ();
9564       }
9565     }
9566   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9567       if (!AOP_INDPTRn(left)) {
9568           _startLazyDPSEvaluation ();
9569           aopPut ( AOP (left), "dpl", 0);
9570           aopPut ( AOP (left), "dph", 1);
9571           if (options.model == MODEL_FLAT24)
9572               aopPut ( AOP (left), "dpx", 2);
9573           _endLazyDPSEvaluation ();
9574       }
9575     pi->generated = 1;
9576   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9577              AOP_SIZE(result) > 1 &&
9578              IS_SYMOP(left) &&
9579              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9580       
9581       size = AOP_SIZE (result) - 1;
9582       if (AOP_INDPTRn(left)) {
9583           genSetDPTR(AOP(left)->aopu.dptr);
9584       }
9585       while (size--) emitcode ("lcall","__decdptr");
9586       if (AOP_INDPTRn(left)) {
9587           genSetDPTR(0);
9588       }
9589   }
9590
9591   freeAsmop (left, NULL, ic, TRUE);
9592   freeAsmop (result, NULL, ic, TRUE);
9593 }
9594
9595 /*-----------------------------------------------------------------*/
9596 /* genCodePointerGet - get value from code space                  */
9597 /*-----------------------------------------------------------------*/
9598 static void
9599 genCodePointerGet (operand * left,
9600                     operand * result, iCode * ic, iCode *pi)
9601 {
9602   int size, offset, dopi=1;
9603   sym_link *retype = getSpec (operandType (result));
9604
9605   aopOp (left, ic, FALSE, FALSE);
9606
9607   /* if the operand is already in dptr
9608      then we do nothing else we move the value to dptr */
9609   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9610     {
9611       /* if this is remateriazable */
9612       if (AOP_TYPE (left) == AOP_IMMD)
9613         {
9614           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9615         }
9616       else
9617         {                       /* we need to get it byte by byte */
9618           _startLazyDPSEvaluation ();
9619           if (AOP_TYPE (left) != AOP_DPTR)
9620             {
9621               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9622               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9623               if (options.model == MODEL_FLAT24)
9624                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9625             }
9626           else
9627             {
9628               /* We need to generate a load to DPTR indirect through DPTR. */
9629               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9630               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9631               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9632               if (options.model == MODEL_FLAT24)
9633                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9634               emitcode ("pop", "dph");
9635               emitcode ("pop", "dpl");
9636               dopi=0;
9637             }
9638           _endLazyDPSEvaluation ();
9639         }
9640     }
9641   /* so dptr know contains the address */
9642   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9643
9644   /* if bit then unpack */
9645   if (IS_BITVAR (retype)) {
9646       if (AOP_INDPTRn(left)) {
9647           genSetDPTR(AOP(left)->aopu.dptr);
9648       }
9649       genUnpackBits (result, "dptr", CPOINTER);
9650       if (AOP_INDPTRn(left)) {
9651           genSetDPTR(0);
9652       }
9653   } else
9654     {
9655       size = AOP_SIZE (result);
9656       offset = 0;
9657       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9658           while (size--) {
9659               genSetDPTR(AOP(left)->aopu.dptr);
9660               emitcode ("clr", "a");
9661               emitcode ("movc", "a,@a+dptr");
9662               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9663                   emitcode ("inc", "dptr");
9664               genSetDPTR (0);
9665               aopPut (AOP (result), "a", offset++);
9666           }
9667       } else {
9668           _startLazyDPSEvaluation ();
9669           while (size--)
9670               {
9671                   if (AOP_INDPTRn(left)) {
9672                       genSetDPTR(AOP(left)->aopu.dptr);
9673                   } else {
9674                       genSetDPTR (0);
9675                   }
9676                   _flushLazyDPS ();
9677                   
9678                   emitcode ("clr", "a");
9679                   emitcode ("movc", "a,@a+dptr");
9680                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9681                       emitcode ("inc", "dptr");
9682                   aopPut (AOP (result), "a", offset++);
9683               }
9684           _endLazyDPSEvaluation ();
9685       }
9686     }
9687   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9688       if (!AOP_INDPTRn(left)) {
9689           _startLazyDPSEvaluation ();
9690           
9691           aopPut ( AOP (left), "dpl", 0);
9692           aopPut ( AOP (left), "dph", 1);
9693           if (options.model == MODEL_FLAT24)
9694               aopPut ( AOP (left), "dpx", 2);
9695
9696           _endLazyDPSEvaluation ();
9697       }
9698       pi->generated = 1;
9699   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9700              AOP_SIZE(result) > 1 &&
9701              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9702       
9703       size = AOP_SIZE (result) - 1;
9704       if (AOP_INDPTRn(left)) {
9705           genSetDPTR(AOP(left)->aopu.dptr);
9706       }
9707       while (size--) emitcode ("lcall","__decdptr");
9708       if (AOP_INDPTRn(left)) {
9709           genSetDPTR(0);
9710       }
9711   }
9712   
9713   freeAsmop (left, NULL, ic, TRUE);
9714   freeAsmop (result, NULL, ic, TRUE);
9715 }
9716
9717 /*-----------------------------------------------------------------*/
9718 /* genGenPointerGet - gget value from generic pointer space        */
9719 /*-----------------------------------------------------------------*/
9720 static void
9721 genGenPointerGet (operand * left,
9722                   operand * result, iCode * ic, iCode * pi)
9723 {
9724   int size, offset;
9725   sym_link *retype = getSpec (operandType (result));
9726   sym_link *letype = getSpec (operandType (left));
9727
9728   D (emitcode (";", "genGenPointerGet "); );
9729
9730   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9731
9732   /* if the operand is already in dptr
9733      then we do nothing else we move the value to dptr */
9734   if (AOP_TYPE (left) != AOP_STR)
9735     {
9736       /* if this is remateriazable */
9737       if (AOP_TYPE (left) == AOP_IMMD)
9738         {
9739           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9740           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9741             {
9742                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9743             }
9744             else
9745             {
9746                 emitcode ("mov", "b,#%d", pointerCode (retype));
9747             }
9748         }
9749       else
9750         {                       /* we need to get it byte by byte */
9751             _startLazyDPSEvaluation ();
9752             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9753             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9754             if (options.model == MODEL_FLAT24) {
9755                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9756                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9757             } else {
9758                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9759             }
9760             _endLazyDPSEvaluation ();
9761         }
9762     }
9763
9764   /* so dptr-b now contains the address */
9765   _G.bInUse++;
9766   aopOp (result, ic, FALSE, TRUE);
9767   _G.bInUse--;
9768
9769   /* if bit then unpack */
9770   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9771   {
9772     genUnpackBits (result, "dptr", GPOINTER);
9773   }
9774   else
9775     {
9776         size = AOP_SIZE (result);
9777         offset = 0;
9778
9779         while (size--)
9780         {
9781             if (size)
9782             {
9783                 // Get two bytes at a time, results in _AP & A.
9784                 // dptr will be incremented ONCE by __gptrgetWord.
9785                 //
9786                 // Note: any change here must be coordinated
9787                 // with the implementation of __gptrgetWord
9788                 // in device/lib/_gptrget.c
9789                 emitcode ("lcall", "__gptrgetWord");
9790                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9791                 aopPut (AOP (result), "a", offset++);
9792                 size--;
9793             }
9794             else
9795             {
9796                 // Only one byte to get.
9797                 emitcode ("lcall", "__gptrget");
9798                 aopPut (AOP (result), "a", offset++);
9799             }
9800             
9801             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9802             {
9803                 emitcode ("inc", "dptr");
9804             }
9805         }
9806     }
9807
9808   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9809     _startLazyDPSEvaluation ();
9810       
9811     aopPut ( AOP (left), "dpl", 0);
9812     aopPut ( AOP (left), "dph", 1);
9813     if (options.model == MODEL_FLAT24) {
9814         aopPut ( AOP (left), "dpx", 2);
9815         aopPut ( AOP (left), "b", 3);   
9816     } else  aopPut ( AOP (left), "b", 2);       
9817     
9818     _endLazyDPSEvaluation ();
9819       
9820     pi->generated = 1;
9821   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9822              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9823       
9824       size = AOP_SIZE (result) - 1;
9825       while (size--) emitcode ("lcall","__decdptr");
9826   }
9827
9828   freeAsmop (left, NULL, ic, TRUE);
9829   freeAsmop (result, NULL, ic, TRUE);
9830 }
9831
9832 /*-----------------------------------------------------------------*/
9833 /* genPointerGet - generate code for pointer get                   */
9834 /*-----------------------------------------------------------------*/
9835 static void
9836 genPointerGet (iCode * ic, iCode *pi)
9837 {
9838   operand *left, *result;
9839   sym_link *type, *etype;
9840   int p_type;
9841
9842   D (emitcode (";", "genPointerGet ");
9843     );
9844
9845   left = IC_LEFT (ic);
9846   result = IC_RESULT (ic);
9847
9848   /* depending on the type of pointer we need to
9849      move it to the correct pointer register */
9850   type = operandType (left);
9851   etype = getSpec (type);
9852   /* if left is of type of pointer then it is simple */
9853   if (IS_PTR (type) && !IS_FUNC (type->next))
9854     p_type = DCL_TYPE (type);
9855   else
9856     {
9857       /* we have to go by the storage class */
9858       p_type = PTR_TYPE (SPEC_OCLS (etype));
9859     }
9860   /* special case when cast remat */
9861   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9862       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9863           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9864           type = operandType (left);
9865           p_type = DCL_TYPE (type);
9866   }
9867   /* now that we have the pointer type we assign
9868      the pointer values */
9869   switch (p_type)
9870     {
9871
9872     case POINTER:
9873     case IPOINTER:
9874       genNearPointerGet (left, result, ic, pi);
9875       break;
9876
9877     case PPOINTER:
9878       genPagedPointerGet (left, result, ic, pi);
9879       break;
9880
9881     case FPOINTER:
9882       genFarPointerGet (left, result, ic, pi);
9883       break;
9884
9885     case CPOINTER:
9886       genCodePointerGet (left, result, ic, pi);
9887       break;
9888
9889     case GPOINTER:
9890       genGenPointerGet (left, result, ic, pi);
9891       break;
9892     }
9893
9894 }
9895
9896 /*-----------------------------------------------------------------*/
9897 /* genPackBits - generates code for packed bit storage             */
9898 /*-----------------------------------------------------------------*/
9899 static void
9900 genPackBits (sym_link * etype,
9901              operand * right,
9902              char *rname, int p_type)
9903 {
9904   int offset = 0;       /* source byte offset */
9905   int rlen = 0;         /* remaining bitfield length */
9906   int blen;             /* bitfield length */
9907   int bstr;             /* bitfield starting bit within byte */
9908   int litval;           /* source literal value (if AOP_LIT) */
9909   unsigned char mask;   /* bitmask within current byte */
9910
9911   D(emitcode (";     genPackBits",""));
9912
9913   blen = SPEC_BLEN (etype);
9914   bstr = SPEC_BSTR (etype);
9915
9916   /* If the bitfield length is less than a byte */
9917   if (blen < 8)
9918     {
9919       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9920               (unsigned char) (0xFF >> (8 - bstr)));
9921
9922       if (AOP_TYPE (right) == AOP_LIT)
9923         {
9924           /* Case with a bitfield length <8 and literal source
9925           */
9926           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9927           litval <<= bstr;
9928           litval &= (~mask) & 0xff;
9929           emitPtrByteGet (rname, p_type, FALSE);
9930           if ((mask|litval)!=0xff)
9931             emitcode ("anl","a,#!constbyte", mask);
9932           if (litval)
9933             emitcode ("orl","a,#!constbyte", litval);
9934         }
9935       else
9936         {
9937           if ((blen==1) && (p_type!=GPOINTER))
9938             {
9939               /* Case with a bitfield length == 1 and no generic pointer
9940               */
9941               if (AOP_TYPE (right) == AOP_CRY)
9942                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9943               else
9944                 {
9945                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9946                   emitcode ("rrc","a");
9947                 }
9948               emitPtrByteGet (rname, p_type, FALSE);
9949               emitcode ("mov","acc.%d,c",bstr);
9950             }
9951           else
9952             {
9953               /* Case with a bitfield length < 8 and arbitrary source
9954               */
9955               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9956               /* shift and mask source value */
9957               AccLsh (bstr);
9958               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9959
9960               /* transfer A to B and get next byte */
9961               emitPtrByteGet (rname, p_type, TRUE);
9962
9963               emitcode ("anl", "a,#!constbyte", mask);
9964               emitcode ("orl", "a,b");
9965               if (p_type == GPOINTER)
9966                 emitcode ("pop", "b");
9967            }
9968         }
9969
9970       emitPtrByteSet (rname, p_type, "a");
9971       return;
9972     }
9973
9974   /* Bit length is greater than 7 bits. In this case, copy  */
9975   /* all except the partial byte at the end                 */
9976   for (rlen=blen;rlen>=8;rlen-=8)
9977     {
9978       emitPtrByteSet (rname, p_type, 
9979                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9980       if (rlen>8)
9981         emitcode ("inc", "%s", rname);
9982     }
9983
9984   /* If there was a partial byte at the end */
9985   if (rlen)
9986     {
9987       mask = (((unsigned char) -1 << rlen) & 0xff);
9988       
9989       if (AOP_TYPE (right) == AOP_LIT)
9990         {
9991           /* Case with partial byte and literal source
9992           */
9993           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9994           litval >>= (blen-rlen);
9995           litval &= (~mask) & 0xff;
9996           emitPtrByteGet (rname, p_type, FALSE);
9997           if ((mask|litval)!=0xff)
9998             emitcode ("anl","a,#!constbyte", mask);
9999           if (litval)
10000             emitcode ("orl","a,#!constbyte", litval);
10001         }
10002       else
10003         {
10004           /* Case with partial byte and arbitrary source
10005           */
10006           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10007           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10008
10009           /* transfer A to B and get next byte */
10010           emitPtrByteGet (rname, p_type, TRUE);
10011
10012           emitcode ("anl", "a,#!constbyte", mask);
10013           emitcode ("orl", "a,b");
10014           if (p_type == GPOINTER)
10015             emitcode ("pop", "b");
10016         }
10017       emitPtrByteSet (rname, p_type, "a");
10018     }
10019
10020 }
10021
10022
10023 /*-----------------------------------------------------------------*/
10024 /* genDataPointerSet - remat pointer to data space                 */
10025 /*-----------------------------------------------------------------*/
10026 static void
10027 genDataPointerSet (operand * right,
10028                    operand * result,
10029                    iCode * ic)
10030 {
10031   int size, offset = 0;
10032   char *l, buff[256];
10033
10034   aopOp (right, ic, FALSE, FALSE);
10035
10036   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10037   size = AOP_SIZE (right);
10038   while (size--)
10039     {
10040       if (offset)
10041         {
10042             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10043         }
10044       else
10045         {
10046             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10047         }
10048         
10049       emitcode ("mov", "%s,%s", buff,
10050                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10051     }
10052
10053   freeAsmop (right, NULL, ic, TRUE);
10054   freeAsmop (result, NULL, ic, TRUE);
10055 }
10056
10057 /*-----------------------------------------------------------------*/
10058 /* genNearPointerSet - emitcode for near pointer put                */
10059 /*-----------------------------------------------------------------*/
10060 static void
10061 genNearPointerSet (operand * right,
10062                    operand * result,
10063                    iCode * ic,
10064                    iCode * pi)
10065 {
10066   asmop *aop = NULL;
10067   char *rname, *l;
10068   sym_link *retype, *letype;
10069   sym_link *ptype = operandType (result);
10070
10071   retype = getSpec (operandType (right));
10072   letype = getSpec (ptype);
10073
10074   aopOp (result, ic, FALSE, FALSE);
10075
10076   /* if the result is rematerializable &
10077      in data space & not a bit variable */
10078   if (AOP_TYPE (result) == AOP_IMMD &&
10079       DCL_TYPE (ptype) == POINTER &&
10080       !IS_BITVAR (retype) &&
10081       !IS_BITVAR (letype))
10082     {
10083       genDataPointerSet (right, result, ic);
10084       return;
10085     }
10086
10087   /* if the value is already in a pointer register
10088      then don't need anything more */
10089   if (!AOP_INPREG (AOP (result)))
10090     {
10091       /* otherwise get a free pointer register */
10092       regs *preg;
10093         
10094       aop = newAsmop (0);
10095       preg = getFreePtr (ic, &aop, FALSE);
10096       emitcode ("mov", "%s,%s",
10097                 preg->name,
10098                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10099       rname = preg->name;
10100     }
10101   else
10102     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10103
10104   aopOp (right, ic, FALSE, FALSE);
10105
10106   /* if bitfield then unpack the bits */
10107   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10108     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10109   else
10110     {
10111       /* we have can just get the values */
10112       int size = AOP_SIZE (right);
10113       int offset = 0;
10114
10115       while (size--)
10116         {
10117           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10118           if (*l == '@')
10119             {
10120               MOVA (l);
10121               emitcode ("mov", "@%s,a", rname);
10122             }
10123           else
10124             emitcode ("mov", "@%s,%s", rname, l);
10125           if (size || pi)
10126             emitcode ("inc", "%s", rname);
10127           offset++;
10128         }
10129     }
10130
10131   /* now some housekeeping stuff */
10132   if (aop)
10133     {
10134       /* we had to allocate for this iCode */
10135       if (pi) aopPut (AOP (result),rname,0);
10136       freeAsmop (NULL, aop, ic, TRUE);
10137     }
10138   else
10139     {
10140       /* we did not allocate which means left
10141          already in a pointer register, then
10142          if size > 0 && this could be used again
10143          we have to point it back to where it
10144          belongs */
10145       if (AOP_SIZE (right) > 1 &&
10146           !OP_SYMBOL (result)->remat &&
10147           (OP_SYMBOL (result)->liveTo > ic->seq ||
10148            ic->depth) &&
10149           !pi)
10150         {
10151           int size = AOP_SIZE (right) - 1;
10152           while (size--)
10153             emitcode ("dec", "%s", rname);
10154         }
10155     }
10156
10157   /* done */
10158   if (pi) pi->generated = 1;
10159   freeAsmop (result, NULL, ic, TRUE);
10160   freeAsmop (right, NULL, ic, TRUE);
10161
10162
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genPagedPointerSet - emitcode for Paged pointer put             */
10167 /*-----------------------------------------------------------------*/
10168 static void
10169 genPagedPointerSet (operand * right,
10170                     operand * result,
10171                     iCode * ic,
10172                     iCode *pi)
10173 {
10174   asmop *aop = NULL;
10175   char *rname;
10176   sym_link *retype, *letype;
10177
10178   retype = getSpec (operandType (right));
10179   letype = getSpec (operandType (result));
10180
10181   aopOp (result, ic, FALSE, FALSE);
10182
10183   /* if the value is already in a pointer register
10184      then don't need anything more */
10185   if (!AOP_INPREG (AOP (result)))
10186     {
10187       /* otherwise get a free pointer register */
10188       regs *preg;
10189         
10190       aop = newAsmop (0);
10191       preg = getFreePtr (ic, &aop, FALSE);
10192       emitcode ("mov", "%s,%s",
10193                 preg->name,
10194                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10195       rname = preg->name;
10196     }
10197   else
10198     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10199
10200   aopOp (right, ic, FALSE, FALSE);
10201
10202   /* if bitfield then unpack the bits */
10203   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10204     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10205   else
10206     {
10207       /* we have can just get the values */
10208       int size = AOP_SIZE (right);
10209       int offset = 0;
10210
10211       while (size--)
10212         {
10213           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10214
10215           emitcode ("movx", "@%s,a", rname);
10216
10217           if (size || pi)
10218             emitcode ("inc", "%s", rname);
10219
10220           offset++;
10221         }
10222     }
10223
10224   /* now some housekeeping stuff */
10225   if (aop)
10226     {
10227       if (pi) aopPut (AOP (result),rname,0);
10228       /* we had to allocate for this iCode */
10229       freeAsmop (NULL, aop, ic, TRUE);
10230     }
10231   else
10232     {
10233       /* we did not allocate which means left
10234          already in a pointer register, then
10235          if size > 0 && this could be used again
10236          we have to point it back to where it
10237          belongs */
10238       if (AOP_SIZE (right) > 1 &&
10239           !OP_SYMBOL (result)->remat &&
10240           (OP_SYMBOL (result)->liveTo > ic->seq ||
10241            ic->depth) &&
10242           !pi)
10243         {
10244           int size = AOP_SIZE (right) - 1;
10245           while (size--)
10246             emitcode ("dec", "%s", rname);
10247         }
10248     }
10249
10250   /* done */
10251   if (pi) pi->generated = 1;
10252   freeAsmop (result, NULL, ic, TRUE);
10253   freeAsmop (right, NULL, ic, TRUE);
10254
10255
10256 }
10257
10258 /*-----------------------------------------------------------------*/
10259 /* genFarPointerSet - set value from far space                     */
10260 /*-----------------------------------------------------------------*/
10261 static void
10262 genFarPointerSet (operand * right,
10263                   operand * result, iCode * ic, iCode *pi)
10264 {
10265   int size, offset, dopi=1;
10266   sym_link *retype = getSpec (operandType (right));
10267   sym_link *letype = getSpec (operandType (result));
10268
10269   aopOp (result, ic, FALSE, FALSE);
10270
10271   /* if the operand is already in dptr
10272      then we do nothing else we move the value to dptr */
10273   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10274     {
10275       /* if this is remateriazable */
10276       if (AOP_TYPE (result) == AOP_IMMD)
10277         emitcode ("mov", "dptr,%s", 
10278                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10279       else
10280         {
10281           /* we need to get it byte by byte */
10282           _startLazyDPSEvaluation ();
10283           if (AOP_TYPE (result) != AOP_DPTR)
10284             {
10285               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10286               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10287               if (options.model == MODEL_FLAT24)
10288                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10289             }
10290           else
10291             {
10292               /* We need to generate a load to DPTR indirect through DPTR. */
10293               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10294                 
10295               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10296               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10297               if (options.model == MODEL_FLAT24)
10298                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10299               emitcode ("pop", "dph");
10300               emitcode ("pop", "dpl");
10301               dopi=0;
10302             }
10303           _endLazyDPSEvaluation ();
10304         }
10305     }
10306   /* so dptr know contains the address */
10307   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10308
10309   /* if bit then unpack */
10310   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10311       if (AOP_INDPTRn(result)) {
10312           genSetDPTR(AOP(result)->aopu.dptr);
10313       }
10314       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10315       if (AOP_INDPTRn(result)) {
10316           genSetDPTR(0);
10317       }
10318   } else {
10319       size = AOP_SIZE (right);
10320       offset = 0;
10321       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10322           while (size--) {
10323               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10324               
10325               genSetDPTR(AOP(result)->aopu.dptr);
10326               emitcode ("movx", "@dptr,a");
10327               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10328                   emitcode ("inc", "dptr");
10329               genSetDPTR (0);
10330           }
10331       } else {
10332           _startLazyDPSEvaluation ();
10333           while (size--) {
10334               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10335               
10336               if (AOP_INDPTRn(result)) {
10337                   genSetDPTR(AOP(result)->aopu.dptr);
10338               } else {
10339                   genSetDPTR (0);
10340               }
10341               _flushLazyDPS ();
10342               
10343               emitcode ("movx", "@dptr,a");
10344               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10345                   emitcode ("inc", "dptr");
10346           }
10347           _endLazyDPSEvaluation ();
10348       }
10349   }
10350   
10351   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10352       if (!AOP_INDPTRn(result)) {
10353           _startLazyDPSEvaluation ();
10354           
10355           aopPut (AOP(result),"dpl",0);
10356           aopPut (AOP(result),"dph",1);
10357           if (options.model == MODEL_FLAT24)
10358               aopPut (AOP(result),"dpx",2);
10359
10360           _endLazyDPSEvaluation ();
10361       }
10362       pi->generated=1;
10363   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10364              AOP_SIZE(right) > 1 &&
10365              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10366       
10367       size = AOP_SIZE (right) - 1;
10368       if (AOP_INDPTRn(result)) {
10369           genSetDPTR(AOP(result)->aopu.dptr);
10370       } 
10371       while (size--) emitcode ("lcall","__decdptr");
10372       if (AOP_INDPTRn(result)) {
10373           genSetDPTR(0);
10374       }
10375   }
10376   freeAsmop (result, NULL, ic, TRUE);
10377   freeAsmop (right, NULL, ic, TRUE);
10378 }
10379
10380 /*-----------------------------------------------------------------*/
10381 /* genGenPointerSet - set value from generic pointer space         */
10382 /*-----------------------------------------------------------------*/
10383 static void
10384 genGenPointerSet (operand * right,
10385                   operand * result, iCode * ic, iCode *pi)
10386 {
10387   int size, offset;
10388   sym_link *retype = getSpec (operandType (right));
10389   sym_link *letype = getSpec (operandType (result));
10390
10391   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10392
10393   /* if the operand is already in dptr
10394      then we do nothing else we move the value to dptr */
10395   if (AOP_TYPE (result) != AOP_STR)
10396     {
10397       _startLazyDPSEvaluation ();
10398       /* if this is remateriazable */
10399       if (AOP_TYPE (result) == AOP_IMMD)
10400         {
10401           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10402           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10403           {
10404               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10405           }
10406           else
10407           {
10408               emitcode ("mov", 
10409                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10410           }
10411         }
10412       else
10413         {                       /* we need to get it byte by byte */
10414           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10415           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10416           if (options.model == MODEL_FLAT24) {
10417             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10418             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10419           } else {
10420             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10421           }
10422         }
10423       _endLazyDPSEvaluation ();
10424     }
10425   /* so dptr + b now contains the address */
10426   _G.bInUse++;
10427   aopOp (right, ic, FALSE, TRUE);
10428   _G.bInUse--;
10429     
10430
10431   /* if bit then unpack */
10432   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10433     {
10434         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10435     }
10436   else
10437     {
10438         size = AOP_SIZE (right);
10439         offset = 0;
10440
10441         _startLazyDPSEvaluation ();
10442         while (size--)
10443         {
10444             if (size)
10445             {
10446                 // Set two bytes at a time, passed in _AP & A.
10447                 // dptr will be incremented ONCE by __gptrputWord.
10448                 //
10449                 // Note: any change here must be coordinated
10450                 // with the implementation of __gptrputWord
10451                 // in device/lib/_gptrput.c
10452                 emitcode("mov", "_ap, %s", 
10453                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10454                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10455                 
10456                 genSetDPTR (0);
10457                 _flushLazyDPS ();
10458                 emitcode ("lcall", "__gptrputWord");
10459                 size--;
10460             }
10461             else
10462             {
10463                 // Only one byte to put.
10464                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10465
10466                 genSetDPTR (0);
10467                 _flushLazyDPS ();               
10468                 emitcode ("lcall", "__gptrput");
10469             }
10470             
10471             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10472             {
10473                 emitcode ("inc", "dptr");
10474             }
10475         }
10476         _endLazyDPSEvaluation ();
10477     }
10478
10479   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10480       _startLazyDPSEvaluation ();
10481       
10482       aopPut (AOP(result),"dpl",0);
10483       aopPut (AOP(result),"dph",1);
10484       if (options.model == MODEL_FLAT24) {
10485           aopPut (AOP(result),"dpx",2);
10486           aopPut (AOP(result),"b",3);
10487       } else {
10488           aopPut (AOP(result),"b",2);
10489       }
10490       _endLazyDPSEvaluation ();
10491       
10492       pi->generated=1;
10493   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10494              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10495       
10496       size = AOP_SIZE (right) - 1;
10497       while (size--) emitcode ("lcall","__decdptr");
10498   }
10499   freeAsmop (result, NULL, ic, TRUE);
10500   freeAsmop (right, NULL, ic, TRUE);
10501 }
10502
10503 /*-----------------------------------------------------------------*/
10504 /* genPointerSet - stores the value into a pointer location        */
10505 /*-----------------------------------------------------------------*/
10506 static void
10507 genPointerSet (iCode * ic, iCode *pi)
10508 {
10509   operand *right, *result;
10510   sym_link *type, *etype;
10511   int p_type;
10512
10513   D (emitcode (";", "genPointerSet "););
10514
10515   right = IC_RIGHT (ic);
10516   result = IC_RESULT (ic);
10517
10518   /* depending on the type of pointer we need to
10519      move it to the correct pointer register */
10520   type = operandType (result);
10521   etype = getSpec (type);
10522   /* if left is of type of pointer then it is simple */
10523   if (IS_PTR (type) && !IS_FUNC (type->next))
10524     {
10525       p_type = DCL_TYPE (type);
10526     }
10527   else
10528     {
10529       /* we have to go by the storage class */
10530       p_type = PTR_TYPE (SPEC_OCLS (etype));
10531     }
10532   /* special case when cast remat */
10533   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10534       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10535           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10536           type = operandType (result);
10537           p_type = DCL_TYPE (type);
10538   }
10539
10540   /* now that we have the pointer type we assign
10541      the pointer values */
10542   switch (p_type)
10543     {
10544
10545     case POINTER:
10546     case IPOINTER:
10547       genNearPointerSet (right, result, ic, pi);
10548       break;
10549
10550     case PPOINTER:
10551       genPagedPointerSet (right, result, ic, pi);
10552       break;
10553
10554     case FPOINTER:
10555       genFarPointerSet (right, result, ic, pi);
10556       break;
10557
10558     case GPOINTER:
10559       genGenPointerSet (right, result, ic, pi);
10560       break;
10561
10562     default:
10563       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10564               "genPointerSet: illegal pointer type");
10565     }
10566
10567 }
10568
10569 /*-----------------------------------------------------------------*/
10570 /* genIfx - generate code for Ifx statement                        */
10571 /*-----------------------------------------------------------------*/
10572 static void
10573 genIfx (iCode * ic, iCode * popIc)
10574 {
10575   operand *cond = IC_COND (ic);
10576   int isbit = 0;
10577
10578   D (emitcode (";", "genIfx "););
10579
10580   aopOp (cond, ic, FALSE, FALSE);
10581
10582   /* get the value into acc */
10583   if (AOP_TYPE (cond) != AOP_CRY)
10584     {
10585         toBoolean (cond);
10586     }
10587   else
10588     {
10589         isbit = 1;
10590     }
10591     
10592   /* the result is now in the accumulator */
10593   freeAsmop (cond, NULL, ic, TRUE);
10594
10595   /* if there was something to be popped then do it */
10596   if (popIc)
10597     genIpop (popIc);
10598
10599   /* if the condition is  a bit variable */
10600   if (isbit && IS_ITEMP (cond) &&
10601       SPIL_LOC (cond))
10602     {
10603         genIfxJump (ic, SPIL_LOC (cond)->rname);
10604     }
10605   else if (isbit && !IS_ITEMP (cond))
10606     {
10607         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10608     }
10609   else
10610     {
10611         genIfxJump (ic, "a");
10612     }
10613
10614   ic->generated = 1;
10615 }
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genAddrOf - generates code for address of                       */
10619 /*-----------------------------------------------------------------*/
10620 static void
10621 genAddrOf (iCode * ic)
10622 {
10623   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10624   int size, offset;
10625
10626   D (emitcode (";", "genAddrOf ");
10627     );
10628
10629   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10630
10631   /* if the operand is on the stack then we
10632      need to get the stack offset of this
10633      variable */
10634   if (sym->onStack) {
10635       
10636       /* if 10 bit stack */
10637       if (options.stack10bit) {
10638           char buff[10];
10639           int  offset;
10640           
10641           tsprintf(buff, sizeof(buff), 
10642                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10643           /* if it has an offset then we need to compute it */
10644 /*        emitcode ("subb", "a,#!constbyte", */
10645 /*                  -((sym->stack < 0) ? */
10646 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10647 /*                    ((short) sym->stack)) & 0xff); */
10648 /*        emitcode ("mov","b,a"); */
10649 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10650 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10651 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10652           if (sym->stack) {
10653               emitcode ("mov", "a,_bpx");
10654               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10655                                              ((char) (sym->stack - _G.nRegsSaved)) :
10656                                              ((char) sym->stack )) & 0xff);
10657               emitcode ("mov", "b,a");
10658               emitcode ("mov", "a,_bpx+1");
10659               
10660               offset = (((sym->stack < 0) ? 
10661                          ((short) (sym->stack - _G.nRegsSaved)) :
10662                          ((short) sym->stack )) >> 8) & 0xff;
10663           
10664               emitcode ("addc","a,#!constbyte", offset);
10665
10666               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10667               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10668               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10669           } else {
10670               /* we can just move _bp */
10671               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10672               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10673               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10674           }       
10675       } else {
10676           /* if it has an offset then we need to compute it */
10677           if (sym->stack) {
10678               emitcode ("mov", "a,_bp");
10679               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10680               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10681           } else {
10682               /* we can just move _bp */
10683               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10684           }
10685           /* fill the result with zero */
10686           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10687           
10688           
10689           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10690               fprintf (stderr,
10691                        "*** warning: pointer to stack var truncated.\n");
10692           }
10693
10694           offset = 1;
10695           while (size--) {
10696               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10697           }      
10698       }
10699       goto release;
10700   }
10701
10702   /* object not on stack then we need the name */
10703   size = AOP_SIZE (IC_RESULT (ic));
10704   offset = 0;
10705
10706   while (size--)
10707     {
10708       char s[SDCC_NAME_MAX];
10709       if (offset) {
10710           switch (offset) {
10711           case 1:
10712               tsprintf(s, sizeof(s), "#!his",sym->rname);
10713               break;
10714           case 2:
10715               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10716               break;
10717           case 3:
10718               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10719               break;
10720           default: /* should not need this (just in case) */
10721               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10722                        sym->rname,
10723                        offset * 8);
10724           }
10725       } 
10726       else
10727       {
10728           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10729       }
10730         
10731       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10732     }
10733
10734 release:
10735   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10736
10737 }
10738
10739 #if 0 // obsolete, and buggy for != xdata
10740 /*-----------------------------------------------------------------*/
10741 /* genArrayInit - generates code for address of                       */
10742 /*-----------------------------------------------------------------*/
10743 static void
10744 genArrayInit (iCode * ic)
10745 {
10746     literalList *iLoop;
10747     int         ix, count;
10748     int         elementSize = 0, eIndex;
10749     unsigned    val, lastVal;
10750     sym_link    *type;
10751     operand     *left=IC_LEFT(ic);
10752     
10753     D (emitcode (";", "genArrayInit "););
10754
10755     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10756     
10757     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10758     {
10759         // Load immediate value into DPTR.
10760         emitcode("mov", "dptr, %s",
10761              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10762     }
10763     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10764     {
10765 #if 0
10766       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10767               "Unexpected operand to genArrayInit.\n");
10768       exit(1);
10769 #else
10770       // a regression because of SDCCcse.c:1.52
10771       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10772       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10773       if (options.model == MODEL_FLAT24)
10774         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10775 #endif
10776     }
10777     
10778     type = operandType(IC_LEFT(ic));
10779     
10780     if (type && type->next)
10781     {
10782         elementSize = getSize(type->next);
10783     }
10784     else
10785     {
10786         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10787                                 "can't determine element size in genArrayInit.\n");
10788         exit(1);
10789     }
10790     
10791     iLoop = IC_ARRAYILIST(ic);
10792     lastVal = 0xffff;
10793     
10794     while (iLoop)
10795     {
10796         bool firstpass = TRUE;
10797         
10798         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10799                  iLoop->count, (int)iLoop->literalValue, elementSize);
10800         
10801         ix = iLoop->count;
10802         
10803         while (ix)
10804         {
10805             symbol *tlbl = NULL;
10806             
10807             count = ix > 256 ? 256 : ix;
10808             
10809             if (count > 1)
10810             {
10811                 tlbl = newiTempLabel (NULL);
10812                 if (firstpass || (count & 0xff))
10813                 {
10814                     emitcode("mov", "b, #!constbyte", count & 0xff);
10815                 }
10816                 
10817                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10818             }
10819             
10820             firstpass = FALSE;
10821                 
10822             for (eIndex = 0; eIndex < elementSize; eIndex++)
10823             {
10824                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10825                 if (val != lastVal)
10826                 {
10827                     emitcode("mov", "a, #!constbyte", val);
10828                     lastVal = val;
10829                 }
10830                 
10831                 emitcode("movx", "@dptr, a");
10832                 emitcode("inc", "dptr");
10833             }
10834             
10835             if (count > 1)
10836             {
10837                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10838             }
10839             
10840             ix -= count;
10841         }
10842         
10843         iLoop = iLoop->next;
10844     }
10845     
10846     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10847 }
10848 #endif
10849
10850 /*-----------------------------------------------------------------*/
10851 /* genFarFarAssign - assignment when both are in far space         */
10852 /*-----------------------------------------------------------------*/
10853 static void
10854 genFarFarAssign (operand * result, operand * right, iCode * ic)
10855 {
10856   int size = AOP_SIZE (right);
10857   int offset = 0;
10858   symbol *rSym = NULL;
10859
10860   if (size == 1)
10861   {
10862       /* quick & easy case. */
10863       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10864       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10865       freeAsmop (right, NULL, ic, FALSE);
10866       /* now assign DPTR to result */
10867       _G.accInUse++;
10868       aopOp(result, ic, FALSE, FALSE);
10869       _G.accInUse--;
10870       aopPut(AOP(result), "a", 0);
10871       freeAsmop(result, NULL, ic, FALSE);
10872       return;
10873   }
10874   
10875   /* See if we've got an underlying symbol to abuse. */
10876   if (IS_SYMOP(result) && OP_SYMBOL(result))
10877   {
10878       if (IS_TRUE_SYMOP(result))
10879       {
10880           rSym = OP_SYMBOL(result);
10881       }
10882       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10883       {
10884           rSym = OP_SYMBOL(result)->usl.spillLoc;
10885       }
10886   }
10887              
10888   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10889   {
10890       /* We can use the '390 auto-toggle feature to good effect here. */
10891       
10892       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10893       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10894       emitcode ("mov", "dptr,#%s", rSym->rname); 
10895       /* DP2 = result, DP1 = right, DP1 is current. */
10896       while (size)
10897       {
10898           emitcode("movx", "a,@dptr");
10899           emitcode("movx", "@dptr,a");
10900           if (--size)
10901           {
10902                emitcode("inc", "dptr");
10903                emitcode("inc", "dptr");
10904           }
10905       }
10906       emitcode("mov", "dps,#0");
10907       freeAsmop (right, NULL, ic, FALSE);
10908 #if 0
10909 some alternative code for processors without auto-toggle
10910 no time to test now, so later well put in...kpb
10911         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10912         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10913         emitcode ("mov", "dptr,#%s", rSym->rname); 
10914         /* DP2 = result, DP1 = right, DP1 is current. */
10915         while (size)
10916         {
10917           --size;
10918           emitcode("movx", "a,@dptr");
10919           if (size)
10920             emitcode("inc", "dptr");
10921           emitcode("inc", "dps");
10922           emitcode("movx", "@dptr,a");
10923           if (size)
10924             emitcode("inc", "dptr");
10925           emitcode("inc", "dps");
10926         }
10927         emitcode("mov", "dps,#0");
10928         freeAsmop (right, NULL, ic, FALSE);
10929 #endif
10930   }
10931   else
10932   {
10933       D (emitcode (";", "genFarFarAssign"););
10934       aopOp (result, ic, TRUE, TRUE);
10935
10936       _startLazyDPSEvaluation ();
10937       
10938       while (size--)
10939         {
10940           aopPut (AOP (result),
10941                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10942           offset++;
10943         }
10944       _endLazyDPSEvaluation ();
10945       freeAsmop (result, NULL, ic, FALSE);
10946       freeAsmop (right, NULL, ic, FALSE);
10947   }
10948 }
10949
10950 /*-----------------------------------------------------------------*/
10951 /* genAssign - generate code for assignment                        */
10952 /*-----------------------------------------------------------------*/
10953 static void
10954 genAssign (iCode * ic)
10955 {
10956   operand *result, *right;
10957   int size, offset;
10958   unsigned long lit = 0L;
10959
10960   D (emitcode (";", "genAssign ");
10961     );
10962
10963   result = IC_RESULT (ic);
10964   right = IC_RIGHT (ic);
10965
10966   /* if they are the same */
10967   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10968     return;
10969
10970   aopOp (right, ic, FALSE, FALSE);
10971
10972   emitcode (";", "genAssign: resultIsFar = %s",
10973             isOperandInFarSpace (result) ?
10974             "TRUE" : "FALSE");
10975
10976   /* special case both in far space */
10977   if ((AOP_TYPE (right) == AOP_DPTR ||
10978        AOP_TYPE (right) == AOP_DPTR2) &&
10979   /* IS_TRUE_SYMOP(result)       && */
10980       isOperandInFarSpace (result))
10981     {
10982       genFarFarAssign (result, right, ic);
10983       return;
10984     }
10985
10986   aopOp (result, ic, TRUE, FALSE);
10987
10988   /* if they are the same registers */
10989   if (sameRegs (AOP (right), AOP (result)))
10990     goto release;
10991
10992   /* if the result is a bit */
10993   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10994     {
10995       /* if the right size is a literal then
10996          we know what the value is */
10997       if (AOP_TYPE (right) == AOP_LIT)
10998         {
10999           if (((int) operandLitValue (right)))
11000             aopPut (AOP (result), one, 0);
11001           else
11002             aopPut (AOP (result), zero, 0);
11003           goto release;
11004         }
11005
11006       /* the right is also a bit variable */
11007       if (AOP_TYPE (right) == AOP_CRY)
11008         {
11009           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11010           aopPut (AOP (result), "c", 0);
11011           goto release;
11012         }
11013
11014       /* we need to or */
11015       toBoolean (right);
11016       aopPut (AOP (result), "a", 0);
11017       goto release;
11018     }
11019
11020   /* bit variables done */
11021   /* general case */
11022   size = AOP_SIZE (result);
11023   offset = 0;
11024   if (AOP_TYPE (right) == AOP_LIT)
11025     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11026
11027   if ((size > 1) &&
11028       (AOP_TYPE (result) != AOP_REG) &&
11029       (AOP_TYPE (right) == AOP_LIT) &&
11030       !IS_FLOAT (operandType (right)))
11031     {
11032       _startLazyDPSEvaluation ();
11033       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11034         {
11035           aopPut (AOP (result),
11036                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11037                   offset);
11038           offset++;
11039           size--;
11040         }
11041       /* And now fill the rest with zeros. */
11042       if (size)
11043         {
11044           emitcode ("clr", "a");
11045         }
11046       while (size--)
11047         {
11048           aopPut (AOP (result), "a", offset++);
11049         }
11050       _endLazyDPSEvaluation ();
11051     }
11052   else
11053     {
11054       _startLazyDPSEvaluation ();
11055       while (size--)
11056         {
11057           aopPut (AOP (result),
11058                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11059                   offset);
11060           offset++;
11061         }
11062       _endLazyDPSEvaluation ();
11063     }
11064
11065 release:
11066   freeAsmop (right, NULL, ic, FALSE);
11067   freeAsmop (result, NULL, ic, TRUE);
11068 }
11069
11070 /*-----------------------------------------------------------------*/
11071 /* genJumpTab - generates code for jump table                      */
11072 /*-----------------------------------------------------------------*/
11073 static void
11074 genJumpTab (iCode * ic)
11075 {
11076   symbol *jtab;
11077   char *l;
11078
11079   D (emitcode (";", "genJumpTab ");
11080     );
11081
11082   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11083   /* get the condition into accumulator */
11084   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11085   MOVA (l);
11086   /* multiply by four! */
11087   emitcode ("add", "a,acc");
11088   emitcode ("add", "a,acc");
11089   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11090
11091   jtab = newiTempLabel (NULL);
11092   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11093   emitcode ("jmp", "@a+dptr");
11094   emitcode ("", "!tlabeldef", jtab->key + 100);
11095   /* now generate the jump labels */
11096   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11097        jtab = setNextItem (IC_JTLABELS (ic)))
11098     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11099
11100 }
11101
11102 /*-----------------------------------------------------------------*/
11103 /* genCast - gen code for casting                                  */
11104 /*-----------------------------------------------------------------*/
11105 static void
11106 genCast (iCode * ic)
11107 {
11108   operand *result = IC_RESULT (ic);
11109   sym_link *ctype = operandType (IC_LEFT (ic));
11110   sym_link *rtype = operandType (IC_RIGHT (ic));
11111   operand *right = IC_RIGHT (ic);
11112   int size, offset;
11113
11114   D (emitcode (";", "genCast "););
11115
11116   /* if they are equivalent then do nothing */
11117   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11118     return;
11119
11120   aopOp (right, ic, FALSE, FALSE);
11121   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11122
11123   /* if the result is a bit */
11124   if (IS_BITVAR (OP_SYMBOL (result)->type)
11125       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11126     {
11127       /* if the right size is a literal then
11128          we know what the value is */
11129       if (AOP_TYPE (right) == AOP_LIT)
11130         {
11131           if (((int) operandLitValue (right)))
11132             aopPut (AOP (result), one, 0);
11133           else
11134             aopPut (AOP (result), zero, 0);
11135
11136           goto release;
11137         }
11138
11139       /* the right is also a bit variable */
11140       if (AOP_TYPE (right) == AOP_CRY)
11141         {
11142           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11143           aopPut (AOP (result), "c", 0);
11144           goto release;
11145         }
11146
11147       /* we need to or */
11148       toBoolean (right);
11149       aopPut (AOP (result), "a", 0);
11150       goto release;
11151     }
11152
11153   /* if they are the same size : or less */
11154   if (AOP_SIZE (result) <= AOP_SIZE (right))
11155     {
11156
11157       /* if they are in the same place */
11158       if (sameRegs (AOP (right), AOP (result)))
11159         goto release;
11160
11161       /* if they in different places then copy */
11162       size = AOP_SIZE (result);
11163       offset = 0;
11164       _startLazyDPSEvaluation ();
11165       while (size--)
11166         {
11167           aopPut (AOP (result),
11168                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11169                   offset);
11170           offset++;
11171         }
11172       _endLazyDPSEvaluation ();
11173       goto release;
11174     }
11175
11176
11177   /* if the result is of type pointer */
11178   if (IS_PTR (ctype))
11179     {
11180
11181       int p_type;
11182       sym_link *type = operandType (right);
11183
11184       /* pointer to generic pointer */
11185       if (IS_GENPTR (ctype))
11186         {
11187           if (IS_PTR (type))
11188             {
11189               p_type = DCL_TYPE (type);
11190             }
11191           else
11192             {
11193 #if OLD_CAST_BEHAVIOR
11194               /* KV: we are converting a non-pointer type to
11195                * a generic pointer. This (ifdef'd out) code
11196                * says that the resulting generic pointer
11197                * should have the same class as the storage
11198                * location of the non-pointer variable.
11199                *
11200                * For example, converting an int (which happens
11201                * to be stored in DATA space) to a pointer results
11202                * in a DATA generic pointer; if the original int
11203                * in XDATA space, so will be the resulting pointer.
11204                *
11205                * I don't like that behavior, and thus this change:
11206                * all such conversions will be forced to XDATA and
11207                * throw a warning. If you want some non-XDATA
11208                * type, or you want to suppress the warning, you
11209                * must go through an intermediate cast, like so:
11210                *
11211                * char _generic *gp = (char _xdata *)(intVar);
11212                */
11213               sym_link *etype = getSpec (type);
11214
11215               /* we have to go by the storage class */
11216               if (SPEC_OCLS (etype) != generic)
11217                 {
11218                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11219                 }
11220               else
11221 #endif
11222                 {
11223                   /* Converting unknown class (i.e. register variable)
11224                    * to generic pointer. This is not good, but
11225                    * we'll make a guess (and throw a warning).
11226                    */
11227                   p_type = FPOINTER;
11228                   werror (W_INT_TO_GEN_PTR_CAST);
11229                 }
11230             }
11231
11232           /* the first two bytes are known */
11233           size = GPTRSIZE - 1;
11234           offset = 0;
11235           _startLazyDPSEvaluation ();
11236           while (size--)
11237             {
11238               aopPut (AOP (result),
11239                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11240                       offset);
11241               offset++;
11242             }
11243           _endLazyDPSEvaluation ();
11244
11245           /* the last byte depending on type */
11246             {
11247                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11248                 char gpValStr[10];
11249             
11250                 if (gpVal == -1)
11251                 {
11252                     // pointerTypeToGPByte will have bitched.
11253                     exit(1);
11254                 }
11255             
11256                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11257                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11258             }
11259           goto release;
11260         }
11261
11262       /* just copy the pointers */
11263       size = AOP_SIZE (result);
11264       offset = 0;
11265       _startLazyDPSEvaluation ();
11266       while (size--)
11267         {
11268           aopPut (AOP (result),
11269                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11270                   offset);
11271           offset++;
11272         }
11273       _endLazyDPSEvaluation ();
11274       goto release;
11275     }
11276
11277   /* so we now know that the size of destination is greater
11278      than the size of the source */
11279   /* we move to result for the size of source */
11280   size = AOP_SIZE (right);
11281   offset = 0;
11282   _startLazyDPSEvaluation ();
11283   while (size--)
11284     {
11285       aopPut (AOP (result),
11286               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11287               offset);
11288       offset++;
11289     }
11290   _endLazyDPSEvaluation ();
11291
11292   /* now depending on the sign of the source && destination */
11293   size = AOP_SIZE (result) - AOP_SIZE (right);
11294   /* if unsigned or not an integral type */
11295   /* also, if the source is a bit, we don't need to sign extend, because
11296    * it can't possibly have set the sign bit.
11297    */
11298   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11299     {
11300       while (size--)
11301         {
11302           aopPut (AOP (result), zero, offset++);
11303         }
11304     }
11305   else
11306     {
11307       /* we need to extend the sign :{ */
11308       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11309                         FALSE, FALSE, NULL));
11310       emitcode ("rlc", "a");
11311       emitcode ("subb", "a,acc");
11312       while (size--)
11313         aopPut (AOP (result), "a", offset++);
11314     }
11315
11316   /* we are done hurray !!!! */
11317
11318 release:
11319   freeAsmop (right, NULL, ic, TRUE);
11320   freeAsmop (result, NULL, ic, TRUE);
11321
11322 }
11323
11324 /*-----------------------------------------------------------------*/
11325 /* genDjnz - generate decrement & jump if not zero instrucion      */
11326 /*-----------------------------------------------------------------*/
11327 static int
11328 genDjnz (iCode * ic, iCode * ifx)
11329 {
11330   symbol *lbl, *lbl1;
11331   if (!ifx)
11332     return 0;
11333
11334   /* if the if condition has a false label
11335      then we cannot save */
11336   if (IC_FALSE (ifx))
11337     return 0;
11338
11339   /* if the minus is not of the form
11340      a = a - 1 */
11341   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11342       !IS_OP_LITERAL (IC_RIGHT (ic)))
11343     return 0;
11344
11345   if (operandLitValue (IC_RIGHT (ic)) != 1)
11346     return 0;
11347
11348   /* if the size of this greater than one then no
11349      saving */
11350   if (getSize (operandType (IC_RESULT (ic))) > 1)
11351     return 0;
11352
11353   /* otherwise we can save BIG */
11354   D(emitcode(";", "genDjnz"););
11355
11356   lbl = newiTempLabel (NULL);
11357   lbl1 = newiTempLabel (NULL);
11358
11359   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11360
11361   if (AOP_NEEDSACC(IC_RESULT(ic)))
11362   {
11363       /* If the result is accessed indirectly via
11364        * the accumulator, we must explicitly write
11365        * it back after the decrement.
11366        */
11367       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11368       
11369       if (strcmp(rByte, "a"))
11370       {
11371            /* Something is hopelessly wrong */
11372            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11373                    __FILE__, __LINE__);
11374            /* We can just give up; the generated code will be inefficient,
11375             * but what the hey.
11376             */
11377            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11378            return 0;
11379       }
11380       emitcode ("dec", "%s", rByte);
11381       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11382       emitcode ("jnz", "!tlabel", lbl->key + 100);
11383   }
11384   else if (IS_AOP_PREG (IC_RESULT (ic)))
11385     {
11386       emitcode ("dec", "%s",
11387                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11388       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11389       emitcode ("jnz", "!tlabel", lbl->key + 100);
11390     }
11391   else
11392     {
11393       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11394                 lbl->key + 100);
11395     }
11396   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11397   emitcode ("", "!tlabeldef", lbl->key + 100);
11398   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11399   emitcode ("", "!tlabeldef", lbl1->key + 100);
11400
11401   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11402   ifx->generated = 1;
11403   return 1;
11404 }
11405
11406 /*-----------------------------------------------------------------*/
11407 /* genReceive - generate code for a receive iCode                  */
11408 /*-----------------------------------------------------------------*/
11409 static void
11410 genReceive (iCode * ic)
11411 {
11412     int size = getSize (operandType (IC_RESULT (ic)));
11413     int offset = 0;
11414     int rb1off ;
11415     
11416     D (emitcode (";", "genReceive "););
11417
11418     if (ic->argreg == 1) 
11419     {
11420         /* first parameter */
11421         if (AOP_IS_STR(IC_RESULT(ic)))
11422         {
11423             /* Nothing to do: it's already in the proper place. */
11424             return;
11425         }
11426         else
11427         {
11428             bool useDp2;
11429             
11430             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11431                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11432                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11433             
11434             _G.accInUse++;
11435             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11436             _G.accInUse--; 
11437             
11438             /* Sanity checking... */
11439             if (AOP_USESDPTR(IC_RESULT(ic)))
11440             {
11441                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11442                         "genReceive got unexpected DPTR.");
11443             }
11444             assignResultValue (IC_RESULT (ic));
11445         }
11446     } 
11447     else 
11448     { 
11449         /* second receive onwards */
11450         /* this gets a little tricky since unused recevies will be
11451          eliminated, we have saved the reg in the type field . and
11452          we use that to figure out which register to use */
11453         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11454         rb1off = ic->argreg;
11455         while (size--) 
11456         {
11457             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11458         }
11459     }
11460     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11461 }
11462
11463 /*-----------------------------------------------------------------*/
11464 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11465 /*-----------------------------------------------------------------*/
11466 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11467 {
11468     operand *from , *to , *count;
11469     symbol *lbl;
11470     bitVect *rsave;
11471     int i;
11472
11473     /* we know it has to be 3 parameters */
11474     assert (nparms == 3);
11475     
11476     rsave = newBitVect(16);
11477     /* save DPTR if it needs to be saved */
11478     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11479             if (bitVectBitValue(ic->rMask,i))
11480                     rsave = bitVectSetBit(rsave,i);
11481     }
11482     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11483                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11484     savermask(rsave);
11485     
11486     to = parms[0];
11487     from = parms[1];
11488     count = parms[2];
11489
11490     aopOp (from, ic->next, FALSE, FALSE);
11491
11492     /* get from into DPTR1 */
11493     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11494     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11495     if (options.model == MODEL_FLAT24) {
11496         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11497     }
11498
11499     freeAsmop (from, NULL, ic, FALSE);
11500     aopOp (to, ic, FALSE, FALSE);
11501     /* get "to" into DPTR */
11502     /* if the operand is already in dptr
11503        then we do nothing else we move the value to dptr */
11504     if (AOP_TYPE (to) != AOP_STR) {
11505         /* if already in DPTR then we need to push */
11506         if (AOP_TYPE(to) == AOP_DPTR) {
11507             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11508             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11509             if (options.model == MODEL_FLAT24)
11510                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11511             emitcode ("pop", "dph");
11512             emitcode ("pop", "dpl");        
11513         } else {
11514             _startLazyDPSEvaluation ();
11515             /* if this is remateriazable */
11516             if (AOP_TYPE (to) == AOP_IMMD) {
11517                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11518             } else {                    /* we need to get it byte by byte */
11519                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11520                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11521                 if (options.model == MODEL_FLAT24) {
11522                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11523                 }
11524             }
11525             _endLazyDPSEvaluation ();
11526         }
11527     }
11528     freeAsmop (to, NULL, ic, FALSE);
11529     _G.dptrInUse = _G.dptr1InUse = 1;
11530     aopOp (count, ic->next->next, FALSE,FALSE);
11531     lbl =newiTempLabel(NULL);
11532
11533     /* now for the actual copy */
11534     if (AOP_TYPE(count) == AOP_LIT && 
11535         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11536         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11537         if (fromc) {
11538             emitcode ("lcall","__bi_memcpyc2x_s");
11539         } else {
11540             emitcode ("lcall","__bi_memcpyx2x_s");
11541         }
11542         freeAsmop (count, NULL, ic, FALSE);
11543     } else {
11544         symbol *lbl1 = newiTempLabel(NULL);
11545         
11546         emitcode (";"," Auto increment but no djnz");
11547         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11548         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11549         freeAsmop (count, NULL, ic, FALSE);
11550         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11551         emitcode ("","!tlabeldef",lbl->key+100);
11552         if (fromc) {
11553             emitcode ("clr","a");
11554             emitcode ("movc", "a,@a+dptr");
11555         } else 
11556             emitcode ("movx", "a,@dptr");
11557         emitcode ("movx", "@dptr,a");
11558         emitcode ("inc", "dptr");
11559         emitcode ("inc", "dptr");
11560         emitcode ("mov","a,b");
11561         emitcode ("orl","a,_ap");
11562         emitcode ("jz","!tlabel",lbl1->key+100);
11563         emitcode ("mov","a,_ap");
11564         emitcode ("add","a,#!constbyte",0xFF);
11565         emitcode ("mov","_ap,a");
11566         emitcode ("mov","a,b");
11567         emitcode ("addc","a,#!constbyte",0xFF);
11568         emitcode ("mov","b,a");
11569         emitcode ("sjmp","!tlabel",lbl->key+100);
11570         emitcode ("","!tlabeldef",lbl1->key+100);
11571     }
11572     emitcode ("mov", "dps,#0"); 
11573     _G.dptrInUse = _G.dptr1InUse = 0;
11574     unsavermask(rsave);
11575
11576 }
11577
11578 /*-----------------------------------------------------------------*/
11579 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11580 /*-----------------------------------------------------------------*/
11581 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11582 {
11583     operand *from , *to , *count;
11584     symbol *lbl,*lbl2;
11585     bitVect *rsave;
11586     int i;
11587
11588     /* we know it has to be 3 parameters */
11589     assert (nparms == 3);
11590     
11591     rsave = newBitVect(16);
11592     /* save DPTR if it needs to be saved */
11593     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11594             if (bitVectBitValue(ic->rMask,i))
11595                     rsave = bitVectSetBit(rsave,i);
11596     }
11597     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11598                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11599     savermask(rsave);
11600     
11601     to = parms[0];
11602     from = parms[1];
11603     count = parms[2];
11604
11605     aopOp (from, ic->next, FALSE, FALSE);
11606
11607     /* get from into DPTR1 */
11608     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11609     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11610     if (options.model == MODEL_FLAT24) {
11611         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11612     }
11613
11614     freeAsmop (from, NULL, ic, FALSE);
11615     aopOp (to, ic, FALSE, FALSE);
11616     /* get "to" into DPTR */
11617     /* if the operand is already in dptr
11618        then we do nothing else we move the value to dptr */
11619     if (AOP_TYPE (to) != AOP_STR) {
11620         /* if already in DPTR then we need to push */
11621         if (AOP_TYPE(to) == AOP_DPTR) {
11622             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11623             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11624             if (options.model == MODEL_FLAT24)
11625                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11626             emitcode ("pop", "dph");
11627             emitcode ("pop", "dpl");        
11628         } else {
11629             _startLazyDPSEvaluation ();
11630             /* if this is remateriazable */
11631             if (AOP_TYPE (to) == AOP_IMMD) {
11632                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11633             } else {                    /* we need to get it byte by byte */
11634                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11635                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11636                 if (options.model == MODEL_FLAT24) {
11637                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11638                 }
11639             }
11640             _endLazyDPSEvaluation ();
11641         }
11642     }
11643     freeAsmop (to, NULL, ic, FALSE);
11644     _G.dptrInUse = _G.dptr1InUse = 1;
11645     aopOp (count, ic->next->next, FALSE,FALSE);
11646     lbl =newiTempLabel(NULL);
11647     lbl2 =newiTempLabel(NULL);
11648
11649     /* now for the actual compare */
11650     if (AOP_TYPE(count) == AOP_LIT && 
11651         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11652         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11653         if (fromc)
11654             emitcode("lcall","__bi_memcmpc2x_s");
11655         else
11656             emitcode("lcall","__bi_memcmpx2x_s");
11657         freeAsmop (count, NULL, ic, FALSE);
11658         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11659         aopPut(AOP(IC_RESULT(ic)),"a",0);
11660         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11661     } else {
11662         symbol *lbl1 = newiTempLabel(NULL);
11663
11664         emitcode("push","ar0");         
11665         emitcode (";"," Auto increment but no djnz");
11666         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11667         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11668         freeAsmop (count, NULL, ic, FALSE);
11669         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11670         emitcode ("","!tlabeldef",lbl->key+100);
11671         if (fromc) {
11672             emitcode ("clr","a");
11673             emitcode ("movc", "a,@a+dptr");
11674         } else 
11675             emitcode ("movx", "a,@dptr");
11676         emitcode ("mov","r0,a");
11677         emitcode ("movx", "a,@dptr");
11678         emitcode ("clr","c");
11679         emitcode ("subb","a,r0");
11680         emitcode ("jnz","!tlabel",lbl2->key+100);
11681         emitcode ("inc", "dptr");
11682         emitcode ("inc", "dptr");
11683         emitcode ("mov","a,b");
11684         emitcode ("orl","a,_ap");
11685         emitcode ("jz","!tlabel",lbl1->key+100);
11686         emitcode ("mov","a,_ap");
11687         emitcode ("add","a,#!constbyte",0xFF);
11688         emitcode ("mov","_ap,a");
11689         emitcode ("mov","a,b");
11690         emitcode ("addc","a,#!constbyte",0xFF);
11691         emitcode ("mov","b,a");
11692         emitcode ("sjmp","!tlabel",lbl->key+100);
11693         emitcode ("","!tlabeldef",lbl1->key+100);
11694         emitcode ("clr","a");
11695         emitcode ("","!tlabeldef",lbl2->key+100);
11696         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11697         aopPut(AOP(IC_RESULT(ic)),"a",0);
11698         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11699         emitcode("pop","ar0");
11700         emitcode ("mov", "dps,#0");      
11701     }
11702     _G.dptrInUse = _G.dptr1InUse = 0;
11703     unsavermask(rsave);
11704
11705 }
11706
11707 /*-----------------------------------------------------------------*/
11708 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11709 /* port, first parameter output area second parameter pointer to   */
11710 /* port third parameter count                                      */
11711 /*-----------------------------------------------------------------*/
11712 static void genInp( iCode *ic, int nparms, operand **parms)
11713 {
11714     operand *from , *to , *count;
11715     symbol *lbl;
11716     bitVect *rsave;
11717     int i;
11718
11719     /* we know it has to be 3 parameters */
11720     assert (nparms == 3);
11721     
11722     rsave = newBitVect(16);
11723     /* save DPTR if it needs to be saved */
11724     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11725             if (bitVectBitValue(ic->rMask,i))
11726                     rsave = bitVectSetBit(rsave,i);
11727     }
11728     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11729                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11730     savermask(rsave);
11731     
11732     to = parms[0];
11733     from = parms[1];
11734     count = parms[2];
11735
11736     aopOp (from, ic->next, FALSE, FALSE);
11737
11738     /* get from into DPTR1 */
11739     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11740     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11741     if (options.model == MODEL_FLAT24) {
11742         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11743     }
11744
11745     freeAsmop (from, NULL, ic, FALSE);
11746     aopOp (to, ic, FALSE, FALSE);
11747     /* get "to" into DPTR */
11748     /* if the operand is already in dptr
11749        then we do nothing else we move the value to dptr */
11750     if (AOP_TYPE (to) != AOP_STR) {
11751         /* if already in DPTR then we need to push */
11752         if (AOP_TYPE(to) == AOP_DPTR) {
11753             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11754             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11755             if (options.model == MODEL_FLAT24)
11756                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11757             emitcode ("pop", "dph");
11758             emitcode ("pop", "dpl");        
11759         } else {
11760             _startLazyDPSEvaluation ();
11761             /* if this is remateriazable */
11762             if (AOP_TYPE (to) == AOP_IMMD) {
11763                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11764             } else {                    /* we need to get it byte by byte */
11765                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11766                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11767                 if (options.model == MODEL_FLAT24) {
11768                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11769                 }
11770             }
11771             _endLazyDPSEvaluation ();
11772         }
11773     }
11774     freeAsmop (to, NULL, ic, FALSE);
11775
11776     _G.dptrInUse = _G.dptr1InUse = 1;
11777     aopOp (count, ic->next->next, FALSE,FALSE);
11778     lbl =newiTempLabel(NULL);
11779
11780     /* now for the actual copy */
11781     if (AOP_TYPE(count) == AOP_LIT && 
11782         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11783         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11784         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11785         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11786         freeAsmop (count, NULL, ic, FALSE);
11787         emitcode ("","!tlabeldef",lbl->key+100);
11788         emitcode ("movx", "a,@dptr");   /* read data from port */
11789         emitcode ("dec","dps");         /* switch to DPTR */
11790         emitcode ("movx", "@dptr,a");   /* save into location */
11791         emitcode ("inc", "dptr");       /* point to next area */
11792         emitcode ("inc","dps");         /* switch to DPTR2 */
11793         emitcode ("djnz","b,!tlabel",lbl->key+100);
11794     } else {
11795         symbol *lbl1 = newiTempLabel(NULL);
11796         
11797         emitcode (";"," Auto increment but no djnz");
11798         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11799         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11800         freeAsmop (count, NULL, ic, FALSE);
11801         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11802         emitcode ("","!tlabeldef",lbl->key+100);
11803         emitcode ("movx", "a,@dptr");
11804         emitcode ("dec","dps");         /* switch to DPTR */
11805         emitcode ("movx", "@dptr,a");
11806         emitcode ("inc", "dptr");
11807         emitcode ("inc","dps");         /* switch to DPTR2 */
11808 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11809 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11810         emitcode ("mov","a,b");
11811         emitcode ("orl","a,_ap");
11812         emitcode ("jz","!tlabel",lbl1->key+100);
11813         emitcode ("mov","a,_ap");
11814         emitcode ("add","a,#!constbyte",0xFF);
11815         emitcode ("mov","_ap,a");
11816         emitcode ("mov","a,b");
11817         emitcode ("addc","a,#!constbyte",0xFF);
11818         emitcode ("mov","b,a");
11819         emitcode ("sjmp","!tlabel",lbl->key+100);
11820         emitcode ("","!tlabeldef",lbl1->key+100);
11821     }
11822     emitcode ("mov", "dps,#0"); 
11823     _G.dptrInUse = _G.dptr1InUse = 0;
11824     unsavermask(rsave);
11825
11826 }
11827
11828 /*-----------------------------------------------------------------*/
11829 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11830 /* port, first parameter output area second parameter pointer to   */
11831 /* port third parameter count                                      */
11832 /*-----------------------------------------------------------------*/
11833 static void genOutp( iCode *ic, int nparms, operand **parms)
11834 {
11835     operand *from , *to , *count;
11836     symbol *lbl;
11837     bitVect *rsave;
11838     int i;
11839
11840     /* we know it has to be 3 parameters */
11841     assert (nparms == 3);
11842     
11843     rsave = newBitVect(16);
11844     /* save DPTR if it needs to be saved */
11845     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11846             if (bitVectBitValue(ic->rMask,i))
11847                     rsave = bitVectSetBit(rsave,i);
11848     }
11849     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11850                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11851     savermask(rsave);
11852     
11853     to = parms[0];
11854     from = parms[1];
11855     count = parms[2];
11856
11857     aopOp (from, ic->next, FALSE, FALSE);
11858
11859     /* get from into DPTR1 */
11860     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11861     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11862     if (options.model == MODEL_FLAT24) {
11863         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11864     }
11865
11866     freeAsmop (from, NULL, ic, FALSE);
11867     aopOp (to, ic, FALSE, FALSE);
11868     /* get "to" into DPTR */
11869     /* if the operand is already in dptr
11870        then we do nothing else we move the value to dptr */
11871     if (AOP_TYPE (to) != AOP_STR) {
11872         /* if already in DPTR then we need to push */
11873         if (AOP_TYPE(to) == AOP_DPTR) {
11874             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11875             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11876             if (options.model == MODEL_FLAT24)
11877                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11878             emitcode ("pop", "dph");
11879             emitcode ("pop", "dpl");        
11880         } else {
11881             _startLazyDPSEvaluation ();
11882             /* if this is remateriazable */
11883             if (AOP_TYPE (to) == AOP_IMMD) {
11884                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11885             } else {                    /* we need to get it byte by byte */
11886                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11887                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11888                 if (options.model == MODEL_FLAT24) {
11889                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11890                 }
11891             }
11892             _endLazyDPSEvaluation ();
11893         }
11894     }
11895     freeAsmop (to, NULL, ic, FALSE);
11896
11897     _G.dptrInUse = _G.dptr1InUse = 1;
11898     aopOp (count, ic->next->next, FALSE,FALSE);
11899     lbl =newiTempLabel(NULL);
11900
11901     /* now for the actual copy */
11902     if (AOP_TYPE(count) == AOP_LIT && 
11903         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11904         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11905         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11906         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11907         emitcode ("","!tlabeldef",lbl->key+100);
11908         emitcode ("movx", "a,@dptr");   /* read data from port */
11909         emitcode ("inc","dps");         /* switch to DPTR2 */
11910         emitcode ("movx", "@dptr,a");   /* save into location */
11911         emitcode ("inc", "dptr");       /* point to next area */
11912         emitcode ("dec","dps");         /* switch to DPTR */
11913         emitcode ("djnz","b,!tlabel",lbl->key+100);
11914         freeAsmop (count, NULL, ic, FALSE);
11915     } else {
11916         symbol *lbl1 = newiTempLabel(NULL);
11917         
11918         emitcode (";"," Auto increment but no djnz");
11919         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11920         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11921         freeAsmop (count, NULL, ic, FALSE);
11922         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11923         emitcode ("","!tlabeldef",lbl->key+100);
11924         emitcode ("movx", "a,@dptr");
11925         emitcode ("inc", "dptr");
11926         emitcode ("inc","dps");         /* switch to DPTR2 */
11927         emitcode ("movx", "@dptr,a");
11928         emitcode ("dec","dps");         /* switch to DPTR */
11929         emitcode ("mov","a,b");
11930         emitcode ("orl","a,_ap");
11931         emitcode ("jz","!tlabel",lbl1->key+100);
11932         emitcode ("mov","a,_ap");
11933         emitcode ("add","a,#!constbyte",0xFF);
11934         emitcode ("mov","_ap,a");
11935         emitcode ("mov","a,b");
11936         emitcode ("addc","a,#!constbyte",0xFF);
11937         emitcode ("mov","b,a");
11938         emitcode ("sjmp","!tlabel",lbl->key+100);
11939         emitcode ("","!tlabeldef",lbl1->key+100);
11940     }
11941     emitcode ("mov", "dps,#0"); 
11942     _G.dptrInUse = _G.dptr1InUse = 0;
11943     unsavermask(rsave);
11944
11945 }
11946
11947 /*-----------------------------------------------------------------*/
11948 /* genSwapW - swap lower & high order bytes                        */
11949 /*-----------------------------------------------------------------*/
11950 static void genSwapW(iCode *ic, int nparms, operand **parms)
11951 {
11952     operand *dest;
11953     operand *src;
11954     assert (nparms==1);
11955
11956     src = parms[0];
11957     dest=IC_RESULT(ic);
11958
11959     assert(getSize(operandType(src))==2);
11960
11961     aopOp (src, ic, FALSE, FALSE);
11962     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11963     _G.accInUse++;
11964     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11965     _G.accInUse--;
11966     freeAsmop (src, NULL, ic, FALSE);
11967     
11968     aopOp (dest,ic, FALSE, FALSE);
11969     aopPut(AOP(dest),"b",0);
11970     aopPut(AOP(dest),"a",1);
11971     freeAsmop (dest, NULL, ic, FALSE);    
11972 }
11973
11974 /*-----------------------------------------------------------------*/
11975 /* genMemsetX - gencode for memSetX data                           */
11976 /*-----------------------------------------------------------------*/
11977 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11978 {
11979     operand *to , *val , *count;
11980     symbol *lbl;
11981     char *l;
11982     int i;
11983     bitVect *rsave;
11984
11985     /* we know it has to be 3 parameters */
11986     assert (nparms == 3);
11987     
11988     to = parms[0];
11989     val = parms[1];
11990     count = parms[2];
11991         
11992     /* save DPTR if it needs to be saved */
11993     rsave = newBitVect(16);
11994     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11995             if (bitVectBitValue(ic->rMask,i))
11996                     rsave = bitVectSetBit(rsave,i);
11997     }
11998     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11999                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12000     savermask(rsave);
12001
12002     aopOp (to, ic, FALSE, FALSE);
12003     /* get "to" into DPTR */
12004     /* if the operand is already in dptr
12005        then we do nothing else we move the value to dptr */
12006     if (AOP_TYPE (to) != AOP_STR) {
12007         /* if already in DPTR then we need to push */
12008         if (AOP_TYPE(to) == AOP_DPTR) {
12009             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12010             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12011             if (options.model == MODEL_FLAT24)
12012                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12013             emitcode ("pop", "dph");
12014             emitcode ("pop", "dpl");        
12015         } else {
12016             _startLazyDPSEvaluation ();
12017             /* if this is remateriazable */
12018             if (AOP_TYPE (to) == AOP_IMMD) {
12019                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12020             } else {                    /* we need to get it byte by byte */
12021                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12022                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12023                 if (options.model == MODEL_FLAT24) {
12024                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12025                 }
12026             }
12027             _endLazyDPSEvaluation ();
12028         }
12029     }
12030     freeAsmop (to, NULL, ic, FALSE);
12031
12032     aopOp (val, ic->next->next, FALSE,FALSE);
12033     aopOp (count, ic->next->next, FALSE,FALSE);    
12034     lbl =newiTempLabel(NULL);
12035     /* now for the actual copy */
12036     if (AOP_TYPE(count) == AOP_LIT && 
12037         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12038         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12039         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12040         MOVA(l);
12041         emitcode ("","!tlabeldef",lbl->key+100);
12042         emitcode ("movx", "@dptr,a");
12043         emitcode ("inc", "dptr");
12044         emitcode ("djnz","b,!tlabel",lbl->key+100);
12045     } else {
12046         symbol *lbl1 = newiTempLabel(NULL);
12047         
12048         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12049         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12050         emitcode ("","!tlabeldef",lbl->key+100);
12051         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12052         emitcode ("movx", "@dptr,a");
12053         emitcode ("inc", "dptr");
12054         emitcode ("mov","a,b");
12055         emitcode ("orl","a,_ap");
12056         emitcode ("jz","!tlabel",lbl1->key+100);
12057         emitcode ("mov","a,_ap");
12058         emitcode ("add","a,#!constbyte",0xFF);
12059         emitcode ("mov","_ap,a");
12060         emitcode ("mov","a,b");
12061         emitcode ("addc","a,#!constbyte",0xFF);
12062         emitcode ("mov","b,a");
12063         emitcode ("sjmp","!tlabel",lbl->key+100);
12064         emitcode ("","!tlabeldef",lbl1->key+100);
12065     }
12066     freeAsmop (count, NULL, ic, FALSE);
12067     unsavermask(rsave);
12068 }
12069
12070 /*-----------------------------------------------------------------*/
12071 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12072 /*-----------------------------------------------------------------*/
12073 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12074 {
12075         bitVect *rsave ;
12076         operand *pnum, *result;
12077         int i;
12078     
12079         assert (nparms==1);
12080         /* save registers that need to be saved */
12081         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12082                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12083     
12084         pnum = parms[0]; 
12085         aopOp (pnum, ic, FALSE, FALSE);
12086         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12087         freeAsmop (pnum, NULL, ic, FALSE);
12088         emitcode ("lcall","NatLib_LoadPrimitive");
12089         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12090         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12091             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12092                 for (i = (size-1) ; i >= 0 ; i-- ) {
12093                         emitcode ("push","a%s",javaRet[i]);
12094                 }
12095                 for (i=0; i < size ; i++ ) {
12096                         emitcode ("pop","a%s",
12097                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12098                 }
12099         } else {
12100                 for (i = 0 ; i < size ; i++ ) {
12101                         aopPut(AOP(result),javaRet[i],i);
12102                 }
12103         }    
12104         freeAsmop (result, NULL, ic, FALSE);
12105         unsavermask(rsave);
12106 }
12107
12108 /*-----------------------------------------------------------------*/
12109 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12110 /*-----------------------------------------------------------------*/
12111 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12112 {
12113         bitVect *rsave ;
12114         operand *pnum, *result;
12115         int size = 3;
12116         int i;
12117     
12118         assert (nparms==1);
12119         /* save registers that need to be saved */
12120         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12122     
12123         pnum = parms[0]; 
12124         aopOp (pnum, ic, FALSE, FALSE);
12125         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12126         freeAsmop (pnum, NULL, ic, FALSE);
12127         emitcode ("lcall","NatLib_LoadPointer");
12128         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12129         if (AOP_TYPE(result)!=AOP_STR) {
12130                 for (i = 0 ; i < size ; i++ ) {
12131                         aopPut(AOP(result),fReturn[i],i);
12132                 }
12133         }    
12134         freeAsmop (result, NULL, ic, FALSE);
12135         unsavermask(rsave);
12136 }
12137
12138 /*-----------------------------------------------------------------*/
12139 /* genNatLibInstallStateBlock -                                    */
12140 /*-----------------------------------------------------------------*/
12141 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12142                                        operand **parms, const char *name)
12143 {
12144         bitVect *rsave ;
12145         operand *psb, *handle;
12146         assert (nparms==2);
12147
12148         /* save registers that need to be saved */
12149         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12150                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12151         psb = parms[0];
12152         handle = parms[1];
12153
12154         /* put pointer to state block into DPTR1 */
12155         aopOp (psb, ic, FALSE, FALSE);
12156         if (AOP_TYPE (psb) == AOP_IMMD) {
12157                 emitcode ("mov","dps,#1");
12158                 emitcode ("mov", "dptr,%s",
12159                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12160                 emitcode ("mov","dps,#0");
12161         } else {
12162                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12163                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12164                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12165         }
12166         freeAsmop (psb, NULL, ic, FALSE);
12167
12168         /* put libraryID into DPTR */
12169         emitcode ("mov","dptr,#LibraryID");
12170
12171         /* put handle into r3:r2 */
12172         aopOp (handle, ic, FALSE, FALSE);
12173         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12174                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12175                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12176                 emitcode ("pop","ar3");
12177                 emitcode ("pop","ar2");
12178         } else {        
12179                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12180                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12181         }
12182         freeAsmop (psb, NULL, ic, FALSE);
12183
12184         /* make the call */
12185         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12186
12187         /* put return value into place*/
12188         _G.accInUse++;
12189         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12190         _G.accInUse--;
12191         aopPut(AOP(IC_RESULT(ic)),"a",0);
12192         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12193         unsavermask(rsave);
12194 }
12195
12196 /*-----------------------------------------------------------------*/
12197 /* genNatLibRemoveStateBlock -                                     */
12198 /*-----------------------------------------------------------------*/
12199 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12200 {
12201         bitVect *rsave ;
12202
12203         assert(nparms==0);
12204
12205         /* save registers that need to be saved */
12206         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12207                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12208
12209         /* put libraryID into DPTR */
12210         emitcode ("mov","dptr,#LibraryID");
12211         /* make the call */
12212         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12213         unsavermask(rsave);
12214 }
12215
12216 /*-----------------------------------------------------------------*/
12217 /* genNatLibGetStateBlock -                                        */
12218 /*-----------------------------------------------------------------*/
12219 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12220                                    operand **parms,const char *name)
12221 {
12222         bitVect *rsave ;
12223         symbol *lbl = newiTempLabel(NULL);
12224         
12225         assert(nparms==0);
12226         /* save registers that need to be saved */
12227         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12228                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12229
12230         /* put libraryID into DPTR */
12231         emitcode ("mov","dptr,#LibraryID");
12232         /* make the call */
12233         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12234         emitcode ("jnz","!tlabel",lbl->key+100);
12235
12236         /* put return value into place */
12237         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12238         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12239                 emitcode ("push","ar3");
12240                 emitcode ("push","ar2");
12241                 emitcode ("pop","%s",
12242                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12243                 emitcode ("pop","%s",
12244                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12245         } else {
12246                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12247                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12248         }
12249         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12250         emitcode ("","!tlabeldef",lbl->key+100);
12251         unsavermask(rsave);
12252 }
12253
12254 /*-----------------------------------------------------------------*/
12255 /* genMMMalloc -                                                   */
12256 /*-----------------------------------------------------------------*/
12257 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12258                          int size, const char *name)
12259 {
12260         bitVect *rsave ;
12261         operand *bsize;
12262         symbol *rsym;
12263         symbol *lbl = newiTempLabel(NULL);
12264
12265         assert (nparms == 1);
12266         /* save registers that need to be saved */
12267         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12268                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12269         
12270         bsize=parms[0];
12271         aopOp (bsize,ic,FALSE,FALSE);
12272
12273         /* put the size in R4-R2 */
12274         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12275                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12276                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12277                 if (size==3) {
12278                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12279                         emitcode("pop","ar4");
12280                 }
12281                 emitcode("pop","ar3");
12282                 emitcode("pop","ar2");          
12283         } else {
12284                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12285                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12286                 if (size==3) {
12287                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12288                 }
12289         }
12290         freeAsmop (bsize, NULL, ic, FALSE);
12291
12292         /* make the call */
12293         emitcode ("lcall","MM_%s",name);
12294         emitcode ("jz","!tlabel",lbl->key+100);
12295         emitcode ("mov","r2,#!constbyte",0xff);
12296         emitcode ("mov","r3,#!constbyte",0xff);
12297         emitcode ("","!tlabeldef",lbl->key+100);
12298         /* we don't care about the pointer : we just save the handle */
12299         rsym = OP_SYMBOL(IC_RESULT(ic));
12300         if (rsym->liveFrom != rsym->liveTo) {
12301                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12302                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12303                         emitcode ("push","ar3");
12304                         emitcode ("push","ar2");
12305                         emitcode ("pop","%s",
12306                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12307                         emitcode ("pop","%s",
12308                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12309                 } else {
12310                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12311                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12312                 }
12313                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12314         }
12315         unsavermask(rsave);
12316 }
12317
12318 /*-----------------------------------------------------------------*/
12319 /* genMMDeref -                                                    */
12320 /*-----------------------------------------------------------------*/
12321 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12322 {
12323         bitVect *rsave ;
12324         operand *handle;
12325
12326         assert (nparms == 1);
12327         /* save registers that need to be saved */
12328         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12329                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12330         
12331         handle=parms[0];
12332         aopOp (handle,ic,FALSE,FALSE);
12333
12334         /* put the size in R4-R2 */
12335         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12336                 emitcode("push","%s",
12337                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12338                 emitcode("push","%s",
12339                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12340                 emitcode("pop","ar3");
12341                 emitcode("pop","ar2");          
12342         } else {
12343                 emitcode ("mov","r2,%s",
12344                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12345                 emitcode ("mov","r3,%s",
12346                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12347         }
12348         freeAsmop (handle, NULL, ic, FALSE);
12349
12350         /* make the call */
12351         emitcode ("lcall","MM_Deref");
12352         
12353         {
12354                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12355                 if (rsym->liveFrom != rsym->liveTo) {                   
12356                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12357                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12358                             _startLazyDPSEvaluation ();
12359                             
12360                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12361                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12362                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12363
12364                             _endLazyDPSEvaluation ();
12365                             
12366                         }
12367                 }
12368         }
12369         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12370         unsavermask(rsave);
12371 }
12372
12373 /*-----------------------------------------------------------------*/
12374 /* genMMUnrestrictedPersist -                                      */
12375 /*-----------------------------------------------------------------*/
12376 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12377 {
12378         bitVect *rsave ;
12379         operand *handle;
12380
12381         assert (nparms == 1);
12382         /* save registers that need to be saved */
12383         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12384                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12385         
12386         handle=parms[0];
12387         aopOp (handle,ic,FALSE,FALSE);
12388
12389         /* put the size in R3-R2 */
12390         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12391                 emitcode("push","%s",
12392                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12393                 emitcode("push","%s",
12394                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12395                 emitcode("pop","ar3");
12396                 emitcode("pop","ar2");          
12397         } else {
12398                 emitcode ("mov","r2,%s",
12399                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12400                 emitcode ("mov","r3,%s",
12401                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12402         }
12403         freeAsmop (handle, NULL, ic, FALSE);
12404
12405         /* make the call */
12406         emitcode ("lcall","MM_UnrestrictedPersist");
12407
12408         {
12409                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12410                 if (rsym->liveFrom != rsym->liveTo) {   
12411                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12412                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12413                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12414                 }
12415         }
12416         unsavermask(rsave);
12417 }
12418
12419 /*-----------------------------------------------------------------*/
12420 /* genSystemExecJavaProcess -                                      */
12421 /*-----------------------------------------------------------------*/
12422 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12423 {
12424         bitVect *rsave ;
12425         operand *handle, *pp;
12426
12427         assert (nparms==2);
12428         /* save registers that need to be saved */
12429         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12430                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12431         
12432         pp = parms[0];
12433         handle = parms[1];
12434         
12435         /* put the handle in R3-R2 */
12436         aopOp (handle,ic,FALSE,FALSE);
12437         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12438                 emitcode("push","%s",
12439                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12440                 emitcode("push","%s",
12441                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12442                 emitcode("pop","ar3");
12443                 emitcode("pop","ar2");          
12444         } else {
12445                 emitcode ("mov","r2,%s",
12446                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12447                 emitcode ("mov","r3,%s",
12448                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12449         }
12450         freeAsmop (handle, NULL, ic, FALSE);
12451         
12452         /* put pointer in DPTR */
12453         aopOp (pp,ic,FALSE,FALSE);
12454         if (AOP_TYPE(pp) == AOP_IMMD) {
12455                 emitcode ("mov", "dptr,%s",
12456                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12457         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12458                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12459                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12460                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12461         }
12462         freeAsmop (handle, NULL, ic, FALSE);
12463
12464         /* make the call */
12465         emitcode ("lcall","System_ExecJavaProcess");
12466         
12467         /* put result in place */
12468         {
12469                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12470                 if (rsym->liveFrom != rsym->liveTo) {   
12471                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12472                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12473                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12474                 }
12475         }
12476         
12477         unsavermask(rsave);
12478 }
12479
12480 /*-----------------------------------------------------------------*/
12481 /* genSystemRTCRegisters -                                         */
12482 /*-----------------------------------------------------------------*/
12483 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12484                                   char *name)
12485 {
12486         bitVect *rsave ;
12487         operand *pp;
12488
12489         assert (nparms==1);
12490         /* save registers that need to be saved */
12491         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12492                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12493         
12494         pp=parms[0];
12495         /* put pointer in DPTR */
12496         aopOp (pp,ic,FALSE,FALSE);
12497         if (AOP_TYPE (pp) == AOP_IMMD) {
12498                 emitcode ("mov","dps,#1");
12499                 emitcode ("mov", "dptr,%s", 
12500                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12501                 emitcode ("mov","dps,#0");
12502         } else {
12503                 emitcode ("mov","dpl1,%s",
12504                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12505                 emitcode ("mov","dph1,%s",
12506                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12507                 emitcode ("mov","dpx1,%s",
12508                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12509         }
12510         freeAsmop (pp, NULL, ic, FALSE);
12511
12512         /* make the call */
12513         emitcode ("lcall","System_%sRTCRegisters",name);
12514
12515         unsavermask(rsave);
12516 }
12517
12518 /*-----------------------------------------------------------------*/
12519 /* genSystemThreadSleep -                                          */
12520 /*-----------------------------------------------------------------*/
12521 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12522 {
12523         bitVect *rsave ;
12524         operand *to, *s;
12525
12526         assert (nparms==1);
12527         /* save registers that need to be saved */
12528         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12529                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12530
12531         to = parms[0];
12532         aopOp(to,ic,FALSE,FALSE);
12533         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12534             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12535                 emitcode ("push","%s",
12536                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12537                 emitcode ("push","%s",
12538                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12539                 emitcode ("push","%s",
12540                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12541                 emitcode ("push","%s",
12542                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12543                 emitcode ("pop","ar3");
12544                 emitcode ("pop","ar2");
12545                 emitcode ("pop","ar1");
12546                 emitcode ("pop","ar0");
12547         } else {
12548                 emitcode ("mov","r0,%s",
12549                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12550                 emitcode ("mov","r1,%s",
12551                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12552                 emitcode ("mov","r2,%s",
12553                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12554                 emitcode ("mov","r3,%s",
12555                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12556         }
12557         freeAsmop (to, NULL, ic, FALSE);
12558
12559         /* suspend in acc */
12560         s = parms[1];
12561         aopOp(s,ic,FALSE,FALSE);
12562         emitcode ("mov","a,%s",
12563                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12564         freeAsmop (s, NULL, ic, FALSE);
12565
12566         /* make the call */
12567         emitcode ("lcall","System_%s",name);
12568
12569         unsavermask(rsave);
12570 }
12571
12572 /*-----------------------------------------------------------------*/
12573 /* genSystemThreadResume -                                         */
12574 /*-----------------------------------------------------------------*/
12575 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12576 {
12577         bitVect *rsave ;
12578         operand *tid,*pid;
12579
12580         assert (nparms==2);
12581         /* save registers that need to be saved */
12582         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12583                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12584         
12585         tid = parms[0];
12586         pid = parms[1];
12587         
12588         /* PID in R0 */
12589         aopOp(pid,ic,FALSE,FALSE);
12590         emitcode ("mov","r0,%s",
12591                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12592         freeAsmop (pid, NULL, ic, FALSE);
12593         
12594         /* tid into ACC */
12595         aopOp(tid,ic,FALSE,FALSE);
12596         emitcode ("mov","a,%s",
12597                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12598         freeAsmop (tid, NULL, ic, FALSE);
12599         
12600         emitcode ("lcall","System_ThreadResume");
12601
12602         /* put result into place */
12603         {
12604                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12605                 if (rsym->liveFrom != rsym->liveTo) {   
12606                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12607                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12608                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12609                 }
12610         }
12611         unsavermask(rsave);
12612 }
12613
12614 /*-----------------------------------------------------------------*/
12615 /* genSystemProcessResume -                                        */
12616 /*-----------------------------------------------------------------*/
12617 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12618 {
12619         bitVect *rsave ;
12620         operand *pid;
12621
12622         assert (nparms==1);
12623         /* save registers that need to be saved */
12624         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12625                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12626         
12627         pid = parms[0];
12628         
12629         /* pid into ACC */
12630         aopOp(pid,ic,FALSE,FALSE);
12631         emitcode ("mov","a,%s",
12632                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12633         freeAsmop (pid, NULL, ic, FALSE);
12634         
12635         emitcode ("lcall","System_ProcessResume");
12636
12637         unsavermask(rsave);
12638 }
12639
12640 /*-----------------------------------------------------------------*/
12641 /* genSystem -                                                     */
12642 /*-----------------------------------------------------------------*/
12643 static void genSystem (iCode *ic,int nparms,char *name)
12644 {
12645         assert(nparms == 0);
12646
12647         emitcode ("lcall","System_%s",name);
12648 }
12649
12650 /*-----------------------------------------------------------------*/
12651 /* genSystemPoll -                                                  */
12652 /*-----------------------------------------------------------------*/
12653 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12654 {
12655         bitVect *rsave ;
12656         operand *fp;
12657
12658         assert (nparms==1);
12659         /* save registers that need to be saved */
12660         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12661                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12662
12663         fp = parms[0];
12664         aopOp (fp,ic,FALSE,FALSE);
12665         if (AOP_TYPE (fp) == AOP_IMMD) {
12666                 emitcode ("mov", "dptr,%s", 
12667                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12668         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12669                 emitcode ("mov","dpl,%s",
12670                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12671                 emitcode ("mov","dph,%s",
12672                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12673                 emitcode ("mov","dpx,%s",
12674                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12675         }
12676         freeAsmop (fp, NULL, ic, FALSE);
12677
12678         emitcode ("lcall","System_%sPoll",name);
12679
12680         /* put result into place */
12681         {
12682                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12683                 if (rsym->liveFrom != rsym->liveTo) {   
12684                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12685                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12686                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12687                 }
12688         }
12689         unsavermask(rsave);
12690 }
12691
12692 /*-----------------------------------------------------------------*/
12693 /* genSystemGetCurrentID -                                         */
12694 /*-----------------------------------------------------------------*/
12695 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12696 {
12697         assert (nparms==0);
12698
12699         emitcode ("lcall","System_GetCurrent%sId",name);
12700         /* put result into place */
12701         {
12702                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12703                 if (rsym->liveFrom != rsym->liveTo) {   
12704                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12705                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12706                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12707                 }
12708         }
12709 }
12710
12711 /*-----------------------------------------------------------------*/
12712 /* genDummyRead - generate code for dummy read of volatiles        */
12713 /*-----------------------------------------------------------------*/
12714 static void
12715 genDummyRead (iCode * ic)
12716 {
12717   operand *op;
12718   int size, offset;
12719
12720   D(emitcode(";     genDummyRead",""));
12721
12722   op = IC_RIGHT (ic);
12723   if (op && IS_SYMOP (op))
12724     {
12725       aopOp (op, ic, FALSE, FALSE);
12726
12727       /* if the result is a bit */
12728       if (AOP_TYPE (op) == AOP_CRY)
12729         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12730       else
12731         {
12732           /* bit variables done */
12733           /* general case */
12734           size = AOP_SIZE (op);
12735           offset = 0;
12736           while (size--)
12737           {
12738             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12739             offset++;
12740           }
12741         }
12742
12743       freeAsmop (op, NULL, ic, TRUE);
12744     }
12745
12746   op = IC_LEFT (ic);
12747   if (op && IS_SYMOP (op))
12748     {
12749       aopOp (op, ic, FALSE, FALSE);
12750
12751       /* if the result is a bit */
12752       if (AOP_TYPE (op) == AOP_CRY)
12753         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12754       else
12755         {
12756           /* bit variables done */
12757           /* general case */
12758           size = AOP_SIZE (op);
12759           offset = 0;
12760           while (size--)
12761           {
12762             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12763             offset++;
12764           }
12765         }
12766
12767       freeAsmop (op, NULL, ic, TRUE);
12768     }
12769     
12770 }
12771
12772 /*-----------------------------------------------------------------*/
12773 /* genCritical - generate code for start of a critical sequence    */
12774 /*-----------------------------------------------------------------*/
12775 static void
12776 genCritical (iCode *ic)
12777 {
12778   symbol *tlbl = newiTempLabel (NULL);
12779
12780   D(emitcode(";     genCritical",""));
12781   
12782   if (IC_RESULT (ic))
12783     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12784
12785   emitcode ("setb", "c");
12786   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12787   emitcode ("clr", "c");
12788   emitcode ("", "%05d$:", (tlbl->key + 100));
12789
12790   if (IC_RESULT (ic))
12791     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12792   else
12793     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12794
12795   if (IC_RESULT (ic))
12796     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12797 }
12798
12799 /*-----------------------------------------------------------------*/
12800 /* genEndCritical - generate code for end of a critical sequence   */
12801 /*-----------------------------------------------------------------*/
12802 static void
12803 genEndCritical (iCode *ic)
12804 {
12805   D(emitcode(";     genEndCritical",""));
12806   
12807   if (IC_RIGHT (ic))
12808     {
12809       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12810       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12811         {
12812           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12813           emitcode ("mov", "ea,c");
12814         }
12815       else
12816         {
12817           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12818           emitcode ("rrc", "a");
12819           emitcode ("mov", "ea,c");
12820         }
12821       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12822     }
12823   else
12824     {
12825       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12826       emitcode ("mov", "ea,c");
12827     }
12828 }
12829
12830
12831
12832 /*-----------------------------------------------------------------*/
12833 /* genBuiltIn - calls the appropriate function to  generating code */
12834 /* for a built in function                                         */
12835 /*-----------------------------------------------------------------*/
12836 static void genBuiltIn (iCode *ic)
12837 {
12838         operand *bi_parms[MAX_BUILTIN_ARGS];
12839         int nbi_parms;
12840         iCode *bi_iCode;
12841         symbol *bif;
12842
12843         /* get all the arguments for a built in function */
12844         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12845
12846         /* which function is it */
12847         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12848         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12849                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12850         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12851                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12852         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12853                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12854         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12855                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12856         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12857                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12858         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12859                 genInp(bi_iCode,nbi_parms,bi_parms);
12860         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12861                 genOutp(bi_iCode,nbi_parms,bi_parms);
12862         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12863                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12864                 /* JavaNative builtIns */               
12865         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12866                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12867         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12868                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12869         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12870                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12871         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12872                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12873         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12874                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12875         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12876                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12877         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12878                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12879         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12880                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12881         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12882                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12883         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12884                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12885         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12886                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12887         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12888                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12889         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12890                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12891         } else if (strcmp(bif->name,"MM_Free")==0) {
12892                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12893         } else if (strcmp(bif->name,"MM_Deref")==0) {
12894                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12895         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12896                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12897         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12898                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12899         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12900                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12901         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12902                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12903         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12904                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12905         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12906                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12907         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12908                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12909         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12910                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12911         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12912                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12913         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12914                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12915         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12916                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12917         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12918                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12919         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12920                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12921         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12922                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12923         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12924                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12925         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12926                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12927         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12928                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12929         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12930                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12931         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12932                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12933         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12934                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12935         } else {
12936                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12937                 return ;
12938         }
12939         return ;    
12940 }
12941
12942 /*-----------------------------------------------------------------*/
12943 /* gen390Code - generate code for Dallas 390 based controllers     */
12944 /*-----------------------------------------------------------------*/
12945 void
12946 gen390Code (iCode * lic)
12947 {
12948   iCode *ic;
12949   int cln = 0;
12950
12951   lineHead = lineCurr = NULL;
12952   dptrn[1][0] = "dpl1";
12953   dptrn[1][1] = "dph1";
12954   dptrn[1][2] = "dpx1";
12955   
12956   if (options.model == MODEL_FLAT24) {
12957     fReturnSizeDS390 = 5;
12958     fReturn = fReturn24;
12959   } else {
12960     fReturnSizeDS390 = 4;
12961     fReturn = fReturn16;
12962     options.stack10bit=0;
12963   }
12964 #if 1
12965   /* print the allocation information */
12966   if (allocInfo && currFunc)
12967     printAllocInfo (currFunc, codeOutFile);
12968 #endif
12969   /* if debug information required */
12970   if (options.debug && currFunc)
12971     {
12972       debugFile->writeFunction(currFunc);
12973       _G.debugLine = 1;
12974       if (IS_STATIC (currFunc->etype))
12975         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12976       else
12977         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12978       _G.debugLine = 0;
12979     }
12980   /* stack pointer name */
12981   if (options.useXstack)
12982     spname = "_spx";
12983   else
12984     spname = "sp";
12985
12986
12987   for (ic = lic; ic; ic = ic->next)
12988     {
12989
12990       if (ic->lineno && cln != ic->lineno)
12991         {
12992           if (options.debug)
12993             {
12994               _G.debugLine = 1;
12995               emitcode ("", "C$%s$%d$%d$%d ==.",
12996                         FileBaseName (ic->filename), ic->lineno,
12997                         ic->level, ic->block);
12998               _G.debugLine = 0;
12999             }
13000           if (!options.noCcodeInAsm) {
13001             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13002                       printCLine(ic->filename, ic->lineno));
13003           }
13004           cln = ic->lineno;
13005         }
13006       if (options.iCodeInAsm) {
13007         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13008       }
13009       /* if the result is marked as
13010          spilt and rematerializable or code for
13011          this has already been generated then
13012          do nothing */
13013       if (resultRemat (ic) || ic->generated)
13014         continue;
13015
13016       /* depending on the operation */
13017       switch (ic->op)
13018         {
13019         case '!':
13020           genNot (ic);
13021           break;
13022
13023         case '~':
13024           genCpl (ic);
13025           break;
13026
13027         case UNARYMINUS:
13028           genUminus (ic);
13029           break;
13030
13031         case IPUSH:
13032           genIpush (ic);
13033           break;
13034
13035         case IPOP:
13036           /* IPOP happens only when trying to restore a
13037              spilt live range, if there is an ifx statement
13038              following this pop then the if statement might
13039              be using some of the registers being popped which
13040              would destory the contents of the register so
13041              we need to check for this condition and handle it */
13042           if (ic->next &&
13043               ic->next->op == IFX &&
13044               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13045             genIfx (ic->next, ic);
13046           else
13047             genIpop (ic);
13048           break;
13049
13050         case CALL:
13051           genCall (ic);
13052           break;
13053
13054         case PCALL:
13055           genPcall (ic);
13056           break;
13057
13058         case FUNCTION:
13059           genFunction (ic);
13060           break;
13061
13062         case ENDFUNCTION:
13063           genEndFunction (ic);
13064           break;
13065
13066         case RETURN:
13067           genRet (ic);
13068           break;
13069
13070         case LABEL:
13071           genLabel (ic);
13072           break;
13073
13074         case GOTO:
13075           genGoto (ic);
13076           break;
13077
13078         case '+':
13079           genPlus (ic);
13080           break;
13081
13082         case '-':
13083           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13084             genMinus (ic);
13085           break;
13086
13087         case '*':
13088           genMult (ic);
13089           break;
13090
13091         case '/':
13092           genDiv (ic);
13093           break;
13094
13095         case '%':
13096           genMod (ic);
13097           break;
13098
13099         case '>':
13100           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13101           break;
13102
13103         case '<':
13104           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13105           break;
13106
13107         case LE_OP:
13108         case GE_OP:
13109         case NE_OP:
13110
13111           /* note these two are xlated by algebraic equivalence
13112              during parsing SDCC.y */
13113           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13114                   "got '>=' or '<=' shouldn't have come here");
13115           break;
13116
13117         case EQ_OP:
13118           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13119           break;
13120
13121         case AND_OP:
13122           genAndOp (ic);
13123           break;
13124
13125         case OR_OP:
13126           genOrOp (ic);
13127           break;
13128
13129         case '^':
13130           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13131           break;
13132
13133         case '|':
13134           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13135           break;
13136
13137         case BITWISEAND:
13138           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13139           break;
13140
13141         case INLINEASM:
13142           genInline (ic);
13143           break;
13144
13145         case RRC:
13146           genRRC (ic);
13147           break;
13148
13149         case RLC:
13150           genRLC (ic);
13151           break;
13152
13153         case GETHBIT:
13154           genGetHbit (ic);
13155           break;
13156
13157         case LEFT_OP:
13158           genLeftShift (ic);
13159           break;
13160
13161         case RIGHT_OP:
13162           genRightShift (ic);
13163           break;
13164
13165         case GET_VALUE_AT_ADDRESS:
13166           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13167           break;
13168
13169         case '=':
13170           if (POINTER_SET (ic))
13171             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13172           else
13173             genAssign (ic);
13174           break;
13175
13176         case IFX:
13177           genIfx (ic, NULL);
13178           break;
13179
13180         case ADDRESS_OF:
13181           genAddrOf (ic);
13182           break;
13183
13184         case JUMPTABLE:
13185           genJumpTab (ic);
13186           break;
13187
13188         case CAST:
13189           genCast (ic);
13190           break;
13191
13192         case RECEIVE:
13193           genReceive (ic);
13194           break;
13195
13196         case SEND:
13197           if (ic->builtinSEND) genBuiltIn(ic);
13198           else addSet (&_G.sendSet, ic);
13199           break;
13200
13201         case DUMMY_READ_VOLATILE:
13202           genDummyRead (ic);
13203           break;
13204
13205         case CRITICAL:
13206           genCritical (ic);
13207           break;
13208
13209         case ENDCRITICAL:
13210           genEndCritical (ic);
13211           break;
13212         
13213         case SWAP:
13214           genSwap (ic);
13215           break;
13216           
13217 #if 0 // obsolete, and buggy for != xdata
13218         case ARRAYINIT:
13219             genArrayInit(ic);
13220             break;
13221 #endif
13222             
13223         default:
13224           ic = ic;
13225         }
13226     }
13227
13228
13229   /* now we are ready to call the
13230      peep hole optimizer */
13231   if (!options.nopeep)
13232     peepHole (&lineHead);
13233
13234   /* now do the actual printing */
13235   printLine (lineHead, codeOutFile);
13236   return;
13237 }