* src/ds390/gen.c (genCall): fixed a double use of acc and b after
[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     {
520       if ((sym->aop->type == AOP_DPTR && useDP2)
521           || (sym->aop->type == AOP_DPTR2 && !useDP2))
522         sym->aop = NULL;
523       else
524         return sym->aop;
525     }
526
527   /* assign depending on the storage class */
528   /* if it is on the stack or indirectly addressable */
529   /* space we need to assign either r0 or r1 to it   */
530   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
531     {
532       sym->aop = aop = newAsmop (0);
533       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
534       aop->size = getSize (sym->type);
535
536       /* now assign the address of the variable to
537          the pointer register */
538       if (aop->type != AOP_STK)
539         {
540
541           if (sym->onStack)
542             {
543               if (_G.accInUse || accuse)
544                 emitcode ("push", "acc");
545
546               if (_G.bInUse || (accuse>1))
547                 emitcode ("push", "b");
548
549               emitcode ("mov", "a,_bp");
550               emitcode ("add", "a,#!constbyte",
551                         ((sym->stack < 0) ?
552                          ((char) (sym->stack - _G.nRegsSaved)) :
553                          ((char) sym->stack)) & 0xff);
554               emitcode ("mov", "%s,a",
555                         aop->aopu.aop_ptr->name);
556
557               if (_G.bInUse || (accuse>1))
558                 emitcode ("pop", "b");
559
560               if (_G.accInUse || accuse)
561                 emitcode ("pop", "acc");
562             }
563           else
564             emitcode ("mov", "%s,#%s",
565                       aop->aopu.aop_ptr->name,
566                       sym->rname);
567           aop->paged = space->paged;
568         }
569       else
570         aop->aopu.aop_stk = sym->stack;
571       return aop;
572     }
573
574   if (sym->onStack && options.stack10bit)
575     {
576         short stack_val = -((sym->stack < 0) ?
577                             ((short) (sym->stack - _G.nRegsSaved)) :
578                             ((short) sym->stack)) ;
579         if (useDP2 && _G.dptr1InUse) {
580             emitcode ("push","dpl1");
581             emitcode ("push","dph1");
582             emitcode ("push","dpx1");
583         } else if (_G.dptrInUse ) {
584             emitcode ("push","dpl");
585             emitcode ("push","dph");
586             emitcode ("push","dpx");
587         }
588       /* It's on the 10 bit stack, which is located in
589        * far data space.
590        */           
591         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
592             if (useDP2) {
593                 if (options.model == MODEL_FLAT24)
594                 {
595                     emitcode ("mov", "dpx1,#!constbyte",
596                               (options.stack_loc >> 16) & 0xff);
597                 }
598                 emitcode ("mov", "dph1,_bpx+1");
599                 
600                 emitcode ("mov", "dpl1,_bpx");
601                 emitcode ("mov","dps,#1");
602             } else {
603                 if (options.model == MODEL_FLAT24)
604                 {
605                     emitcode ("mov", "dpx,#!constbyte",
606                               (options.stack_loc >> 16) & 0xff);
607                 }
608                 emitcode ("mov", "dph,_bpx+1");
609                 emitcode ("mov", "dpl,_bpx");
610             }
611             stack_val = -stack_val;
612             while (stack_val--) {
613                 emitcode ("inc","dptr");
614             }
615             if (useDP2) {
616                 emitcode("mov","dps,#0");
617             }
618         }  else {
619             if (_G.accInUse || accuse)
620                 emitcode ("push", "acc");
621             
622             if (_G.bInUse || (accuse>1))
623                 emitcode ("push", "b");
624         
625             emitcode ("mov", "a,_bpx");
626             emitcode ("clr","c");
627             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
628             emitcode ("mov","b,a");
629             emitcode ("mov","a,_bpx+1");
630             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
631             if (useDP2) {
632                 if (options.model == MODEL_FLAT24)
633                 {
634                     emitcode ("mov", "dpx1,#!constbyte",
635                               (options.stack_loc >> 16) & 0xff);
636                 }
637                 emitcode ("mov", "dph1,a");
638                 emitcode ("mov", "dpl1,b");
639             } else {
640                 if (options.model == MODEL_FLAT24)
641                 {
642                     emitcode ("mov", "dpx,#!constbyte",
643                               (options.stack_loc >> 16) & 0xff);
644                 }
645                 emitcode ("mov", "dph,a");
646                 emitcode ("mov", "dpl,b");
647             }
648             
649             if (_G.bInUse || (accuse>1))
650                 emitcode ("pop", "b");
651             
652             if (_G.accInUse || accuse)
653                 emitcode ("pop", "acc");
654         }
655         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
656         aop->size = getSize (sym->type);
657         return aop;
658     }
659
660   /* if in bit space */
661   if (IN_BITSPACE (space))
662     {
663       sym->aop = aop = newAsmop (AOP_CRY);
664       aop->aopu.aop_dir = sym->rname;
665       aop->size = getSize (sym->type);
666       return aop;
667     }
668   /* if it is in direct space */
669   if (IN_DIRSPACE (space))
670     {
671       sym->aop = aop = newAsmop (AOP_DIR);
672       aop->aopu.aop_dir = sym->rname;
673       aop->size = getSize (sym->type);
674       return aop;
675     }
676
677   /* special case for a function */
678   if (IS_FUNC (sym->type) && !(sym->isitmp))
679     {
680       sym->aop = aop = newAsmop (AOP_IMMD);
681       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
682       aop->size = FPTRSIZE;
683       return aop;
684     }
685
686   /* only remaining is far space */
687   /* in which case DPTR gets the address */
688   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
689   if (useDP2)
690     {
691       genSetDPTR (1);
692       _flushLazyDPS ();
693       emitcode ("mov", "dptr,#%s", sym->rname);
694       genSetDPTR (0);
695     }
696   else
697     {
698       emitcode ("mov", "dptr,#%s", sym->rname);
699     }
700   aop->size = getSize (sym->type);
701
702   /* if it is in code space */
703   if (IN_CODESPACE (space))
704     aop->code = 1;
705
706   return aop;
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* aopForRemat - rematerialzes an object                           */
711 /*-----------------------------------------------------------------*/
712 static asmop *
713 aopForRemat (symbol * sym)
714 {
715   iCode *ic = sym->rematiCode;
716   asmop *aop = newAsmop (AOP_IMMD);
717   int ptr_type =0;
718   int val = 0;
719
720   for (;;)
721     {
722       if (ic->op == '+')
723         val += (int) operandLitValue (IC_RIGHT (ic));
724       else if (ic->op == '-')
725         val -= (int) operandLitValue (IC_RIGHT (ic));
726       else if (IS_CAST_ICODE(ic)) {
727               sym_link *from_type = operandType(IC_RIGHT(ic));
728               aop->aopu.aop_immd.from_cast_remat = 1;
729               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
730               ptr_type = DCL_TYPE(from_type);
731               if (ptr_type == IPOINTER) {
732                 // bug #481053
733                 ptr_type = POINTER;
734               }
735               continue ;
736       } else break;
737       
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742   {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffffff);
748   }
749   else 
750   {
751       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
752       {
753           SNPRINTF(buffer, sizeof(buffer), 
754                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
755       }
756       else
757       {
758           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
759       }
760   }
761
762   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
763   /* set immd2 field if required */
764   if (aop->aopu.aop_immd.from_cast_remat) 
765   {
766       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
767       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768   }
769
770   return aop;
771 }
772
773 /*-----------------------------------------------------------------*/
774 /* aopHasRegs - returns true if aop has regs between from-to       */
775 /*-----------------------------------------------------------------*/
776 static int aopHasRegs(asmop *aop, int from, int to)
777 {
778     int size =0;
779
780     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
781
782     for (; size < aop->size ; size++) {
783         int reg;
784         for (reg = from ; reg <= to ; reg++)
785             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
786     }
787     return 0;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* regsInCommon - two operands have some registers in common       */
792 /*-----------------------------------------------------------------*/
793 static bool
794 regsInCommon (operand * op1, operand * op2)
795 {
796   symbol *sym1, *sym2;
797   int i;
798
799   /* if they have registers in common */
800   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
801     return FALSE;
802
803   sym1 = OP_SYMBOL (op1);
804   sym2 = OP_SYMBOL (op2);
805
806   if (sym1->nRegs == 0 || sym2->nRegs == 0)
807     return FALSE;
808
809   for (i = 0; i < sym1->nRegs; i++)
810     {
811       int j;
812       if (!sym1->regs[i])
813         continue;
814
815       for (j = 0; j < sym2->nRegs; j++)
816         {
817           if (!sym2->regs[j])
818             continue;
819
820           if (sym2->regs[j] == sym1->regs[i])
821             return TRUE;
822         }
823     }
824
825   return FALSE;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* operandsEqu - equivalent                                        */
830 /*-----------------------------------------------------------------*/
831 static bool
832 operandsEqu (operand * op1, operand * op2)
833 {
834   symbol *sym1, *sym2;
835
836   /* if they not symbols */
837   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
838     return FALSE;
839
840   sym1 = OP_SYMBOL (op1);
841   sym2 = OP_SYMBOL (op2);
842
843   /* if both are itemps & one is spilt
844      and the other is not then false */
845   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
846       sym1->isspilt != sym2->isspilt)
847     return FALSE;
848
849   /* if they are the same */
850   if (sym1 == sym2)
851     return TRUE;
852
853   if (strcmp (sym1->rname, sym2->rname) == 0)
854     return TRUE;
855
856
857   /* if left is a tmp & right is not */
858   if (IS_ITEMP (op1) &&
859       !IS_ITEMP (op2) &&
860       sym1->isspilt &&
861       (sym1->usl.spillLoc == sym2))
862     return TRUE;
863
864   if (IS_ITEMP (op2) &&
865       !IS_ITEMP (op1) &&
866       sym2->isspilt &&
867       sym1->level > 0 &&
868       (sym2->usl.spillLoc == sym1))
869     return TRUE;
870
871   /* are they spilt to the same location */
872   if (IS_ITEMP (op2) &&
873       IS_ITEMP (op1) &&
874       sym2->isspilt &&
875       sym1->isspilt &&
876       (sym1->usl.spillLoc == sym2->usl.spillLoc))
877     return TRUE;
878     
879   return FALSE;
880 }
881
882 /*-----------------------------------------------------------------*/
883 /* sameRegs - two asmops have the same registers                   */
884 /*-----------------------------------------------------------------*/
885 static bool
886 sameRegs (asmop * aop1, asmop * aop2)
887 {
888   int i;
889
890   if (aop1 == aop2)
891     {
892       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
893         {
894           return FALSE;
895         }
896       return TRUE;
897     }
898
899   if (aop1->type != AOP_REG ||
900       aop2->type != AOP_REG)
901     return FALSE;
902
903   if (aop1->size != aop2->size)
904     return FALSE;
905
906   for (i = 0; i < aop1->size; i++)
907     if (aop1->aopu.aop_reg[i] !=
908         aop2->aopu.aop_reg[i])
909       return FALSE;
910
911   return TRUE;
912 }
913
914 /*-----------------------------------------------------------------*/
915 /* aopOp - allocates an asmop for an operand  :                    */
916 /*-----------------------------------------------------------------*/
917 static void
918 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
919 {
920   asmop *aop;
921   symbol *sym;
922   int i;
923
924   if (!op)
925     return;
926
927   /* if this a literal */
928   if (IS_OP_LITERAL (op))
929     {
930       op->aop = aop = newAsmop (AOP_LIT);
931       aop->aopu.aop_lit = op->operand.valOperand;
932       aop->size = getSize (operandType (op));
933       return;
934     }
935
936   /* if already has a asmop then continue */
937   if (op->aop)
938     {
939       if ((op->aop->type == AOP_DPTR && useDP2)
940           || (op->aop->type == AOP_DPTR2 && !useDP2))
941         op->aop = NULL;
942       else
943         return;
944     }
945
946   /* if the underlying symbol has a aop */
947   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
948     {
949       op->aop = OP_SYMBOL (op)->aop;
950       if ((op->aop->type == AOP_DPTR && useDP2)
951           || (op->aop->type == AOP_DPTR2 && !useDP2))
952         op->aop = NULL;
953       else
954         return;
955     }
956
957   /* if this is a true symbol */
958   if (IS_TRUE_SYMOP (op))
959     {
960       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
961       return;
962     }
963
964   /* this is a temporary : this has
965      only four choices :
966      a) register
967      b) spillocation
968      c) rematerialize
969      d) conditional
970      e) can be a return use only */
971
972   sym = OP_SYMBOL (op);
973
974
975   /* if the type is a conditional */
976   if (sym->regType == REG_CND)
977     {
978       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
979       aop->size = 0;
980       return;
981     }
982
983   /* if it is spilt then two situations
984      a) is rematerialize
985      b) has a spill location */
986   if (sym->isspilt || sym->nRegs == 0)
987     {
988
989       /* rematerialize it NOW */
990       if (sym->remat)
991         {
992           sym->aop = op->aop = aop =
993             aopForRemat (sym);
994           aop->size = getSize (sym->type);
995           return;
996         }
997
998       if (sym->accuse)
999         {
1000           int i;
1001           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1002           aop->size = getSize (sym->type);
1003           for (i = 0; i < 2; i++)
1004             aop->aopu.aop_str[i] = accUse[i];
1005           return;
1006         }
1007
1008       if (sym->ruonly)
1009         {
1010           int i;
1011
1012           if (useDP2)
1013             {
1014               /* a AOP_STR uses DPTR, but DPTR is already in use;
1015                * we're just hosed.
1016                */
1017                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1018             }
1019
1020           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1021           aop->size = getSize (sym->type);
1022           for (i = 0; i < (int) fReturnSizeDS390; i++)
1023             aop->aopu.aop_str[i] = fReturn[i];
1024           return;
1025         }
1026       
1027       if (sym->dptr) { /* has been allocated to a DPTRn */
1028           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1029           aop->size = getSize (sym->type);
1030           aop->aopu.dptr = sym->dptr;
1031           return ;
1032       }
1033       
1034       if (sym->usl.spillLoc)
1035         {
1036           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1037             {
1038               /* force a new aop if sizes differ */
1039               sym->usl.spillLoc->aop = NULL;
1040             }
1041           sym->aop = op->aop = aop =
1042                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1043           aop->size = getSize (sym->type);
1044           return;
1045         }
1046       
1047       /* else must be a dummy iTemp */
1048       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1049       aop->size = getSize (sym->type);
1050       return;
1051     }
1052
1053   /* must be in a register */
1054   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1055   aop->size = sym->nRegs;
1056   for (i = 0; i < sym->nRegs; i++)
1057     aop->aopu.aop_reg[i] = sym->regs[i];
1058 }
1059
1060 /*-----------------------------------------------------------------*/
1061 /* freeAsmop - free up the asmop given to an operand               */
1062 /*----------------------------------------------------------------*/
1063 static void
1064 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1065 {
1066   asmop *aop;
1067
1068   if (!op)
1069     aop = aaop;
1070   else
1071     aop = op->aop;
1072
1073   if (!aop)
1074     return;
1075
1076   if (aop->freed)
1077     goto dealloc;
1078
1079   aop->freed = 1;
1080
1081   /* depending on the asmop type only three cases need work AOP_RO
1082      , AOP_R1 && AOP_STK */
1083   switch (aop->type)
1084     {
1085     case AOP_R0:
1086       if (_G.r0Pushed)
1087         {
1088           if (pop)
1089             {
1090               emitcode ("pop", "ar0");
1091               _G.r0Pushed--;
1092             }
1093         }
1094       bitVectUnSetBit (ic->rUsed, R0_IDX);
1095       break;
1096
1097     case AOP_R1:
1098       if (_G.r1Pushed)
1099         {
1100           if (pop)
1101             {
1102               emitcode ("pop", "ar1");
1103               _G.r1Pushed--;
1104             }
1105         }
1106       bitVectUnSetBit (ic->rUsed, R1_IDX);
1107       break;
1108
1109     case AOP_STK:
1110       {
1111         int sz = aop->size;
1112         int stk = aop->aopu.aop_stk + aop->size;
1113         bitVectUnSetBit (ic->rUsed, R0_IDX);
1114         bitVectUnSetBit (ic->rUsed, R1_IDX);
1115
1116         getFreePtr (ic, &aop, FALSE);
1117
1118         if (options.stack10bit)
1119           {
1120             /* I'm not sure what to do here yet... */
1121             /* #STUB */
1122             fprintf (stderr,
1123                      "*** Warning: probably generating bad code for "
1124                      "10 bit stack mode.\n");
1125           }
1126
1127         if (stk)
1128           {
1129             emitcode ("mov", "a,_bp");
1130             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1131             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1132           }
1133         else
1134           {
1135             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1136           }
1137
1138         while (sz--)
1139           {
1140             emitcode ("pop", "acc");
1141             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1142             if (!sz)
1143               break;
1144             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1145           }
1146         op->aop = aop;
1147         freeAsmop (op, NULL, ic, TRUE);
1148         if (_G.r0Pushed)
1149           {
1150             emitcode ("pop", "ar0");
1151             _G.r0Pushed--;
1152           }
1153
1154         if (_G.r1Pushed)
1155           {
1156             emitcode ("pop", "ar1");
1157             _G.r1Pushed--;
1158           }
1159       }
1160     case AOP_DPTR2:
1161         if (_G.dptr1InUse) {
1162             emitcode ("pop","dpx1");
1163             emitcode ("pop","dph1");
1164             emitcode ("pop","dpl1");
1165         }
1166         break;
1167     case AOP_DPTR:
1168         if (_G.dptrInUse) {
1169             emitcode ("pop","dpx");
1170             emitcode ("pop","dph");
1171             emitcode ("pop","dpl");
1172         }
1173         break;
1174     }
1175 dealloc:
1176   /* all other cases just dealloc */
1177   if (op)
1178     {
1179       op->aop = NULL;
1180       if (IS_SYMOP (op))
1181         {
1182           OP_SYMBOL (op)->aop = NULL;
1183           /* if the symbol has a spill */
1184           if (SPIL_LOC (op))
1185             SPIL_LOC (op)->aop = NULL;
1186         }
1187     }
1188 }
1189
1190 #define DEFAULT_ACC_WARNING 0
1191 static int saveAccWarn = DEFAULT_ACC_WARNING;
1192
1193 /*-------------------------------------------------------------------*/
1194 /* aopGet - for fetching value of the aop                            */
1195 /*                                                                   */
1196 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1197 /* in the accumulator. Set it to the name of a free register         */
1198 /* if acc must be preserved; the register will be used to preserve   */
1199 /* acc temporarily and to return the result byte.                    */
1200 /*-------------------------------------------------------------------*/
1201
1202 static char *
1203 aopGet (asmop *aop,
1204         int   offset,
1205         bool  bit16,
1206         bool  dname,
1207         char  *saveAcc)
1208 {
1209   /* offset is greater than
1210      size then zero */
1211   if (offset > (aop->size - 1) &&
1212       aop->type != AOP_LIT)
1213     return zero;
1214
1215   /* depending on type */
1216   switch (aop->type)
1217     {
1218     case AOP_DUMMY:
1219       return zero;
1220
1221     case AOP_R0:
1222     case AOP_R1:
1223       /* if we need to increment it */
1224       while (offset > aop->coff)
1225         {
1226           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1227           aop->coff++;
1228         }
1229
1230       while (offset < aop->coff)
1231         {
1232           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1233           aop->coff--;
1234         }
1235
1236       aop->coff = offset;
1237       if (aop->paged)
1238         {
1239           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1240           return (dname ? "acc" : "a");
1241         }
1242       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1243       return Safe_strdup(buffer);       
1244
1245     case AOP_DPTRn:
1246         assert(offset <= 3);
1247         return dptrn[aop->aopu.dptr][offset];
1248
1249     case AOP_DPTR:
1250     case AOP_DPTR2:
1251
1252       if (aop->type == AOP_DPTR2)
1253         {
1254           genSetDPTR (1);
1255         }
1256         
1257       if (saveAcc)
1258         {
1259             TR_AP("#1");
1260 //          if (aop->type != AOP_DPTR2)
1261 //          {
1262 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1263 //              emitcode(";", "spanky: saveAcc for DPTR");
1264 //          }
1265             
1266             emitcode ("xch", "a, %s", saveAcc);
1267         }
1268
1269       _flushLazyDPS ();
1270
1271       while (offset > aop->coff)
1272         {
1273           emitcode ("inc", "dptr");
1274           aop->coff++;
1275         }
1276
1277       while (offset < aop->coff)
1278         {
1279           emitcode ("lcall", "__decdptr");
1280           aop->coff--;
1281         }
1282
1283       aop->coff = offset;
1284       if (aop->code)
1285         {
1286           emitcode ("clr", "a");
1287           emitcode ("movc", "a,@a+dptr");
1288         }
1289       else
1290         {
1291           emitcode ("movx", "a,@dptr");
1292         }
1293
1294       if (aop->type == AOP_DPTR2)
1295         {
1296           genSetDPTR (0);
1297         }
1298         
1299         if (saveAcc)
1300         {
1301        TR_AP("#2");
1302               emitcode ("xch", "a, %s", saveAcc);
1303 //            if (strcmp(saveAcc, "_ap"))
1304 //            {
1305 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1306 //            }
1307                   
1308               return saveAcc;
1309         }
1310       return (dname ? "acc" : "a");
1311
1312     case AOP_IMMD:
1313       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1314       {
1315           SNPRINTF(buffer, sizeof(buffer), 
1316                    "%s",aop->aopu.aop_immd.aop_immd2);
1317       } 
1318       else if (bit16)
1319       {
1320          SNPRINTF(buffer, sizeof(buffer), 
1321                   "#%s", aop->aopu.aop_immd.aop_immd1);
1322       }
1323       else if (offset) 
1324       {
1325           switch (offset) {
1326           case 1:
1327               tsprintf(buffer, sizeof(buffer),
1328                        "#!his",aop->aopu.aop_immd.aop_immd1);
1329               break;
1330           case 2:
1331               tsprintf(buffer, sizeof(buffer), 
1332                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1333               break;
1334           case 3:
1335               tsprintf(buffer, sizeof(buffer),
1336                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1337               break;
1338           default: /* should not need this (just in case) */
1339               SNPRINTF (buffer, sizeof(buffer), 
1340                         "#(%s >> %d)",
1341                        aop->aopu.aop_immd.aop_immd1,
1342                        offset * 8);
1343           }
1344       }
1345       else
1346       {
1347         SNPRINTF (buffer, sizeof(buffer), 
1348                   "#%s", aop->aopu.aop_immd.aop_immd1);
1349       }
1350       return Safe_strdup(buffer);       
1351
1352     case AOP_DIR:
1353       if (offset)
1354       {
1355         SNPRINTF (buffer, sizeof(buffer),
1356                   "(%s + %d)",
1357                  aop->aopu.aop_dir,
1358                  offset);
1359       }
1360       else
1361       {
1362         SNPRINTF(buffer, sizeof(buffer), 
1363                  "%s", aop->aopu.aop_dir);
1364       }
1365
1366       return Safe_strdup(buffer);
1367
1368     case AOP_REG:
1369       if (dname)
1370         return aop->aopu.aop_reg[offset]->dname;
1371       else
1372         return aop->aopu.aop_reg[offset]->name;
1373
1374     case AOP_CRY:
1375       emitcode ("clr", "a");
1376       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1377       emitcode ("rlc", "a");
1378       return (dname ? "acc" : "a");
1379
1380     case AOP_ACC:
1381       if (!offset && dname)
1382         return "acc";
1383       return aop->aopu.aop_str[offset];
1384
1385     case AOP_LIT:
1386       return aopLiteral (aop->aopu.aop_lit, offset);
1387
1388     case AOP_STR:
1389       aop->coff = offset;
1390       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1391           dname)
1392         return "acc";
1393
1394       return aop->aopu.aop_str[offset];
1395
1396     }
1397
1398   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1399           "aopget got unsupported aop->type");
1400   exit (1);
1401     
1402   return NULL;  // not reached, but makes compiler happy.
1403 }
1404 /*-----------------------------------------------------------------*/
1405 /* aopPut - puts a string for a aop                                */
1406 /*-----------------------------------------------------------------*/
1407 static void
1408 aopPut (asmop * aop, char *s, int offset)
1409 {
1410   if (aop->size && offset > (aop->size - 1))
1411     {
1412       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1413               "aopPut got offset > aop->size");
1414       exit (1);
1415     }
1416
1417   /* will assign value to value */
1418   /* depending on where it is ofcourse */
1419   switch (aop->type)
1420     {
1421     case AOP_DUMMY:
1422       MOVA (s);         /* read s in case it was volatile */
1423       break;
1424       
1425     case AOP_DIR:
1426         if (offset)
1427         {
1428             SNPRINTF (buffer, sizeof(buffer),
1429                       "(%s + %d)",
1430                       aop->aopu.aop_dir, offset);
1431         }
1432         else
1433         {
1434             SNPRINTF (buffer, sizeof(buffer), 
1435                      "%s", aop->aopu.aop_dir);
1436         }
1437         
1438
1439         if (strcmp (buffer, s))
1440         {
1441             emitcode ("mov", "%s,%s", buffer, s);
1442         }
1443       break;
1444
1445     case AOP_REG:
1446       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1447           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1448         {
1449           if (*s == '@' ||
1450               strcmp (s, "r0") == 0 ||
1451               strcmp (s, "r1") == 0 ||
1452               strcmp (s, "r2") == 0 ||
1453               strcmp (s, "r3") == 0 ||
1454               strcmp (s, "r4") == 0 ||
1455               strcmp (s, "r5") == 0 ||
1456               strcmp (s, "r6") == 0 ||
1457               strcmp (s, "r7") == 0)
1458             {
1459                 emitcode ("mov", "%s,%s",
1460                           aop->aopu.aop_reg[offset]->dname, s);
1461             }
1462             else
1463             {
1464                 emitcode ("mov", "%s,%s",
1465                           aop->aopu.aop_reg[offset]->name, s);
1466             }
1467         }
1468       break;
1469
1470     case AOP_DPTRn:
1471         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1472         break;
1473
1474     case AOP_DPTR:
1475     case AOP_DPTR2:
1476
1477       if (aop->type == AOP_DPTR2)
1478         {
1479           genSetDPTR (1);
1480         }
1481       _flushLazyDPS ();
1482
1483       if (aop->code)
1484         {
1485           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1486                   "aopPut writting to code space");
1487           exit (1);
1488         }
1489
1490       while (offset > aop->coff)
1491         {
1492           aop->coff++;
1493           emitcode ("inc", "dptr");
1494         }
1495
1496       while (offset < aop->coff)
1497         {
1498           aop->coff--;
1499           emitcode ("lcall", "__decdptr");
1500         }
1501
1502       aop->coff = offset;
1503
1504       /* if not in accumulater */
1505       MOVA (s);
1506
1507       emitcode ("movx", "@dptr,a");
1508
1509       if (aop->type == AOP_DPTR2)
1510         {
1511           genSetDPTR (0);
1512         }
1513       break;
1514
1515     case AOP_R0:
1516     case AOP_R1:
1517       while (offset > aop->coff)
1518         {
1519           aop->coff++;
1520           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1521         }
1522       while (offset < aop->coff)
1523         {
1524           aop->coff--;
1525           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1526         }
1527       aop->coff = offset;
1528
1529       if (aop->paged)
1530         {
1531           MOVA (s);
1532           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1533
1534         }
1535       else if (*s == '@')
1536         {
1537           MOVA (s);
1538           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1539         }
1540       else if (strcmp (s, "r0") == 0 ||
1541                strcmp (s, "r1") == 0 ||
1542                strcmp (s, "r2") == 0 ||
1543                strcmp (s, "r3") == 0 ||
1544                strcmp (s, "r4") == 0 ||
1545                strcmp (s, "r5") == 0 ||
1546                strcmp (s, "r6") == 0 ||
1547                strcmp (s, "r7") == 0)
1548         {
1549           char buff[10];
1550           SNPRINTF(buff, sizeof(buff), 
1551                    "a%s", s);
1552           emitcode ("mov", "@%s,%s",
1553                     aop->aopu.aop_ptr->name, buff);
1554         }
1555         else
1556         {
1557             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1558         }
1559       break;
1560
1561     case AOP_STK:
1562       if (strcmp (s, "a") == 0)
1563         emitcode ("push", "acc");
1564       else
1565         if (*s=='@') {
1566           MOVA(s);
1567           emitcode ("push", "acc");
1568         } else {
1569           emitcode ("push", s);
1570         }
1571
1572       break;
1573
1574     case AOP_CRY:
1575       /* if bit variable */
1576       if (!aop->aopu.aop_dir)
1577         {
1578           emitcode ("clr", "a");
1579           emitcode ("rlc", "a");
1580         }
1581       else
1582         {
1583           if (s == zero)
1584             emitcode ("clr", "%s", aop->aopu.aop_dir);
1585           else if (s == one)
1586             emitcode ("setb", "%s", aop->aopu.aop_dir);
1587           else if (!strcmp (s, "c"))
1588             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1589           else
1590             {
1591               if (strcmp (s, "a"))
1592                 {
1593                   MOVA (s);
1594                 }
1595               {
1596                 /* set C, if a >= 1 */
1597                 emitcode ("add", "a,#!constbyte",0xff);
1598                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1599               }
1600             }
1601         }
1602       break;
1603
1604     case AOP_STR:
1605       aop->coff = offset;
1606       if (strcmp (aop->aopu.aop_str[offset], s))
1607         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1608       break;
1609
1610     case AOP_ACC:
1611       aop->coff = offset;
1612       if (!offset && (strcmp (s, "acc") == 0))
1613         break;
1614
1615       if (strcmp (aop->aopu.aop_str[offset], s))
1616         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1617       break;
1618
1619     default:
1620       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1621               "aopPut got unsupported aop->type");
1622       exit (1);
1623     }
1624
1625 }
1626
1627
1628 /*--------------------------------------------------------------------*/
1629 /* reAdjustPreg - points a register back to where it should (coff==0) */
1630 /*--------------------------------------------------------------------*/
1631 static void
1632 reAdjustPreg (asmop * aop)
1633 {
1634   if ((aop->coff==0) || (aop->size <= 1)) {
1635     return;
1636   }
1637
1638   switch (aop->type)
1639     {
1640     case AOP_R0:
1641     case AOP_R1:
1642       while (aop->coff--)
1643         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1644       break;
1645     case AOP_DPTR:
1646     case AOP_DPTR2:
1647       if (aop->type == AOP_DPTR2)
1648         {
1649           genSetDPTR (1);
1650           _flushLazyDPS ();
1651         }
1652       while (aop->coff--)
1653         {
1654           emitcode ("lcall", "__decdptr");
1655         }
1656
1657       if (aop->type == AOP_DPTR2)
1658         {
1659           genSetDPTR (0);
1660         }
1661       break;
1662
1663     }
1664   aop->coff=0;
1665 }
1666
1667 #define AOP(op) op->aop
1668 #define AOP_TYPE(op) AOP(op)->type
1669 #define AOP_SIZE(op) AOP(op)->size
1670 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1671                        AOP_TYPE(x) == AOP_R0))
1672
1673 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1674                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1675                          AOP(x)->paged))
1676
1677 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1678                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1679                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1680 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1681 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1682 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1683
1684 // The following two macros can be used even if the aop has not yet been aopOp'd.
1685 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1686 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1687
1688 /* Workaround for DS80C390 bug: div ab may return bogus results
1689  * if A is accessed in instruction immediately before the div.
1690  *
1691  * Will be fixed in B4 rev of processor, Dallas claims.
1692  */
1693
1694 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1695     if (!AOP_NEEDSACC(RIGHT))         \
1696     {               \
1697       /* We can load A first, then B, since     \
1698        * B (the RIGHT operand) won't clobber A,   \
1699        * thus avoiding touching A right before the div. \
1700        */             \
1701       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1702       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1703       MOVA(L);            \
1704       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1705       MOVB(L); \
1706     }               \
1707     else              \
1708     {               \
1709       /* Just stuff in a nop after loading A. */    \
1710       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1711       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1712       MOVA(L);            \
1713       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1714     }
1715
1716
1717 /*-----------------------------------------------------------------*/
1718 /* opIsGptr: returns non-zero if the passed operand is       */
1719 /* a generic pointer type.             */
1720 /*-----------------------------------------------------------------*/
1721 static int
1722 opIsGptr (operand * op)
1723 {
1724   sym_link *type = operandType (op);
1725
1726   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1727     {
1728       return 1;
1729     }
1730   return 0;
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* getDataSize - get the operand data size                         */
1735 /*-----------------------------------------------------------------*/
1736 static int
1737 getDataSize (operand * op)
1738 {
1739   int size;
1740   size = AOP_SIZE (op);
1741   if (size == GPTRSIZE)
1742     {
1743       sym_link *type = operandType (op);
1744       if (IS_GENPTR (type))
1745         {
1746           /* generic pointer; arithmetic operations
1747            * should ignore the high byte (pointer type).
1748            */
1749           size--;
1750         }
1751     }
1752   return size;
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* outAcc - output Acc                                             */
1757 /*-----------------------------------------------------------------*/
1758 static void
1759 outAcc (operand * result)
1760 {
1761   int size, offset;
1762   size = getDataSize (result);
1763   if (size)
1764     {
1765       aopPut (AOP (result), "a", 0);
1766       size--;
1767       offset = 1;
1768       /* unsigned or positive */
1769       while (size--)
1770         {
1771           aopPut (AOP (result), zero, offset++);
1772         }
1773     }
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* outBitC - output a bit C                                        */
1778 /*-----------------------------------------------------------------*/
1779 static void
1780 outBitC (operand * result)
1781 {
1782   /* if the result is bit */
1783   if (AOP_TYPE (result) == AOP_CRY)
1784     {
1785       aopPut (AOP (result), "c", 0);
1786     }
1787   else
1788     {
1789       emitcode ("clr", "a");
1790       emitcode ("rlc", "a");
1791       outAcc (result);
1792     }
1793 }
1794
1795 /*-----------------------------------------------------------------*/
1796 /* toBoolean - emit code for orl a,operator(sizeop)                */
1797 /*-----------------------------------------------------------------*/
1798 static void
1799 toBoolean (operand * oper)
1800 {
1801   int   size = AOP_SIZE (oper) - 1;
1802   int   offset = 1;
1803   bool usedB = FALSE;
1804
1805   /* The generic part of a generic pointer should
1806    * not participate in it's truth value.
1807    *
1808    * i.e. 0x10000000 is zero.
1809    */
1810   if (opIsGptr (oper))
1811     {
1812       D (emitcode (";", "toBoolean: generic ptr special case."););
1813       size--;
1814     }
1815
1816   _startLazyDPSEvaluation ();
1817   if (AOP_NEEDSACC (oper) && size)
1818     {
1819       usedB = TRUE;
1820       if (_G.bInUse)
1821       {
1822           emitcode ("push", "b");
1823       }
1824       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1825     }
1826   else
1827     {
1828       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1829     }
1830     
1831   while (size--)
1832     {
1833       if (usedB)
1834         {
1835           emitcode ("orl", "b,%s",
1836                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1837         }
1838       else
1839         {
1840           emitcode ("orl", "a,%s",
1841                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1842         }
1843     }
1844   _endLazyDPSEvaluation ();
1845
1846   if (usedB)
1847     {
1848       emitcode ("mov", "a,b");
1849       if (_G.bInUse)
1850       {
1851           emitcode ("pop", "b");
1852       }
1853         
1854     }
1855 }
1856
1857
1858 /*-----------------------------------------------------------------*/
1859 /* genNot - generate code for ! operation                          */
1860 /*-----------------------------------------------------------------*/
1861 static void
1862 genNot (iCode * ic)
1863 {
1864   symbol *tlbl;
1865
1866   D (emitcode (";", "genNot "););
1867
1868   /* assign asmOps to operand & result */
1869   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1870   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1871
1872   /* if in bit space then a special case */
1873   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1874     {
1875       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876       emitcode ("cpl", "c");
1877       outBitC (IC_RESULT (ic));
1878       goto release;
1879     }
1880
1881   toBoolean (IC_LEFT (ic));
1882
1883   tlbl = newiTempLabel (NULL);
1884   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1885   emitcode ("", "!tlabeldef", tlbl->key + 100);
1886   outBitC (IC_RESULT (ic));
1887
1888 release:
1889   /* release the aops */
1890   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1892 }
1893
1894
1895 /*-----------------------------------------------------------------*/
1896 /* genCpl - generate code for complement                           */
1897 /*-----------------------------------------------------------------*/
1898 static void
1899 genCpl (iCode * ic)
1900 {
1901   int offset = 0;
1902   int size;
1903   symbol *tlbl;
1904
1905   D (emitcode (";", "genCpl "););
1906
1907
1908   /* assign asmOps to operand & result */
1909   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1910   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1911
1912   /* special case if in bit space */
1913   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1914     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1915       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1916       emitcode ("cpl", "c");
1917       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1918       goto release;
1919     }
1920     tlbl=newiTempLabel(NULL);
1921     emitcode ("cjne", "%s,#0x01,%05d$", 
1922               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1923     emitcode ("", "%05d$:", tlbl->key+100);
1924     outBitC (IC_RESULT(ic));
1925     goto release;
1926   }
1927
1928   size = AOP_SIZE (IC_RESULT (ic));
1929   _startLazyDPSEvaluation ();
1930   while (size--)
1931     {
1932       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1933       emitcode ("cpl", "a");
1934       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1935     }
1936   _endLazyDPSEvaluation ();
1937
1938
1939 release:
1940   /* release the aops */
1941   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1942   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* genUminusFloat - unary minus for floating points                */
1947 /*-----------------------------------------------------------------*/
1948 static void
1949 genUminusFloat (operand * op, operand * result)
1950 {
1951   int size, offset = 0;
1952     
1953   D(emitcode (";", "genUminusFloat"););
1954   
1955   /* for this we just copy and then flip the bit */
1956     
1957   _startLazyDPSEvaluation ();
1958   size = AOP_SIZE (op) - 1;
1959
1960   while (size--)
1961   {
1962       aopPut (AOP (result),
1963               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1964               offset);
1965       offset++;
1966     }
1967   
1968   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1969
1970   emitcode ("cpl", "acc.7");
1971   aopPut (AOP (result), "a", offset);    
1972   _endLazyDPSEvaluation ();
1973 }
1974
1975 /*-----------------------------------------------------------------*/
1976 /* genUminus - unary minus code generation                         */
1977 /*-----------------------------------------------------------------*/
1978 static void
1979 genUminus (iCode * ic)
1980 {
1981   int offset, size;
1982   sym_link *optype;
1983
1984   D (emitcode (";", "genUminus "););
1985
1986   /* assign asmops */
1987   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1988   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1989
1990   /* if both in bit space then special
1991      case */
1992   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1993       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1994     {
1995
1996       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997       emitcode ("cpl", "c");
1998       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1999       goto release;
2000     }
2001
2002   optype = operandType (IC_LEFT (ic));
2003
2004   /* if float then do float stuff */
2005   if (IS_FLOAT (optype))
2006     {
2007       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2008       goto release;
2009     }
2010
2011   /* otherwise subtract from zero */
2012   size = AOP_SIZE (IC_LEFT (ic));
2013   offset = 0;
2014   _startLazyDPSEvaluation ();
2015   while (size--)
2016     {
2017       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2018       if (!strcmp (l, "a"))
2019         {
2020           if (offset == 0)
2021             SETC;
2022           emitcode ("cpl", "a");
2023           emitcode ("addc", "a,#0");
2024         }
2025       else
2026         {
2027           if (offset == 0)
2028             CLRC;
2029           emitcode ("clr", "a");
2030           emitcode ("subb", "a,%s", l);
2031         }
2032       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2033     }
2034   _endLazyDPSEvaluation ();
2035
2036   /* if any remaining bytes in the result */
2037   /* we just need to propagate the sign   */
2038   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2039     {
2040       emitcode ("rlc", "a");
2041       emitcode ("subb", "a,acc");
2042       while (size--)
2043         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2044     }
2045
2046 release:
2047   /* release the aops */
2048   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2049   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2050 }
2051
2052 /*-----------------------------------------------------------------*/
2053 /* savermask - saves registers in the mask                         */
2054 /*-----------------------------------------------------------------*/
2055 static void savermask(bitVect *rs_mask)
2056 {
2057     int i;
2058     if (options.useXstack) {
2059         if (bitVectBitValue (rs_mask, R0_IDX))
2060             emitcode ("mov", "b,r0");
2061         emitcode ("mov", "r0,%s", spname);
2062         for (i = 0; i < ds390_nRegs; i++) {
2063             if (bitVectBitValue (rs_mask, i)) {
2064                 if (i == R0_IDX)
2065                     emitcode ("mov", "a,b");
2066                 else
2067                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2068                 emitcode ("movx", "@r0,a");
2069                 emitcode ("inc", "r0");
2070             }
2071         }
2072         emitcode ("mov", "%s,r0", spname);
2073         if (bitVectBitValue (rs_mask, R0_IDX))
2074             emitcode ("mov", "r0,b");
2075     } else {
2076         for (i = 0; i < ds390_nRegs; i++) {
2077             if (bitVectBitValue (rs_mask, i))
2078                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2079         }
2080     }
2081 }
2082
2083 /*-----------------------------------------------------------------*/
2084 /* saveRegisters - will look for a call and save the registers     */
2085 /*-----------------------------------------------------------------*/
2086 static void
2087 saveRegisters (iCode * lic)
2088 {
2089   iCode *ic;
2090   bitVect *rsave;
2091
2092   /* look for call */
2093   for (ic = lic; ic; ic = ic->next)
2094     if (ic->op == CALL || ic->op == PCALL)
2095       break;
2096
2097   if (!ic)
2098     {
2099       fprintf (stderr, "found parameter push with no function call\n");
2100       return;
2101     }
2102
2103   /* if the registers have been saved already then
2104      do nothing */
2105   if (ic->regsSaved 
2106       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2107     return ;
2108
2109   /* special case if DPTR alive across a function call then must save it 
2110      even though callee saves */
2111   if (IS_SYMOP(IC_LEFT(ic)) &&
2112       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2113       int i;
2114       rsave = newBitVect(ic->rMask->size);
2115       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2116           if (bitVectBitValue(ic->rMask,i))
2117               rsave = bitVectSetBit(rsave,i);
2118       }
2119       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2120   } else {
2121     /* safe the registers in use at this time but skip the
2122        ones for the result */
2123     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2124                            ds390_rUmaskForOp (IC_RESULT(ic)));
2125   }
2126   ic->regsSaved = 1;
2127   savermask(rsave);
2128 }
2129
2130 /*-----------------------------------------------------------------*/
2131 /* usavermask - restore registers with mask                        */
2132 /*-----------------------------------------------------------------*/
2133 static void unsavermask(bitVect *rs_mask)
2134 {
2135     int i;
2136     if (options.useXstack) {
2137         emitcode ("mov", "r0,%s", spname);
2138         for (i = ds390_nRegs; i >= 0; i--) {
2139             if (bitVectBitValue (rs_mask, i)) {
2140                 emitcode ("dec", "r0");
2141                 emitcode ("movx", "a,@r0");
2142                 if (i == R0_IDX)
2143                     emitcode ("mov", "b,a");
2144                 else
2145                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2146             }       
2147         }
2148         emitcode ("mov", "%s,r0", spname);
2149         if (bitVectBitValue (rs_mask, R0_IDX))
2150             emitcode ("mov", "r0,b");
2151     } else {
2152         for (i = ds390_nRegs; i >= 0; i--) {
2153             if (bitVectBitValue (rs_mask, i))
2154                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2155         }
2156     }
2157 }
2158
2159 /*-----------------------------------------------------------------*/
2160 /* unsaveRegisters - pop the pushed registers                      */
2161 /*-----------------------------------------------------------------*/
2162 static void
2163 unsaveRegisters (iCode * ic)
2164 {
2165   bitVect *rsave;
2166
2167   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2168       int i;
2169       rsave = newBitVect(ic->rMask->size);
2170       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2171           if (bitVectBitValue(ic->rMask,i))
2172               rsave = bitVectSetBit(rsave,i);
2173       }
2174       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2175   } else {
2176     /* restore the registers in use at this time but skip the
2177        ones for the result */
2178     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2179                            ds390_rUmaskForOp (IC_RESULT(ic)));
2180   }
2181   unsavermask(rsave);
2182 }
2183
2184
2185 /*-----------------------------------------------------------------*/
2186 /* pushSide -                */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 pushSide (operand * oper, int size)
2190 {
2191   int offset = 0;
2192   _startLazyDPSEvaluation ();
2193   while (size--)
2194     {
2195       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2196       if (AOP_TYPE (oper) != AOP_REG &&
2197           AOP_TYPE (oper) != AOP_DIR &&
2198           strcmp (l, "a"))
2199         {
2200           emitcode ("mov", "a,%s", l);
2201           emitcode ("push", "acc");
2202         }
2203       else
2204         emitcode ("push", "%s", l);
2205     }
2206   _endLazyDPSEvaluation ();
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue -               */
2211 /*-----------------------------------------------------------------*/
2212 static void
2213 assignResultValue (operand * oper)
2214 {
2215   int offset = 0;
2216   int size = AOP_SIZE (oper);
2217   bool pushedAcc = FALSE;
2218
2219   if (size == fReturnSizeDS390)
2220   {
2221       /* I don't think this case can ever happen... */
2222       /* ACC is the last part of this. If writing the result
2223        * uses AC, we must preserve it.
2224        */
2225       if (AOP_NEEDSACC(oper))
2226       {
2227           emitcode(";", "assignResultValue special case for ACC.");
2228           emitcode("push", "acc");
2229           pushedAcc = TRUE;
2230           size--;
2231       }
2232   }
2233     
2234     
2235   _startLazyDPSEvaluation ();
2236   while (size--)
2237     {
2238       aopPut (AOP (oper), fReturn[offset], offset);
2239       offset++;
2240     }
2241   _endLazyDPSEvaluation ();
2242     
2243   if (pushedAcc)
2244     {
2245         emitcode("pop", "acc");
2246         aopPut(AOP(oper), "a", offset);
2247     }
2248 }
2249
2250
2251 /*-----------------------------------------------------------------*/
2252 /* genXpush - pushes onto the external stack                       */
2253 /*-----------------------------------------------------------------*/
2254 static void
2255 genXpush (iCode * ic)
2256 {
2257   asmop *aop = newAsmop (0);
2258   regs *r;
2259   int size, offset = 0;
2260
2261   D (emitcode (";", "genXpush ");
2262     );
2263
2264   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265   r = getFreePtr (ic, &aop, FALSE);
2266
2267
2268   emitcode ("mov", "%s,_spx", r->name);
2269
2270   size = AOP_SIZE (IC_LEFT (ic));
2271   _startLazyDPSEvaluation ();
2272   while (size--)
2273     {
2274
2275       MOVA (aopGet (AOP (IC_LEFT (ic)),
2276                         offset++, FALSE, FALSE, NULL));
2277       emitcode ("movx", "@%s,a", r->name);
2278       emitcode ("inc", "%s", r->name);
2279
2280     }
2281   _endLazyDPSEvaluation ();
2282
2283
2284   emitcode ("mov", "_spx,%s", r->name);
2285
2286   freeAsmop (NULL, aop, ic, TRUE);
2287   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* genIpush - generate code for pushing this gets a little complex  */
2292 /*-----------------------------------------------------------------*/
2293 static void
2294 genIpush (iCode * ic)
2295 {
2296   int size, offset = 0;
2297   char *l;
2298
2299   D (emitcode (";", "genIpush ");
2300     );
2301
2302   /* if this is not a parm push : ie. it is spill push
2303      and spill push is always done on the local stack */
2304   if (!ic->parmPush)
2305     {
2306
2307       /* and the item is spilt then do nothing */
2308       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2309         return;
2310
2311       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2312       size = AOP_SIZE (IC_LEFT (ic));
2313       /* push it on the stack */
2314       _startLazyDPSEvaluation ();
2315       while (size--)
2316         {
2317           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2318           if (*l == '#')
2319             {
2320               MOVA (l);
2321               l = "acc";
2322             }
2323           emitcode ("push", "%s", l);
2324         }
2325       _endLazyDPSEvaluation ();
2326       return;
2327     }
2328
2329   /* this is a paramter push: in this case we call
2330      the routine to find the call and save those
2331      registers that need to be saved */
2332   saveRegisters (ic);
2333
2334   /* if use external stack then call the external
2335      stack pushing routine */
2336   if (options.useXstack)
2337     {
2338       genXpush (ic);
2339       return;
2340     }
2341
2342   /* then do the push */
2343   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2344
2345   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2346   size = AOP_SIZE (IC_LEFT (ic));
2347
2348   _startLazyDPSEvaluation ();
2349   while (size--)
2350     {
2351       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2352       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2353           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2354           strcmp (l, "acc"))
2355         {
2356           emitcode ("mov", "a,%s", l);
2357           emitcode ("push", "acc");
2358         }
2359       else
2360         {
2361             emitcode ("push", "%s", l);
2362         }
2363     }
2364   _endLazyDPSEvaluation ();
2365
2366   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling   */
2371 /*-----------------------------------------------------------------*/
2372 static void
2373 genIpop (iCode * ic)
2374 {
2375   int size, offset;
2376
2377   D (emitcode (";", "genIpop ");
2378     );
2379
2380
2381   /* if the temp was not pushed then */
2382   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2383     return;
2384
2385   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2386   size = AOP_SIZE (IC_LEFT (ic));
2387   offset = (size - 1);
2388   _startLazyDPSEvaluation ();
2389   while (size--)
2390     {
2391       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2392                                      FALSE, TRUE, NULL));
2393     }
2394   _endLazyDPSEvaluation ();
2395
2396   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2397 }
2398
2399 /*-----------------------------------------------------------------*/
2400 /* unsaveRBank - restores the resgister bank from stack            */
2401 /*-----------------------------------------------------------------*/
2402 static void
2403 unsaveRBank (int bank, iCode * ic, bool popPsw)
2404 {
2405   int i;
2406   asmop *aop = NULL;
2407   regs *r = NULL;
2408
2409   if (options.useXstack)
2410   {
2411       if (!ic)
2412       {
2413           /* Assume r0 is available for use. */
2414           r = ds390_regWithIdx (R0_IDX);;          
2415       } 
2416       else
2417       {
2418           aop = newAsmop (0);
2419           r = getFreePtr (ic, &aop, FALSE);
2420       }
2421       emitcode ("mov", "%s,_spx", r->name);      
2422   }
2423   
2424   if (popPsw)
2425     {
2426       if (options.useXstack)
2427       {
2428           emitcode ("movx", "a,@%s", r->name);
2429           emitcode ("mov", "psw,a");
2430           emitcode ("dec", "%s", r->name);
2431         }
2432       else
2433       {
2434         emitcode ("pop", "psw");
2435       }
2436     }
2437
2438   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2439     {
2440       if (options.useXstack)
2441         {
2442           emitcode ("movx", "a,@%s", r->name);
2443           emitcode ("mov", "(%s+%d),a",
2444                     regs390[i].base, 8 * bank + regs390[i].offset);
2445           emitcode ("dec", "%s", r->name);
2446
2447         }
2448       else
2449         emitcode ("pop", "(%s+%d)",
2450                   regs390[i].base, 8 * bank + regs390[i].offset);
2451     }
2452
2453   if (options.useXstack)
2454     {
2455       emitcode ("mov", "_spx,%s", r->name);
2456     }
2457     
2458   if (aop)
2459   {
2460       freeAsmop (NULL, aop, ic, TRUE);  
2461   }    
2462 }
2463
2464 /*-----------------------------------------------------------------*/
2465 /* saveRBank - saves an entire register bank on the stack          */
2466 /*-----------------------------------------------------------------*/
2467 static void
2468 saveRBank (int bank, iCode * ic, bool pushPsw)
2469 {
2470   int i;
2471   asmop *aop = NULL;
2472   regs *r = NULL;
2473
2474   if (options.useXstack)
2475     {
2476         if (!ic)
2477         {
2478           /* Assume r0 is available for use. */
2479                   r = ds390_regWithIdx (R0_IDX);;
2480         }
2481         else
2482         {
2483           aop = newAsmop (0);
2484           r = getFreePtr (ic, &aop, FALSE);
2485         }
2486         emitcode ("mov", "%s,_spx", r->name);    
2487     }
2488
2489   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2490     {
2491       if (options.useXstack)
2492         {
2493           emitcode ("inc", "%s", r->name);
2494           emitcode ("mov", "a,(%s+%d)",
2495                     regs390[i].base, 8 * bank + regs390[i].offset);
2496           emitcode ("movx", "@%s,a", r->name);
2497         }
2498       else
2499         emitcode ("push", "(%s+%d)",
2500                   regs390[i].base, 8 * bank + regs390[i].offset);
2501     }
2502
2503   if (pushPsw)
2504     {
2505       if (options.useXstack)
2506         {
2507           emitcode ("mov", "a,psw");
2508           emitcode ("movx", "@%s,a", r->name);
2509           emitcode ("inc", "%s", r->name);
2510           emitcode ("mov", "_spx,%s", r->name);
2511         }
2512       else
2513       {
2514         emitcode ("push", "psw");
2515       }
2516
2517       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2518     }
2519   
2520   if (aop)
2521   {
2522        freeAsmop (NULL, aop, ic, TRUE);
2523   }    
2524     
2525   if (ic)
2526   {  
2527       ic->bankSaved = 1;
2528   }
2529 }
2530
2531 /*-----------------------------------------------------------------*/
2532 /* genSend - gen code for SEND                                     */
2533 /*-----------------------------------------------------------------*/
2534 static void genSend(set *sendSet)
2535 {
2536     iCode *sic;
2537     int sendCount = 0 ;
2538     static int rb1_count = 0;
2539
2540     for (sic = setFirstItem (sendSet); sic;
2541          sic = setNextItem (sendSet)) {     
2542         int size, offset = 0;
2543         
2544         size=getSize(operandType(IC_LEFT(sic)));
2545         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2546         if (sendCount == 0) { /* first parameter */
2547             // we know that dpl(hxb) is the result, so
2548             rb1_count = 0 ;
2549             _startLazyDPSEvaluation ();
2550             if (size>1) {
2551                 aopOp (IC_LEFT (sic), sic, FALSE, 
2552                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2553             } else {
2554                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2555             }
2556             while (size--) {
2557                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2558                                   FALSE, FALSE, NULL);
2559                 if (strcmp (l, fReturn[offset])) {
2560                     emitcode ("mov", "%s,%s",
2561                               fReturn[offset],
2562                               l);
2563                 }
2564                 offset++;
2565             }
2566             _endLazyDPSEvaluation ();
2567             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2568             rb1_count =0;
2569         } else { /* if more parameter in registers */
2570             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2571             while (size--) {
2572                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2573                                                                 FALSE, FALSE, NULL));
2574             }
2575             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2576         }
2577         sendCount++;
2578     }
2579 }
2580
2581 static void
2582 adjustEsp(const char *reg)
2583 {
2584     emitcode ("anl","%s,#3", reg);
2585     if (TARGET_IS_DS400)
2586     {
2587         emitcode ("orl","%s,#!constbyte",
2588                   reg,
2589                   (options.stack_loc >> 8) & 0xff);
2590     }
2591 }
2592
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement                            */
2595 /*-----------------------------------------------------------------*/
2596 static void
2597 genCall (iCode * ic)
2598 {
2599   sym_link *dtype;
2600   bool restoreBank = FALSE;
2601   bool swapBanks = FALSE;
2602
2603   D (emitcode (";", "genCall "););
2604
2605   /* if we are calling a not _naked function that is not using
2606      the same register bank then we need to save the
2607      destination registers on the stack */
2608   dtype = operandType (IC_LEFT (ic));
2609   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2610       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2611       IFFUNC_ISISR (currFunc->type))
2612   {
2613       if (!ic->bankSaved) 
2614       {
2615            /* This is unexpected; the bank should have been saved in
2616             * genFunction.
2617             */
2618            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2619            restoreBank = TRUE;
2620       }
2621       swapBanks = TRUE;
2622   }
2623   
2624     /* if caller saves & we have not saved then */
2625     if (!ic->regsSaved)
2626       saveRegisters (ic);
2627   
2628   /* if send set is not empty the assign */
2629   /* We've saved all the registers we care about;
2630   * therefore, we may clobber any register not used
2631   * in the calling convention (i.e. anything not in
2632   * fReturn.
2633   */
2634   if (_G.sendSet)
2635     {
2636         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2637             genSend(reverseSet(_G.sendSet));
2638         } else {
2639             genSend(_G.sendSet);
2640         }
2641       _G.sendSet = NULL;
2642     }  
2643     
2644   if (swapBanks)
2645   {
2646         emitcode ("mov", "psw,#!constbyte", 
2647            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2648   }
2649
2650   /* make the call */
2651   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2652                             OP_SYMBOL (IC_LEFT (ic))->rname :
2653                             OP_SYMBOL (IC_LEFT (ic))->name));
2654
2655   if (swapBanks)
2656   {
2657        emitcode ("mov", "psw,#!constbyte", 
2658           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2659   }
2660
2661   /* if we need assign a result value */
2662   if ((IS_ITEMP (IC_RESULT (ic)) &&
2663        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2664         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2665         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666       IS_TRUE_SYMOP (IC_RESULT (ic)))
2667     {
2668       if (isOperandInFarSpace (IC_RESULT (ic))
2669           && getSize (operandType (IC_RESULT (ic))) <= 2)
2670         {
2671           int size = getSize (operandType (IC_RESULT (ic)));
2672
2673           /* Special case for 1 or 2 byte return in far space. */
2674           MOVA (fReturn[0]);
2675           if (size > 1)
2676             {
2677               emitcode ("mov", "b,%s", fReturn[1]);
2678               _G.bInUse++;
2679             }
2680
2681           _G.accInUse++;
2682           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2683           _G.accInUse--;
2684           
2685           if (size > 1)
2686             _G.bInUse--;
2687
2688           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2689
2690           if (size > 1)
2691             {
2692               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2693             }
2694           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2695         }
2696       else
2697         {
2698           _G.bInUse++;
2699           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2700           _G.bInUse--;
2701
2702           assignResultValue (IC_RESULT (ic));
2703
2704           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2705         }
2706     }
2707
2708   /* adjust the stack for parameters if
2709      required */
2710   if (ic->parmBytes) {
2711       int i;
2712       if (options.stack10bit) {
2713           if (ic->parmBytes <= 10) {
2714               emitcode(";","stack adjustment for parms");
2715               for (i=0; i < ic->parmBytes ; i++) {
2716                   emitcode("pop","acc");
2717               }
2718           } else {            
2719               PROTECT_SP;
2720               emitcode ("clr","c");
2721               emitcode ("mov","a,sp");
2722               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2723               emitcode ("mov","sp,a");
2724               emitcode ("mov","a,esp");
2725               adjustEsp("a");
2726               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2727               emitcode ("mov","esp,a");   
2728               UNPROTECT_SP;
2729           }
2730       } else {
2731           if (ic->parmBytes > 3) {
2732               emitcode ("mov", "a,%s", spname);
2733               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2734               emitcode ("mov", "%s,a", spname);
2735           } else
2736               for (i = 0; i < ic->parmBytes; i++)
2737                   emitcode ("dec", "%s", spname);
2738       }
2739   }
2740
2741   /* if we hade saved some registers then unsave them */
2742   if (ic->regsSaved)
2743     unsaveRegisters (ic);
2744
2745   /* if register bank was saved then pop them */
2746   if (restoreBank)
2747     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2748 }
2749
2750 /*-----------------------------------------------------------------*/
2751 /* genPcall - generates a call by pointer statement                */
2752 /*-----------------------------------------------------------------*/
2753 static void
2754 genPcall (iCode * ic)
2755 {
2756   sym_link *dtype;
2757   symbol *rlbl = newiTempLabel (NULL);
2758   bool restoreBank=FALSE;
2759
2760   D (emitcode (";", "genPcall ");
2761     );
2762
2763
2764   /* if caller saves & we have not saved then */
2765   if (!ic->regsSaved)
2766     saveRegisters (ic);
2767
2768   /* if we are calling a function that is not using
2769      the same register bank then we need to save the
2770      destination registers on the stack */
2771   dtype = operandType (IC_LEFT (ic));
2772   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2773       IFFUNC_ISISR (currFunc->type) &&
2774       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2775     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2776     restoreBank=TRUE;
2777   }
2778
2779   /* push the return address on to the stack */
2780   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2781   emitcode ("push", "acc");
2782   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2783   emitcode ("push", "acc");
2784
2785   if (options.model == MODEL_FLAT24)
2786     {
2787       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2788       emitcode ("push", "acc");
2789     }
2790
2791   /* now push the calling address */
2792   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2793
2794   pushSide (IC_LEFT (ic), FPTRSIZE);
2795
2796   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2797
2798   /* if send set is not empty the assign */
2799   if (_G.sendSet)
2800     {
2801         genSend(reverseSet(_G.sendSet));
2802         _G.sendSet = NULL;
2803     }
2804
2805   emitcode ("ret", "");
2806   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2807
2808
2809   /* if we need assign a result value */
2810   if ((IS_ITEMP (IC_RESULT (ic)) &&
2811        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2812         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2813       IS_TRUE_SYMOP (IC_RESULT (ic)))
2814     {
2815
2816       _G.accInUse++;
2817       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2818       _G.accInUse--;
2819
2820       assignResultValue (IC_RESULT (ic));
2821
2822       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2823     }
2824
2825   /* adjust the stack for parameters if
2826      required */
2827   if (ic->parmBytes)
2828     {
2829       int i;
2830       if (options.stack10bit) {
2831           if (ic->parmBytes <= 10) {
2832               emitcode(";","stack adjustment for parms");
2833               for (i=0; i < ic->parmBytes ; i++) {
2834                   emitcode("pop","acc");
2835               }
2836           } else {            
2837               PROTECT_SP;
2838               emitcode ("clr","c");
2839               emitcode ("mov","a,sp");
2840               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2841               emitcode ("mov","sp,a");
2842               emitcode ("mov","a,esp");
2843               adjustEsp("a");
2844               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2845               emitcode ("mov","esp,a");   
2846               UNPROTECT_SP;
2847           }
2848       } else {
2849           if (ic->parmBytes > 3) {
2850               emitcode ("mov", "a,%s", spname);
2851               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2852               emitcode ("mov", "%s,a", spname);
2853           }
2854           else
2855               for (i = 0; i < ic->parmBytes; i++)
2856                   emitcode ("dec", "%s", spname);
2857           
2858       }
2859     }
2860   /* if register bank was saved then unsave them */
2861   if (restoreBank)
2862     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2863   
2864   /* if we hade saved some registers then
2865      unsave them */
2866   if (ic->regsSaved)
2867     unsaveRegisters (ic);
2868
2869 }
2870
2871 /*-----------------------------------------------------------------*/
2872 /* resultRemat - result  is rematerializable                       */
2873 /*-----------------------------------------------------------------*/
2874 static int
2875 resultRemat (iCode * ic)
2876 {
2877   if (SKIP_IC (ic) || ic->op == IFX)
2878     return 0;
2879
2880   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2881     {
2882       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2883       if (sym->remat && !POINTER_SET (ic))
2884         return 1;
2885     }
2886
2887   return 0;
2888 }
2889
2890 #if defined(__BORLANDC__) || defined(_MSC_VER)
2891 #define STRCASECMP stricmp
2892 #else
2893 #define STRCASECMP strcasecmp
2894 #endif
2895
2896 /*-----------------------------------------------------------------*/
2897 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2898 /*-----------------------------------------------------------------*/
2899 static int
2900 regsCmp(void *p1, void *p2)
2901 {
2902   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2903 }
2904
2905 static bool
2906 inExcludeList (char *s)
2907 {
2908   const char *p = setFirstItem(options.excludeRegsSet);
2909
2910   if (p == NULL || STRCASECMP(p, "none") == 0)
2911     return FALSE;
2912
2913
2914   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2915 }
2916
2917 /*-----------------------------------------------------------------*/
2918 /* genFunction - generated code for function entry                 */
2919 /*-----------------------------------------------------------------*/
2920 static void
2921 genFunction (iCode * ic)
2922 {
2923   symbol *sym;
2924   sym_link *ftype;
2925   bool   switchedPSW = FALSE;
2926
2927   D (emitcode (";", "genFunction "););
2928
2929   _G.nRegsSaved = 0;
2930   /* create the function header */
2931   emitcode (";", "-----------------------------------------");
2932   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2933   emitcode (";", "-----------------------------------------");
2934
2935   emitcode ("", "%s:", sym->rname);
2936   ftype = operandType (IC_LEFT (ic));
2937
2938   if (IFFUNC_ISNAKED(ftype))
2939   {
2940       emitcode(";", "naked function: no prologue.");
2941       return;
2942   }
2943   
2944   if (options.stack_probe) 
2945       emitcode ("lcall","__stack_probe");
2946
2947   /* here we need to generate the equates for the
2948      register bank if required */
2949   if (FUNC_REGBANK (ftype) != rbank)
2950     {
2951       int i;
2952
2953       rbank = FUNC_REGBANK (ftype);
2954       for (i = 0; i < ds390_nRegs; i++)
2955         {
2956           if (regs390[i].print) {
2957               if (strcmp (regs390[i].base, "0") == 0)
2958                   emitcode ("", "%s !equ !constbyte",
2959                             regs390[i].dname,
2960                             8 * rbank + regs390[i].offset);
2961               else
2962                   emitcode ("", "%s !equ %s + !constbyte",
2963                             regs390[i].dname,
2964                             regs390[i].base,
2965                             8 * rbank + regs390[i].offset);
2966           }
2967         }
2968     }
2969
2970   /* if this is an interrupt service routine then
2971      save acc, b, dpl, dph  */
2972   if (IFFUNC_ISISR (sym->type))
2973       { /* is ISR */
2974       if (!inExcludeList ("acc"))
2975         emitcode ("push", "acc");
2976       if (!inExcludeList ("b"))
2977         emitcode ("push", "b");
2978       if (!inExcludeList ("dpl"))
2979         emitcode ("push", "dpl");
2980       if (!inExcludeList ("dph"))
2981         emitcode ("push", "dph");
2982       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2983         {
2984           emitcode ("push", "dpx");
2985           /* Make sure we're using standard DPTR */
2986           emitcode ("push", "dps");
2987           emitcode ("mov", "dps,#0");
2988           if (options.stack10bit)
2989             {
2990               /* This ISR could conceivably use DPTR2. Better save it. */
2991               emitcode ("push", "dpl1");
2992               emitcode ("push", "dph1");
2993               emitcode ("push", "dpx1");
2994               emitcode ("push",  DP2_RESULT_REG);
2995             }
2996         }
2997       /* if this isr has no bank i.e. is going to
2998          run with bank 0 , then we need to save more
2999          registers :-) */
3000       if (!FUNC_REGBANK (sym->type))
3001         {
3002             int i;
3003
3004           /* if this function does not call any other
3005              function then we can be economical and
3006              save only those registers that are used */
3007           if (!IFFUNC_HASFCALL(sym->type))
3008             {
3009
3010               /* if any registers used */
3011               if (sym->regsUsed)
3012                 {
3013                   /* save the registers used */
3014                   for (i = 0; i < sym->regsUsed->size; i++)
3015                     {
3016                       if (bitVectBitValue (sym->regsUsed, i) ||
3017                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3018                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3019                     }
3020                 }
3021
3022             }
3023           else
3024             {
3025               /* this function has  a function call cannot
3026                  determines register usage so we will have to push the
3027                  entire bank */
3028               saveRBank (0, ic, FALSE);
3029               if (options.parms_in_bank1) {
3030                   for (i=0; i < 8 ; i++ ) {
3031                       emitcode ("push","%s",rb1regs[i]);
3032                   }
3033               }
3034             }
3035         }
3036         else
3037         {
3038             /* This ISR uses a non-zero bank.
3039              *
3040              * We assume that the bank is available for our
3041              * exclusive use.
3042              *
3043              * However, if this ISR calls a function which uses some
3044              * other bank, we must save that bank entirely.
3045              */
3046             unsigned long banksToSave = 0;
3047             
3048             if (IFFUNC_HASFCALL(sym->type))
3049             {
3050
3051 #define MAX_REGISTER_BANKS 4
3052
3053                 iCode *i;
3054                 int ix;
3055
3056                 for (i = ic; i; i = i->next)
3057                 {
3058                     if (i->op == ENDFUNCTION)
3059                     {
3060                         /* we got to the end OK. */
3061                         break;
3062                     }
3063                     
3064                     if (i->op == CALL)
3065                     {
3066                         sym_link *dtype;
3067                         
3068                         dtype = operandType (IC_LEFT(i));
3069                         if (dtype 
3070                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3071                         {
3072                              /* Mark this bank for saving. */
3073                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3074                              {
3075                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3076                              }
3077                              else
3078                              {
3079                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3080                              }
3081                              
3082                              /* And note that we don't need to do it in 
3083                               * genCall.
3084                               */
3085                              i->bankSaved = 1;
3086                         }
3087                     }
3088                     if (i->op == PCALL)
3089                     {
3090                         /* This is a mess; we have no idea what
3091                          * register bank the called function might
3092                          * use.
3093                          *
3094                          * The only thing I can think of to do is
3095                          * throw a warning and hope.
3096                          */
3097                         werror(W_FUNCPTR_IN_USING_ISR);   
3098                     }
3099                 }
3100
3101                 if (banksToSave && options.useXstack)
3102                 {
3103                     /* Since we aren't passing it an ic, 
3104                      * saveRBank will assume r0 is available to abuse.
3105                      *
3106                      * So switch to our (trashable) bank now, so
3107                      * the caller's R0 isn't trashed.
3108                      */
3109                     emitcode ("push", "psw");
3110                     emitcode ("mov", "psw,#!constbyte", 
3111                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3112                     switchedPSW = TRUE;
3113                 }
3114                 
3115                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3116                 {
3117                      if (banksToSave & (1 << ix))
3118                      {
3119                          saveRBank(ix, NULL, FALSE);
3120                      }
3121                 }
3122             }
3123             // TODO: this needs a closer look
3124             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3125         }
3126     }
3127   else
3128     {
3129       /* if callee-save to be used for this function
3130          then save the registers being used in this function */
3131       if (IFFUNC_CALLEESAVES(sym->type))
3132         {
3133           int i;
3134
3135           /* if any registers used */
3136           if (sym->regsUsed)
3137             {
3138               /* save the registers used */
3139               for (i = 0; i < sym->regsUsed->size; i++)
3140                 {
3141                   if (bitVectBitValue (sym->regsUsed, i) ||
3142                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3143                     {
3144                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3145                       _G.nRegsSaved++;
3146                     }
3147                 }
3148             }
3149         }
3150     }
3151
3152   /* set the register bank to the desired value */
3153   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3154    && !switchedPSW)
3155     {
3156       emitcode ("push", "psw");
3157       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3158     }
3159
3160   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3161        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3162       if (options.stack10bit) {
3163           emitcode ("push","_bpx");
3164           emitcode ("push","_bpx+1");
3165           emitcode ("mov","_bpx,%s",spname);
3166           emitcode ("mov","_bpx+1,esp");
3167           adjustEsp("_bpx+1");
3168       } else {
3169           if (options.useXstack) {
3170               emitcode ("mov", "r0,%s", spname);
3171               emitcode ("mov", "a,_bp");
3172               emitcode ("movx", "@r0,a");
3173               emitcode ("inc", "%s", spname);
3174           } else {
3175               /* set up the stack */
3176               emitcode ("push", "_bp"); /* save the callers stack  */
3177           }
3178           emitcode ("mov", "_bp,%s", spname);
3179       }
3180   }
3181
3182   /* adjust the stack for the function */
3183   if (sym->stack) {
3184       int i = sym->stack;
3185       if (options.stack10bit) {
3186           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3187           assert (sym->recvSize <= 4);
3188           if (sym->stack <= 8) {
3189               while (i--) emitcode ("push","acc");
3190           } else {
3191               PROTECT_SP;
3192               emitcode ("mov","a,sp");
3193               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3194               emitcode ("mov","sp,a");
3195               emitcode ("mov","a,esp");
3196               adjustEsp("a");
3197               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3198               emitcode ("mov","esp,a");
3199               UNPROTECT_SP;
3200           }
3201       } else {
3202           if (i > 256)
3203               werror (W_STACK_OVERFLOW, sym->name);
3204           
3205           if (i > 3 && sym->recvSize < 4) {
3206               
3207               emitcode ("mov", "a,sp");
3208               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3209               emitcode ("mov", "sp,a");
3210               
3211           } else
3212               while (i--)
3213                   emitcode ("inc", "sp");
3214       }
3215   }
3216
3217   if (sym->xstack)
3218     {
3219
3220       emitcode ("mov", "a,_spx");
3221       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3222       emitcode ("mov", "_spx,a");
3223     }
3224   
3225   /* if critical function then turn interrupts off */
3226   if (IFFUNC_ISCRITICAL (ftype))
3227     {
3228       symbol *tlbl = newiTempLabel (NULL);
3229       emitcode ("setb", "c");
3230       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3231       emitcode ("clr", "c");
3232       emitcode ("", "%05d$:", (tlbl->key + 100));
3233       emitcode ("push", "psw"); /* save old ea via c in psw */
3234     }
3235
3236 }
3237
3238 /*-----------------------------------------------------------------*/
3239 /* genEndFunction - generates epilogue for functions               */
3240 /*-----------------------------------------------------------------*/
3241 static void
3242 genEndFunction (iCode * ic)
3243 {
3244   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3245
3246   D (emitcode (";", "genEndFunction "););
3247
3248   if (IFFUNC_ISNAKED(sym->type))
3249   {
3250       emitcode(";", "naked function: no epilogue.");
3251       return;
3252   }
3253
3254   if (IFFUNC_ISCRITICAL (sym->type))
3255     {
3256       emitcode ("pop", "psw"); /* restore ea via c in psw */
3257       emitcode ("mov", "ea,c");
3258     }
3259   
3260   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3261        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3262
3263       if (options.stack10bit) {
3264           PROTECT_SP;     
3265           emitcode ("mov", "sp,_bpx", spname);
3266           emitcode ("mov", "esp,_bpx+1", spname);
3267           UNPROTECT_SP;
3268       } else {
3269           emitcode ("mov", "%s,_bp", spname);
3270       }
3271   }
3272
3273   /* if use external stack but some variables were
3274      added to the local stack then decrement the
3275      local stack */
3276   if (options.useXstack && sym->stack) {
3277       emitcode ("mov", "a,sp");
3278       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3279       emitcode ("mov", "sp,a");
3280   }
3281
3282
3283   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3284        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3285
3286       if (options.useXstack) {
3287           emitcode ("mov", "r0,%s", spname);
3288           emitcode ("movx", "a,@r0");
3289           emitcode ("mov", "_bp,a");
3290           emitcode ("dec", "%s", spname);
3291       } else {
3292           if (options.stack10bit) {
3293               emitcode ("pop", "_bpx+1");
3294               emitcode ("pop", "_bpx");
3295           } else {
3296               emitcode ("pop", "_bp");
3297           }
3298       }
3299   }
3300
3301   /* restore the register bank  */
3302   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3303   {
3304     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3305      || !options.useXstack)
3306     {
3307         /* Special case of ISR using non-zero bank with useXstack
3308          * is handled below.
3309          */
3310         emitcode ("pop", "psw");
3311     }
3312   } 
3313
3314   if (IFFUNC_ISISR (sym->type))
3315       { /* is ISR */  
3316
3317       /* now we need to restore the registers */
3318       /* if this isr has no bank i.e. is going to
3319          run with bank 0 , then we need to save more
3320          registers :-) */
3321       if (!FUNC_REGBANK (sym->type))
3322         {
3323             int i;
3324           /* if this function does not call any other
3325              function then we can be economical and
3326              save only those registers that are used */
3327           if (!IFFUNC_HASFCALL(sym->type))
3328             {
3329
3330               /* if any registers used */
3331               if (sym->regsUsed)
3332                 {
3333                   /* save the registers used */
3334                   for (i = sym->regsUsed->size; i >= 0; i--)
3335                     {
3336                       if (bitVectBitValue (sym->regsUsed, i) ||
3337                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3339                     }
3340                 }
3341
3342             }
3343           else
3344             {
3345               /* this function has  a function call cannot
3346                  determines register usage so we will have to pop the
3347                  entire bank */
3348               if (options.parms_in_bank1) {
3349                   for (i = 7 ; i >= 0 ; i-- ) {
3350                       emitcode ("pop","%s",rb1regs[i]);
3351                   }
3352               }
3353               unsaveRBank (0, ic, FALSE);
3354             }
3355         }
3356         else
3357         {
3358             /* This ISR uses a non-zero bank.
3359              *
3360              * Restore any register banks saved by genFunction
3361              * in reverse order.
3362              */
3363             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3364             int ix;
3365           
3366             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3367             {
3368                 if (savedBanks & (1 << ix))
3369                 {
3370                     unsaveRBank(ix, NULL, FALSE);
3371                 }
3372             }
3373             
3374             if (options.useXstack)
3375             {
3376                 /* Restore bank AFTER calling unsaveRBank,
3377                  * since it can trash r0.
3378                  */
3379                 emitcode ("pop", "psw");
3380             }
3381         }
3382
3383       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3384         {
3385           if (options.stack10bit)
3386             {
3387               emitcode ("pop", DP2_RESULT_REG);
3388               emitcode ("pop", "dpx1");
3389               emitcode ("pop", "dph1");
3390               emitcode ("pop", "dpl1");
3391             }
3392           emitcode ("pop", "dps");
3393           emitcode ("pop", "dpx");
3394         }
3395       if (!inExcludeList ("dph"))
3396         emitcode ("pop", "dph");
3397       if (!inExcludeList ("dpl"))
3398         emitcode ("pop", "dpl");
3399       if (!inExcludeList ("b"))
3400         emitcode ("pop", "b");
3401       if (!inExcludeList ("acc"))
3402         emitcode ("pop", "acc");
3403
3404       /* if debug then send end of function */
3405       if (options.debug && currFunc) {
3406           _G.debugLine = 1;
3407           emitcode ("", "C$%s$%d$%d$%d ==.",
3408                     FileBaseName (ic->filename), currFunc->lastLine,
3409                     ic->level, ic->block);
3410           if (IS_STATIC (currFunc->etype))
3411             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3412           else
3413             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3414           _G.debugLine = 0;
3415         }
3416
3417       emitcode ("reti", "");
3418     }
3419   else
3420     {
3421       if (IFFUNC_CALLEESAVES(sym->type))
3422         {
3423           int i;
3424
3425           /* if any registers used */
3426           if (sym->regsUsed)
3427             {
3428               /* save the registers used */
3429               for (i = sym->regsUsed->size; i >= 0; i--)
3430                 {
3431                   if (bitVectBitValue (sym->regsUsed, i) ||
3432                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3433                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3434                 }
3435             }
3436
3437         }
3438
3439       /* if debug then send end of function */
3440       if (options.debug && currFunc)
3441         {
3442           _G.debugLine = 1;
3443           emitcode ("", "C$%s$%d$%d$%d ==.",
3444                     FileBaseName (ic->filename), currFunc->lastLine,
3445                     ic->level, ic->block);
3446           if (IS_STATIC (currFunc->etype))
3447             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3448           else
3449             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3450           _G.debugLine = 0;
3451         }
3452
3453       emitcode ("ret", "");
3454     }
3455
3456 }
3457
3458 /*-----------------------------------------------------------------*/
3459 /* genJavaNativeRet - generate code for return JavaNative          */
3460 /*-----------------------------------------------------------------*/
3461 static void genJavaNativeRet(iCode *ic)
3462 {
3463     int i, size;
3464
3465     aopOp (IC_LEFT (ic), ic, FALSE, 
3466            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3467     size = AOP_SIZE (IC_LEFT (ic));
3468
3469     assert (size <= 4);
3470
3471     /* it is assigned to GPR0-R3 then push them */
3472     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3473         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3474         for (i = 0 ; i < size ; i++ ) {
3475             emitcode ("push","%s",
3476                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3477         }
3478         for (i = (size-1) ; i >= 0 ; i--) {
3479             emitcode ("pop","a%s",javaRet[i]);
3480         }
3481     } else {
3482         for (i = 0 ; i < size ; i++) 
3483             emitcode ("mov","%s,%s",javaRet[i],
3484                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3485     }
3486     for (i = size ; i < 4 ; i++ )
3487             emitcode ("mov","%s,#0",javaRet[i]);
3488     return;
3489 }
3490
3491 /*-----------------------------------------------------------------*/
3492 /* genRet - generate code for return statement                     */
3493 /*-----------------------------------------------------------------*/
3494 static void
3495 genRet (iCode * ic)
3496 {
3497   int size, offset = 0, pushed = 0;
3498
3499   D (emitcode (";", "genRet "););
3500
3501   /* if we have no return value then
3502      just generate the "ret" */
3503   if (!IC_LEFT (ic))
3504     goto jumpret;
3505
3506   /* if this is a JavaNative function then return 
3507      value in different register */
3508   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3509       genJavaNativeRet(ic);
3510       goto jumpret;
3511   }
3512   /* we have something to return then
3513      move the return value into place */
3514   aopOp (IC_LEFT (ic), ic, FALSE, 
3515          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3516   size = AOP_SIZE (IC_LEFT (ic));
3517
3518   _startLazyDPSEvaluation ();
3519   while (size--)
3520     {
3521       char *l;
3522       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3523         {
3524           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3525                       FALSE, TRUE, NULL);
3526           emitcode ("push", "%s", l);
3527           pushed++;
3528         }
3529       else
3530         {
3531           /* Since A is the last element of fReturn,
3532            * is is OK to clobber it in the aopGet.
3533            */
3534           l = aopGet (AOP (IC_LEFT (ic)), offset,
3535                       FALSE, FALSE, NULL);
3536           if (strcmp (fReturn[offset], l))
3537             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3538         }
3539     }
3540   _endLazyDPSEvaluation ();
3541
3542   if (pushed)
3543     {
3544       while (pushed)
3545         {
3546           pushed--;
3547           if (strcmp (fReturn[pushed], "a"))
3548             emitcode ("pop", fReturn[pushed]);
3549           else
3550             emitcode ("pop", "acc");
3551         }
3552     }
3553   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3554
3555 jumpret:
3556   /* generate a jump to the return label
3557      if the next is not the return statement */
3558   if (!(ic->next && ic->next->op == LABEL &&
3559         IC_LABEL (ic->next) == returnLabel))
3560
3561     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3562
3563 }
3564
3565 /*-----------------------------------------------------------------*/
3566 /* genLabel - generates a label                                    */
3567 /*-----------------------------------------------------------------*/
3568 static void
3569 genLabel (iCode * ic)
3570 {
3571   /* special case never generate */
3572   if (IC_LABEL (ic) == entryLabel)
3573     return;
3574
3575   D (emitcode (";", "genLabel ");
3576     );
3577
3578   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* genGoto - generates a ljmp                                      */
3583 /*-----------------------------------------------------------------*/
3584 static void
3585 genGoto (iCode * ic)
3586 {
3587   D (emitcode (";", "genGoto ");
3588     );
3589   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3590 }
3591
3592 /*-----------------------------------------------------------------*/
3593 /* findLabelBackwards: walks back through the iCode chain looking  */
3594 /* for the given label. Returns number of iCode instructions     */
3595 /* between that label and given ic.          */
3596 /* Returns zero if label not found.          */
3597 /*-----------------------------------------------------------------*/
3598 static int
3599 findLabelBackwards (iCode * ic, int key)
3600 {
3601   int count = 0;
3602
3603   while (ic->prev)
3604     {
3605       ic = ic->prev;
3606       count++;
3607
3608       /* If we have any pushes or pops, we cannot predict the distance.
3609          I don't like this at all, this should be dealt with in the 
3610          back-end */
3611       if (ic->op == IPUSH || ic->op == IPOP) {
3612         return 0;
3613       }
3614
3615       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3616         {
3617           /* printf("findLabelBackwards = %d\n", count); */
3618           return count;
3619         }
3620     }
3621
3622   return 0;
3623 }
3624
3625 /*-----------------------------------------------------------------*/
3626 /* genPlusIncr :- does addition with increment if possible         */
3627 /*-----------------------------------------------------------------*/
3628 static bool
3629 genPlusIncr (iCode * ic)
3630 {
3631   unsigned int icount;
3632   unsigned int size = getDataSize (IC_RESULT (ic));
3633
3634   /* will try to generate an increment */
3635   /* if the right side is not a literal
3636      we cannot */
3637   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3638     return FALSE;
3639
3640   /* if the literal value of the right hand side
3641      is greater than 4 then it is not worth it */
3642   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3643     return FALSE;
3644
3645   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3646       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3647       while (icount--) {
3648           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3649       }
3650       return TRUE;
3651   }
3652   /* if increment 16 bits in register */
3653   if (
3654        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3657        (size > 1) &&
3658        (icount == 1))
3659     {
3660       symbol  *tlbl;
3661       int     emitTlbl;
3662       int     labelRange;
3663       char    *l;
3664
3665       /* If the next instruction is a goto and the goto target
3666        * is <= 5 instructions previous to this, we can generate
3667        * jumps straight to that target.
3668        */
3669       if (ic->next && ic->next->op == GOTO
3670           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3671           && labelRange <= 5)
3672         {
3673           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3674           tlbl = IC_LABEL (ic->next);
3675           emitTlbl = 0;
3676         }
3677       else
3678         {
3679           tlbl = newiTempLabel (NULL);
3680           emitTlbl = 1;
3681         }
3682         
3683       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3684       emitcode ("inc", "%s", l);
3685       
3686       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3687           IS_AOP_PREG (IC_RESULT (ic)))
3688       {   
3689         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3690       }
3691       else
3692       {
3693           emitcode ("clr", "a");
3694           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3695       }
3696
3697       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3698       emitcode ("inc", "%s", l);
3699       if (size > 2)
3700         {
3701             if (!strcmp(l, "acc"))
3702             {
3703                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3704             }
3705             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3706                      IS_AOP_PREG (IC_RESULT (ic)))
3707             {
3708                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3709             }
3710             else
3711             {
3712                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3713             }
3714
3715             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3716             emitcode ("inc", "%s", l);
3717         }
3718       if (size > 3)
3719         {
3720             if (!strcmp(l, "acc"))
3721             {
3722                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3723             }
3724             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3725                      IS_AOP_PREG (IC_RESULT (ic)))
3726             {
3727                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3728             }
3729             else
3730             {
3731                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3732             }
3733
3734             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3735             emitcode ("inc", "%s", l);  }
3736
3737       if (emitTlbl)
3738         {
3739           emitcode ("", "!tlabeldef", tlbl->key + 100);
3740         }
3741       return TRUE;
3742     }
3743
3744   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3745       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3746       options.model == MODEL_FLAT24 ) {
3747
3748       switch (size) {
3749       case 3:
3750           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3751       case 2:
3752           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3753       case 1:
3754           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3755           break;
3756       }
3757       while (icount--) emitcode ("inc","dptr");      
3758       return TRUE;
3759   }
3760
3761   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3762       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3763       icount <= 5 ) {
3764       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3765       while (icount--) emitcode ("inc","dptr");
3766       emitcode ("mov","dps,#0");
3767       return TRUE;
3768   }
3769
3770   /* if the sizes are greater than 1 then we cannot */
3771   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3772       AOP_SIZE (IC_LEFT (ic)) > 1)
3773     return FALSE;
3774
3775   /* we can if the aops of the left & result match or
3776      if they are in registers and the registers are the
3777      same */
3778   if (
3779        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3780        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3781        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3782     {
3783
3784       if (icount > 3)
3785         {
3786           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3787           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3788           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3789         }
3790       else
3791         {
3792
3793           _startLazyDPSEvaluation ();
3794           while (icount--)
3795             {
3796               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3797             }
3798           _endLazyDPSEvaluation ();
3799         }
3800
3801       return TRUE;
3802     }
3803
3804   return FALSE;
3805 }
3806
3807 /*-----------------------------------------------------------------*/
3808 /* outBitAcc - output a bit in acc                                 */
3809 /*-----------------------------------------------------------------*/
3810 static void
3811 outBitAcc (operand * result)
3812 {
3813   symbol *tlbl = newiTempLabel (NULL);
3814   /* if the result is a bit */
3815   if (AOP_TYPE (result) == AOP_CRY)
3816     {
3817       aopPut (AOP (result), "a", 0);
3818     }
3819   else
3820     {
3821       emitcode ("jz", "!tlabel", tlbl->key + 100);
3822       emitcode ("mov", "a,%s", one);
3823       emitcode ("", "!tlabeldef", tlbl->key + 100);
3824       outAcc (result);
3825     }
3826 }
3827
3828 /*-----------------------------------------------------------------*/
3829 /* genPlusBits - generates code for addition of two bits           */
3830 /*-----------------------------------------------------------------*/
3831 static void
3832 genPlusBits (iCode * ic)
3833 {
3834   D (emitcode (";", "genPlusBits "););
3835     
3836   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3837     {
3838       symbol *lbl = newiTempLabel (NULL);
3839       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3840       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3841       emitcode ("cpl", "c");
3842       emitcode ("", "!tlabeldef", (lbl->key + 100));
3843       outBitC (IC_RESULT (ic));
3844     }
3845   else
3846     {
3847       emitcode ("clr", "a");
3848       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3849       emitcode ("rlc", "a");
3850       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3851       emitcode ("addc", "a,#0");
3852       outAcc (IC_RESULT (ic));
3853     }
3854 }
3855
3856 static void
3857 adjustArithmeticResult (iCode * ic)
3858 {
3859   if (opIsGptr (IC_RESULT (ic)) &&
3860       opIsGptr (IC_LEFT (ic)) &&
3861       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3862     {
3863       aopPut (AOP (IC_RESULT (ic)),
3864               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3865               GPTRSIZE - 1);
3866     }
3867
3868   if (opIsGptr (IC_RESULT (ic)) &&
3869       opIsGptr (IC_RIGHT (ic)) &&
3870       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3871     {
3872       aopPut (AOP (IC_RESULT (ic)),
3873             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3874               GPTRSIZE - 1);
3875     }
3876
3877   if (opIsGptr (IC_RESULT (ic)) &&
3878       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3879       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3880       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3881       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3882     {
3883       char buff[5];
3884       SNPRINTF (buff, sizeof(buff), 
3885                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3886       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3887     }
3888 }
3889
3890 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3891 // generates the result if possible. If result is generated, returns TRUE; otherwise
3892 // returns false and caller must deal with fact that result isn't aopOp'd.
3893 bool aopOp3(iCode * ic)
3894 {
3895     bool dp1InUse, dp2InUse;
3896     bool useDp2;
3897     
3898     // First, generate the right opcode. DPTR may be used if neither left nor result are
3899     // of type AOP_STR.
3900     
3901 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3902 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3903 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3904 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3905 //      );
3906 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3907 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3908 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3909 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3910 //      );
3911     
3912     // Right uses DPTR unless left or result is an AOP_STR; however,
3913     // if right is an AOP_STR, it must use DPTR regardless.
3914     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3915      && !AOP_IS_STR(IC_RIGHT(ic)))
3916     {
3917         useDp2 = TRUE;
3918     }
3919     else
3920     {
3921         useDp2 = FALSE;
3922     }
3923         
3924     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3925     
3926     // if the right used DPTR, left MUST use DPTR2.
3927     // if the right used DPTR2, left MUST use DPTR.
3928     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3929     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3930     // enabling us to assign DPTR to result.
3931      
3932     if (AOP_USESDPTR(IC_RIGHT(ic)))
3933     {
3934         useDp2 = TRUE;
3935     }
3936     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3937     {
3938         useDp2 = FALSE;
3939     }
3940     else
3941     {
3942         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3943         {
3944             useDp2 = TRUE;
3945         }
3946         else
3947         {
3948             useDp2 = FALSE;
3949         }
3950     }
3951
3952     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3953
3954         
3955     // We've op'd the left & right. So, if left or right are the same operand as result, 
3956     // we know aopOp will succeed, and we can just do it & bail.
3957     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3958         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3959     {
3960 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3961         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3962         return TRUE;
3963     }
3964     
3965     // Operands may be equivalent (but not equal) if they share a spill location. If
3966     // so, use the same DPTR or DPTR2.
3967     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3968       {
3969         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3970         return TRUE;
3971       }
3972     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3973       {
3974         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3975         return TRUE;
3976       }
3977     
3978     // Note which dptrs are currently in use.
3979     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3980     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3981     
3982     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3983     // generate it.
3984     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3985     {
3986         return FALSE;
3987     }
3988     
3989     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3990     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3991     {
3992         return FALSE;
3993     }
3994     
3995     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3996     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3997     {
3998         return FALSE;
3999     }
4000
4001     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4002
4003     // Some sanity checking...
4004     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4005     {
4006         fprintf(stderr,
4007                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4008                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4009         emitcode(";", ">>> unexpected DPTR here.");
4010     }
4011     
4012     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4013     {
4014         fprintf(stderr,
4015                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4016                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4017         emitcode(";", ">>> unexpected DPTR2 here.");
4018     }    
4019     
4020     return TRUE;
4021 }
4022
4023 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4024 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4025 // will be set TRUE. The caller must then handle the case specially, noting
4026 // that the IC_RESULT operand is not aopOp'd.
4027 // 
4028 #define AOP_OP_3_NOFATAL(ic, rc) \
4029             do { rc = !aopOp3(ic); } while (0)
4030
4031 // aopOp the left & right operands of an ic.
4032 #define AOP_OP_2(ic) \
4033     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4034     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4035
4036 // convienience macro.
4037 #define AOP_SET_LOCALS(ic) \
4038     left = IC_LEFT(ic); \
4039     right = IC_RIGHT(ic); \
4040     result = IC_RESULT(ic);
4041
4042
4043 // Given an integer value of pushedSize bytes on the stack,
4044 // adjust it to be resultSize bytes, either by discarding
4045 // the most significant bytes or by zero-padding.
4046 //
4047 // On exit from this macro, pushedSize will have been adjusted to
4048 // equal resultSize, and ACC may be trashed.
4049 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4050       /* If the pushed data is bigger than the result,          \
4051        * simply discard unused bytes. Icky, but works.          \
4052        */                                                       \
4053       while (pushedSize > resultSize)                           \
4054       {                                                         \
4055           D (emitcode (";", "discarding unused result byte."););\
4056           emitcode ("pop", "acc");                              \
4057           pushedSize--;                                         \
4058       }                                                         \
4059       if (pushedSize < resultSize)                              \
4060       {                                                         \
4061           emitcode ("clr", "a");                                \
4062           /* Conversly, we haven't pushed enough here.          \
4063            * just zero-pad, and all is well.                    \
4064            */                                                   \
4065           while (pushedSize < resultSize)                       \
4066           {                                                     \
4067               emitcode("push", "acc");                          \
4068               pushedSize++;                                     \
4069           }                                                     \
4070       }                                                         \
4071       assert(pushedSize == resultSize);
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genPlus - generates code for addition                           */
4075 /*-----------------------------------------------------------------*/
4076 static void
4077 genPlus (iCode * ic)
4078 {
4079   int size, offset = 0;
4080   bool pushResult;
4081   int rSize;
4082
4083   D (emitcode (";", "genPlus "););
4084
4085   /* special cases :- */
4086   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4087       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4088       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4089       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4090       if (size <= 9) {
4091           while (size--) emitcode ("inc","dptr");
4092       } else {
4093           emitcode ("mov","a,dpl");
4094           emitcode ("add","a,#!constbyte",size & 0xff);
4095           emitcode ("mov","dpl,a");
4096           emitcode ("mov","a,dph");
4097           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4098           emitcode ("mov","dph,a");
4099           emitcode ("mov","a,dpx");
4100           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4101           emitcode ("mov","dpx,a");
4102       }
4103       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4104       return ;
4105   }
4106   if ( IS_SYMOP(IC_LEFT(ic)) && 
4107        OP_SYMBOL(IC_LEFT(ic))->remat &&
4108        isOperandInFarSpace(IC_RIGHT(ic))) {
4109       operand *op = IC_RIGHT(ic);
4110       IC_RIGHT(ic) = IC_LEFT(ic);
4111       IC_LEFT(ic) = op;
4112   }
4113                 
4114   AOP_OP_3_NOFATAL (ic, pushResult);
4115     
4116   if (pushResult)
4117     {
4118       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4119     }
4120
4121   if (!pushResult)
4122     {
4123       /* if literal, literal on the right or
4124          if left requires ACC or right is already
4125          in ACC */
4126       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4127        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4128           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4129         {
4130           operand *t = IC_RIGHT (ic);
4131           IC_RIGHT (ic) = IC_LEFT (ic);
4132           IC_LEFT (ic) = t;
4133           emitcode (";", "Swapped plus args.");
4134         }
4135
4136       /* if both left & right are in bit
4137          space */
4138       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4139           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4140         {
4141           genPlusBits (ic);
4142           goto release;
4143         }
4144
4145       /* if left in bit space & right literal */
4146       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4147           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4148         {
4149           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4150           /* if result in bit space */
4151           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4152             {
4153               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4154                 emitcode ("cpl", "c");
4155               outBitC (IC_RESULT (ic));
4156             }
4157           else
4158             {
4159               size = getDataSize (IC_RESULT (ic));
4160               _startLazyDPSEvaluation ();
4161               while (size--)
4162                 {
4163                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4164                   emitcode ("addc", "a,#0");
4165                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4166                 }
4167               _endLazyDPSEvaluation ();
4168             }
4169           goto release;
4170         }
4171
4172       /* if I can do an increment instead
4173          of add then GOOD for ME */
4174       if (genPlusIncr (ic) == TRUE)
4175         {
4176           emitcode (";", "did genPlusIncr");
4177           goto release;
4178         }
4179
4180     }
4181   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4182
4183   _startLazyDPSEvaluation ();
4184   while (size--)
4185     {
4186       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4187         {
4188           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4189           if (offset == 0)
4190             emitcode ("add", "a,%s",
4191                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4192           else
4193             emitcode ("addc", "a,%s",
4194                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4195         }
4196       else
4197         {
4198           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4199           {
4200               /* right is going to use ACC or we would have taken the
4201                * above branch.
4202                */
4203               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4204        TR_AP("#3");
4205               D(emitcode(";", "+ AOP_ACC special case."););
4206               emitcode("xch", "a, %s", DP2_RESULT_REG);
4207           }
4208           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4209           if (offset == 0)
4210           {
4211             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4212             {
4213          TR_AP("#4");
4214                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4215             }
4216             else
4217             {
4218                 emitcode ("add", "a,%s",
4219                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4220                                   DP2_RESULT_REG));
4221             }
4222           }
4223           else
4224           {
4225             emitcode ("addc", "a,%s",
4226                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4227                           DP2_RESULT_REG));
4228           }
4229         }
4230       if (!pushResult)
4231         {
4232           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4233         }
4234       else
4235         {
4236           emitcode ("push", "acc");
4237         }
4238       offset++;
4239     }
4240   _endLazyDPSEvaluation ();
4241
4242   if (pushResult)
4243     {
4244       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4245
4246       size = getDataSize (IC_LEFT (ic));
4247       rSize = getDataSize (IC_RESULT (ic));
4248
4249       ADJUST_PUSHED_RESULT(size, rSize);
4250
4251       _startLazyDPSEvaluation ();
4252       while (size--)
4253         {
4254           emitcode ("pop", "acc");
4255           aopPut (AOP (IC_RESULT (ic)), "a", size);
4256         }
4257       _endLazyDPSEvaluation ();
4258     }
4259
4260   adjustArithmeticResult (ic);
4261
4262 release:
4263   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4264   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4265   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4266 }
4267
4268 /*-----------------------------------------------------------------*/
4269 /* genMinusDec :- does subtraction with deccrement if possible     */
4270 /*-----------------------------------------------------------------*/
4271 static bool
4272 genMinusDec (iCode * ic)
4273 {
4274   unsigned int icount;
4275   unsigned int size = getDataSize (IC_RESULT (ic));
4276
4277   /* will try to generate an increment */
4278   /* if the right side is not a literal
4279      we cannot */
4280   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4281     return FALSE;
4282
4283   /* if the literal value of the right hand side
4284      is greater than 4 then it is not worth it */
4285   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4286     return FALSE;
4287
4288   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4289       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4290       while (icount--) {
4291           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4292       }
4293       return TRUE;
4294   }
4295   /* if decrement 16 bits in register */
4296   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4297       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4298       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4299       (size > 1) &&
4300       (icount == 1))
4301     {
4302       symbol *tlbl;
4303       int    emitTlbl;
4304       int    labelRange;
4305       char   *l;
4306
4307       /* If the next instruction is a goto and the goto target
4308          * is <= 5 instructions previous to this, we can generate
4309          * jumps straight to that target.
4310        */
4311       if (ic->next && ic->next->op == GOTO
4312           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4313           && labelRange <= 5)
4314         {
4315           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4316           tlbl = IC_LABEL (ic->next);
4317           emitTlbl = 0;
4318         }
4319       else
4320         {
4321           tlbl = newiTempLabel (NULL);
4322           emitTlbl = 1;
4323         }
4324
4325       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4326       emitcode ("dec", "%s", l);
4327  
4328       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4329           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4330           IS_AOP_PREG (IC_RESULT (ic)))
4331       {     
4332           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4333       }
4334       else
4335       {
4336           emitcode ("mov", "a,#!constbyte",0xff);
4337           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4338       }
4339       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4340       emitcode ("dec", "%s", l);
4341       if (size > 2)
4342         {
4343             if (!strcmp(l, "acc"))
4344             {
4345                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4346             }
4347             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4348                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4349                      IS_AOP_PREG (IC_RESULT (ic)))
4350             {       
4351                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4352             }
4353             else
4354             {
4355                 emitcode ("mov", "a,#!constbyte",0xff);
4356                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4357             }
4358             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4359             emitcode ("dec", "%s", l);
4360         }
4361       if (size > 3)
4362         {
4363             if (!strcmp(l, "acc"))
4364             {
4365                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4366             }
4367             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4369                      IS_AOP_PREG (IC_RESULT (ic)))
4370             {       
4371                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4372             }
4373             else
4374             {
4375                 emitcode ("mov", "a,#!constbyte",0xff);
4376                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4377             }       
4378             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4379             emitcode ("dec", "%s", l);
4380         }
4381       if (emitTlbl)
4382         {
4383           emitcode ("", "!tlabeldef", tlbl->key + 100);
4384         }
4385       return TRUE;
4386     }
4387
4388   /* if the sizes are greater than 1 then we cannot */
4389   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4390       AOP_SIZE (IC_LEFT (ic)) > 1)
4391     return FALSE;
4392
4393   /* we can if the aops of the left & result match or
4394      if they are in registers and the registers are the
4395      same */
4396   if (
4397        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4398        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4399        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4400     {
4401
4402       _startLazyDPSEvaluation ();
4403       while (icount--)
4404         {
4405           emitcode ("dec", "%s",
4406                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4407         }
4408       _endLazyDPSEvaluation ();
4409
4410       return TRUE;
4411     }
4412
4413   return FALSE;
4414 }
4415
4416 /*-----------------------------------------------------------------*/
4417 /* addSign - complete with sign                                    */
4418 /*-----------------------------------------------------------------*/
4419 static void
4420 addSign (operand * result, int offset, int sign)
4421 {
4422   int size = (getDataSize (result) - offset);
4423   if (size > 0)
4424     {
4425       _startLazyDPSEvaluation();
4426       if (sign)
4427         {
4428           emitcode ("rlc", "a");
4429           emitcode ("subb", "a,acc");
4430           while (size--)
4431           {
4432             aopPut (AOP (result), "a", offset++);
4433           }
4434         }
4435       else
4436       {
4437         while (size--)
4438         {
4439           aopPut (AOP (result), zero, offset++);
4440         }
4441       }
4442       _endLazyDPSEvaluation();
4443     }
4444 }
4445
4446 /*-----------------------------------------------------------------*/
4447 /* genMinusBits - generates code for subtraction  of two bits      */
4448 /*-----------------------------------------------------------------*/
4449 static void
4450 genMinusBits (iCode * ic)
4451 {
4452   symbol *lbl = newiTempLabel (NULL);
4453
4454   D (emitcode (";", "genMinusBits "););
4455
4456   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4457     {
4458       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4459       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4460       emitcode ("cpl", "c");
4461       emitcode ("", "!tlabeldef", (lbl->key + 100));
4462       outBitC (IC_RESULT (ic));
4463     }
4464   else
4465     {
4466       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4467       emitcode ("subb", "a,acc");
4468       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4469       emitcode ("inc", "a");
4470       emitcode ("", "!tlabeldef", (lbl->key + 100));
4471       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4472       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4473     }
4474 }
4475
4476 /*-----------------------------------------------------------------*/
4477 /* genMinus - generates code for subtraction                       */
4478 /*-----------------------------------------------------------------*/
4479 static void
4480 genMinus (iCode * ic)
4481 {
4482     int size, offset = 0;
4483     int rSize;
4484     long lit = 0L;
4485     bool pushResult;
4486
4487     D (emitcode (";", "genMinus "););
4488
4489     AOP_OP_3_NOFATAL(ic, pushResult);   
4490
4491     if (!pushResult)
4492     {
4493       /* special cases :- */
4494       /* if both left & right are in bit space */
4495       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4496           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4497         {
4498           genMinusBits (ic);
4499           goto release;
4500         }
4501
4502       /* if I can do an decrement instead
4503          of subtract then GOOD for ME */
4504       if (genMinusDec (ic) == TRUE)
4505         goto release;
4506
4507     }
4508
4509   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4510
4511   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4512     {
4513       CLRC;
4514     }
4515   else
4516     {
4517       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4518       lit = -lit;
4519     }
4520
4521
4522   /* if literal, add a,#-lit, else normal subb */
4523   _startLazyDPSEvaluation ();
4524   while (size--) {
4525       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4526           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4527               emitcode ("mov","b,%s",
4528                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4529               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4530               emitcode ("subb","a,b");
4531           } else {
4532               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4533               emitcode ("subb", "a,%s",
4534                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4535                                 DP2_RESULT_REG));
4536           }
4537       } else {
4538           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4539           /* first add without previous c */
4540           if (!offset) {
4541               if (!size && lit==-1) {
4542                   emitcode ("dec", "a");
4543               } else {
4544                   emitcode ("add", "a,#!constbyte",
4545                             (unsigned int) (lit & 0x0FFL));
4546               }
4547           } else {
4548               emitcode ("addc", "a,#!constbyte",
4549                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4550           }
4551       }
4552       
4553       if (pushResult) {
4554           emitcode ("push", "acc");
4555       } else {
4556           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4557       }
4558       offset++;
4559   }
4560   _endLazyDPSEvaluation ();
4561   
4562   if (pushResult)
4563     {
4564       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4565
4566       size = getDataSize (IC_LEFT (ic));
4567       rSize = getDataSize (IC_RESULT (ic));
4568
4569       ADJUST_PUSHED_RESULT(size, rSize);
4570
4571       _startLazyDPSEvaluation ();
4572       while (size--)
4573         {
4574           emitcode ("pop", "acc");
4575           aopPut (AOP (IC_RESULT (ic)), "a", size);
4576         }
4577       _endLazyDPSEvaluation ();
4578     }
4579
4580   adjustArithmeticResult (ic);
4581
4582 release:
4583   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4584   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4585   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4586 }
4587
4588
4589 /*-----------------------------------------------------------------*/
4590 /* genMultbits :- multiplication of bits                           */
4591 /*-----------------------------------------------------------------*/
4592 static void
4593 genMultbits (operand * left,
4594              operand * right,
4595              operand * result,
4596              iCode   * ic)
4597 {
4598   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4599   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4600   aopOp(result, ic, TRUE, FALSE);
4601   outBitC (result);
4602 }
4603
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4607 /*-----------------------------------------------------------------*/
4608 static void
4609 genMultOneByte (operand * left,
4610                 operand * right,
4611                 operand * result,
4612                 iCode   * ic)
4613 {
4614   sym_link *opetype = operandType (result);
4615   symbol *lbl;
4616
4617
4618   /* (if two literals: the value is computed before) */
4619   /* if one literal, literal on the right */
4620   if (AOP_TYPE (left) == AOP_LIT)
4621     {
4622       operand *t = right;
4623       right = left;
4624       left = t;
4625       emitcode (";", "swapped left and right");
4626     }
4627
4628   if (SPEC_USIGN(opetype)
4629       // ignore the sign of left and right, what else can we do?
4630       || (SPEC_USIGN(operandType(left)) && 
4631           SPEC_USIGN(operandType(right)))) {
4632     // just an unsigned 8*8=8/16 multiply
4633     //emitcode (";","unsigned");
4634     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4635     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4636     emitcode ("mul", "ab");
4637    
4638     _G.accInUse++; _G.bInUse++;
4639     aopOp(result, ic, TRUE, FALSE);
4640       
4641       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4642       {
4643           // this should never happen
4644           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4645                    AOP_SIZE(result), __FILE__, lineno);
4646           exit (1);
4647       }      
4648       
4649     aopPut (AOP (result), "a", 0);
4650     _G.accInUse--; _G.bInUse--;
4651     if (AOP_SIZE(result)==2) 
4652     {
4653       aopPut (AOP (result), "b", 1);
4654     }
4655     return;
4656   }
4657
4658   // we have to do a signed multiply
4659
4660   emitcode (";", "signed");
4661   emitcode ("clr", "F0"); // reset sign flag
4662   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4663
4664   lbl=newiTempLabel(NULL);
4665   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4666   // left side is negative, 8-bit two's complement, this fails for -128
4667   emitcode ("setb", "F0"); // set sign flag
4668   emitcode ("cpl", "a");
4669   emitcode ("inc", "a");
4670
4671   emitcode ("", "!tlabeldef", lbl->key+100);
4672
4673   /* if literal */
4674   if (AOP_TYPE(right)==AOP_LIT) {
4675     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4676     /* AND literal negative */
4677     if ((int) val < 0) {
4678       emitcode ("cpl", "F0"); // complement sign flag
4679       emitcode ("mov", "b,#!constbyte", -val);
4680     } else {
4681       emitcode ("mov", "b,#!constbyte", val);
4682     }
4683   } else {
4684     lbl=newiTempLabel(NULL);
4685     emitcode ("mov", "b,a");
4686     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4687     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4688     // right side is negative, 8-bit two's complement
4689     emitcode ("cpl", "F0"); // complement sign flag
4690     emitcode ("cpl", "a");
4691     emitcode ("inc", "a");
4692     emitcode ("", "!tlabeldef", lbl->key+100);
4693   }
4694   emitcode ("mul", "ab");
4695     
4696   _G.accInUse++;_G.bInUse++;
4697   aopOp(result, ic, TRUE, FALSE);
4698     
4699   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4700   {
4701     // this should never happen
4702       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4703                AOP_SIZE(result), __FILE__, lineno);
4704       exit (1);
4705   }    
4706     
4707   lbl=newiTempLabel(NULL);
4708   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4709   // only ONE op was negative, we have to do a 8/16-bit two's complement
4710   emitcode ("cpl", "a"); // lsb
4711   if (AOP_SIZE(result)==1) {
4712     emitcode ("inc", "a");
4713   } else {
4714     emitcode ("add", "a,#1");
4715     emitcode ("xch", "a,b");
4716     emitcode ("cpl", "a"); // msb
4717     emitcode ("addc", "a,#0");
4718     emitcode ("xch", "a,b");
4719   }
4720
4721   emitcode ("", "!tlabeldef", lbl->key+100);
4722   aopPut (AOP (result), "a", 0);
4723   _G.accInUse--;_G.bInUse--;
4724   if (AOP_SIZE(result)==2) {
4725     aopPut (AOP (result), "b", 1);
4726   }
4727 }
4728
4729 /*-----------------------------------------------------------------*/
4730 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4731 /*-----------------------------------------------------------------*/
4732 static void genMultTwoByte (operand *left, operand *right, 
4733                             operand *result, iCode *ic)
4734 {
4735         sym_link *retype = getSpec(operandType(right));
4736         sym_link *letype = getSpec(operandType(left));
4737         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4738         symbol *lbl;
4739
4740         if (AOP_TYPE (left) == AOP_LIT) {
4741                 operand *t = right;
4742                 right = left;
4743                 left = t;
4744         }
4745         /* save EA bit in F1 */
4746         lbl = newiTempLabel(NULL);
4747         emitcode ("setb","F1");
4748         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4749         emitcode ("clr","F1");
4750         emitcode("","!tlabeldef",lbl->key+100);
4751
4752         /* load up MB with right */
4753         if (!umult) {
4754                 emitcode("clr","F0");
4755                 if (AOP_TYPE(right) == AOP_LIT) {
4756                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4757                         if (val < 0) {
4758                                 emitcode("setb","F0");
4759                                 val = -val;
4760                         }
4761                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4762                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4763                 } else {
4764                         lbl = newiTempLabel(NULL);
4765                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4766                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4767                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4768                         emitcode ("xch", "a,b");
4769                         emitcode ("cpl","a");
4770                         emitcode ("add", "a,#1");
4771                         emitcode ("xch", "a,b");
4772                         emitcode ("cpl", "a"); // msb
4773                         emitcode ("addc", "a,#0");
4774                         emitcode ("setb","F0");
4775                         emitcode ("","!tlabeldef",lbl->key+100);
4776                         emitcode ("mov","mb,b");
4777                         emitcode ("mov","mb,a");
4778                 }
4779         } else {
4780                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4781                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4782         }
4783         /* load up MA with left */
4784         if (!umult) {
4785                 lbl = newiTempLabel(NULL);
4786                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4787                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4788                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4789                 emitcode ("xch", "a,b");
4790                 emitcode ("cpl","a");
4791                 emitcode ("add", "a,#1");
4792                 emitcode ("xch", "a,b");
4793                 emitcode ("cpl", "a"); // msb
4794                 emitcode ("addc","a,#0");
4795                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4796                 emitcode ("setb","F0");
4797                 emitcode ("","!tlabeldef",lbl->key+100);
4798                 emitcode ("mov","ma,b");
4799                 emitcode ("mov","ma,a");
4800         } else {
4801                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4802                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4803         }
4804         /* wait for multiplication to finish */
4805         lbl = newiTempLabel(NULL);
4806         emitcode("","!tlabeldef", lbl->key+100);
4807         emitcode("mov","a,mcnt1");
4808         emitcode("anl","a,#!constbyte",0x80);
4809         emitcode("jnz","!tlabel",lbl->key+100);
4810         
4811         freeAsmop (left, NULL, ic, TRUE);
4812         freeAsmop (right, NULL, ic,TRUE);
4813         aopOp(result, ic, TRUE, FALSE);
4814
4815         /* if unsigned then simple */   
4816         if (umult) {
4817                 emitcode ("mov","a,ma");
4818                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4819                 emitcode ("mov","a,ma");
4820                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4821                 aopPut(AOP(result),"ma",1);
4822                 aopPut(AOP(result),"ma",0);
4823         } else {
4824                 emitcode("push","ma");
4825                 emitcode("push","ma");
4826                 emitcode("push","ma");
4827                 MOVA("ma");
4828                 /* negate result if needed */
4829                 lbl = newiTempLabel(NULL);      
4830                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4831                 emitcode("cpl","a");
4832                 emitcode("add","a,#1");
4833                 emitcode("","!tlabeldef", lbl->key+100);
4834                 if (AOP_TYPE(result) == AOP_ACC)
4835                 {
4836                     D(emitcode(";", "ACC special case."););
4837                     /* We know result is the only live aop, and 
4838                      * it's obviously not a DPTR2, so AP is available.
4839                      */
4840                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4841                 }
4842                 else
4843                 {
4844                     aopPut(AOP(result),"a",0);
4845                 }
4846             
4847                 emitcode("pop","acc");
4848                 lbl = newiTempLabel(NULL);      
4849                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4850                 emitcode("cpl","a");
4851                 emitcode("addc","a,#0");
4852                 emitcode("","!tlabeldef", lbl->key+100);
4853                 aopPut(AOP(result),"a",1);
4854                 emitcode("pop","acc");
4855                 if (AOP_SIZE(result) >= 3) {
4856                         lbl = newiTempLabel(NULL);      
4857                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4858                         emitcode("cpl","a");
4859                         emitcode("addc","a,#0");                        
4860                         emitcode("","!tlabeldef", lbl->key+100);
4861                         aopPut(AOP(result),"a",2);
4862                 }
4863                 emitcode("pop","acc");
4864                 if (AOP_SIZE(result) >= 4) {
4865                         lbl = newiTempLabel(NULL);      
4866                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4867                         emitcode("cpl","a");
4868                         emitcode("addc","a,#0");                        
4869                         emitcode("","!tlabeldef", lbl->key+100);
4870                         aopPut(AOP(result),"a",3);
4871                 }
4872                 if (AOP_TYPE(result) == AOP_ACC)
4873                 {
4874                     /* We stashed the result away above. */
4875                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4876                 }           
4877                 
4878         }
4879         freeAsmop (result, NULL, ic, TRUE);
4880
4881         /* restore EA bit in F1 */
4882         lbl = newiTempLabel(NULL);
4883         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4884         emitcode ("setb","EA");
4885         emitcode("","!tlabeldef",lbl->key+100);
4886         return ;
4887 }
4888
4889 /*-----------------------------------------------------------------*/
4890 /* genMult - generates code for multiplication                     */
4891 /*-----------------------------------------------------------------*/
4892 static void
4893 genMult (iCode * ic)
4894 {
4895   operand *left = IC_LEFT (ic);
4896   operand *right = IC_RIGHT (ic);
4897   operand *result = IC_RESULT (ic);
4898
4899   D (emitcode (";", "genMult "););
4900
4901   /* assign the amsops */
4902   AOP_OP_2 (ic);
4903
4904   /* special cases first */
4905   /* both are bits */
4906   if (AOP_TYPE (left) == AOP_CRY &&
4907       AOP_TYPE (right) == AOP_CRY)
4908     {
4909       genMultbits (left, right, result, ic);
4910       goto release;
4911     }
4912
4913   /* if both are of size == 1 */
4914   if (AOP_SIZE (left) == 1 &&
4915       AOP_SIZE (right) == 1)
4916     {
4917       genMultOneByte (left, right, result, ic);
4918       goto release;
4919     }
4920
4921   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4922           /* use the ds390 ARITHMETIC accel UNIT */
4923           genMultTwoByte (left, right, result, ic);
4924           return ;
4925   }
4926   /* should have been converted to function call */
4927   assert (0);
4928
4929 release:
4930   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4931   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4932   freeAsmop (result, NULL, ic, TRUE);
4933 }
4934
4935 /*-----------------------------------------------------------------*/
4936 /* genDivbits :- division of bits                                  */
4937 /*-----------------------------------------------------------------*/
4938 static void
4939 genDivbits (operand * left,
4940             operand * right,
4941             operand * result,
4942             iCode   * ic)
4943 {
4944
4945   char *l;
4946
4947   /* the result must be bit */
4948   LOAD_AB_FOR_DIV (left, right, l);
4949   emitcode ("div", "ab");
4950   emitcode ("rrc", "a");
4951   aopOp(result, ic, TRUE, FALSE);
4952     
4953   aopPut (AOP (result), "c", 0);
4954 }
4955
4956 /*-----------------------------------------------------------------*/
4957 /* genDivOneByte : 8 bit division                                  */
4958 /*-----------------------------------------------------------------*/
4959 static void
4960 genDivOneByte (operand * left,
4961                operand * right,
4962                operand * result,
4963                iCode   * ic)
4964 {
4965   sym_link *opetype = operandType (result);
4966   char *l;
4967   symbol *lbl;
4968   int size, offset;
4969
4970   offset = 1;
4971   /* signed or unsigned */
4972   if (SPEC_USIGN (opetype))
4973     {
4974         /* unsigned is easy */
4975         LOAD_AB_FOR_DIV (left, right, l);
4976         emitcode ("div", "ab");
4977
4978         _G.accInUse++;
4979         aopOp(result, ic, TRUE, FALSE);
4980         aopPut (AOP (result), "a", 0);
4981         _G.accInUse--;
4982
4983         size = AOP_SIZE (result) - 1;
4984         
4985         while (size--)
4986         {
4987             aopPut (AOP (result), zero, offset++);
4988         }
4989       return;
4990     }
4991
4992   /* signed is a little bit more difficult */
4993
4994   /* save the signs of the operands */
4995   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4996   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4997   emitcode ("push", "acc");     /* save it on the stack */
4998
4999   /* now sign adjust for both left & right */
5000   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5001   lbl = newiTempLabel (NULL);
5002   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5003   emitcode ("cpl", "a");
5004   emitcode ("inc", "a");
5005   emitcode ("", "!tlabeldef", (lbl->key + 100));
5006   emitcode ("mov", "b,a");
5007
5008   /* sign adjust left side */
5009   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5010
5011   lbl = newiTempLabel (NULL);
5012   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5013   emitcode ("cpl", "a");
5014   emitcode ("inc", "a");
5015   emitcode ("", "!tlabeldef", (lbl->key + 100));
5016
5017   /* now the division */
5018   emitcode ("nop", "; workaround for DS80C390 div bug.");
5019   emitcode ("div", "ab");
5020   /* we are interested in the lower order
5021      only */
5022   emitcode ("mov", "b,a");
5023   lbl = newiTempLabel (NULL);
5024   emitcode ("pop", "acc");
5025   /* if there was an over flow we don't
5026      adjust the sign of the result */
5027   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5028   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5029   CLRC;
5030   emitcode ("clr", "a");
5031   emitcode ("subb", "a,b");
5032   emitcode ("mov", "b,a");
5033   emitcode ("", "!tlabeldef", (lbl->key + 100));
5034
5035   /* now we are done */
5036   _G.accInUse++;     _G.bInUse++;
5037     aopOp(result, ic, TRUE, FALSE);
5038     
5039     aopPut (AOP (result), "b", 0);
5040     
5041     size = AOP_SIZE (result) - 1;
5042     
5043     if (size > 0)
5044     {
5045       emitcode ("mov", "c,b.7");
5046       emitcode ("subb", "a,acc");
5047     }
5048     while (size--)
5049     {
5050         aopPut (AOP (result), "a", offset++);
5051     }
5052     _G.accInUse--;     _G.bInUse--;
5053
5054 }
5055
5056 /*-----------------------------------------------------------------*/
5057 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5058 /*-----------------------------------------------------------------*/
5059 static void genDivTwoByte (operand *left, operand *right, 
5060                             operand *result, iCode *ic)
5061 {
5062         sym_link *retype = getSpec(operandType(right));
5063         sym_link *letype = getSpec(operandType(left));
5064         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5065         symbol *lbl;
5066
5067         /* save EA bit in F1 */
5068         lbl = newiTempLabel(NULL);
5069         emitcode ("setb","F1");
5070         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5071         emitcode ("clr","F1");
5072         emitcode("","!tlabeldef",lbl->key+100);
5073
5074         /* load up MA with left */
5075         if (!umult) {
5076                 emitcode("clr","F0");
5077                 lbl = newiTempLabel(NULL);
5078                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5079                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5080                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5081                 emitcode ("xch", "a,b");
5082                 emitcode ("cpl","a");
5083                 emitcode ("add", "a,#1");
5084                 emitcode ("xch", "a,b");
5085                 emitcode ("cpl", "a"); // msb
5086                 emitcode ("addc","a,#0");
5087                 emitcode ("setb","F0");
5088                 emitcode ("","!tlabeldef",lbl->key+100);
5089                 emitcode ("mov","ma,b");
5090                 emitcode ("mov","ma,a");
5091         } else {
5092                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5093                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5094         }
5095
5096         /* load up MB with right */
5097         if (!umult) {
5098                 if (AOP_TYPE(right) == AOP_LIT) {
5099                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5100                         if (val < 0) {
5101                                 lbl = newiTempLabel(NULL);
5102                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5103                                 emitcode("setb","F0");
5104                                 emitcode ("","!tlabeldef",lbl->key+100);
5105                                 val = -val;
5106                         } 
5107                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5108                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5109                 } else {
5110                         lbl = newiTempLabel(NULL);
5111                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5112                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5113                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5114                         emitcode ("xch", "a,b");
5115                         emitcode ("cpl","a");
5116                         emitcode ("add", "a,#1");
5117                         emitcode ("xch", "a,b");
5118                         emitcode ("cpl", "a"); // msb
5119                         emitcode ("addc", "a,#0");
5120                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5121                         emitcode ("setb","F0");
5122                         emitcode ("","!tlabeldef",lbl->key+100);
5123                         emitcode ("mov","mb,b");
5124                         emitcode ("mov","mb,a");
5125                 }
5126         } else {
5127                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5128                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5129         }
5130
5131         /* wait for multiplication to finish */
5132         lbl = newiTempLabel(NULL);
5133         emitcode("","!tlabeldef", lbl->key+100);
5134         emitcode("mov","a,mcnt1");
5135         emitcode("anl","a,#!constbyte",0x80);
5136         emitcode("jnz","!tlabel",lbl->key+100);
5137         
5138         freeAsmop (left, NULL, ic, TRUE);
5139         freeAsmop (right, NULL, ic,TRUE);
5140         aopOp(result, ic, TRUE, FALSE);
5141
5142         /* if unsigned then simple */   
5143         if (umult) {
5144                 aopPut(AOP(result),"ma",1);
5145                 aopPut(AOP(result),"ma",0);
5146         } else {
5147                 emitcode("push","ma");
5148                 MOVA("ma");
5149                 /* negate result if needed */
5150                 lbl = newiTempLabel(NULL);      
5151                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5152                 emitcode("cpl","a");
5153                 emitcode("add","a,#1");
5154                 emitcode("","!tlabeldef", lbl->key+100);
5155                 aopPut(AOP(result),"a",0);
5156                 emitcode("pop","acc");
5157                 lbl = newiTempLabel(NULL);      
5158                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5159                 emitcode("cpl","a");
5160                 emitcode("addc","a,#0");
5161                 emitcode("","!tlabeldef", lbl->key+100);
5162                 aopPut(AOP(result),"a",1);
5163         }
5164         freeAsmop (result, NULL, ic, TRUE);
5165         /* restore EA bit in F1 */
5166         lbl = newiTempLabel(NULL);
5167         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5168         emitcode ("setb","EA");
5169         emitcode("","!tlabeldef",lbl->key+100);
5170         return ;
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genDiv - generates code for division                            */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genDiv (iCode * ic)
5178 {
5179   operand *left = IC_LEFT (ic);
5180   operand *right = IC_RIGHT (ic);
5181   operand *result = IC_RESULT (ic);
5182
5183   D (emitcode (";", "genDiv "););
5184
5185   /* assign the amsops */
5186   AOP_OP_2 (ic);
5187
5188   /* special cases first */
5189   /* both are bits */
5190   if (AOP_TYPE (left) == AOP_CRY &&
5191       AOP_TYPE (right) == AOP_CRY)
5192     {
5193       genDivbits (left, right, result, ic);
5194       goto release;
5195     }
5196
5197   /* if both are of size == 1 */
5198   if (AOP_SIZE (left) == 1 &&
5199       AOP_SIZE (right) == 1)
5200     {
5201       genDivOneByte (left, right, result, ic);
5202       goto release;
5203     }
5204
5205   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5206           /* use the ds390 ARITHMETIC accel UNIT */
5207           genDivTwoByte (left, right, result, ic);
5208           return ;
5209   }
5210   /* should have been converted to function call */
5211   assert (0);
5212 release:
5213   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5215   freeAsmop (result, NULL, ic, TRUE);
5216 }
5217
5218 /*-----------------------------------------------------------------*/
5219 /* genModbits :- modulus of bits                                   */
5220 /*-----------------------------------------------------------------*/
5221 static void
5222 genModbits (operand * left,
5223             operand * right,
5224             operand * result,
5225             iCode   * ic)
5226 {
5227
5228   char *l;
5229
5230   /* the result must be bit */
5231   LOAD_AB_FOR_DIV (left, right, l);
5232   emitcode ("div", "ab");
5233   emitcode ("mov", "a,b");
5234   emitcode ("rrc", "a");
5235   aopOp(result, ic, TRUE, FALSE);
5236   aopPut (AOP (result), "c", 0);
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* genModOneByte : 8 bit modulus                                   */
5241 /*-----------------------------------------------------------------*/
5242 static void
5243 genModOneByte (operand * left,
5244                operand * right,
5245                operand * result,
5246                iCode   * ic)
5247 {
5248   sym_link *opetype = operandType (result);
5249   char *l;
5250   symbol *lbl;
5251
5252   /* signed or unsigned */
5253   if (SPEC_USIGN (opetype))
5254     {
5255       /* unsigned is easy */
5256       LOAD_AB_FOR_DIV (left, right, l);
5257       emitcode ("div", "ab");
5258       aopOp(result, ic, TRUE, FALSE);   
5259       aopPut (AOP (result), "b", 0);
5260       return;
5261     }
5262
5263   /* signed is a little bit more difficult */
5264
5265   /* save the signs of the operands */
5266   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5267
5268   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5269   emitcode ("push", "acc");     /* save it on the stack */
5270
5271   /* now sign adjust for both left & right */
5272   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5273
5274   lbl = newiTempLabel (NULL);
5275   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5276   emitcode ("cpl", "a");
5277   emitcode ("inc", "a");
5278   emitcode ("", "!tlabeldef", (lbl->key + 100));
5279   emitcode ("mov", "b,a");
5280
5281   /* sign adjust left side */
5282   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5283
5284   lbl = newiTempLabel (NULL);
5285   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5286   emitcode ("cpl", "a");
5287   emitcode ("inc", "a");
5288   emitcode ("", "!tlabeldef", (lbl->key + 100));
5289
5290   /* now the multiplication */
5291   emitcode ("nop", "; workaround for DS80C390 div bug.");
5292   emitcode ("div", "ab");
5293   /* we are interested in the lower order
5294      only */
5295   lbl = newiTempLabel (NULL);
5296   emitcode ("pop", "acc");
5297   /* if there was an over flow we don't
5298      adjust the sign of the result */
5299   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5300   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5301   CLRC;
5302   emitcode ("clr", "a");
5303   emitcode ("subb", "a,b");
5304   emitcode ("mov", "b,a");
5305   emitcode ("", "!tlabeldef", (lbl->key + 100));
5306   
5307   _G.bInUse++;
5308   /* now we are done */
5309   aopOp(result, ic, TRUE, FALSE);    
5310   aopPut (AOP (result), "b", 0);
5311   _G.bInUse--;
5312
5313 }
5314
5315 /*-----------------------------------------------------------------*/
5316 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5317 /*-----------------------------------------------------------------*/
5318 static void genModTwoByte (operand *left, operand *right, 
5319                             operand *result, iCode *ic)
5320 {
5321         sym_link *retype = getSpec(operandType(right));
5322         sym_link *letype = getSpec(operandType(left));
5323         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5324         symbol *lbl;
5325
5326         /* load up MA with left */
5327         /* save EA bit in F1 */
5328         lbl = newiTempLabel(NULL);
5329         emitcode ("setb","F1");
5330         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5331         emitcode ("clr","F1");
5332         emitcode("","!tlabeldef",lbl->key+100);
5333
5334         if (!umult) {
5335                 lbl = newiTempLabel(NULL);
5336                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5337                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5338                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5339                 emitcode ("xch", "a,b");
5340                 emitcode ("cpl","a");
5341                 emitcode ("add", "a,#1");
5342                 emitcode ("xch", "a,b");
5343                 emitcode ("cpl", "a"); // msb
5344                 emitcode ("addc","a,#0");
5345                 emitcode ("","!tlabeldef",lbl->key+100);
5346                 emitcode ("mov","ma,b");
5347                 emitcode ("mov","ma,a");
5348         } else {
5349                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5350                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5351         }
5352
5353         /* load up MB with right */
5354         if (!umult) {
5355                 if (AOP_TYPE(right) == AOP_LIT) {
5356                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5357                         if (val < 0) {
5358                                 val = -val;
5359                         } 
5360                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5361                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5362                 } else {
5363                         lbl = newiTempLabel(NULL);
5364                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5365                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5366                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5367                         emitcode ("xch", "a,b");
5368                         emitcode ("cpl","a");
5369                         emitcode ("add", "a,#1");
5370                         emitcode ("xch", "a,b");
5371                         emitcode ("cpl", "a"); // msb
5372                         emitcode ("addc", "a,#0");
5373                         emitcode ("","!tlabeldef",lbl->key+100);
5374                         emitcode ("mov","mb,b");
5375                         emitcode ("mov","mb,a");
5376                 }
5377         } else {
5378                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5379                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5380         }
5381
5382         /* wait for multiplication to finish */
5383         lbl = newiTempLabel(NULL);
5384         emitcode("","!tlabeldef", lbl->key+100);
5385         emitcode("mov","a,mcnt1");
5386         emitcode("anl","a,#!constbyte",0x80);
5387         emitcode("jnz","!tlabel",lbl->key+100);
5388         
5389         freeAsmop (left, NULL, ic, TRUE);
5390         freeAsmop (right, NULL, ic,TRUE);
5391         aopOp(result, ic, TRUE, FALSE);
5392
5393         aopPut(AOP(result),"mb",1);
5394         aopPut(AOP(result),"mb",0);
5395         freeAsmop (result, NULL, ic, TRUE);
5396
5397         /* restore EA bit in F1 */
5398         lbl = newiTempLabel(NULL);
5399         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5400         emitcode ("setb","EA");
5401         emitcode("","!tlabeldef",lbl->key+100);
5402         return ;
5403 }
5404
5405 /*-----------------------------------------------------------------*/
5406 /* genMod - generates code for division                            */
5407 /*-----------------------------------------------------------------*/
5408 static void
5409 genMod (iCode * ic)
5410 {
5411   operand *left = IC_LEFT (ic);
5412   operand *right = IC_RIGHT (ic);
5413   operand *result = IC_RESULT (ic);
5414
5415   D (emitcode (";", "genMod "); );
5416
5417   /* assign the amsops */
5418   AOP_OP_2 (ic);
5419
5420   /* special cases first */
5421   /* both are bits */
5422   if (AOP_TYPE (left) == AOP_CRY &&
5423       AOP_TYPE (right) == AOP_CRY)
5424     {
5425       genModbits (left, right, result, ic);
5426       goto release;
5427     }
5428
5429   /* if both are of size == 1 */
5430   if (AOP_SIZE (left) == 1 &&
5431       AOP_SIZE (right) == 1)
5432     {
5433       genModOneByte (left, right, result, ic);
5434       goto release;
5435     }
5436
5437   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5438           /* use the ds390 ARITHMETIC accel UNIT */
5439           genModTwoByte (left, right, result, ic);
5440           return ;
5441   }
5442
5443   /* should have been converted to function call */
5444   assert (0);
5445
5446 release:
5447   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5448   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5449   freeAsmop (result, NULL, ic, TRUE);
5450 }
5451
5452 /*-----------------------------------------------------------------*/
5453 /* genIfxJump :- will create a jump depending on the ifx           */
5454 /*-----------------------------------------------------------------*/
5455 static void
5456 genIfxJump (iCode * ic, char *jval)
5457 {
5458   symbol *jlbl;
5459   symbol *tlbl = newiTempLabel (NULL);
5460   char *inst;
5461
5462   D (emitcode (";", "genIfxJump"););
5463
5464   /* if true label then we jump if condition
5465      supplied is true */
5466   if (IC_TRUE (ic))
5467     {
5468       jlbl = IC_TRUE (ic);
5469       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5470                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5471     }
5472   else
5473     {
5474       /* false label is present */
5475       jlbl = IC_FALSE (ic);
5476       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5477                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5478     }
5479   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5480     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5481   else
5482     emitcode (inst, "!tlabel", tlbl->key + 100);
5483   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5484   emitcode ("", "!tlabeldef", tlbl->key + 100);
5485
5486   /* mark the icode as generated */
5487   ic->generated = 1;
5488 }
5489
5490 /*-----------------------------------------------------------------*/
5491 /* genCmp :- greater or less than comparison                       */
5492 /*-----------------------------------------------------------------*/
5493 static void
5494 genCmp (operand * left, operand * right,
5495         iCode * ic, iCode * ifx, int sign)
5496 {
5497   int size, offset = 0;
5498   unsigned long lit = 0L;
5499   operand *result;
5500
5501   D (emitcode (";", "genCmp"););
5502
5503   result = IC_RESULT (ic);
5504
5505   /* if left & right are bit variables */
5506   if (AOP_TYPE (left) == AOP_CRY &&
5507       AOP_TYPE (right) == AOP_CRY)
5508     {
5509       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5510       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5511     }
5512   else
5513     {
5514       /* subtract right from left if at the
5515          end the carry flag is set then we know that
5516          left is greater than right */
5517       size = max (AOP_SIZE (left), AOP_SIZE (right));
5518
5519       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5520       if ((size == 1) && !sign 
5521           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5522         {
5523           symbol *lbl = newiTempLabel (NULL);
5524           emitcode ("cjne", "%s,%s,!tlabel",
5525                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5526                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5527                     lbl->key + 100);
5528           emitcode ("", "!tlabeldef", lbl->key + 100);
5529         }
5530       else
5531         {
5532           if (AOP_TYPE (right) == AOP_LIT)
5533             {
5534               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5535               /* optimize if(x < 0) or if(x >= 0) */
5536               if (lit == 0L)
5537                 {
5538                   if (!sign)
5539                     {
5540                       CLRC;
5541                     }
5542                   else
5543                     {
5544                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5545
5546                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5547                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5548
5549                       aopOp (result, ic, FALSE, FALSE);
5550
5551                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5552                         {
5553                           freeAsmop (result, NULL, ic, TRUE);
5554                           genIfxJump (ifx, "acc.7");
5555                           return;
5556                         }
5557                       else
5558                         {
5559                           emitcode ("rlc", "a");
5560                         }
5561                       goto release_freedLR;
5562                     }
5563                   goto release;
5564                 }
5565             }
5566           CLRC;
5567           while (size--)
5568             {
5569               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5570               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5571               // emitcode (";", "genCmp #2");
5572               if (sign && (size == 0))
5573                 {
5574                   // emitcode (";", "genCmp #3");
5575                   emitcode ("xrl", "a,#!constbyte",0x80);
5576                   if (AOP_TYPE (right) == AOP_LIT)
5577                     {
5578                       unsigned long lit = (unsigned long)
5579                       floatFromVal (AOP (right)->aopu.aop_lit);
5580                       // emitcode (";", "genCmp #3.1");
5581                       emitcode ("subb", "a,#!constbyte",
5582                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5583                     }
5584                   else
5585                     {
5586                       // emitcode (";", "genCmp #3.2");
5587                       saveAccWarn = 0;  
5588                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5589                       saveAccWarn = DEFAULT_ACC_WARNING;
5590                       emitcode ("xrl", "b,#!constbyte",0x80);
5591                       emitcode ("subb", "a,b");
5592                     }
5593                 }
5594               else
5595                 {
5596                   const char *s;
5597
5598                   // emitcode (";", "genCmp #4");
5599                   saveAccWarn = 0;
5600                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5601                   saveAccWarn = DEFAULT_ACC_WARNING;
5602
5603                   emitcode ("subb", "a,%s", s);
5604                 }
5605             }
5606         }
5607     }
5608
5609 release:
5610 /* Don't need the left & right operands any more; do need the result. */
5611   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5612   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5613
5614   aopOp (result, ic, FALSE, FALSE);
5615
5616 release_freedLR:
5617
5618   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5619     {
5620       outBitC (result);
5621     }
5622   else
5623     {
5624       /* if the result is used in the next
5625          ifx conditional branch then generate
5626          code a little differently */
5627       if (ifx)
5628         {
5629           genIfxJump (ifx, "c");
5630         }
5631       else
5632         {
5633           outBitC (result);
5634         }
5635       /* leave the result in acc */
5636     }
5637   freeAsmop (result, NULL, ic, TRUE);
5638 }
5639
5640 /*-----------------------------------------------------------------*/
5641 /* genCmpGt :- greater than comparison                             */
5642 /*-----------------------------------------------------------------*/
5643 static void
5644 genCmpGt (iCode * ic, iCode * ifx)
5645 {
5646   operand *left, *right;
5647   sym_link *letype, *retype;
5648   int sign;
5649
5650   D (emitcode (";", "genCmpGt ");
5651     );
5652
5653   left = IC_LEFT (ic);
5654   right = IC_RIGHT (ic);
5655
5656   letype = getSpec (operandType (left));
5657   retype = getSpec (operandType (right));
5658   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5659
5660   /* assign the left & right amsops */
5661   AOP_OP_2 (ic);
5662
5663   genCmp (right, left, ic, ifx, sign);
5664 }
5665
5666 /*-----------------------------------------------------------------*/
5667 /* genCmpLt - less than comparisons                                */
5668 /*-----------------------------------------------------------------*/
5669 static void
5670 genCmpLt (iCode * ic, iCode * ifx)
5671 {
5672   operand *left, *right;
5673   sym_link *letype, *retype;
5674   int sign;
5675
5676   D (emitcode (";", "genCmpLt "););
5677
5678   left = IC_LEFT (ic);
5679   right = IC_RIGHT (ic);
5680
5681   letype = getSpec (operandType (left));
5682   retype = getSpec (operandType (right));
5683   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5684
5685   /* assign the left & right amsops */
5686   AOP_OP_2 (ic);
5687
5688   genCmp (left, right, ic, ifx, sign);
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* gencjneshort - compare and jump if not equal                    */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 gencjneshort (operand * left, operand * right, symbol * lbl)
5696 {
5697   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5698   int offset = 0;
5699   unsigned long lit = 0L;
5700
5701   D (emitcode (";", "gencjneshort");
5702     );
5703
5704   /* if the left side is a literal or
5705      if the right is in a pointer register and left
5706      is not */
5707   if ((AOP_TYPE (left) == AOP_LIT) ||
5708       (AOP_TYPE (left) == AOP_IMMD) ||
5709       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5710     {
5711       operand *t = right;
5712       right = left;
5713       left = t;
5714     }
5715
5716   if (AOP_TYPE (right) == AOP_LIT)
5717     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5718
5719   if (opIsGptr (left) || opIsGptr (right))
5720     {
5721       /* We are comparing a generic pointer to something.
5722        * Exclude the generic type byte from the comparison.
5723        */
5724       size--;
5725       D (emitcode (";", "cjneshort: generic ptr special case."););
5726     }
5727
5728
5729   /* if the right side is a literal then anything goes */
5730   if (AOP_TYPE (right) == AOP_LIT &&
5731       AOP_TYPE (left) != AOP_DIR)
5732     {
5733       while (size--)
5734         {
5735           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5736           emitcode ("cjne", "a,%s,!tlabel",
5737                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5738                     lbl->key + 100);
5739           offset++;
5740         }
5741     }
5742
5743   /* if the right side is in a register or in direct space or
5744      if the left is a pointer register & right is not */
5745   else if (AOP_TYPE (right) == AOP_REG ||
5746            AOP_TYPE (right) == AOP_DIR ||
5747            AOP_TYPE (right) == AOP_LIT ||
5748            AOP_TYPE (right) == AOP_IMMD ||
5749            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5750            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5751     {
5752       while (size--)
5753         {
5754           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5755           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5756               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5757             emitcode ("jnz", "!tlabel", lbl->key + 100);
5758           else
5759             emitcode ("cjne", "a,%s,!tlabel",
5760                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5761                       lbl->key + 100);
5762           offset++;
5763         }
5764     }
5765   else
5766     {
5767       /* right is a pointer reg need both a & b */
5768       while (size--)
5769         {
5770           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5771           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5772           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5773           offset++;
5774         }
5775     }
5776 }
5777
5778 /*-----------------------------------------------------------------*/
5779 /* gencjne - compare and jump if not equal                         */
5780 /*-----------------------------------------------------------------*/
5781 static void
5782 gencjne (operand * left, operand * right, symbol * lbl)
5783 {
5784   symbol *tlbl = newiTempLabel (NULL);
5785
5786   D (emitcode (";", "gencjne");
5787     );
5788
5789   gencjneshort (left, right, lbl);
5790
5791   emitcode ("mov", "a,%s", one);
5792   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5793   emitcode ("", "!tlabeldef", lbl->key + 100);
5794   emitcode ("clr", "a");
5795   emitcode ("", "!tlabeldef", tlbl->key + 100);
5796 }
5797
5798 /*-----------------------------------------------------------------*/
5799 /* genCmpEq - generates code for equal to                          */
5800 /*-----------------------------------------------------------------*/
5801 static void
5802 genCmpEq (iCode * ic, iCode * ifx)
5803 {
5804   operand *left, *right, *result;
5805
5806   D (emitcode (";", "genCmpEq ");
5807     );
5808
5809   AOP_OP_2 (ic);
5810   AOP_SET_LOCALS (ic);
5811
5812   /* if literal, literal on the right or
5813      if the right is in a pointer register and left
5814      is not */
5815   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5816       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5817     {
5818       operand *t = IC_RIGHT (ic);
5819       IC_RIGHT (ic) = IC_LEFT (ic);
5820       IC_LEFT (ic) = t;
5821     }
5822
5823   if (ifx &&                    /* !AOP_SIZE(result) */
5824       OP_SYMBOL (result) &&
5825       OP_SYMBOL (result)->regType == REG_CND)
5826     {
5827       symbol *tlbl;
5828       /* if they are both bit variables */
5829       if (AOP_TYPE (left) == AOP_CRY &&
5830           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5831         {
5832           if (AOP_TYPE (right) == AOP_LIT)
5833             {
5834               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5835               if (lit == 0L)
5836                 {
5837                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838                   emitcode ("cpl", "c");
5839                 }
5840               else if (lit == 1L)
5841                 {
5842                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5843                 }
5844               else
5845                 {
5846                   emitcode ("clr", "c");
5847                 }
5848               /* AOP_TYPE(right) == AOP_CRY */
5849             }
5850           else
5851             {
5852               symbol *lbl = newiTempLabel (NULL);
5853               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5854               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5855               emitcode ("cpl", "c");
5856               emitcode ("", "!tlabeldef", (lbl->key + 100));
5857             }
5858           /* if true label then we jump if condition
5859              supplied is true */
5860           tlbl = newiTempLabel (NULL);
5861           if (IC_TRUE (ifx))
5862             {
5863               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5864               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5865             }
5866           else
5867             {
5868               emitcode ("jc", "!tlabel", tlbl->key + 100);
5869               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5870             }
5871           emitcode ("", "!tlabeldef", tlbl->key + 100);
5872         }
5873       else
5874         {
5875           tlbl = newiTempLabel (NULL);
5876           gencjneshort (left, right, tlbl);
5877           if (IC_TRUE (ifx))
5878             {
5879               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5880               emitcode ("", "!tlabeldef", tlbl->key + 100);
5881             }
5882           else
5883             {
5884               symbol *lbl = newiTempLabel (NULL);
5885               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5886               emitcode ("", "!tlabeldef", tlbl->key + 100);
5887               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5888               emitcode ("", "!tlabeldef", lbl->key + 100);
5889             }
5890         }
5891       /* mark the icode as generated */
5892       ifx->generated = 1;
5893
5894       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5895       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5896       return;
5897     }
5898
5899   /* if they are both bit variables */
5900   if (AOP_TYPE (left) == AOP_CRY &&
5901       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5902     {
5903       if (AOP_TYPE (right) == AOP_LIT)
5904         {
5905           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5906           if (lit == 0L)
5907             {
5908               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5909               emitcode ("cpl", "c");
5910             }
5911           else if (lit == 1L)
5912             {
5913               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5914             }
5915           else
5916             {
5917               emitcode ("clr", "c");
5918             }
5919           /* AOP_TYPE(right) == AOP_CRY */
5920         }
5921       else
5922         {
5923           symbol *lbl = newiTempLabel (NULL);
5924           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5925           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5926           emitcode ("cpl", "c");
5927           emitcode ("", "!tlabeldef", (lbl->key + 100));
5928         }
5929
5930       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5932
5933       aopOp (result, ic, TRUE, FALSE);
5934
5935       /* c = 1 if egal */
5936       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5937         {
5938           outBitC (result);
5939           goto release;
5940         }
5941       if (ifx)
5942         {
5943           genIfxJump (ifx, "c");
5944           goto release;
5945         }
5946       /* if the result is used in an arithmetic operation
5947          then put the result in place */
5948       outBitC (result);
5949     }
5950   else
5951     {
5952       gencjne (left, right, newiTempLabel (NULL));
5953
5954       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5956
5957       aopOp (result, ic, TRUE, FALSE);
5958
5959       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5960         {
5961           aopPut (AOP (result), "a", 0);
5962           goto release;
5963         }
5964       if (ifx)
5965         {
5966           genIfxJump (ifx, "a");
5967           goto release;
5968         }
5969       /* if the result is used in an arithmetic operation
5970          then put the result in place */
5971       if (AOP_TYPE (result) != AOP_CRY)
5972         outAcc (result);
5973       /* leave the result in acc */
5974     }
5975
5976 release:
5977   freeAsmop (result, NULL, ic, TRUE);
5978 }
5979
5980 /*-----------------------------------------------------------------*/
5981 /* ifxForOp - returns the icode containing the ifx for operand     */
5982 /*-----------------------------------------------------------------*/
5983 static iCode *
5984 ifxForOp (operand * op, iCode * ic)
5985 {
5986   /* if true symbol then needs to be assigned */
5987   if (IS_TRUE_SYMOP (op))
5988     return NULL;
5989
5990   /* if this has register type condition and
5991      the next instruction is ifx with the same operand
5992      and live to of the operand is upto the ifx only then */
5993   if (ic->next &&
5994       ic->next->op == IFX &&
5995       IC_COND (ic->next)->key == op->key &&
5996       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5997     return ic->next;
5998
5999   return NULL;
6000 }
6001 /*-----------------------------------------------------------------*/
6002 /* hasInc - operand is incremented before any other use            */
6003 /*-----------------------------------------------------------------*/
6004 static iCode *
6005 hasInc (operand *op, iCode *ic, int osize)
6006 {
6007   sym_link *type = operandType(op);
6008   sym_link *retype = getSpec (type);
6009   iCode *lic = ic->next;
6010   int isize ;
6011   
6012   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6013   if (!IS_SYMOP(op)) return NULL;
6014
6015   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6016   if (IS_AGGREGATE(type->next)) return NULL;
6017   if (osize != (isize = getSize(type->next))) return NULL;
6018
6019   while (lic) {
6020       /* if operand of the form op = op + <sizeof *op> */
6021       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6022           isOperandEqual(IC_RESULT(lic),op) && 
6023           isOperandLiteral(IC_RIGHT(lic)) &&
6024           operandLitValue(IC_RIGHT(lic)) == isize) {
6025           return lic;
6026       }
6027       /* if the operand used or deffed */
6028       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6029           return NULL;
6030       }
6031       /* if GOTO or IFX */
6032       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6033       lic = lic->next;
6034   }
6035   return NULL;
6036 }
6037
6038 /*-----------------------------------------------------------------*/
6039 /* genAndOp - for && operation                                     */
6040 /*-----------------------------------------------------------------*/
6041 static void
6042 genAndOp (iCode * ic)
6043 {
6044   operand *left, *right, *result;
6045   symbol *tlbl;
6046
6047   D (emitcode (";", "genAndOp "););
6048
6049   /* note here that && operations that are in an
6050      if statement are taken away by backPatchLabels
6051      only those used in arthmetic operations remain */
6052   AOP_OP_2 (ic);
6053   AOP_SET_LOCALS (ic);
6054
6055   /* if both are bit variables */
6056   if (AOP_TYPE (left) == AOP_CRY &&
6057       AOP_TYPE (right) == AOP_CRY)
6058     {
6059       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6060       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6061       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6062       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063   
6064       aopOp (result,ic,FALSE, FALSE);
6065       outBitC (result);
6066     }
6067   else
6068     {
6069       tlbl = newiTempLabel (NULL);
6070       toBoolean (left);
6071       emitcode ("jz", "!tlabel", tlbl->key + 100);
6072       toBoolean (right);
6073       emitcode ("", "!tlabeldef", tlbl->key + 100);
6074       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6075       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6076   
6077       aopOp (result,ic,FALSE, FALSE);
6078       outBitAcc (result);
6079     }
6080     freeAsmop (result, NULL, ic, TRUE);
6081 }
6082
6083
6084 /*-----------------------------------------------------------------*/
6085 /* genOrOp - for || operation                                      */
6086 /*-----------------------------------------------------------------*/
6087 static void
6088 genOrOp (iCode * ic)
6089 {
6090   operand *left, *right, *result;
6091   symbol *tlbl;
6092
6093   D (emitcode (";", "genOrOp "););
6094
6095   /* note here that || operations that are in an
6096      if statement are taken away by backPatchLabels
6097      only those used in arthmetic operations remain */
6098   AOP_OP_2 (ic);
6099   AOP_SET_LOCALS (ic);
6100
6101   /* if both are bit variables */
6102   if (AOP_TYPE (left) == AOP_CRY &&
6103       AOP_TYPE (right) == AOP_CRY)
6104     {
6105       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6106       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6107       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6108       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6109   
6110       aopOp (result,ic,FALSE, FALSE);
6111       
6112       outBitC (result);
6113     }
6114   else
6115     {
6116       tlbl = newiTempLabel (NULL);
6117       toBoolean (left);
6118       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6119       toBoolean (right);
6120       emitcode ("", "!tlabeldef", tlbl->key + 100);
6121       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6122       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6123   
6124       aopOp (result,ic,FALSE, FALSE);
6125       
6126       outBitAcc (result);
6127     }
6128
6129   freeAsmop (result, NULL, ic, TRUE);
6130 }
6131
6132 /*-----------------------------------------------------------------*/
6133 /* isLiteralBit - test if lit == 2^n                               */
6134 /*-----------------------------------------------------------------*/
6135 static int
6136 isLiteralBit (unsigned long lit)
6137 {
6138   unsigned long pw[32] =
6139   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6140    0x100L, 0x200L, 0x400L, 0x800L,
6141    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6142    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6143    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6144    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6145    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6146   int idx;
6147
6148   for (idx = 0; idx < 32; idx++)
6149     if (lit == pw[idx])
6150       return idx + 1;
6151   return 0;
6152 }
6153
6154 /*-----------------------------------------------------------------*/
6155 /* continueIfTrue -                                                */
6156 /*-----------------------------------------------------------------*/
6157 static void
6158 continueIfTrue (iCode * ic)
6159 {
6160   if (IC_TRUE (ic))
6161     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6162   ic->generated = 1;
6163 }
6164
6165 /*-----------------------------------------------------------------*/
6166 /* jmpIfTrue -                                                     */
6167 /*-----------------------------------------------------------------*/
6168 static void
6169 jumpIfTrue (iCode * ic)
6170 {
6171   if (!IC_TRUE (ic))
6172     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6173   ic->generated = 1;
6174 }
6175
6176 /*-----------------------------------------------------------------*/
6177 /* jmpTrueOrFalse -                                                */
6178 /*-----------------------------------------------------------------*/
6179 static void
6180 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6181 {
6182   // ugly but optimized by peephole
6183   if (IC_TRUE (ic))
6184     {
6185       symbol *nlbl = newiTempLabel (NULL);
6186       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6187       emitcode ("", "!tlabeldef", tlbl->key + 100);
6188       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6189       emitcode ("", "!tlabeldef", nlbl->key + 100);
6190     }
6191   else
6192     {
6193       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6194       emitcode ("", "!tlabeldef", tlbl->key + 100);
6195     }
6196   ic->generated = 1;
6197 }
6198
6199 // Generate code to perform a bit-wise logic operation
6200 // on two operands in far space (assumed to already have been 
6201 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6202 // in far space. This requires pushing the result on the stack
6203 // then popping it into the result.
6204 static void
6205 genFarFarLogicOp(iCode *ic, char *logicOp)
6206 {
6207       int size, resultSize, compSize;
6208       int offset = 0;
6209       
6210       TR_AP("#5");
6211       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6212       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6213                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6214       
6215       _startLazyDPSEvaluation();
6216       for (size = compSize; (size--); offset++)
6217       {
6218           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6219           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6220           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6221           
6222           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6223           emitcode ("push", "acc");
6224       }
6225       _endLazyDPSEvaluation();
6226      
6227       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6228       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6229       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6230      
6231       resultSize = AOP_SIZE(IC_RESULT(ic));
6232
6233       ADJUST_PUSHED_RESULT(compSize, resultSize);
6234
6235       _startLazyDPSEvaluation();
6236       while (compSize--)
6237       {
6238           emitcode ("pop", "acc");
6239           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6240       }
6241       _endLazyDPSEvaluation();
6242       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6243 }
6244
6245
6246 /*-----------------------------------------------------------------*/
6247 /* genAnd  - code for and                                          */
6248 /*-----------------------------------------------------------------*/
6249 static void
6250 genAnd (iCode * ic, iCode * ifx)
6251 {
6252   operand *left, *right, *result;
6253   int size, offset = 0;
6254   unsigned long lit = 0L;
6255   int bytelit;
6256   char buff[10];
6257   bool pushResult;
6258
6259   D (emitcode (";", "genAnd "););
6260
6261   AOP_OP_3_NOFATAL (ic, pushResult);
6262   AOP_SET_LOCALS (ic);
6263
6264   if (pushResult)
6265   {
6266       genFarFarLogicOp(ic, "anl");
6267       return;
6268   }  
6269
6270 #ifdef DEBUG_TYPE
6271   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6272             AOP_TYPE (result),
6273             AOP_TYPE (left), AOP_TYPE (right));
6274   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6275             AOP_SIZE (result),
6276             AOP_SIZE (left), AOP_SIZE (right));
6277 #endif
6278
6279   /* if left is a literal & right is not then exchange them */
6280   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6281 #ifdef LOGIC_OPS_BROKEN      
6282     ||  AOP_NEEDSACC (left)
6283 #endif
6284     )
6285     {
6286       operand *tmp = right;
6287       right = left;
6288       left = tmp;
6289     }
6290
6291   /* if result = right then exchange them */
6292   if (sameRegs (AOP (result), AOP (right)))
6293     {
6294       operand *tmp = right;
6295       right = left;
6296       left = tmp;
6297     }
6298
6299   /* if right is bit then exchange them */
6300   if (AOP_TYPE (right) == AOP_CRY &&
6301       AOP_TYPE (left) != AOP_CRY)
6302     {
6303       operand *tmp = right;
6304       right = left;
6305       left = tmp;
6306     }
6307   if (AOP_TYPE (right) == AOP_LIT)
6308     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6309
6310   size = AOP_SIZE (result);
6311
6312   // if(bit & yy)
6313   // result = bit & yy;
6314   if (AOP_TYPE (left) == AOP_CRY)
6315     {
6316       // c = bit & literal;
6317       if (AOP_TYPE (right) == AOP_LIT)
6318         {
6319           if (lit & 1)
6320             {
6321               if (size && sameRegs (AOP (result), AOP (left)))
6322                 // no change
6323                 goto release;
6324               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6325             }
6326           else
6327             {
6328               // bit(result) = 0;
6329               if (size && (AOP_TYPE (result) == AOP_CRY))
6330                 {
6331                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6332                   goto release;
6333                 }
6334               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6335                 {
6336                   jumpIfTrue (ifx);
6337                   goto release;
6338                 }
6339               emitcode ("clr", "c");
6340             }
6341         }
6342       else
6343         {
6344           if (AOP_TYPE (right) == AOP_CRY)
6345             {
6346               // c = bit & bit;
6347               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6348               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6349             }
6350           else
6351             {
6352               // c = bit & val;
6353               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6354               // c = lsb
6355               emitcode ("rrc", "a");
6356               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6357             }
6358         }
6359       // bit = c
6360       // val = c
6361       if (size)
6362         outBitC (result);
6363       // if(bit & ...)
6364       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6365         genIfxJump (ifx, "c");
6366       goto release;
6367     }
6368
6369   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6370   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6371   if ((AOP_TYPE (right) == AOP_LIT) &&
6372       (AOP_TYPE (result) == AOP_CRY) &&
6373       (AOP_TYPE (left) != AOP_CRY))
6374     {
6375       int posbit = isLiteralBit (lit);
6376       /* left &  2^n */
6377       if (posbit)
6378         {
6379           posbit--;
6380           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6381           // bit = left & 2^n
6382           if (size)
6383             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6384           // if(left &  2^n)
6385           else
6386             {
6387               if (ifx)
6388                 {
6389                   SNPRINTF (buff, sizeof(buff), 
6390                             "acc.%d", posbit & 0x07);
6391                   genIfxJump (ifx, buff);
6392                 }
6393               else 
6394                   {
6395                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6396                   }
6397               goto release;
6398             }
6399         }
6400       else
6401         {
6402           symbol *tlbl = newiTempLabel (NULL);
6403           int sizel = AOP_SIZE (left);
6404           if (size)
6405             emitcode ("setb", "c");
6406           while (sizel--)
6407             {
6408               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6409                 {
6410                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6411                   // byte ==  2^n ?
6412                   if ((posbit = isLiteralBit (bytelit)) != 0)
6413                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6414                   else
6415                     {
6416                       if (bytelit != 0x0FFL)
6417                         emitcode ("anl", "a,%s",
6418                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6419                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6420                     }
6421                 }
6422               offset++;
6423             }
6424           // bit = left & literal
6425           if (size)
6426             {
6427               emitcode ("clr", "c");
6428               emitcode ("", "!tlabeldef", tlbl->key + 100);
6429             }
6430           // if(left & literal)
6431           else
6432             {
6433               if (ifx)
6434                 jmpTrueOrFalse (ifx, tlbl);
6435               else
6436                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6437               goto release;
6438             }
6439         }
6440       outBitC (result);
6441       goto release;
6442     }
6443
6444   /* if left is same as result */
6445   if (sameRegs (AOP (result), AOP (left)))
6446     {
6447       for (; size--; offset++)
6448         {
6449           if (AOP_TYPE (right) == AOP_LIT)
6450             {
6451               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6452                 continue;
6453               else if (bytelit == 0)
6454                 aopPut (AOP (result), zero, offset);
6455               else if (IS_AOP_PREG (result))
6456                 {
6457                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6458                   emitcode ("anl", "a,%s",
6459                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6460                   aopPut (AOP (result), "a", offset);
6461                 }
6462               else
6463                 emitcode ("anl", "%s,%s",
6464                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6465                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6466             }
6467           else
6468             {
6469               if (AOP_TYPE (left) == AOP_ACC)
6470                 emitcode ("anl", "a,%s",
6471                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6472               else
6473                 {
6474                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6475                   if (IS_AOP_PREG (result))
6476                     {
6477                       emitcode ("anl", "a,%s",
6478                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6479                       aopPut (AOP (result), "a", offset);
6480                     }
6481                   else
6482                     emitcode ("anl", "%s,a",
6483                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6484                 }
6485             }
6486         }
6487     }
6488   else
6489     {
6490       // left & result in different registers
6491       if (AOP_TYPE (result) == AOP_CRY)
6492         {
6493           // result = bit
6494           // if(size), result in bit
6495           // if(!size && ifx), conditional oper: if(left & right)
6496           symbol *tlbl = newiTempLabel (NULL);
6497           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6498           if (size)
6499             emitcode ("setb", "c");
6500           while (sizer--)
6501             {
6502               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6503                 emitcode ("anl", "a,%s",
6504                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6505               } else {
6506                 if (AOP_TYPE(left)==AOP_ACC) {
6507                   emitcode("mov", "b,a");
6508                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6509                   emitcode("anl", "a,b");
6510                 }else {
6511                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6512                   emitcode ("anl", "a,%s",
6513                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6514                 }
6515               }
6516               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6517               offset++;
6518             }
6519           if (size)
6520             {
6521               CLRC;
6522               emitcode ("", "!tlabeldef", tlbl->key + 100);
6523               outBitC (result);
6524             }
6525           else if (ifx)
6526             jmpTrueOrFalse (ifx, tlbl);
6527           else
6528             emitcode ("", "!tlabeldef", tlbl->key + 100);
6529         }
6530       else
6531         {
6532           for (; (size--); offset++)
6533             {
6534               // normal case
6535               // result = left & right
6536               if (AOP_TYPE (right) == AOP_LIT)
6537                 {
6538                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6539                     {
6540                       aopPut (AOP (result),
6541                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6542                               offset);
6543                       continue;
6544                     }
6545                   else if (bytelit == 0)
6546                     {
6547                       aopPut (AOP (result), zero, offset);
6548                       continue;
6549                     }
6550                   D (emitcode (";", "better literal AND."););
6551                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6552                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6553                                                     FALSE, FALSE, DP2_RESULT_REG));
6554
6555                 }
6556               else
6557                 {
6558                   // faster than result <- left, anl result,right
6559                   // and better if result is SFR
6560                   if (AOP_TYPE (left) == AOP_ACC)
6561                     {
6562                       emitcode ("anl", "a,%s", 
6563                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6564                     }
6565                   else
6566                     {
6567                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6568                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6569                       {
6570                           emitcode("mov", "b,a");
6571                           rOp = "b";
6572                       }
6573                         
6574                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6575                       emitcode ("anl", "a,%s", rOp);
6576                     }                   
6577                 }
6578               aopPut (AOP (result), "a", offset);
6579             }
6580         }
6581     }
6582
6583 release:
6584   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6585   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6586   freeAsmop (result, NULL, ic, TRUE);
6587 }
6588
6589
6590 /*-----------------------------------------------------------------*/
6591 /* genOr  - code for or                                            */
6592 /*-----------------------------------------------------------------*/
6593 static void
6594 genOr (iCode * ic, iCode * ifx)
6595 {
6596   operand *left, *right, *result;
6597   int size, offset = 0;
6598   unsigned long lit = 0L;
6599   bool     pushResult;
6600
6601   D (emitcode (";", "genOr "););
6602
6603   AOP_OP_3_NOFATAL (ic, pushResult);
6604   AOP_SET_LOCALS (ic);
6605
6606   if (pushResult)
6607   {
6608       genFarFarLogicOp(ic, "orl");
6609       return;
6610   }
6611
6612
6613 #ifdef DEBUG_TYPE
6614   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6615             AOP_TYPE (result),
6616             AOP_TYPE (left), AOP_TYPE (right));
6617   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6618             AOP_SIZE (result),
6619             AOP_SIZE (left), AOP_SIZE (right));
6620 #endif
6621
6622   /* if left is a literal & right is not then exchange them */
6623   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6624 #ifdef LOGIC_OPS_BROKEN
6625    || AOP_NEEDSACC (left) // I think this is a net loss now.
6626 #endif      
6627       )
6628     {
6629       operand *tmp = right;
6630       right = left;
6631       left = tmp;
6632     }
6633
6634   /* if result = right then exchange them */
6635   if (sameRegs (AOP (result), AOP (right)))
6636     {
6637       operand *tmp = right;
6638       right = left;
6639       left = tmp;
6640     }
6641
6642   /* if right is bit then exchange them */
6643   if (AOP_TYPE (right) == AOP_CRY &&
6644       AOP_TYPE (left) != AOP_CRY)
6645     {
6646       operand *tmp = right;
6647       right = left;
6648       left = tmp;
6649     }
6650   if (AOP_TYPE (right) == AOP_LIT)
6651     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6652
6653   size = AOP_SIZE (result);
6654
6655   // if(bit | yy)
6656   // xx = bit | yy;
6657   if (AOP_TYPE (left) == AOP_CRY)
6658     {
6659       if (AOP_TYPE (right) == AOP_LIT)
6660         {
6661           // c = bit & literal;
6662           if (lit)
6663             {
6664               // lit != 0 => result = 1
6665               if (AOP_TYPE (result) == AOP_CRY)
6666                 {
6667                   if (size)
6668                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6669                   else if (ifx)
6670                     continueIfTrue (ifx);
6671                   goto release;
6672                 }
6673               emitcode ("setb", "c");
6674             }
6675           else
6676             {
6677               // lit == 0 => result = left
6678               if (size && sameRegs (AOP (result), AOP (left)))
6679                 goto release;
6680               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6681             }
6682         }
6683       else
6684         {
6685           if (AOP_TYPE (right) == AOP_CRY)
6686             {
6687               // c = bit | bit;
6688               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6689               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6690             }
6691           else
6692             {
6693               // c = bit | val;
6694               symbol *tlbl = newiTempLabel (NULL);
6695               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6696                 emitcode ("setb", "c");
6697               emitcode ("jb", "%s,!tlabel",
6698                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6699               toBoolean (right);
6700               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6701               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6702                 {
6703                   jmpTrueOrFalse (ifx, tlbl);
6704                   goto release;
6705                 }
6706               else
6707                 {
6708                   CLRC;
6709                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6710                 }
6711             }
6712         }
6713       // bit = c
6714       // val = c
6715       if (size)
6716         outBitC (result);
6717       // if(bit | ...)
6718       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6719            genIfxJump (ifx, "c");
6720       goto release;
6721     }
6722
6723   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6724   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6725   if ((AOP_TYPE (right) == AOP_LIT) &&
6726       (AOP_TYPE (result) == AOP_CRY) &&
6727       (AOP_TYPE (left) != AOP_CRY))
6728     {
6729       if (lit)
6730         {
6731           // result = 1
6732           if (size)
6733             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6734           else
6735             continueIfTrue (ifx);
6736           goto release;
6737         }
6738       else
6739         {
6740           // lit = 0, result = boolean(left)
6741           if (size)
6742             emitcode ("setb", "c");
6743           toBoolean (right);
6744           if (size)
6745             {
6746               symbol *tlbl = newiTempLabel (NULL);
6747               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6748               CLRC;
6749               emitcode ("", "!tlabeldef", tlbl->key + 100);
6750             }
6751           else
6752             {
6753               genIfxJump (ifx, "a");
6754               goto release;
6755             }
6756         }
6757       outBitC (result);
6758       goto release;
6759     }
6760
6761   /* if left is same as result */
6762   if (sameRegs (AOP (result), AOP (left)))
6763     {
6764       for (; size--; offset++)
6765         {
6766           if (AOP_TYPE (right) == AOP_LIT)
6767             {
6768               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6769                 {
6770                   continue;
6771                 }
6772               else
6773                 {
6774                   if (IS_AOP_PREG (left))
6775                     {
6776                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6777                       emitcode ("orl", "a,%s",
6778                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6779                       aopPut (AOP (result), "a", offset);
6780                     }
6781                   else
6782                     {
6783                       emitcode ("orl", "%s,%s",
6784                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6785                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6786                     }
6787                 }
6788             }
6789           else
6790             {
6791               if (AOP_TYPE (left) == AOP_ACC)
6792                 {
6793                   emitcode ("orl", "a,%s",
6794                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6795                 }
6796               else
6797                 {
6798                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6799                   if (IS_AOP_PREG (left))
6800                     {
6801                       emitcode ("orl", "a,%s", 
6802                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6803                       aopPut (AOP (result), "a", offset);
6804                     }
6805                   else
6806                     {
6807                       emitcode ("orl", "%s,a",
6808                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6809                     }
6810                 }
6811             }
6812         }
6813     }
6814   else
6815     {
6816       // left & result in different registers
6817       if (AOP_TYPE (result) == AOP_CRY)
6818         {
6819           // result = bit
6820           // if(size), result in bit
6821           // if(!size && ifx), conditional oper: if(left | right)
6822           symbol *tlbl = newiTempLabel (NULL);
6823           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6824           if (size)
6825             emitcode ("setb", "c");
6826           while (sizer--)
6827             {
6828               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6829                 emitcode ("orl", "a,%s",
6830                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6831               } else {
6832                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6833                 emitcode ("orl", "a,%s",
6834                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6835               }
6836               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6837               offset++;
6838             }
6839           if (size)
6840             {
6841               CLRC;
6842               emitcode ("", "!tlabeldef", tlbl->key + 100);
6843               outBitC (result);
6844             }
6845           else if (ifx)
6846             jmpTrueOrFalse (ifx, tlbl);
6847           else
6848             emitcode ("", "!tlabeldef", tlbl->key + 100);
6849         }
6850       else
6851         {
6852             _startLazyDPSEvaluation();
6853           for (; (size--); offset++)
6854             {
6855               // normal case
6856               // result = left & right
6857               if (AOP_TYPE (right) == AOP_LIT)
6858                 {
6859                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6860                     {
6861                       aopPut (AOP (result),
6862                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6863                               offset);
6864                       continue;
6865                     }
6866                   D (emitcode (";", "better literal OR."););
6867                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6868                   emitcode ("orl", "a, %s",
6869                             aopGet (AOP (right), offset,
6870                                     FALSE, FALSE, DP2_RESULT_REG));
6871
6872                 }
6873               else
6874                 {
6875                   // faster than result <- left, anl result,right
6876                   // and better if result is SFR
6877                   if (AOP_TYPE (left) == AOP_ACC)
6878                     {
6879                       emitcode ("orl", "a,%s",
6880                                 aopGet (AOP (right), offset,
6881                                         FALSE, FALSE, DP2_RESULT_REG));
6882                     }
6883                   else
6884                     {
6885                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6886                         
6887                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6888                       {
6889                           emitcode("mov", "b,a");
6890                           rOp = "b";
6891                       }
6892                         
6893                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6894                       emitcode ("orl", "a,%s", rOp);
6895                     }
6896                 }
6897               aopPut (AOP (result), "a", offset);
6898             }
6899             _endLazyDPSEvaluation();
6900         }
6901     }
6902
6903 release:
6904   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6905   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6906   freeAsmop (result, NULL, ic, TRUE);
6907 }
6908
6909 /*-----------------------------------------------------------------*/
6910 /* genXor - code for xclusive or                                   */
6911 /*-----------------------------------------------------------------*/
6912 static void
6913 genXor (iCode * ic, iCode * ifx)
6914 {
6915   operand *left, *right, *result;
6916   int size, offset = 0;
6917   unsigned long lit = 0L;
6918   bool pushResult;
6919
6920   D (emitcode (";", "genXor "););
6921
6922   AOP_OP_3_NOFATAL (ic, pushResult);
6923   AOP_SET_LOCALS (ic);
6924
6925   if (pushResult)
6926   {
6927       genFarFarLogicOp(ic, "xrl");
6928       return;
6929   }  
6930
6931 #ifdef DEBUG_TYPE
6932   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6933             AOP_TYPE (result),
6934             AOP_TYPE (left), AOP_TYPE (right));
6935   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6936             AOP_SIZE (result),
6937             AOP_SIZE (left), AOP_SIZE (right));
6938 #endif
6939
6940   /* if left is a literal & right is not ||
6941      if left needs acc & right does not */
6942   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6943 #ifdef LOGIC_OPS_BROKEN      
6944       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6945 #endif
6946      )
6947     {
6948       operand *tmp = right;
6949       right = left;
6950       left = tmp;
6951     }
6952
6953   /* if result = right then exchange them */
6954   if (sameRegs (AOP (result), AOP (right)))
6955     {
6956       operand *tmp = right;
6957       right = left;
6958       left = tmp;
6959     }
6960
6961   /* if right is bit then exchange them */
6962   if (AOP_TYPE (right) == AOP_CRY &&
6963       AOP_TYPE (left) != AOP_CRY)
6964     {
6965       operand *tmp = right;
6966       right = left;
6967       left = tmp;
6968     }
6969   if (AOP_TYPE (right) == AOP_LIT)
6970     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6971
6972   size = AOP_SIZE (result);
6973
6974   // if(bit ^ yy)
6975   // xx = bit ^ yy;
6976   if (AOP_TYPE (left) == AOP_CRY)
6977     {
6978       if (AOP_TYPE (right) == AOP_LIT)
6979         {
6980           // c = bit & literal;
6981           if (lit >> 1)
6982             {
6983               // lit>>1  != 0 => result = 1
6984               if (AOP_TYPE (result) == AOP_CRY)
6985                 {
6986                   if (size)
6987                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6988                   else if (ifx)
6989                     continueIfTrue (ifx);
6990                   goto release;
6991                 }
6992               emitcode ("setb", "c");
6993             }
6994           else
6995             {
6996               // lit == (0 or 1)
6997               if (lit == 0)
6998                 {
6999                   // lit == 0, result = left
7000                   if (size && sameRegs (AOP (result), AOP (left)))
7001                     goto release;
7002                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7003                 }
7004               else
7005                 {
7006                   // lit == 1, result = not(left)
7007                   if (size && sameRegs (AOP (result), AOP (left)))
7008                     {
7009                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7010                       goto release;
7011                     }
7012                   else
7013                     {
7014                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7015                       emitcode ("cpl", "c");
7016                     }
7017                 }
7018             }
7019
7020         }
7021       else
7022         {
7023           // right != literal
7024           symbol *tlbl = newiTempLabel (NULL);
7025           if (AOP_TYPE (right) == AOP_CRY)
7026             {
7027               // c = bit ^ bit;
7028               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7029             }
7030           else
7031             {
7032               int sizer = AOP_SIZE (right);
7033               // c = bit ^ val
7034               // if val>>1 != 0, result = 1
7035               emitcode ("setb", "c");
7036               while (sizer)
7037                 {
7038                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7039                   if (sizer == 1)
7040                     // test the msb of the lsb
7041                     emitcode ("anl", "a,#!constbyte",0xfe);
7042                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7043                   sizer--;
7044                 }
7045               // val = (0,1)
7046               emitcode ("rrc", "a");
7047             }
7048           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7049           emitcode ("cpl", "c");
7050           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7051         }
7052       // bit = c
7053       // val = c
7054       if (size)
7055         outBitC (result);
7056       // if(bit | ...)
7057       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7058         genIfxJump (ifx, "c");
7059       goto release;
7060     }
7061
7062   if (sameRegs (AOP (result), AOP (left)))
7063     {
7064       /* if left is same as result */
7065       for (; size--; offset++)
7066         {
7067           if (AOP_TYPE (right) == AOP_LIT)
7068             {
7069               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7070                 continue;
7071               else if (IS_AOP_PREG (left))
7072                 {
7073                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7074                   emitcode ("xrl", "a,%s",
7075                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7076                   aopPut (AOP (result), "a", offset);
7077                 }
7078               else
7079                 emitcode ("xrl", "%s,%s",
7080                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7081                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7082             }
7083           else
7084             {
7085               if (AOP_TYPE (left) == AOP_ACC)
7086                 emitcode ("xrl", "a,%s",
7087                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7088               else
7089                 {
7090                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7091                   if (IS_AOP_PREG (left))
7092                     {
7093                       emitcode ("xrl", "a,%s",
7094                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7095                       aopPut (AOP (result), "a", offset);
7096                     }
7097                   else
7098                     emitcode ("xrl", "%s,a",
7099                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7100                 }
7101             }
7102         }
7103     }
7104   else
7105     {
7106       // left & result in different registers
7107       if (AOP_TYPE (result) == AOP_CRY)
7108         {
7109           // result = bit
7110           // if(size), result in bit
7111           // if(!size && ifx), conditional oper: if(left ^ right)
7112           symbol *tlbl = newiTempLabel (NULL);
7113           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7114                   
7115           if (size)
7116             emitcode ("setb", "c");
7117           while (sizer--)
7118             {
7119               if ((AOP_TYPE (right) == AOP_LIT) &&
7120                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7121                 {
7122                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7123                 }
7124               else
7125                 {
7126                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7127                     emitcode ("xrl", "a,%s",
7128                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7129                   } else {
7130                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7131                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7132                       {
7133                           emitcode("mov", "b,a");
7134                           rOp = "b";
7135                       }
7136                         
7137                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7138                       emitcode ("xrl", "a,%s", rOp);                  
7139                   }
7140                 }
7141               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7142               offset++;
7143             }
7144           if (size)
7145             {
7146               CLRC;
7147               emitcode ("", "!tlabeldef", tlbl->key + 100);
7148               outBitC (result);
7149             }
7150           else if (ifx)
7151             jmpTrueOrFalse (ifx, tlbl);
7152         }
7153       else
7154         {
7155         for (; (size--); offset++)
7156           {
7157             // normal case
7158             // result = left & right
7159             if (AOP_TYPE (right) == AOP_LIT)
7160               {
7161                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7162                   {
7163                     aopPut (AOP (result),
7164                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7165                             offset);
7166                     continue;
7167                   }
7168                 D (emitcode (";", "better literal XOR."););
7169                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7170                 emitcode ("xrl", "a, %s",
7171                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7172               }
7173             else
7174               {
7175                 // faster than result <- left, anl result,right
7176                 // and better if result is SFR
7177                 if (AOP_TYPE (left) == AOP_ACC)
7178                   {
7179                     emitcode ("xrl", "a,%s",
7180                               aopGet (AOP (right), offset,
7181                                       FALSE, FALSE, DP2_RESULT_REG));
7182                   }
7183                 else
7184                   {
7185                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7186                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7187                       {
7188                           emitcode("mov", "b,a");
7189                           rOp = "b";
7190                       }
7191                         
7192                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7193                       emitcode ("xrl", "a,%s", rOp);
7194                   }
7195               }
7196             aopPut (AOP (result), "a", offset);
7197           }
7198         }
7199         
7200     }
7201
7202 release:
7203   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7204   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7205   freeAsmop (result, NULL, ic, TRUE);
7206 }
7207
7208 /*-----------------------------------------------------------------*/
7209 /* genInline - write the inline code out                           */
7210 /*-----------------------------------------------------------------*/
7211 static void
7212 genInline (iCode * ic)
7213 {
7214   char *buffer, *bp, *bp1;
7215
7216   D (emitcode (";", "genInline "); );
7217
7218   _G.inLine += (!options.asmpeep);
7219
7220   buffer = Safe_strdup(IC_INLINE(ic));
7221   bp = buffer;
7222   bp1 = buffer;
7223
7224   /* emit each line as a code */
7225   while (*bp)
7226     {
7227       if (*bp == '\n')
7228         {
7229           *bp++ = '\0';
7230           emitcode (bp1, "");
7231           bp1 = bp;
7232         }
7233       else
7234         {
7235           if (*bp == ':')
7236             {
7237               bp++;
7238               *bp = '\0';
7239               bp++;
7240               emitcode (bp1, "");
7241               bp1 = bp;
7242             }
7243           else
7244             bp++;
7245         }
7246     }
7247   if (bp1 != bp)
7248     emitcode (bp1, "");
7249   /*     emitcode("",buffer); */
7250   _G.inLine -= (!options.asmpeep);
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genRRC - rotate right with carry                                */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 genRRC (iCode * ic)
7258 {
7259   operand *left, *result;
7260   int     size, offset;
7261
7262   D (emitcode (";", "genRRC "););
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 = size - 1;
7273   CLRC;
7274
7275   _startLazyDPSEvaluation ();
7276   while (size--)
7277     {
7278       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279       emitcode ("rrc", "a");
7280       if (AOP_SIZE (result) > 1)
7281         aopPut (AOP (result), "a", offset--);
7282     }
7283   _endLazyDPSEvaluation ();
7284
7285   /* now we need to put the carry into the
7286      highest order byte of the result */
7287   if (AOP_SIZE (result) > 1)
7288     {
7289       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7290     }
7291   emitcode ("mov", "acc.7,c");
7292   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7293   freeAsmop (left, NULL, ic, TRUE);
7294   freeAsmop (result, NULL, ic, TRUE);
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* genRLC - generate code for rotate left with carry               */
7299 /*-----------------------------------------------------------------*/
7300 static void
7301 genRLC (iCode * ic)
7302 {
7303   operand *left, *result;
7304   int size, offset;
7305   char *l;
7306
7307   D (emitcode (";", "genRLC "););
7308
7309   /* rotate right with carry */
7310   left = IC_LEFT (ic);
7311   result = IC_RESULT (ic);
7312   aopOp (left, ic, FALSE, FALSE);
7313   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7314
7315   /* move it to the result */
7316   size = AOP_SIZE (result);
7317   offset = 0;
7318   if (size--)
7319     {
7320       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7321       MOVA (l);
7322       emitcode ("add", "a,acc");
7323       if (AOP_SIZE (result) > 1)
7324         {
7325           aopPut (AOP (result), "a", offset++);
7326         }
7327
7328       _startLazyDPSEvaluation ();
7329       while (size--)
7330         {
7331           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7332           MOVA (l);
7333           emitcode ("rlc", "a");
7334           if (AOP_SIZE (result) > 1)
7335             aopPut (AOP (result), "a", offset++);
7336         }
7337       _endLazyDPSEvaluation ();
7338     }
7339   /* now we need to put the carry into the
7340      highest order byte of the result */
7341   if (AOP_SIZE (result) > 1)
7342     {
7343       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7344       MOVA (l);
7345     }
7346   emitcode ("mov", "acc.0,c");
7347   aopPut (AOP (result), "a", 0);
7348   freeAsmop (left, NULL, ic, TRUE);
7349   freeAsmop (result, NULL, ic, TRUE);
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* genGetHbit - generates code get highest order bit               */
7354 /*-----------------------------------------------------------------*/
7355 static void
7356 genGetHbit (iCode * ic)
7357 {
7358   operand *left, *result;
7359   left = IC_LEFT (ic);
7360   result = IC_RESULT (ic);
7361   aopOp (left, ic, FALSE, FALSE);
7362   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7363
7364   D (emitcode (";", "genGetHbit "););
7365
7366   /* get the highest order byte into a */
7367   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7368   if (AOP_TYPE (result) == AOP_CRY)
7369     {
7370       emitcode ("rlc", "a");
7371       outBitC (result);
7372     }
7373   else
7374     {
7375       emitcode ("rl", "a");
7376       emitcode ("anl", "a,#1");
7377       outAcc (result);
7378     }
7379
7380
7381   freeAsmop (left, NULL, ic, TRUE);
7382   freeAsmop (result, NULL, ic, TRUE);
7383 }
7384
7385 /*-----------------------------------------------------------------*/
7386 /* genSwap - generates code to swap nibbles or bytes               */
7387 /*-----------------------------------------------------------------*/
7388 static void
7389 genSwap (iCode * ic)
7390 {
7391   operand *left, *result;
7392
7393   D(emitcode (";     genSwap",""));
7394
7395   left = IC_LEFT (ic);
7396   result = IC_RESULT (ic);
7397   aopOp (left, ic, FALSE, FALSE);
7398   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7399   
7400   _startLazyDPSEvaluation ();
7401   switch (AOP_SIZE (left))
7402     {
7403     case 1: /* swap nibbles in byte */
7404       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7405       emitcode ("swap", "a");
7406       aopPut (AOP (result), "a", 0);
7407       break;
7408     case 2: /* swap bytes in word */
7409       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7410         {
7411           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7412           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7413           aopPut (AOP (result), "a", 1);
7414         }
7415       else if (operandsEqu (left, result))
7416         {
7417           char * reg = "a";
7418           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7419           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7420             {
7421               emitcode ("mov", "b,a");
7422               reg = "b";
7423               _G.bInUse=1;
7424             }
7425           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7426           aopPut (AOP (result), reg, 1);
7427           _G.bInUse=0;
7428         }
7429       else
7430         {
7431           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7432           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7433         }
7434       break;
7435     default:
7436       wassertl(FALSE, "unsupported SWAP operand size");
7437     }
7438   _endLazyDPSEvaluation ();
7439   
7440   freeAsmop (left, NULL, ic, TRUE);
7441   freeAsmop (result, NULL, ic, TRUE);
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* AccRol - rotate left accumulator by known count                 */
7446 /*-----------------------------------------------------------------*/
7447 static void
7448 AccRol (int shCount)
7449 {
7450   shCount &= 0x0007;            // shCount : 0..7
7451
7452   switch (shCount)
7453     {
7454     case 0:
7455       break;
7456     case 1:
7457       emitcode ("rl", "a");
7458       break;
7459     case 2:
7460       emitcode ("rl", "a");
7461       emitcode ("rl", "a");
7462       break;
7463     case 3:
7464       emitcode ("swap", "a");
7465       emitcode ("rr", "a");
7466       break;
7467     case 4:
7468       emitcode ("swap", "a");
7469       break;
7470     case 5:
7471       emitcode ("swap", "a");
7472       emitcode ("rl", "a");
7473       break;
7474     case 6:
7475       emitcode ("rr", "a");
7476       emitcode ("rr", "a");
7477       break;
7478     case 7:
7479       emitcode ("rr", "a");
7480       break;
7481     }
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* AccLsh - left shift accumulator by known count                  */
7486 /*-----------------------------------------------------------------*/
7487 static void
7488 AccLsh (int shCount)
7489 {
7490   if (shCount != 0)
7491     {
7492       if (shCount == 1)
7493         emitcode ("add", "a,acc");
7494       else if (shCount == 2)
7495         {
7496           emitcode ("add", "a,acc");
7497           emitcode ("add", "a,acc");
7498         }
7499       else
7500         {
7501           /* rotate left accumulator */
7502           AccRol (shCount);
7503           /* and kill the lower order bits */
7504           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7505         }
7506     }
7507 }
7508
7509 /*-----------------------------------------------------------------*/
7510 /* AccRsh - right shift accumulator by known count                 */
7511 /*-----------------------------------------------------------------*/
7512 static void
7513 AccRsh (int shCount)
7514 {
7515   if (shCount != 0)
7516     {
7517       if (shCount == 1)
7518         {
7519           CLRC;
7520           emitcode ("rrc", "a");
7521         }
7522       else
7523         {
7524           /* rotate right accumulator */
7525           AccRol (8 - shCount);
7526           /* and kill the higher order bits */
7527           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7528         }
7529     }
7530 }
7531
7532 #ifdef BETTER_LITERAL_SHIFT
7533 /*-----------------------------------------------------------------*/
7534 /* AccSRsh - signed right shift accumulator by known count                 */
7535 /*-----------------------------------------------------------------*/
7536 static void
7537 AccSRsh (int shCount)
7538 {
7539   symbol *tlbl;
7540   if (shCount != 0)
7541     {
7542       if (shCount == 1)
7543         {
7544           emitcode ("mov", "c,acc.7");
7545           emitcode ("rrc", "a");
7546         }
7547       else if (shCount == 2)
7548         {
7549           emitcode ("mov", "c,acc.7");
7550           emitcode ("rrc", "a");
7551           emitcode ("mov", "c,acc.7");
7552           emitcode ("rrc", "a");
7553         }
7554       else
7555         {
7556           tlbl = newiTempLabel (NULL);
7557           /* rotate right accumulator */
7558           AccRol (8 - shCount);
7559           /* and kill the higher order bits */
7560           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7561           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7562           emitcode ("orl", "a,#!constbyte",
7563                     (unsigned char) ~SRMask[shCount]);
7564           emitcode ("", "!tlabeldef", tlbl->key + 100);
7565         }
7566     }
7567 }
7568 #endif
7569
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* shiftR1Left2Result - shift right one byte from left to result   */
7573 /*-----------------------------------------------------------------*/
7574 static void
7575 shiftR1Left2Result (operand * left, int offl,
7576                     operand * result, int offr,
7577                     int shCount, int sign)
7578 {
7579   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7580   /* shift right accumulator */
7581   if (sign)
7582     AccSRsh (shCount);
7583   else
7584     AccRsh (shCount);
7585   aopPut (AOP (result), "a", offr);
7586 }
7587 #endif
7588
7589 #ifdef BETTER_LITERAL_SHIFT
7590 /*-----------------------------------------------------------------*/
7591 /* shiftL1Left2Result - shift left one byte from left to result    */
7592 /*-----------------------------------------------------------------*/
7593 static void
7594 shiftL1Left2Result (operand * left, int offl,
7595                     operand * result, int offr, int shCount)
7596 {
7597   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7598   /* shift left accumulator */
7599   AccLsh (shCount);
7600   aopPut (AOP (result), "a", offr);
7601 }
7602 #endif
7603
7604 #ifdef BETTER_LITERAL_SHIFT
7605 /*-----------------------------------------------------------------*/
7606 /* movLeft2Result - move byte from left to result                  */
7607 /*-----------------------------------------------------------------*/
7608 static void
7609 movLeft2Result (operand * left, int offl,
7610                 operand * result, int offr, int sign)
7611 {
7612   char *l;
7613   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7614   {
7615       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7616
7617       if (*l == '@' && (IS_AOP_PREG (result)))
7618       {
7619           emitcode ("mov", "a,%s", l);
7620           aopPut (AOP (result), "a", offr);
7621       }
7622       else
7623       {
7624           if (!sign)
7625           {
7626             aopPut (AOP (result), l, offr);
7627           }
7628           else
7629             {
7630               /* MSB sign in acc.7 ! */
7631               if (getDataSize (left) == offl + 1)
7632                 {
7633                   emitcode ("mov", "a,%s", l);
7634                   aopPut (AOP (result), "a", offr);
7635                 }
7636             }
7637       }
7638   }
7639 }
7640 #endif
7641
7642 #ifdef BETTER_LITERAL_SHIFT
7643 /*-----------------------------------------------------------------*/
7644 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7645 /*-----------------------------------------------------------------*/
7646 static void
7647 AccAXRrl1 (char *x)
7648 {
7649   emitcode ("rrc", "a");
7650   emitcode ("xch", "a,%s", x);
7651   emitcode ("rrc", "a");
7652   emitcode ("xch", "a,%s", x);
7653 }
7654 #endif
7655
7656 #ifdef BETTER_LITERAL_SHIFT
7657 //REMOVE ME!!!
7658 /*-----------------------------------------------------------------*/
7659 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7660 /*-----------------------------------------------------------------*/
7661 static void
7662 AccAXLrl1 (char *x)
7663 {
7664   emitcode ("xch", "a,%s", x);
7665   emitcode ("rlc", "a");
7666   emitcode ("xch", "a,%s", x);
7667   emitcode ("rlc", "a");
7668 }
7669 #endif
7670
7671 #ifdef BETTER_LITERAL_SHIFT
7672 /*-----------------------------------------------------------------*/
7673 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7674 /*-----------------------------------------------------------------*/
7675 static void
7676 AccAXLsh1 (char *x)
7677 {
7678   emitcode ("xch", "a,%s", x);
7679   emitcode ("add", "a,acc");
7680   emitcode ("xch", "a,%s", x);
7681   emitcode ("rlc", "a");
7682 }
7683 #endif
7684
7685 #ifdef BETTER_LITERAL_SHIFT
7686 /*-----------------------------------------------------------------*/
7687 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7688 /*-----------------------------------------------------------------*/
7689 static void
7690 AccAXLsh (char *x, int shCount)
7691 {
7692   switch (shCount)
7693     {
7694     case 0:
7695       break;
7696     case 1:
7697       AccAXLsh1 (x);
7698       break;
7699     case 2:
7700       AccAXLsh1 (x);
7701       AccAXLsh1 (x);
7702       break;
7703     case 3:
7704     case 4:
7705     case 5:                     // AAAAABBB:CCCCCDDD
7706
7707       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7708
7709       emitcode ("anl", "a,#!constbyte",
7710                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7711
7712       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7713
7714       AccRol (shCount);         // DDDCCCCC:BBB00000
7715
7716       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7717
7718       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7719
7720       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7721
7722       emitcode ("anl", "a,#!constbyte",
7723                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7724
7725       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7726
7727       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7728
7729       break;
7730     case 6:                     // AAAAAABB:CCCCCCDD
7731       emitcode ("anl", "a,#!constbyte",
7732                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7733       emitcode ("mov", "c,acc.0");      // c = B
7734       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7735 #if 0
7736       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7737       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7738 #else
7739       emitcode("rrc","a"); 
7740       emitcode("xch","a,%s", x); 
7741       emitcode("rrc","a"); 
7742       emitcode("mov","c,acc.0"); //<< get correct bit 
7743       emitcode("xch","a,%s", x); 
7744
7745       emitcode("rrc","a"); 
7746       emitcode("xch","a,%s", x); 
7747       emitcode("rrc","a"); 
7748       emitcode("xch","a,%s", x); 
7749 #endif
7750       break;
7751     case 7:                     // a:x <<= 7
7752
7753       emitcode ("anl", "a,#!constbyte",
7754                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7755
7756       emitcode ("mov", "c,acc.0");      // c = B
7757
7758       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7759
7760       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7761
7762       break;
7763     default:
7764       break;
7765     }
7766 }
7767 #endif
7768
7769 #ifdef BETTER_LITERAL_SHIFT
7770 //REMOVE ME!!!
7771 /*-----------------------------------------------------------------*/
7772 /* AccAXRsh - right shift a:x known count (0..7)                   */
7773 /*-----------------------------------------------------------------*/
7774 static void
7775 AccAXRsh (char *x, int shCount)
7776 {
7777   switch (shCount)
7778     {
7779     case 0:
7780       break;
7781     case 1:
7782       CLRC;
7783       AccAXRrl1 (x);            // 0->a:x
7784
7785       break;
7786     case 2:
7787       CLRC;
7788       AccAXRrl1 (x);            // 0->a:x
7789
7790       CLRC;
7791       AccAXRrl1 (x);            // 0->a:x
7792
7793       break;
7794     case 3:
7795     case 4:
7796     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7797
7798       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7799
7800       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7801
7802       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7803
7804       emitcode ("anl", "a,#!constbyte",
7805                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7806
7807       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7808
7809       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7810
7811       emitcode ("anl", "a,#!constbyte",
7812                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7813
7814       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7815
7816       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7817
7818       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7819
7820       break;
7821     case 6:                     // AABBBBBB:CCDDDDDD
7822
7823       emitcode ("mov", "c,acc.7");
7824       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7825
7826       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7827
7828       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7829
7830       emitcode ("anl", "a,#!constbyte",
7831                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7832
7833       break;
7834     case 7:                     // ABBBBBBB:CDDDDDDD
7835
7836       emitcode ("mov", "c,acc.7");      // c = A
7837
7838       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7839
7840       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7841
7842       emitcode ("anl", "a,#!constbyte",
7843                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7844
7845       break;
7846     default:
7847       break;
7848     }
7849 }
7850 #endif
7851
7852 #ifdef BETTER_LITERAL_SHIFT
7853 /*-----------------------------------------------------------------*/
7854 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7855 /*-----------------------------------------------------------------*/
7856 static void
7857 AccAXRshS (char *x, int shCount)
7858 {
7859   symbol *tlbl;
7860   switch (shCount)
7861     {
7862     case 0:
7863       break;
7864     case 1:
7865       emitcode ("mov", "c,acc.7");
7866       AccAXRrl1 (x);            // s->a:x
7867
7868       break;
7869     case 2:
7870       emitcode ("mov", "c,acc.7");
7871       AccAXRrl1 (x);            // s->a:x
7872
7873       emitcode ("mov", "c,acc.7");
7874       AccAXRrl1 (x);            // s->a:x
7875
7876       break;
7877     case 3:
7878     case 4:
7879     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7880
7881       tlbl = newiTempLabel (NULL);
7882       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7883
7884       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7885
7886       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7887
7888       emitcode ("anl", "a,#!constbyte",
7889                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7890
7891       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7892
7893       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7894
7895       emitcode ("anl", "a,#!constbyte",
7896                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7897
7898       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7899
7900       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7901
7902       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7903
7904       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7905       emitcode ("orl", "a,#!constbyte",
7906                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7907
7908       emitcode ("", "!tlabeldef", tlbl->key + 100);
7909       break;                    // SSSSAAAA:BBBCCCCC
7910
7911     case 6:                     // AABBBBBB:CCDDDDDD
7912
7913       tlbl = newiTempLabel (NULL);
7914       emitcode ("mov", "c,acc.7");
7915       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7916
7917       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7918
7919       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7920
7921       emitcode ("anl", "a,#!constbyte",
7922                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7923
7924       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7925       emitcode ("orl", "a,#!constbyte",
7926                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7927
7928       emitcode ("", "!tlabeldef", tlbl->key + 100);
7929       break;
7930     case 7:                     // ABBBBBBB:CDDDDDDD
7931
7932       tlbl = newiTempLabel (NULL);
7933       emitcode ("mov", "c,acc.7");      // c = A
7934
7935       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7936
7937       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7938
7939       emitcode ("anl", "a,#!constbyte",
7940                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7941
7942       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7943       emitcode ("orl", "a,#!constbyte",
7944                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7945
7946       emitcode ("", "!tlabeldef", tlbl->key + 100);
7947       break;
7948     default:
7949       break;
7950     }
7951 }
7952 #endif
7953
7954 #ifdef BETTER_LITERAL_SHIFT
7955 static void
7956 _loadLeftIntoAx(char    **lsb, 
7957                 operand *left, 
7958                 operand *result,
7959                 int     offl,
7960                 int     offr)
7961 {
7962   // Get the initial value from left into a pair of registers.
7963   // MSB must be in A, LSB can be any register.
7964   //
7965   // If the result is held in registers, it is an optimization
7966   // if the LSB can be held in the register which will hold the,
7967   // result LSB since this saves us from having to copy it into
7968   // the result following AccAXLsh.
7969   //
7970   // If the result is addressed indirectly, this is not a gain.
7971   if (AOP_NEEDSACC(result))
7972   {
7973        char *leftByte;
7974        
7975        _startLazyDPSEvaluation();
7976       if (AOP_TYPE(left) == AOP_DPTR2)
7977        {
7978            // Get MSB in A.
7979            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7980            // get LSB in DP2_RESULT_REG.
7981            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7982            assert(!strcmp(leftByte, DP2_RESULT_REG));
7983        }
7984        else
7985        {
7986            // get LSB into DP2_RESULT_REG
7987            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7988            if (strcmp(leftByte, DP2_RESULT_REG))
7989            {
7990                TR_AP("#7");
7991                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7992            }
7993            // And MSB in A.
7994            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7995            assert(strcmp(leftByte, DP2_RESULT_REG));
7996            MOVA(leftByte);
7997        }
7998        _endLazyDPSEvaluation();
7999        *lsb = DP2_RESULT_REG;
8000   }
8001   else
8002   {
8003       if (sameRegs (AOP (result), AOP (left)) &&
8004         ((offl + MSB16) == offr))
8005       {
8006           /* don't crash result[offr] */
8007           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8008           emitcode ("xch", "a,%s", 
8009                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8010       }
8011       else
8012       {
8013           movLeft2Result (left, offl, result, offr, 0);
8014           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8015       }
8016       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8017       assert(strcmp(*lsb,"a"));      
8018   }
8019 }
8020
8021 static void
8022 _storeAxResults(char    *lsb,
8023                 operand *result,
8024                 int     offr)
8025 {
8026   _startLazyDPSEvaluation();
8027   if (AOP_NEEDSACC(result))
8028   {
8029       /* We have to explicitly update the result LSB.
8030        */
8031       emitcode("xch","a,%s", lsb);
8032       aopPut(AOP(result), "a", offr);
8033       emitcode("mov","a,%s", lsb);
8034   }
8035   if (getDataSize (result) > 1)
8036   {
8037       aopPut (AOP (result), "a", offr + MSB16);
8038   }
8039   _endLazyDPSEvaluation();
8040 }
8041
8042 /*-----------------------------------------------------------------*/
8043 /* shiftL2Left2Result - shift left two bytes from left to result   */
8044 /*-----------------------------------------------------------------*/
8045 static void
8046 shiftL2Left2Result (operand * left, int offl,
8047                     operand * result, int offr, int shCount)
8048 {
8049   char *lsb;
8050
8051   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8052   
8053   AccAXLsh (lsb, shCount);
8054   
8055   _storeAxResults(lsb, result, offr);
8056 }
8057 #endif
8058
8059 #ifdef BETTER_LITERAL_SHIFT
8060 /*-----------------------------------------------------------------*/
8061 /* shiftR2Left2Result - shift right two bytes from left to result  */
8062 /*-----------------------------------------------------------------*/
8063 static void
8064 shiftR2Left2Result (operand * left, int offl,
8065                     operand * result, int offr,
8066                     int shCount, int sign)
8067 {
8068   char *lsb;
8069   
8070   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8071   
8072   /* a:x >> shCount (x = lsb(result)) */
8073   if (sign)
8074   {
8075      AccAXRshS(lsb, shCount);
8076   }
8077   else
8078   {
8079     AccAXRsh(lsb, shCount);
8080   }
8081   
8082   _storeAxResults(lsb, result, offr);
8083 }
8084 #endif
8085
8086 /*-----------------------------------------------------------------*/
8087 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8088 /*-----------------------------------------------------------------*/
8089 static void
8090 shiftLLeftOrResult (operand * left, int offl,
8091                     operand * result, int offr, int shCount)
8092 {
8093   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8094   /* shift left accumulator */
8095   AccLsh (shCount);
8096   /* or with result */
8097   emitcode ("orl", "a,%s",
8098             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8099   /* back to result */
8100   aopPut (AOP (result), "a", offr);
8101 }
8102
8103 #if 0
8104 //REMOVE ME!!!
8105 /*-----------------------------------------------------------------*/
8106 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8107 /*-----------------------------------------------------------------*/
8108 static void
8109 shiftRLeftOrResult (operand * left, int offl,
8110                     operand * result, int offr, int shCount)
8111 {
8112   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8113   /* shift right accumulator */
8114   AccRsh (shCount);
8115   /* or with result */
8116   emitcode ("orl", "a,%s",
8117             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8118   /* back to result */
8119   aopPut (AOP (result), "a", offr);
8120 }
8121 #endif
8122
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* genlshOne - left shift a one byte quantity by known count       */
8126 /*-----------------------------------------------------------------*/
8127 static void
8128 genlshOne (operand * result, operand * left, int shCount)
8129 {
8130   D (emitcode (";", "genlshOne "););
8131   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8132 }
8133 #endif
8134
8135 #ifdef BETTER_LITERAL_SHIFT
8136 /*-----------------------------------------------------------------*/
8137 /* genlshTwo - left shift two bytes by known amount != 0           */
8138 /*-----------------------------------------------------------------*/
8139 static void
8140 genlshTwo (operand * result, operand * left, int shCount)
8141 {
8142   int size;
8143
8144   D (emitcode (";", "genlshTwo "););
8145
8146   size = getDataSize (result);
8147
8148   /* if shCount >= 8 */
8149   if (shCount >= 8)
8150   {
8151       shCount -= 8;
8152
8153       _startLazyDPSEvaluation();
8154
8155       if (size > 1)
8156         {
8157           if (shCount)
8158           {
8159             _endLazyDPSEvaluation();
8160             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8161             aopPut (AOP (result), zero, LSB);       
8162           }
8163           else
8164           {
8165             movLeft2Result (left, LSB, result, MSB16, 0);
8166             aopPut (AOP (result), zero, LSB);
8167             _endLazyDPSEvaluation();
8168           }
8169         }
8170         else
8171         {
8172           aopPut (AOP (result), zero, LSB);
8173           _endLazyDPSEvaluation();
8174         }
8175   }
8176
8177   /*  1 <= shCount <= 7 */
8178   else
8179     {
8180       if (size == 1)
8181       {
8182         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8183       }
8184       else
8185       {
8186         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8187       }
8188     }
8189 }
8190 #endif
8191
8192 #if 0
8193 //REMOVE ME!!!
8194 /*-----------------------------------------------------------------*/
8195 /* shiftLLong - shift left one long from left to result            */
8196 /* offl = LSB or MSB16                                             */
8197 /*-----------------------------------------------------------------*/
8198 static void
8199 shiftLLong (operand * left, operand * result, int offr)
8200 {
8201   char *l;
8202   int size = AOP_SIZE (result);
8203
8204   if (size >= LSB + offr)
8205     {
8206       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8207       MOVA (l);
8208       emitcode ("add", "a,acc");
8209       if (sameRegs (AOP (left), AOP (result)) &&
8210           size >= MSB16 + offr && offr != LSB)
8211         emitcode ("xch", "a,%s",
8212                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8213       else
8214         aopPut (AOP (result), "a", LSB + offr);
8215     }
8216
8217   if (size >= MSB16 + offr)
8218     {
8219       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8220         {
8221           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8222         }
8223       emitcode ("rlc", "a");
8224       if (sameRegs (AOP (left), AOP (result)) &&
8225           size >= MSB24 + offr && offr != LSB)
8226         emitcode ("xch", "a,%s",
8227                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8228       else
8229         aopPut (AOP (result), "a", MSB16 + offr);
8230     }
8231
8232   if (size >= MSB24 + offr)
8233     {
8234       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8235         {
8236           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8237         }
8238       emitcode ("rlc", "a");
8239       if (sameRegs (AOP (left), AOP (result)) &&
8240           size >= MSB32 + offr && offr != LSB)
8241         emitcode ("xch", "a,%s",
8242                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8243       else
8244         aopPut (AOP (result), "a", MSB24 + offr);
8245     }
8246
8247   if (size > MSB32 + offr)
8248     {
8249       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8250         {
8251           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8252         }
8253       emitcode ("rlc", "a");
8254       aopPut (AOP (result), "a", MSB32 + offr);
8255     }
8256   if (offr != LSB)
8257     aopPut (AOP (result), zero, LSB);
8258 }
8259 #endif
8260
8261 #if 0
8262 //REMOVE ME!!!
8263 /*-----------------------------------------------------------------*/
8264 /* genlshFour - shift four byte by a known amount != 0             */
8265 /*-----------------------------------------------------------------*/
8266 static void
8267 genlshFour (operand * result, operand * left, int shCount)
8268 {
8269   int size;
8270
8271   D (emitcode (";", "genlshFour ");
8272     );
8273
8274   size = AOP_SIZE (result);
8275
8276   /* if shifting more that 3 bytes */
8277   if (shCount >= 24)
8278     {
8279       shCount -= 24;
8280       if (shCount)
8281         /* lowest order of left goes to the highest
8282            order of the destination */
8283         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8284       else
8285         movLeft2Result (left, LSB, result, MSB32, 0);
8286       aopPut (AOP (result), zero, LSB);
8287       aopPut (AOP (result), zero, MSB16);
8288       aopPut (AOP (result), zero, MSB24);
8289       return;
8290     }
8291
8292   /* more than two bytes */
8293   else if (shCount >= 16)
8294     {
8295       /* lower order two bytes goes to higher order two bytes */
8296       shCount -= 16;
8297       /* if some more remaining */
8298       if (shCount)
8299         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8300       else
8301         {
8302           movLeft2Result (left, MSB16, result, MSB32, 0);
8303           movLeft2Result (left, LSB, result, MSB24, 0);
8304         }
8305       aopPut (AOP (result), zero, MSB16);
8306       aopPut (AOP (result), zero, LSB);
8307       return;
8308     }
8309
8310   /* if more than 1 byte */
8311   else if (shCount >= 8)
8312     {
8313       /* lower order three bytes goes to higher order  three bytes */
8314       shCount -= 8;
8315       if (size == 2)
8316         {
8317           if (shCount)
8318             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8319           else
8320             movLeft2Result (left, LSB, result, MSB16, 0);
8321         }
8322       else
8323         {                       /* size = 4 */
8324           if (shCount == 0)
8325             {
8326               movLeft2Result (left, MSB24, result, MSB32, 0);
8327               movLeft2Result (left, MSB16, result, MSB24, 0);
8328               movLeft2Result (left, LSB, result, MSB16, 0);
8329               aopPut (AOP (result), zero, LSB);
8330             }
8331           else if (shCount == 1)
8332             shiftLLong (left, result, MSB16);
8333           else
8334             {
8335               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8336               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8337               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8338               aopPut (AOP (result), zero, LSB);
8339             }
8340         }
8341     }
8342
8343   /* 1 <= shCount <= 7 */
8344   else if (shCount <= 2)
8345     {
8346       shiftLLong (left, result, LSB);
8347       if (shCount == 2)
8348         shiftLLong (result, result, LSB);
8349     }
8350   /* 3 <= shCount <= 7, optimize */
8351   else
8352     {
8353       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8354       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8355       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8356     }
8357 }
8358 #endif
8359
8360 #ifdef BETTER_LITERAL_SHIFT
8361 /*-----------------------------------------------------------------*/
8362 /* genLeftShiftLiteral - left shifting by known count              */
8363 /*-----------------------------------------------------------------*/
8364 static bool
8365 genLeftShiftLiteral (operand * left,
8366                      operand * right,
8367                      operand * result,
8368                      iCode * ic)
8369 {
8370   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8371   int size;
8372
8373   size = getSize (operandType (result));
8374
8375   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8376
8377   /* We only handle certain easy cases so far. */
8378   if ((shCount != 0)
8379    && (shCount < (size * 8))
8380    && (size != 1)
8381    && (size != 2))
8382   {
8383       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8384       return FALSE;
8385   }
8386
8387   freeAsmop (right, NULL, ic, TRUE);
8388
8389   aopOp(left, ic, FALSE, FALSE);
8390   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8391
8392 #if 0 // debug spew
8393   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8394   {
8395         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8396         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8397         {
8398            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8399         }
8400   }
8401   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8402   {
8403         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8404         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8405         {
8406            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8407         }       
8408   }  
8409 #endif
8410   
8411 #if VIEW_SIZE
8412   emitcode ("; shift left ", "result %d, left %d", size,
8413             AOP_SIZE (left));
8414 #endif
8415
8416   /* I suppose that the left size >= result size */
8417   if (shCount == 0)
8418   {
8419         _startLazyDPSEvaluation();
8420         while (size--)
8421         {
8422           movLeft2Result (left, size, result, size, 0);
8423         }
8424         _endLazyDPSEvaluation();
8425   }
8426   else if (shCount >= (size * 8))
8427   {
8428     _startLazyDPSEvaluation();
8429     while (size--)
8430     {
8431       aopPut (AOP (result), zero, size);
8432     }
8433     _endLazyDPSEvaluation();
8434   }
8435   else
8436   {
8437       switch (size)
8438         {
8439         case 1:
8440           genlshOne (result, left, shCount);
8441           break;
8442
8443         case 2:
8444           genlshTwo (result, left, shCount);
8445           break;
8446 #if 0
8447         case 4:
8448           genlshFour (result, left, shCount);
8449           break;
8450 #endif
8451         default:
8452           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8453           break;
8454         }
8455     }
8456   freeAsmop (left, NULL, ic, TRUE);
8457   freeAsmop (result, NULL, ic, TRUE);
8458   return TRUE;
8459 }
8460 #endif
8461
8462 /*-----------------------------------------------------------------*/
8463 /* genLeftShift - generates code for left shifting                 */
8464 /*-----------------------------------------------------------------*/
8465 static void
8466 genLeftShift (iCode * ic)
8467 {
8468   operand *left, *right, *result;
8469   int size, offset;
8470   char *l;
8471   symbol *tlbl, *tlbl1;
8472
8473   D (emitcode (";", "genLeftShift "););
8474
8475   right = IC_RIGHT (ic);
8476   left = IC_LEFT (ic);
8477   result = IC_RESULT (ic);
8478
8479   aopOp (right, ic, FALSE, FALSE);
8480
8481
8482 #ifdef BETTER_LITERAL_SHIFT
8483   /* if the shift count is known then do it
8484      as efficiently as possible */
8485   if (AOP_TYPE (right) == AOP_LIT)
8486     {
8487       if (genLeftShiftLiteral (left, right, result, ic))
8488       {
8489         return;
8490       }
8491     }
8492 #endif
8493
8494   /* shift count is unknown then we have to form
8495      a loop get the loop count in B : Note: we take
8496      only the lower order byte since shifting
8497      more that 32 bits make no sense anyway, ( the
8498      largest size of an object can be only 32 bits ) */
8499
8500   if (AOP_TYPE (right) == AOP_LIT)
8501   {
8502       /* Really should be handled by genLeftShiftLiteral,
8503        * but since I'm too lazy to fix that today, at least we can make
8504        * some small improvement.
8505        */
8506        emitcode("mov", "b,#!constbyte",
8507                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8508   }
8509   else
8510   {
8511       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8512       emitcode ("inc", "b");
8513   }
8514   freeAsmop (right, NULL, ic, TRUE);
8515   aopOp (left, ic, FALSE, FALSE);
8516   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8517
8518   /* now move the left to the result if they are not the
8519      same */
8520   if (!sameRegs (AOP (left), AOP (result)) &&
8521       AOP_SIZE (result) > 1)
8522     {
8523
8524       size = AOP_SIZE (result);
8525       offset = 0;
8526       _startLazyDPSEvaluation ();
8527       while (size--)
8528         {
8529           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8530           if (*l == '@' && (IS_AOP_PREG (result)))
8531             {
8532
8533               emitcode ("mov", "a,%s", l);
8534               aopPut (AOP (result), "a", offset);
8535             }
8536           else
8537             aopPut (AOP (result), l, offset);
8538           offset++;
8539         }
8540       _endLazyDPSEvaluation ();
8541     }
8542
8543   tlbl = newiTempLabel (NULL);
8544   size = AOP_SIZE (result);
8545   offset = 0;
8546   tlbl1 = newiTempLabel (NULL);
8547
8548   /* if it is only one byte then */
8549   if (size == 1)
8550     {
8551       symbol *tlbl1 = newiTempLabel (NULL);
8552
8553       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8554       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8555       emitcode ("", "!tlabeldef", tlbl->key + 100);
8556       emitcode ("add", "a,acc");
8557       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8558       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8559       aopPut (AOP (result), "a", 0);
8560       goto release;
8561     }
8562
8563   reAdjustPreg (AOP (result));
8564
8565   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8566   emitcode ("", "!tlabeldef", tlbl->key + 100);
8567   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8568   emitcode ("add", "a,acc");
8569   aopPut (AOP (result), "a", offset++);
8570   _startLazyDPSEvaluation ();
8571   while (--size)
8572     {
8573       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8574       emitcode ("rlc", "a");
8575       aopPut (AOP (result), "a", offset++);
8576     }
8577   _endLazyDPSEvaluation ();
8578   reAdjustPreg (AOP (result));
8579
8580   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8581   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8582 release:
8583   freeAsmop (left, NULL, ic, TRUE);
8584   freeAsmop (result, NULL, ic, TRUE);
8585 }
8586
8587 #ifdef BETTER_LITERAL_SHIFT
8588 /*-----------------------------------------------------------------*/
8589 /* genrshOne - right shift a one byte quantity by known count      */
8590 /*-----------------------------------------------------------------*/
8591 static void
8592 genrshOne (operand * result, operand * left,
8593            int shCount, int sign)
8594 {
8595   D (emitcode (";", "genrshOne"););
8596   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8597 }
8598 #endif
8599
8600 #ifdef BETTER_LITERAL_SHIFT
8601 /*-----------------------------------------------------------------*/
8602 /* genrshTwo - right shift two bytes by known amount != 0          */
8603 /*-----------------------------------------------------------------*/
8604 static void
8605 genrshTwo (operand * result, operand * left,
8606            int shCount, int sign)
8607 {
8608   D (emitcode (";", "genrshTwo"););
8609
8610   /* if shCount >= 8 */
8611   if (shCount >= 8)
8612     {
8613       shCount -= 8;
8614       _startLazyDPSEvaluation();
8615       if (shCount)
8616       {
8617         shiftR1Left2Result (left, MSB16, result, LSB,
8618                             shCount, sign);
8619       }                     
8620       else
8621       {
8622         movLeft2Result (left, MSB16, result, LSB, sign);
8623       }
8624       addSign (result, MSB16, sign);
8625       _endLazyDPSEvaluation();
8626     }
8627
8628   /*  1 <= shCount <= 7 */
8629   else
8630   {
8631     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8632   }
8633 }
8634 #endif
8635
8636 /*-----------------------------------------------------------------*/
8637 /* shiftRLong - shift right one long from left to result           */
8638 /* offl = LSB or MSB16                                             */
8639 /*-----------------------------------------------------------------*/
8640 static void
8641 shiftRLong (operand * left, int offl,
8642             operand * result, int sign)
8643 {
8644   int isSameRegs=sameRegs(AOP(left),AOP(result));
8645
8646   if (isSameRegs && offl>1) {
8647     // we are in big trouble, but this shouldn't happen
8648     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8649   }
8650
8651   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8652   
8653   if (offl==MSB16) {
8654     // shift is > 8
8655     if (sign) {
8656       emitcode ("rlc", "a");
8657       emitcode ("subb", "a,acc");
8658       emitcode ("xch", "a,%s",
8659                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8660     } else {
8661       aopPut (AOP(result), zero, MSB32);
8662     }
8663   }
8664
8665   if (!sign) {
8666     emitcode ("clr", "c");
8667   } else {
8668     emitcode ("mov", "c,acc.7");
8669   }
8670
8671   emitcode ("rrc", "a");
8672
8673   if (isSameRegs && offl==MSB16) {
8674     emitcode ("xch",
8675               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8676   } else {
8677     aopPut (AOP (result), "a", MSB32);
8678     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8679   }
8680
8681   emitcode ("rrc", "a");
8682   if (isSameRegs && offl==1) {
8683     emitcode ("xch", "a,%s",
8684               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8685   } else {
8686     aopPut (AOP (result), "a", MSB24);
8687     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8688   }
8689   emitcode ("rrc", "a");
8690   aopPut (AOP (result), "a", MSB16 - offl);
8691
8692   if (offl == LSB)
8693     {
8694       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8695       emitcode ("rrc", "a");
8696       aopPut (AOP (result), "a", LSB);
8697     }
8698 }
8699
8700 /*-----------------------------------------------------------------*/
8701 /* genrshFour - shift four byte by a known amount != 0             */
8702 /*-----------------------------------------------------------------*/
8703 static void
8704 genrshFour (operand * result, operand * left,
8705             int shCount, int sign)
8706 {
8707   D (emitcode (";", "genrshFour"););
8708
8709   /* if shifting more that 3 bytes */
8710   if (shCount >= 24)
8711     {
8712       shCount -= 24;
8713       _startLazyDPSEvaluation();
8714       if (shCount)
8715         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8716       else
8717         movLeft2Result (left, MSB32, result, LSB, sign);
8718       addSign (result, MSB16, sign);
8719       _endLazyDPSEvaluation();
8720     }
8721   else if (shCount >= 16)
8722     {
8723       shCount -= 16;
8724       _startLazyDPSEvaluation();
8725       if (shCount)
8726         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8727       else
8728         {
8729           movLeft2Result (left, MSB24, result, LSB, 0);
8730           movLeft2Result (left, MSB32, result, MSB16, sign);
8731         }
8732       addSign (result, MSB24, sign);
8733       _endLazyDPSEvaluation();
8734     }
8735   else if (shCount >= 8)
8736     {
8737       shCount -= 8;
8738       _startLazyDPSEvaluation();
8739       if (shCount == 1)
8740         {
8741             shiftRLong (left, MSB16, result, sign);
8742         }
8743       else if (shCount == 0)
8744         {
8745           movLeft2Result (left, MSB16, result, LSB, 0);
8746           movLeft2Result (left, MSB24, result, MSB16, 0);
8747           movLeft2Result (left, MSB32, result, MSB24, sign);
8748           addSign (result, MSB32, sign);
8749         }
8750       else
8751         {
8752           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8753           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8754           /* the last shift is signed */
8755           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8756           addSign (result, MSB32, sign);
8757         }
8758         _endLazyDPSEvaluation();
8759     }
8760   else
8761     {   
8762         /* 1 <= shCount <= 7 */
8763       if (shCount <= 2)
8764         {
8765           shiftRLong (left, LSB, result, sign);
8766           if (shCount == 2)
8767             shiftRLong (result, LSB, result, sign);
8768         }
8769       else
8770         {
8771           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8772           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8773           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8774         }
8775     }
8776 }
8777
8778 #ifdef BETTER_LITERAL_SHIFT
8779 /*-----------------------------------------------------------------*/
8780 /* genRightShiftLiteral - right shifting by known count            */
8781 /*-----------------------------------------------------------------*/
8782 static bool
8783 genRightShiftLiteral (operand * left,
8784                       operand * right,
8785                       operand * result,
8786                       iCode * ic,
8787                       int sign)
8788 {
8789   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8790   int size;
8791
8792   size = getSize (operandType (result));
8793
8794   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8795
8796   /* We only handle certain easy cases so far. */
8797   if ((shCount != 0)
8798    && (shCount < (size * 8))
8799    && (size != 1)
8800    && (size != 2)
8801    && (size != 4))
8802   {
8803       D(emitcode (";", "genRightShiftLiteral wimping out"););
8804       return FALSE;
8805   }
8806
8807   freeAsmop (right, NULL, ic, TRUE);
8808
8809   aopOp (left, ic, FALSE, FALSE);
8810   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8811
8812 #if VIEW_SIZE
8813   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8814             AOP_SIZE (left));
8815 #endif
8816
8817   /* test the LEFT size !!! */
8818
8819   /* I suppose that the left size >= result size */
8820   if (shCount == 0)
8821   {
8822       size = getDataSize (result);
8823       _startLazyDPSEvaluation();
8824       while (size--)
8825       {
8826         movLeft2Result (left, size, result, size, 0);
8827       }
8828       _endLazyDPSEvaluation();
8829   }
8830   else if (shCount >= (size * 8))
8831     {
8832       if (sign)
8833       {
8834         /* get sign in acc.7 */
8835         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8836       }
8837       addSign (result, LSB, sign);
8838     }
8839   else
8840     {
8841       switch (size)
8842         {
8843         case 1:
8844           genrshOne (result, left, shCount, sign);
8845           break;
8846
8847         case 2:
8848           genrshTwo (result, left, shCount, sign);
8849           break;
8850 #if 1
8851         case 4:
8852           genrshFour (result, left, shCount, sign);
8853           break;
8854 #endif    
8855         default:
8856           break;
8857         }
8858     }
8859   freeAsmop (left, NULL, ic, TRUE);
8860   freeAsmop (result, NULL, ic, TRUE);
8861   
8862   return TRUE;
8863 }
8864 #endif
8865
8866 /*-----------------------------------------------------------------*/
8867 /* genSignedRightShift - right shift of signed number              */
8868 /*-----------------------------------------------------------------*/
8869 static void
8870 genSignedRightShift (iCode * ic)
8871 {
8872   operand *right, *left, *result;
8873   int size, offset;
8874   char *l;
8875   symbol *tlbl, *tlbl1;
8876
8877   D (emitcode (";", "genSignedRightShift "););
8878
8879   /* we do it the hard way put the shift count in b
8880      and loop thru preserving the sign */
8881
8882   right = IC_RIGHT (ic);
8883   left = IC_LEFT (ic);
8884   result = IC_RESULT (ic);
8885
8886   aopOp (right, ic, FALSE, FALSE);
8887
8888 #ifdef BETTER_LITERAL_SHIFT
8889   if (AOP_TYPE (right) == AOP_LIT)
8890     {
8891       if (genRightShiftLiteral (left, right, result, ic, 1))
8892       {
8893         return;
8894       }
8895     }
8896 #endif
8897   /* shift count is unknown then we have to form
8898      a loop get the loop count in B : Note: we take
8899      only the lower order byte since shifting
8900      more that 32 bits make no sense anyway, ( the
8901      largest size of an object can be only 32 bits ) */
8902
8903   if (AOP_TYPE (right) == AOP_LIT)
8904   {
8905       /* Really should be handled by genRightShiftLiteral,
8906        * but since I'm too lazy to fix that today, at least we can make
8907        * some small improvement.
8908        */
8909        emitcode("mov", "b,#!constbyte",
8910                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8911   }
8912   else
8913   {
8914         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8915         emitcode ("inc", "b");
8916   }
8917   freeAsmop (right, NULL, ic, TRUE);
8918   aopOp (left, ic, FALSE, FALSE);
8919   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8920
8921   /* now move the left to the result if they are not the
8922      same */
8923   if (!sameRegs (AOP (left), AOP (result)) &&
8924       AOP_SIZE (result) > 1)
8925     {
8926
8927       size = AOP_SIZE (result);
8928       offset = 0;
8929       _startLazyDPSEvaluation ();
8930       while (size--)
8931         {
8932           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8933           if (*l == '@' && IS_AOP_PREG (result))
8934             {
8935
8936               emitcode ("mov", "a,%s", l);
8937               aopPut (AOP (result), "a", offset);
8938             }
8939           else
8940             aopPut (AOP (result), l, offset);
8941           offset++;
8942         }
8943       _endLazyDPSEvaluation ();
8944     }
8945
8946   /* mov the highest order bit to OVR */
8947   tlbl = newiTempLabel (NULL);
8948   tlbl1 = newiTempLabel (NULL);
8949
8950   size = AOP_SIZE (result);
8951   offset = size - 1;
8952   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8953   emitcode ("rlc", "a");
8954   emitcode ("mov", "ov,c");
8955   /* if it is only one byte then */
8956   if (size == 1)
8957     {
8958       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8959       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8960       emitcode ("", "!tlabeldef", tlbl->key + 100);
8961       emitcode ("mov", "c,ov");
8962       emitcode ("rrc", "a");
8963       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8964       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8965       aopPut (AOP (result), "a", 0);
8966       goto release;
8967     }
8968
8969   reAdjustPreg (AOP (result));
8970   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8971   emitcode ("", "!tlabeldef", tlbl->key + 100);
8972   emitcode ("mov", "c,ov");
8973   _startLazyDPSEvaluation ();
8974   while (size--)
8975     {
8976       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8977       emitcode ("rrc", "a");
8978       aopPut (AOP (result), "a", offset--);
8979     }
8980   _endLazyDPSEvaluation ();
8981   reAdjustPreg (AOP (result));
8982   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8983   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8984
8985 release:
8986   freeAsmop (left, NULL, ic, TRUE);
8987   freeAsmop (result, NULL, ic, TRUE);
8988 }
8989
8990 /*-----------------------------------------------------------------*/
8991 /* genRightShift - generate code for right shifting                */
8992 /*-----------------------------------------------------------------*/
8993 static void
8994 genRightShift (iCode * ic)
8995 {
8996   operand *right, *left, *result;
8997   sym_link *letype;
8998   int size, offset;
8999   char *l;
9000   symbol *tlbl, *tlbl1;
9001
9002   D (emitcode (";", "genRightShift "););
9003
9004   /* if signed then we do it the hard way preserve the
9005      sign bit moving it inwards */
9006   letype = getSpec (operandType (IC_LEFT (ic)));
9007
9008   if (!SPEC_USIGN (letype))
9009     {
9010       genSignedRightShift (ic);
9011       return;
9012     }
9013
9014   /* signed & unsigned types are treated the same : i.e. the
9015      signed is NOT propagated inwards : quoting from the
9016      ANSI - standard : "for E1 >> E2, is equivalent to division
9017      by 2**E2 if unsigned or if it has a non-negative value,
9018      otherwise the result is implementation defined ", MY definition
9019      is that the sign does not get propagated */
9020
9021   right = IC_RIGHT (ic);
9022   left = IC_LEFT (ic);
9023   result = IC_RESULT (ic);
9024
9025   aopOp (right, ic, FALSE, FALSE);
9026
9027 #ifdef BETTER_LITERAL_SHIFT
9028   /* if the shift count is known then do it
9029      as efficiently as possible */
9030   if (AOP_TYPE (right) == AOP_LIT)
9031     {
9032       if (genRightShiftLiteral (left, right, result, ic, 0))
9033       {
9034         return;
9035       }
9036     }
9037 #endif
9038
9039   /* shift count is unknown then we have to form
9040      a loop get the loop count in B : Note: we take
9041      only the lower order byte since shifting
9042      more that 32 bits make no sense anyway, ( the
9043      largest size of an object can be only 32 bits ) */
9044   
9045   if (AOP_TYPE (right) == AOP_LIT)
9046   {
9047       /* Really should be handled by genRightShiftLiteral,
9048        * but since I'm too lazy to fix that today, at least we can make
9049        * some small improvement.
9050        */
9051        emitcode("mov", "b,#!constbyte",
9052                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9053   }
9054   else
9055   {
9056       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9057       emitcode ("inc", "b");
9058   }
9059   freeAsmop (right, NULL, ic, TRUE);
9060   aopOp (left, ic, FALSE, FALSE);
9061   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9062
9063   /* now move the left to the result if they are not the
9064      same */
9065   if (!sameRegs (AOP (left), AOP (result)) &&
9066       AOP_SIZE (result) > 1)
9067     {
9068
9069       size = AOP_SIZE (result);
9070       offset = 0;
9071       _startLazyDPSEvaluation ();
9072       while (size--)
9073         {
9074           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9075           if (*l == '@' && IS_AOP_PREG (result))
9076             {
9077
9078               emitcode ("mov", "a,%s", l);
9079               aopPut (AOP (result), "a", offset);
9080             }
9081           else
9082             aopPut (AOP (result), l, offset);
9083           offset++;
9084         }
9085       _endLazyDPSEvaluation ();
9086     }
9087
9088   tlbl = newiTempLabel (NULL);
9089   tlbl1 = newiTempLabel (NULL);
9090   size = AOP_SIZE (result);
9091   offset = size - 1;
9092
9093   /* if it is only one byte then */
9094   if (size == 1)
9095     {
9096       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9097       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9098       emitcode ("", "!tlabeldef", tlbl->key + 100);
9099       CLRC;
9100       emitcode ("rrc", "a");
9101       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9102       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9103       aopPut (AOP (result), "a", 0);
9104       goto release;
9105     }
9106
9107   reAdjustPreg (AOP (result));
9108   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9109   emitcode ("", "!tlabeldef", tlbl->key + 100);
9110   CLRC;
9111   _startLazyDPSEvaluation ();
9112   while (size--)
9113     {
9114       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9115       emitcode ("rrc", "a");
9116       aopPut (AOP (result), "a", offset--);
9117     }
9118   _endLazyDPSEvaluation ();
9119   reAdjustPreg (AOP (result));
9120
9121   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9122   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9123
9124 release:
9125   freeAsmop (left, NULL, ic, TRUE);
9126   freeAsmop (result, NULL, ic, TRUE);
9127 }
9128
9129
9130 /*-----------------------------------------------------------------*/
9131 /* emitPtrByteGet - emits code to get a byte into A through a      */
9132 /*                  pointer register (R0, R1, or DPTR). The        */
9133 /*                  original value of A can be preserved in B.     */
9134 /*-----------------------------------------------------------------*/
9135 static void
9136 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9137 {
9138   switch (p_type)
9139     {
9140     case IPOINTER:
9141     case POINTER:
9142       if (preserveAinB)
9143         emitcode ("mov", "b,a");
9144       emitcode ("mov", "a,@%s", rname);
9145       break;
9146
9147     case PPOINTER:
9148       if (preserveAinB)
9149         emitcode ("mov", "b,a");
9150       emitcode ("movx", "a,@%s", rname);
9151       break;
9152       
9153     case FPOINTER:
9154       if (preserveAinB)
9155         emitcode ("mov", "b,a");
9156       emitcode ("movx", "a,@dptr");
9157       break;
9158
9159     case CPOINTER:
9160       if (preserveAinB)
9161         emitcode ("mov", "b,a");
9162       emitcode ("clr", "a");
9163       emitcode ("movc", "a,@a+dptr");
9164       break;
9165
9166     case GPOINTER:
9167       if (preserveAinB)
9168         {
9169           emitcode ("push", "b");
9170           emitcode ("push", "acc");
9171         }
9172       emitcode ("lcall", "__gptrget");
9173       if (preserveAinB)
9174         emitcode ("pop", "b");
9175       break;
9176     }
9177 }
9178
9179 /*-----------------------------------------------------------------*/
9180 /* emitPtrByteSet - emits code to set a byte from src through a    */
9181 /*                  pointer register (R0, R1, or DPTR).            */
9182 /*-----------------------------------------------------------------*/
9183 static void
9184 emitPtrByteSet (char *rname, int p_type, char *src)
9185 {
9186   switch (p_type)
9187     {
9188     case IPOINTER:
9189     case POINTER:
9190       if (*src=='@')
9191         {
9192           MOVA (src);
9193           emitcode ("mov", "@%s,a", rname);
9194         }
9195       else
9196         emitcode ("mov", "@%s,%s", rname, src);
9197       break;
9198
9199     case PPOINTER:
9200       MOVA (src);
9201       emitcode ("movx", "@%s,a", rname);
9202       break;
9203       
9204     case FPOINTER:
9205       MOVA (src);
9206       emitcode ("movx", "@dptr,a");
9207       break;
9208
9209     case GPOINTER:
9210       MOVA (src);
9211       emitcode ("lcall", "__gptrput");
9212       break;
9213     }
9214 }
9215
9216 /*-----------------------------------------------------------------*/
9217 /* genUnpackBits - generates code for unpacking bits               */
9218 /*-----------------------------------------------------------------*/
9219 static void
9220 genUnpackBits (operand * result, char *rname, int ptype)
9221 {
9222   int offset = 0;       /* result byte offset */
9223   int rsize;            /* result size */
9224   int rlen = 0;         /* remaining bitfield length */
9225   sym_link *etype;      /* bitfield type information */
9226   int blen;             /* bitfield length */
9227   int bstr;             /* bitfield starting bit within byte */
9228
9229   D(emitcode (";     genUnpackBits",""));
9230
9231   etype = getSpec (operandType (result));
9232   rsize = getSize (operandType (result));
9233   blen = SPEC_BLEN (etype);
9234   bstr = SPEC_BSTR (etype);
9235
9236   /* If the bitfield length is less than a byte */
9237   if (blen < 8)
9238     {
9239       emitPtrByteGet (rname, ptype, FALSE);
9240       AccRsh (bstr);
9241       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9242       aopPut (AOP (result), "a", offset++);
9243       goto finish;
9244     }
9245
9246   /* Bit field did not fit in a byte. Copy all
9247      but the partial byte at the end.  */
9248   for (rlen=blen;rlen>=8;rlen-=8)
9249     {
9250       emitPtrByteGet (rname, ptype, FALSE);
9251       aopPut (AOP (result), "a", offset++);
9252       if (rlen>8)
9253         emitcode ("inc", "%s", rname);
9254     }
9255
9256   /* Handle the partial byte at the end */
9257   if (rlen)
9258     {
9259       emitPtrByteGet (rname, ptype, FALSE);
9260       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9261       aopPut (AOP (result), "a", offset++);
9262     }
9263
9264 finish:
9265   if (offset < rsize)
9266     {
9267       rsize -= offset;
9268       while (rsize--)
9269         aopPut (AOP (result), zero, offset++);
9270     }
9271 }
9272
9273
9274 /*-----------------------------------------------------------------*/
9275 /* genDataPointerGet - generates code when ptr offset is known     */
9276 /*-----------------------------------------------------------------*/
9277 static void
9278 genDataPointerGet (operand * left,
9279                    operand * result,
9280                    iCode * ic)
9281 {
9282   char *l;
9283   char buff[256];
9284   int size, offset = 0;
9285   aopOp (result, ic, TRUE, FALSE);
9286
9287   /* get the string representation of the name */
9288   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9289   size = AOP_SIZE (result);
9290   _startLazyDPSEvaluation ();
9291   while (size--)
9292     {
9293         if (offset)
9294         {
9295             SNPRINTF (buff, sizeof(buff), 
9296                       "(%s + %d)", l + 1, offset);
9297         }
9298         else
9299         {
9300             SNPRINTF (buff, sizeof(buff), 
9301                       "%s", l + 1);
9302         }
9303       aopPut (AOP (result), buff, offset++);
9304     }
9305   _endLazyDPSEvaluation ();
9306
9307   freeAsmop (left, NULL, ic, TRUE);
9308   freeAsmop (result, NULL, ic, TRUE);
9309 }
9310
9311 /*-----------------------------------------------------------------*/
9312 /* genNearPointerGet - emitcode for near pointer fetch             */
9313 /*-----------------------------------------------------------------*/
9314 static void
9315 genNearPointerGet (operand * left,
9316                    operand * result,
9317                    iCode * ic,
9318                    iCode *pi)
9319 {
9320   asmop *aop = NULL;
9321   regs *preg;
9322   char *rname;
9323   sym_link *rtype, *retype, *letype;
9324   sym_link *ltype = operandType (left);
9325   char buff[80];
9326
9327   rtype = operandType (result);
9328   retype = getSpec (rtype);
9329   letype = getSpec (ltype);
9330
9331   aopOp (left, ic, FALSE, FALSE);
9332
9333   /* if left is rematerialisable and
9334      result is not bit variable type and
9335      the left is pointer to data space i.e
9336      lower 128 bytes of space */
9337   if (AOP_TYPE (left) == AOP_IMMD &&
9338       !IS_BITVAR (retype) &&
9339       !IS_BITVAR (letype) &&
9340       DCL_TYPE (ltype) == POINTER)
9341     {
9342       genDataPointerGet (left, result, ic);
9343       return;
9344     }
9345
9346   /* if the value is already in a pointer register
9347      then don't need anything more */
9348   if (!AOP_INPREG (AOP (left)))
9349     {
9350       /* otherwise get a free pointer register */
9351       aop = newAsmop (0);
9352       preg = getFreePtr (ic, &aop, FALSE);
9353       emitcode ("mov", "%s,%s",
9354                 preg->name,
9355                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9356       rname = preg->name;
9357     }
9358   else
9359     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9360
9361   freeAsmop (left, NULL, ic, TRUE);
9362   aopOp (result, ic, FALSE, FALSE);
9363
9364   /* if bitfield then unpack the bits */
9365   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9366     genUnpackBits (result, rname, POINTER);
9367   else
9368     {
9369       /* we have can just get the values */
9370       int size = AOP_SIZE (result);
9371       int offset = 0;
9372
9373       while (size--)
9374         {
9375           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9376             {
9377
9378               emitcode ("mov", "a,@%s", rname);
9379               aopPut (AOP (result), "a", offset);
9380             }
9381           else
9382             {
9383               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9384               aopPut (AOP (result), buff, offset);
9385             }
9386           offset++;
9387           if (size || pi)
9388             {
9389                 emitcode ("inc", "%s", rname);
9390             }
9391         }
9392     }
9393
9394   /* now some housekeeping stuff */
9395   if (aop)
9396     {
9397       /* we had to allocate for this iCode */
9398       if (pi) { /* post increment present */
9399         aopPut(AOP ( left ),rname,0);
9400       }
9401       freeAsmop (NULL, aop, ic, TRUE);
9402     }
9403   else
9404     {
9405       /* we did not allocate which means left
9406          already in a pointer register, then
9407          if size > 0 && this could be used again
9408          we have to point it back to where it
9409          belongs */
9410       if (AOP_SIZE (result) > 1 &&
9411           !OP_SYMBOL (left)->remat &&
9412           (OP_SYMBOL (left)->liveTo > ic->seq ||
9413            ic->depth) &&
9414           !pi)
9415         {
9416           int size = AOP_SIZE (result) - 1;
9417           while (size--)
9418             emitcode ("dec", "%s", rname);
9419         }
9420     }
9421
9422   /* done */
9423   freeAsmop (result, NULL, ic, TRUE);
9424   if (pi) pi->generated = 1;
9425 }
9426
9427 /*-----------------------------------------------------------------*/
9428 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9429 /*-----------------------------------------------------------------*/
9430 static void
9431 genPagedPointerGet (operand * left,
9432                     operand * result,
9433                     iCode * ic,
9434                     iCode * pi)
9435 {
9436   asmop *aop = NULL;
9437   regs *preg;
9438   char *rname;
9439   sym_link *rtype, *retype, *letype;
9440
9441   rtype = operandType (result);
9442   retype = getSpec (rtype);
9443   letype = getSpec (operandType (left));
9444   aopOp (left, ic, FALSE, FALSE);
9445
9446   /* if the value is already in a pointer register
9447      then don't need anything more */
9448   if (!AOP_INPREG (AOP (left)))
9449     {
9450       /* otherwise get a free pointer register */
9451       aop = newAsmop (0);
9452       preg = getFreePtr (ic, &aop, FALSE);
9453       emitcode ("mov", "%s,%s",
9454                 preg->name,
9455                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9456       rname = preg->name;
9457     }
9458   else
9459     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9460
9461   freeAsmop (left, NULL, ic, TRUE);
9462   aopOp (result, ic, FALSE, FALSE);
9463
9464   /* if bitfield then unpack the bits */
9465   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9466     genUnpackBits (result, rname, PPOINTER);
9467   else
9468     {
9469       /* we have can just get the values */
9470       int size = AOP_SIZE (result);
9471       int offset = 0;
9472
9473       while (size--)
9474         {
9475
9476           emitcode ("movx", "a,@%s", rname);
9477           aopPut (AOP (result), "a", offset);
9478
9479           offset++;
9480
9481           if (size || pi)
9482             emitcode ("inc", "%s", rname);
9483         }
9484     }
9485
9486   /* now some housekeeping stuff */
9487   if (aop)
9488     {
9489       /* we had to allocate for this iCode */
9490       if (pi) aopPut ( AOP (left), rname, 0);
9491       freeAsmop (NULL, aop, ic, TRUE);
9492     }
9493   else
9494     {
9495       /* we did not allocate which means left
9496          already in a pointer register, then
9497          if size > 0 && this could be used again
9498          we have to point it back to where it
9499          belongs */
9500       if (AOP_SIZE (result) > 1 &&
9501           !OP_SYMBOL (left)->remat &&
9502           (OP_SYMBOL (left)->liveTo > ic->seq ||
9503            ic->depth) &&
9504           !pi)
9505         {
9506           int size = AOP_SIZE (result) - 1;
9507           while (size--)
9508             emitcode ("dec", "%s", rname);
9509         }
9510     }
9511
9512   /* done */
9513   freeAsmop (result, NULL, ic, TRUE);
9514   if (pi) pi->generated = 1;
9515 }
9516
9517 /*-----------------------------------------------------------------*/
9518 /* genFarPointerGet - gget value from far space                    */
9519 /*-----------------------------------------------------------------*/
9520 static void
9521 genFarPointerGet (operand * left,
9522                   operand * result, iCode * ic, iCode *pi)
9523 {
9524     int size, offset, dopi=1;
9525   sym_link *retype = getSpec (operandType (result));
9526   sym_link *letype = getSpec (operandType (left));
9527   D (emitcode (";", "genFarPointerGet"););
9528
9529   aopOp (left, ic, FALSE, FALSE);
9530
9531   /* if the operand is already in dptr
9532      then we do nothing else we move the value to dptr */
9533   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9534     {
9535       /* if this is remateriazable */
9536       if (AOP_TYPE (left) == AOP_IMMD)
9537         {
9538           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9539         }
9540       else
9541         {
9542           /* we need to get it byte by byte */
9543           _startLazyDPSEvaluation ();
9544           if (AOP_TYPE (left) != AOP_DPTR)
9545             {
9546               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9547               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9548               if (options.model == MODEL_FLAT24)
9549                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9550             }
9551           else
9552             {
9553               /* We need to generate a load to DPTR indirect through DPTR. */
9554               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9555               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9556               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9557               if (options.model == MODEL_FLAT24)
9558                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9559               emitcode ("pop", "dph");
9560               emitcode ("pop", "dpl");
9561               dopi =0;
9562             }
9563           _endLazyDPSEvaluation ();
9564         }
9565     }
9566   /* so dptr know contains the address */
9567   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9568
9569   /* if bit then unpack */
9570   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9571       if (AOP_INDPTRn(left)) {
9572           genSetDPTR(AOP(left)->aopu.dptr);
9573       }
9574       genUnpackBits (result, "dptr", FPOINTER);
9575       if (AOP_INDPTRn(left)) {
9576           genSetDPTR(0);
9577       }
9578   } else
9579     {
9580       size = AOP_SIZE (result);
9581       offset = 0;
9582
9583       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9584           while (size--) {
9585               genSetDPTR(AOP(left)->aopu.dptr);
9586               emitcode ("movx", "a,@dptr");
9587               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9588                   emitcode ("inc", "dptr");
9589               genSetDPTR (0);
9590               aopPut (AOP (result), "a", offset++);
9591           }
9592       } else {
9593           _startLazyDPSEvaluation ();
9594           while (size--) {
9595               if (AOP_INDPTRn(left)) {
9596                   genSetDPTR(AOP(left)->aopu.dptr);
9597               } else {
9598                   genSetDPTR (0);
9599               }
9600               _flushLazyDPS ();
9601               
9602               emitcode ("movx", "a,@dptr");
9603               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9604                   emitcode ("inc", "dptr");
9605               
9606               aopPut (AOP (result), "a", offset++);
9607           }
9608           _endLazyDPSEvaluation ();
9609       }
9610     }
9611   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9612       if (!AOP_INDPTRn(left)) {
9613           _startLazyDPSEvaluation ();
9614           aopPut ( AOP (left), "dpl", 0);
9615           aopPut ( AOP (left), "dph", 1);
9616           if (options.model == MODEL_FLAT24)
9617               aopPut ( AOP (left), "dpx", 2);
9618           _endLazyDPSEvaluation ();
9619       }
9620     pi->generated = 1;
9621   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9622              AOP_SIZE(result) > 1 &&
9623              IS_SYMOP(left) &&
9624              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9625       
9626       size = AOP_SIZE (result) - 1;
9627       if (AOP_INDPTRn(left)) {
9628           genSetDPTR(AOP(left)->aopu.dptr);
9629       }
9630       while (size--) emitcode ("lcall","__decdptr");
9631       if (AOP_INDPTRn(left)) {
9632           genSetDPTR(0);
9633       }
9634   }
9635
9636   freeAsmop (left, NULL, ic, TRUE);
9637   freeAsmop (result, NULL, ic, TRUE);
9638 }
9639
9640 /*-----------------------------------------------------------------*/
9641 /* genCodePointerGet - get value from code space                  */
9642 /*-----------------------------------------------------------------*/
9643 static void
9644 genCodePointerGet (operand * left,
9645                     operand * result, iCode * ic, iCode *pi)
9646 {
9647   int size, offset, dopi=1;
9648   sym_link *retype = getSpec (operandType (result));
9649
9650   aopOp (left, ic, FALSE, FALSE);
9651
9652   /* if the operand is already in dptr
9653      then we do nothing else we move the value to dptr */
9654   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9655     {
9656       /* if this is remateriazable */
9657       if (AOP_TYPE (left) == AOP_IMMD)
9658         {
9659           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9660         }
9661       else
9662         {                       /* we need to get it byte by byte */
9663           _startLazyDPSEvaluation ();
9664           if (AOP_TYPE (left) != AOP_DPTR)
9665             {
9666               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9667               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9668               if (options.model == MODEL_FLAT24)
9669                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9670             }
9671           else
9672             {
9673               /* We need to generate a load to DPTR indirect through DPTR. */
9674               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9675               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9676               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9677               if (options.model == MODEL_FLAT24)
9678                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9679               emitcode ("pop", "dph");
9680               emitcode ("pop", "dpl");
9681               dopi=0;
9682             }
9683           _endLazyDPSEvaluation ();
9684         }
9685     }
9686   /* so dptr know contains the address */
9687   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9688
9689   /* if bit then unpack */
9690   if (IS_BITVAR (retype)) {
9691       if (AOP_INDPTRn(left)) {
9692           genSetDPTR(AOP(left)->aopu.dptr);
9693       }
9694       genUnpackBits (result, "dptr", CPOINTER);
9695       if (AOP_INDPTRn(left)) {
9696           genSetDPTR(0);
9697       }
9698   } else
9699     {
9700       size = AOP_SIZE (result);
9701       offset = 0;
9702       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9703           while (size--) {
9704               genSetDPTR(AOP(left)->aopu.dptr);
9705               emitcode ("clr", "a");
9706               emitcode ("movc", "a,@a+dptr");
9707               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9708                   emitcode ("inc", "dptr");
9709               genSetDPTR (0);
9710               aopPut (AOP (result), "a", offset++);
9711           }
9712       } else {
9713           _startLazyDPSEvaluation ();
9714           while (size--)
9715               {
9716                   if (AOP_INDPTRn(left)) {
9717                       genSetDPTR(AOP(left)->aopu.dptr);
9718                   } else {
9719                       genSetDPTR (0);
9720                   }
9721                   _flushLazyDPS ();
9722                   
9723                   emitcode ("clr", "a");
9724                   emitcode ("movc", "a,@a+dptr");
9725                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9726                       emitcode ("inc", "dptr");
9727                   aopPut (AOP (result), "a", offset++);
9728               }
9729           _endLazyDPSEvaluation ();
9730       }
9731     }
9732   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9733       if (!AOP_INDPTRn(left)) {
9734           _startLazyDPSEvaluation ();
9735           
9736           aopPut ( AOP (left), "dpl", 0);
9737           aopPut ( AOP (left), "dph", 1);
9738           if (options.model == MODEL_FLAT24)
9739               aopPut ( AOP (left), "dpx", 2);
9740
9741           _endLazyDPSEvaluation ();
9742       }
9743       pi->generated = 1;
9744   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9745              AOP_SIZE(result) > 1 &&
9746              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9747       
9748       size = AOP_SIZE (result) - 1;
9749       if (AOP_INDPTRn(left)) {
9750           genSetDPTR(AOP(left)->aopu.dptr);
9751       }
9752       while (size--) emitcode ("lcall","__decdptr");
9753       if (AOP_INDPTRn(left)) {
9754           genSetDPTR(0);
9755       }
9756   }
9757   
9758   freeAsmop (left, NULL, ic, TRUE);
9759   freeAsmop (result, NULL, ic, TRUE);
9760 }
9761
9762 /*-----------------------------------------------------------------*/
9763 /* genGenPointerGet - gget value from generic pointer space        */
9764 /*-----------------------------------------------------------------*/
9765 static void
9766 genGenPointerGet (operand * left,
9767                   operand * result, iCode * ic, iCode * pi)
9768 {
9769   int size, offset;
9770   sym_link *retype = getSpec (operandType (result));
9771   sym_link *letype = getSpec (operandType (left));
9772
9773   D (emitcode (";", "genGenPointerGet "); );
9774
9775   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9776
9777   /* if the operand is already in dptr
9778      then we do nothing else we move the value to dptr */
9779   if (AOP_TYPE (left) != AOP_STR)
9780     {
9781       /* if this is remateriazable */
9782       if (AOP_TYPE (left) == AOP_IMMD)
9783         {
9784           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9785           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9786             {
9787                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9788             }
9789             else
9790             {
9791                 emitcode ("mov", "b,#%d", pointerCode (retype));
9792             }
9793         }
9794       else
9795         {                       /* we need to get it byte by byte */
9796             _startLazyDPSEvaluation ();
9797             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9798             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9799             if (options.model == MODEL_FLAT24) {
9800                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9801                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9802             } else {
9803                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9804             }
9805             _endLazyDPSEvaluation ();
9806         }
9807     }
9808
9809   /* so dptr-b now contains the address */
9810   _G.bInUse++;
9811   aopOp (result, ic, FALSE, TRUE);
9812   _G.bInUse--;
9813
9814   /* if bit then unpack */
9815   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9816   {
9817     genUnpackBits (result, "dptr", GPOINTER);
9818   }
9819   else
9820     {
9821         size = AOP_SIZE (result);
9822         offset = 0;
9823
9824         while (size--)
9825         {
9826             if (size)
9827             {
9828                 // Get two bytes at a time, results in _AP & A.
9829                 // dptr will be incremented ONCE by __gptrgetWord.
9830                 //
9831                 // Note: any change here must be coordinated
9832                 // with the implementation of __gptrgetWord
9833                 // in device/lib/_gptrget.c
9834                 emitcode ("lcall", "__gptrgetWord");
9835                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9836                 aopPut (AOP (result), "a", offset++);
9837                 size--;
9838             }
9839             else
9840             {
9841                 // Only one byte to get.
9842                 emitcode ("lcall", "__gptrget");
9843                 aopPut (AOP (result), "a", offset++);
9844             }
9845             
9846             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9847             {
9848                 emitcode ("inc", "dptr");
9849             }
9850         }
9851     }
9852
9853   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9854     _startLazyDPSEvaluation ();
9855       
9856     aopPut ( AOP (left), "dpl", 0);
9857     aopPut ( AOP (left), "dph", 1);
9858     if (options.model == MODEL_FLAT24) {
9859         aopPut ( AOP (left), "dpx", 2);
9860         aopPut ( AOP (left), "b", 3);   
9861     } else  aopPut ( AOP (left), "b", 2);       
9862     
9863     _endLazyDPSEvaluation ();
9864       
9865     pi->generated = 1;
9866   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9867              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9868       
9869       size = AOP_SIZE (result) - 1;
9870       while (size--) emitcode ("lcall","__decdptr");
9871   }
9872
9873   freeAsmop (left, NULL, ic, TRUE);
9874   freeAsmop (result, NULL, ic, TRUE);
9875 }
9876
9877 /*-----------------------------------------------------------------*/
9878 /* genPointerGet - generate code for pointer get                   */
9879 /*-----------------------------------------------------------------*/
9880 static void
9881 genPointerGet (iCode * ic, iCode *pi)
9882 {
9883   operand *left, *result;
9884   sym_link *type, *etype;
9885   int p_type;
9886
9887   D (emitcode (";", "genPointerGet ");
9888     );
9889
9890   left = IC_LEFT (ic);
9891   result = IC_RESULT (ic);
9892
9893   /* depending on the type of pointer we need to
9894      move it to the correct pointer register */
9895   type = operandType (left);
9896   etype = getSpec (type);
9897   /* if left is of type of pointer then it is simple */
9898   if (IS_PTR (type) && !IS_FUNC (type->next))
9899     p_type = DCL_TYPE (type);
9900   else
9901     {
9902       /* we have to go by the storage class */
9903       p_type = PTR_TYPE (SPEC_OCLS (etype));
9904     }
9905   /* special case when cast remat */
9906   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9907       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9908           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9909           type = operandType (left);
9910           p_type = DCL_TYPE (type);
9911   }
9912   /* now that we have the pointer type we assign
9913      the pointer values */
9914   switch (p_type)
9915     {
9916
9917     case POINTER:
9918     case IPOINTER:
9919       genNearPointerGet (left, result, ic, pi);
9920       break;
9921
9922     case PPOINTER:
9923       genPagedPointerGet (left, result, ic, pi);
9924       break;
9925
9926     case FPOINTER:
9927       genFarPointerGet (left, result, ic, pi);
9928       break;
9929
9930     case CPOINTER:
9931       genCodePointerGet (left, result, ic, pi);
9932       break;
9933
9934     case GPOINTER:
9935       genGenPointerGet (left, result, ic, pi);
9936       break;
9937     }
9938
9939 }
9940
9941 /*-----------------------------------------------------------------*/
9942 /* genPackBits - generates code for packed bit storage             */
9943 /*-----------------------------------------------------------------*/
9944 static void
9945 genPackBits (sym_link * etype,
9946              operand * right,
9947              char *rname, int p_type)
9948 {
9949   int offset = 0;       /* source byte offset */
9950   int rlen = 0;         /* remaining bitfield length */
9951   int blen;             /* bitfield length */
9952   int bstr;             /* bitfield starting bit within byte */
9953   int litval;           /* source literal value (if AOP_LIT) */
9954   unsigned char mask;   /* bitmask within current byte */
9955
9956   D(emitcode (";     genPackBits",""));
9957
9958   blen = SPEC_BLEN (etype);
9959   bstr = SPEC_BSTR (etype);
9960
9961   /* If the bitfield length is less than a byte */
9962   if (blen < 8)
9963     {
9964       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9965               (unsigned char) (0xFF >> (8 - bstr)));
9966
9967       if (AOP_TYPE (right) == AOP_LIT)
9968         {
9969           /* Case with a bitfield length <8 and literal source
9970           */
9971           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9972           litval <<= bstr;
9973           litval &= (~mask) & 0xff;
9974           emitPtrByteGet (rname, p_type, FALSE);
9975           if ((mask|litval)!=0xff)
9976             emitcode ("anl","a,#!constbyte", mask);
9977           if (litval)
9978             emitcode ("orl","a,#!constbyte", litval);
9979         }
9980       else
9981         {
9982           if ((blen==1) && (p_type!=GPOINTER))
9983             {
9984               /* Case with a bitfield length == 1 and no generic pointer
9985               */
9986               if (AOP_TYPE (right) == AOP_CRY)
9987                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9988               else
9989                 {
9990                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9991                   emitcode ("rrc","a");
9992                 }
9993               emitPtrByteGet (rname, p_type, FALSE);
9994               emitcode ("mov","acc.%d,c",bstr);
9995             }
9996           else
9997             {
9998               /* Case with a bitfield length < 8 and arbitrary source
9999               */
10000               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10001               /* shift and mask source value */
10002               AccLsh (bstr);
10003               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10004
10005               /* transfer A to B and get next byte */
10006               emitPtrByteGet (rname, p_type, TRUE);
10007
10008               emitcode ("anl", "a,#!constbyte", mask);
10009               emitcode ("orl", "a,b");
10010               if (p_type == GPOINTER)
10011                 emitcode ("pop", "b");
10012            }
10013         }
10014
10015       emitPtrByteSet (rname, p_type, "a");
10016       return;
10017     }
10018
10019   /* Bit length is greater than 7 bits. In this case, copy  */
10020   /* all except the partial byte at the end                 */
10021   for (rlen=blen;rlen>=8;rlen-=8)
10022     {
10023       emitPtrByteSet (rname, p_type, 
10024                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10025       if (rlen>8)
10026         emitcode ("inc", "%s", rname);
10027     }
10028
10029   /* If there was a partial byte at the end */
10030   if (rlen)
10031     {
10032       mask = (((unsigned char) -1 << rlen) & 0xff);
10033       
10034       if (AOP_TYPE (right) == AOP_LIT)
10035         {
10036           /* Case with partial byte and literal source
10037           */
10038           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10039           litval >>= (blen-rlen);
10040           litval &= (~mask) & 0xff;
10041           emitPtrByteGet (rname, p_type, FALSE);
10042           if ((mask|litval)!=0xff)
10043             emitcode ("anl","a,#!constbyte", mask);
10044           if (litval)
10045             emitcode ("orl","a,#!constbyte", litval);
10046         }
10047       else
10048         {
10049           /* Case with partial byte and arbitrary source
10050           */
10051           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10052           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10053
10054           /* transfer A to B and get next byte */
10055           emitPtrByteGet (rname, p_type, TRUE);
10056
10057           emitcode ("anl", "a,#!constbyte", mask);
10058           emitcode ("orl", "a,b");
10059           if (p_type == GPOINTER)
10060             emitcode ("pop", "b");
10061         }
10062       emitPtrByteSet (rname, p_type, "a");
10063     }
10064
10065 }
10066
10067
10068 /*-----------------------------------------------------------------*/
10069 /* genDataPointerSet - remat pointer to data space                 */
10070 /*-----------------------------------------------------------------*/
10071 static void
10072 genDataPointerSet (operand * right,
10073                    operand * result,
10074                    iCode * ic)
10075 {
10076   int size, offset = 0;
10077   char *l, buff[256];
10078
10079   aopOp (right, ic, FALSE, FALSE);
10080
10081   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10082   size = AOP_SIZE (right);
10083   while (size--)
10084     {
10085       if (offset)
10086         {
10087             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10088         }
10089       else
10090         {
10091             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10092         }
10093         
10094       emitcode ("mov", "%s,%s", buff,
10095                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10096     }
10097
10098   freeAsmop (right, NULL, ic, TRUE);
10099   freeAsmop (result, NULL, ic, TRUE);
10100 }
10101
10102 /*-----------------------------------------------------------------*/
10103 /* genNearPointerSet - emitcode for near pointer put                */
10104 /*-----------------------------------------------------------------*/
10105 static void
10106 genNearPointerSet (operand * right,
10107                    operand * result,
10108                    iCode * ic,
10109                    iCode * pi)
10110 {
10111   asmop *aop = NULL;
10112   char *rname, *l;
10113   sym_link *retype, *letype;
10114   sym_link *ptype = operandType (result);
10115
10116   retype = getSpec (operandType (right));
10117   letype = getSpec (ptype);
10118
10119   aopOp (result, ic, FALSE, FALSE);
10120
10121   /* if the result is rematerializable &
10122      in data space & not a bit variable */
10123   if (AOP_TYPE (result) == AOP_IMMD &&
10124       DCL_TYPE (ptype) == POINTER &&
10125       !IS_BITVAR (retype) &&
10126       !IS_BITVAR (letype))
10127     {
10128       genDataPointerSet (right, result, ic);
10129       return;
10130     }
10131
10132   /* if the value is already in a pointer register
10133      then don't need anything more */
10134   if (!AOP_INPREG (AOP (result)))
10135     {
10136       /* otherwise get a free pointer register */
10137       regs *preg;
10138         
10139       aop = newAsmop (0);
10140       preg = getFreePtr (ic, &aop, FALSE);
10141       emitcode ("mov", "%s,%s",
10142                 preg->name,
10143                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10144       rname = preg->name;
10145     }
10146   else
10147     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10148
10149   aopOp (right, ic, FALSE, FALSE);
10150
10151   /* if bitfield then unpack the bits */
10152   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10153     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10154   else
10155     {
10156       /* we have can just get the values */
10157       int size = AOP_SIZE (right);
10158       int offset = 0;
10159
10160       while (size--)
10161         {
10162           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10163           if (*l == '@')
10164             {
10165               MOVA (l);
10166               emitcode ("mov", "@%s,a", rname);
10167             }
10168           else
10169             emitcode ("mov", "@%s,%s", rname, l);
10170           if (size || pi)
10171             emitcode ("inc", "%s", rname);
10172           offset++;
10173         }
10174     }
10175
10176   /* now some housekeeping stuff */
10177   if (aop)
10178     {
10179       /* we had to allocate for this iCode */
10180       if (pi) aopPut (AOP (result),rname,0);
10181       freeAsmop (NULL, aop, ic, TRUE);
10182     }
10183   else
10184     {
10185       /* we did not allocate which means left
10186          already in a pointer register, then
10187          if size > 0 && this could be used again
10188          we have to point it back to where it
10189          belongs */
10190       if (AOP_SIZE (right) > 1 &&
10191           !OP_SYMBOL (result)->remat &&
10192           (OP_SYMBOL (result)->liveTo > ic->seq ||
10193            ic->depth) &&
10194           !pi)
10195         {
10196           int size = AOP_SIZE (right) - 1;
10197           while (size--)
10198             emitcode ("dec", "%s", rname);
10199         }
10200     }
10201
10202   /* done */
10203   if (pi) pi->generated = 1;
10204   freeAsmop (result, NULL, ic, TRUE);
10205   freeAsmop (right, NULL, ic, TRUE);
10206
10207
10208 }
10209
10210 /*-----------------------------------------------------------------*/
10211 /* genPagedPointerSet - emitcode for Paged pointer put             */
10212 /*-----------------------------------------------------------------*/
10213 static void
10214 genPagedPointerSet (operand * right,
10215                     operand * result,
10216                     iCode * ic,
10217                     iCode *pi)
10218 {
10219   asmop *aop = NULL;
10220   char *rname;
10221   sym_link *retype, *letype;
10222
10223   retype = getSpec (operandType (right));
10224   letype = getSpec (operandType (result));
10225
10226   aopOp (result, ic, FALSE, FALSE);
10227
10228   /* if the value is already in a pointer register
10229      then don't need anything more */
10230   if (!AOP_INPREG (AOP (result)))
10231     {
10232       /* otherwise get a free pointer register */
10233       regs *preg;
10234         
10235       aop = newAsmop (0);
10236       preg = getFreePtr (ic, &aop, FALSE);
10237       emitcode ("mov", "%s,%s",
10238                 preg->name,
10239                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10240       rname = preg->name;
10241     }
10242   else
10243     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10244
10245   aopOp (right, ic, FALSE, FALSE);
10246
10247   /* if bitfield then unpack the bits */
10248   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10249     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10250   else
10251     {
10252       /* we have can just get the values */
10253       int size = AOP_SIZE (right);
10254       int offset = 0;
10255
10256       while (size--)
10257         {
10258           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10259
10260           emitcode ("movx", "@%s,a", rname);
10261
10262           if (size || pi)
10263             emitcode ("inc", "%s", rname);
10264
10265           offset++;
10266         }
10267     }
10268
10269   /* now some housekeeping stuff */
10270   if (aop)
10271     {
10272       if (pi) aopPut (AOP (result),rname,0);
10273       /* we had to allocate for this iCode */
10274       freeAsmop (NULL, aop, ic, TRUE);
10275     }
10276   else
10277     {
10278       /* we did not allocate which means left
10279          already in a pointer register, then
10280          if size > 0 && this could be used again
10281          we have to point it back to where it
10282          belongs */
10283       if (AOP_SIZE (right) > 1 &&
10284           !OP_SYMBOL (result)->remat &&
10285           (OP_SYMBOL (result)->liveTo > ic->seq ||
10286            ic->depth) &&
10287           !pi)
10288         {
10289           int size = AOP_SIZE (right) - 1;
10290           while (size--)
10291             emitcode ("dec", "%s", rname);
10292         }
10293     }
10294
10295   /* done */
10296   if (pi) pi->generated = 1;
10297   freeAsmop (result, NULL, ic, TRUE);
10298   freeAsmop (right, NULL, ic, TRUE);
10299
10300
10301 }
10302
10303 /*-----------------------------------------------------------------*/
10304 /* genFarPointerSet - set value from far space                     */
10305 /*-----------------------------------------------------------------*/
10306 static void
10307 genFarPointerSet (operand * right,
10308                   operand * result, iCode * ic, iCode *pi)
10309 {
10310   int size, offset, dopi=1;
10311   sym_link *retype = getSpec (operandType (right));
10312   sym_link *letype = getSpec (operandType (result));
10313
10314   aopOp (result, ic, FALSE, FALSE);
10315
10316   /* if the operand is already in dptr
10317      then we do nothing else we move the value to dptr */
10318   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10319     {
10320       /* if this is remateriazable */
10321       if (AOP_TYPE (result) == AOP_IMMD)
10322         emitcode ("mov", "dptr,%s", 
10323                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10324       else
10325         {
10326           /* we need to get it byte by byte */
10327           _startLazyDPSEvaluation ();
10328           if (AOP_TYPE (result) != AOP_DPTR)
10329             {
10330               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10331               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10332               if (options.model == MODEL_FLAT24)
10333                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10334             }
10335           else
10336             {
10337               /* We need to generate a load to DPTR indirect through DPTR. */
10338               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10339                 
10340               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10341               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10342               if (options.model == MODEL_FLAT24)
10343                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10344               emitcode ("pop", "dph");
10345               emitcode ("pop", "dpl");
10346               dopi=0;
10347             }
10348           _endLazyDPSEvaluation ();
10349         }
10350     }
10351   /* so dptr know contains the address */
10352   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10353
10354   /* if bit then unpack */
10355   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10356       if (AOP_INDPTRn(result)) {
10357           genSetDPTR(AOP(result)->aopu.dptr);
10358       }
10359       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10360       if (AOP_INDPTRn(result)) {
10361           genSetDPTR(0);
10362       }
10363   } else {
10364       size = AOP_SIZE (right);
10365       offset = 0;
10366       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10367           while (size--) {
10368               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10369               
10370               genSetDPTR(AOP(result)->aopu.dptr);
10371               emitcode ("movx", "@dptr,a");
10372               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10373                   emitcode ("inc", "dptr");
10374               genSetDPTR (0);
10375           }
10376       } else {
10377           _startLazyDPSEvaluation ();
10378           while (size--) {
10379               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10380               
10381               if (AOP_INDPTRn(result)) {
10382                   genSetDPTR(AOP(result)->aopu.dptr);
10383               } else {
10384                   genSetDPTR (0);
10385               }
10386               _flushLazyDPS ();
10387               
10388               emitcode ("movx", "@dptr,a");
10389               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10390                   emitcode ("inc", "dptr");
10391           }
10392           _endLazyDPSEvaluation ();
10393       }
10394   }
10395   
10396   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10397       if (!AOP_INDPTRn(result)) {
10398           _startLazyDPSEvaluation ();
10399           
10400           aopPut (AOP(result),"dpl",0);
10401           aopPut (AOP(result),"dph",1);
10402           if (options.model == MODEL_FLAT24)
10403               aopPut (AOP(result),"dpx",2);
10404
10405           _endLazyDPSEvaluation ();
10406       }
10407       pi->generated=1;
10408   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10409              AOP_SIZE(right) > 1 &&
10410              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10411       
10412       size = AOP_SIZE (right) - 1;
10413       if (AOP_INDPTRn(result)) {
10414           genSetDPTR(AOP(result)->aopu.dptr);
10415       } 
10416       while (size--) emitcode ("lcall","__decdptr");
10417       if (AOP_INDPTRn(result)) {
10418           genSetDPTR(0);
10419       }
10420   }
10421   freeAsmop (result, NULL, ic, TRUE);
10422   freeAsmop (right, NULL, ic, TRUE);
10423 }
10424
10425 /*-----------------------------------------------------------------*/
10426 /* genGenPointerSet - set value from generic pointer space         */
10427 /*-----------------------------------------------------------------*/
10428 static void
10429 genGenPointerSet (operand * right,
10430                   operand * result, iCode * ic, iCode *pi)
10431 {
10432   int size, offset;
10433   sym_link *retype = getSpec (operandType (right));
10434   sym_link *letype = getSpec (operandType (result));
10435
10436   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10437
10438   /* if the operand is already in dptr
10439      then we do nothing else we move the value to dptr */
10440   if (AOP_TYPE (result) != AOP_STR)
10441     {
10442       _startLazyDPSEvaluation ();
10443       /* if this is remateriazable */
10444       if (AOP_TYPE (result) == AOP_IMMD)
10445         {
10446           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10447           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10448           {
10449               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10450           }
10451           else
10452           {
10453               emitcode ("mov", 
10454                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10455           }
10456         }
10457       else
10458         {                       /* we need to get it byte by byte */
10459           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10460           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10461           if (options.model == MODEL_FLAT24) {
10462             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10463             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10464           } else {
10465             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10466           }
10467         }
10468       _endLazyDPSEvaluation ();
10469     }
10470   /* so dptr + b now contains the address */
10471   _G.bInUse++;
10472   aopOp (right, ic, FALSE, TRUE);
10473   _G.bInUse--;
10474     
10475
10476   /* if bit then unpack */
10477   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10478     {
10479         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10480     }
10481   else
10482     {
10483         size = AOP_SIZE (right);
10484         offset = 0;
10485
10486         _startLazyDPSEvaluation ();
10487         while (size--)
10488         {
10489             if (size)
10490             {
10491                 // Set two bytes at a time, passed in _AP & A.
10492                 // dptr will be incremented ONCE by __gptrputWord.
10493                 //
10494                 // Note: any change here must be coordinated
10495                 // with the implementation of __gptrputWord
10496                 // in device/lib/_gptrput.c
10497                 emitcode("mov", "_ap, %s", 
10498                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10499                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10500                 
10501                 genSetDPTR (0);
10502                 _flushLazyDPS ();
10503                 emitcode ("lcall", "__gptrputWord");
10504                 size--;
10505             }
10506             else
10507             {
10508                 // Only one byte to put.
10509                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10510
10511                 genSetDPTR (0);
10512                 _flushLazyDPS ();               
10513                 emitcode ("lcall", "__gptrput");
10514             }
10515             
10516             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10517             {
10518                 emitcode ("inc", "dptr");
10519             }
10520         }
10521         _endLazyDPSEvaluation ();
10522     }
10523
10524   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10525       _startLazyDPSEvaluation ();
10526       
10527       aopPut (AOP(result),"dpl",0);
10528       aopPut (AOP(result),"dph",1);
10529       if (options.model == MODEL_FLAT24) {
10530           aopPut (AOP(result),"dpx",2);
10531           aopPut (AOP(result),"b",3);
10532       } else {
10533           aopPut (AOP(result),"b",2);
10534       }
10535       _endLazyDPSEvaluation ();
10536       
10537       pi->generated=1;
10538   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10539              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10540       
10541       size = AOP_SIZE (right) - 1;
10542       while (size--) emitcode ("lcall","__decdptr");
10543   }
10544   freeAsmop (result, NULL, ic, TRUE);
10545   freeAsmop (right, NULL, ic, TRUE);
10546 }
10547
10548 /*-----------------------------------------------------------------*/
10549 /* genPointerSet - stores the value into a pointer location        */
10550 /*-----------------------------------------------------------------*/
10551 static void
10552 genPointerSet (iCode * ic, iCode *pi)
10553 {
10554   operand *right, *result;
10555   sym_link *type, *etype;
10556   int p_type;
10557
10558   D (emitcode (";", "genPointerSet "););
10559
10560   right = IC_RIGHT (ic);
10561   result = IC_RESULT (ic);
10562
10563   /* depending on the type of pointer we need to
10564      move it to the correct pointer register */
10565   type = operandType (result);
10566   etype = getSpec (type);
10567   /* if left is of type of pointer then it is simple */
10568   if (IS_PTR (type) && !IS_FUNC (type->next))
10569     {
10570       p_type = DCL_TYPE (type);
10571     }
10572   else
10573     {
10574       /* we have to go by the storage class */
10575       p_type = PTR_TYPE (SPEC_OCLS (etype));
10576     }
10577   /* special case when cast remat */
10578   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10579       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10580           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10581           type = operandType (result);
10582           p_type = DCL_TYPE (type);
10583   }
10584
10585   /* now that we have the pointer type we assign
10586      the pointer values */
10587   switch (p_type)
10588     {
10589
10590     case POINTER:
10591     case IPOINTER:
10592       genNearPointerSet (right, result, ic, pi);
10593       break;
10594
10595     case PPOINTER:
10596       genPagedPointerSet (right, result, ic, pi);
10597       break;
10598
10599     case FPOINTER:
10600       genFarPointerSet (right, result, ic, pi);
10601       break;
10602
10603     case GPOINTER:
10604       genGenPointerSet (right, result, ic, pi);
10605       break;
10606
10607     default:
10608       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10609               "genPointerSet: illegal pointer type");
10610     }
10611
10612 }
10613
10614 /*-----------------------------------------------------------------*/
10615 /* genIfx - generate code for Ifx statement                        */
10616 /*-----------------------------------------------------------------*/
10617 static void
10618 genIfx (iCode * ic, iCode * popIc)
10619 {
10620   operand *cond = IC_COND (ic);
10621   int isbit = 0;
10622
10623   D (emitcode (";", "genIfx "););
10624
10625   aopOp (cond, ic, FALSE, FALSE);
10626
10627   /* get the value into acc */
10628   if (AOP_TYPE (cond) != AOP_CRY)
10629     {
10630         toBoolean (cond);
10631     }
10632   else
10633     {
10634         isbit = 1;
10635     }
10636     
10637   /* the result is now in the accumulator */
10638   freeAsmop (cond, NULL, ic, TRUE);
10639
10640   /* if there was something to be popped then do it */
10641   if (popIc)
10642     genIpop (popIc);
10643
10644   /* if the condition is  a bit variable */
10645   if (isbit && IS_ITEMP (cond) &&
10646       SPIL_LOC (cond))
10647     {
10648         genIfxJump (ic, SPIL_LOC (cond)->rname);
10649     }
10650   else if (isbit && !IS_ITEMP (cond))
10651     {
10652         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10653     }
10654   else
10655     {
10656         genIfxJump (ic, "a");
10657     }
10658
10659   ic->generated = 1;
10660 }
10661
10662 /*-----------------------------------------------------------------*/
10663 /* genAddrOf - generates code for address of                       */
10664 /*-----------------------------------------------------------------*/
10665 static void
10666 genAddrOf (iCode * ic)
10667 {
10668   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10669   int size, offset;
10670
10671   D (emitcode (";", "genAddrOf ");
10672     );
10673
10674   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10675
10676   /* if the operand is on the stack then we
10677      need to get the stack offset of this
10678      variable */
10679   if (sym->onStack) {
10680       
10681       /* if 10 bit stack */
10682       if (options.stack10bit) {
10683           char buff[10];
10684           int  offset;
10685           
10686           tsprintf(buff, sizeof(buff), 
10687                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10688           /* if it has an offset then we need to compute it */
10689 /*        emitcode ("subb", "a,#!constbyte", */
10690 /*                  -((sym->stack < 0) ? */
10691 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10692 /*                    ((short) sym->stack)) & 0xff); */
10693 /*        emitcode ("mov","b,a"); */
10694 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10695 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10696 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10697           if (sym->stack) {
10698               emitcode ("mov", "a,_bpx");
10699               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10700                                              ((char) (sym->stack - _G.nRegsSaved)) :
10701                                              ((char) sym->stack )) & 0xff);
10702               emitcode ("mov", "b,a");
10703               emitcode ("mov", "a,_bpx+1");
10704               
10705               offset = (((sym->stack < 0) ? 
10706                          ((short) (sym->stack - _G.nRegsSaved)) :
10707                          ((short) sym->stack )) >> 8) & 0xff;
10708           
10709               emitcode ("addc","a,#!constbyte", offset);
10710
10711               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10712               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10713               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10714           } else {
10715               /* we can just move _bp */
10716               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10717               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10718               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10719           }       
10720       } else {
10721           /* if it has an offset then we need to compute it */
10722           if (sym->stack) {
10723               emitcode ("mov", "a,_bp");
10724               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10725               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10726           } else {
10727               /* we can just move _bp */
10728               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10729           }
10730           /* fill the result with zero */
10731           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10732           
10733           
10734           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10735               fprintf (stderr,
10736                        "*** warning: pointer to stack var truncated.\n");
10737           }
10738
10739           offset = 1;
10740           while (size--) {
10741               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10742           }      
10743       }
10744       goto release;
10745   }
10746
10747   /* object not on stack then we need the name */
10748   size = AOP_SIZE (IC_RESULT (ic));
10749   offset = 0;
10750
10751   while (size--)
10752     {
10753       char s[SDCC_NAME_MAX];
10754       if (offset) {
10755           switch (offset) {
10756           case 1:
10757               tsprintf(s, sizeof(s), "#!his",sym->rname);
10758               break;
10759           case 2:
10760               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10761               break;
10762           case 3:
10763               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10764               break;
10765           default: /* should not need this (just in case) */
10766               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10767                        sym->rname,
10768                        offset * 8);
10769           }
10770       } 
10771       else
10772       {
10773           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10774       }
10775         
10776       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10777     }
10778
10779 release:
10780   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10781
10782 }
10783
10784 #if 0 // obsolete, and buggy for != xdata
10785 /*-----------------------------------------------------------------*/
10786 /* genArrayInit - generates code for address of                       */
10787 /*-----------------------------------------------------------------*/
10788 static void
10789 genArrayInit (iCode * ic)
10790 {
10791     literalList *iLoop;
10792     int         ix, count;
10793     int         elementSize = 0, eIndex;
10794     unsigned    val, lastVal;
10795     sym_link    *type;
10796     operand     *left=IC_LEFT(ic);
10797     
10798     D (emitcode (";", "genArrayInit "););
10799
10800     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10801     
10802     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10803     {
10804         // Load immediate value into DPTR.
10805         emitcode("mov", "dptr, %s",
10806              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10807     }
10808     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10809     {
10810 #if 0
10811       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10812               "Unexpected operand to genArrayInit.\n");
10813       exit(1);
10814 #else
10815       // a regression because of SDCCcse.c:1.52
10816       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10817       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10818       if (options.model == MODEL_FLAT24)
10819         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10820 #endif
10821     }
10822     
10823     type = operandType(IC_LEFT(ic));
10824     
10825     if (type && type->next)
10826     {
10827         elementSize = getSize(type->next);
10828     }
10829     else
10830     {
10831         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10832                                 "can't determine element size in genArrayInit.\n");
10833         exit(1);
10834     }
10835     
10836     iLoop = IC_ARRAYILIST(ic);
10837     lastVal = 0xffff;
10838     
10839     while (iLoop)
10840     {
10841         bool firstpass = TRUE;
10842         
10843         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10844                  iLoop->count, (int)iLoop->literalValue, elementSize);
10845         
10846         ix = iLoop->count;
10847         
10848         while (ix)
10849         {
10850             symbol *tlbl = NULL;
10851             
10852             count = ix > 256 ? 256 : ix;
10853             
10854             if (count > 1)
10855             {
10856                 tlbl = newiTempLabel (NULL);
10857                 if (firstpass || (count & 0xff))
10858                 {
10859                     emitcode("mov", "b, #!constbyte", count & 0xff);
10860                 }
10861                 
10862                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10863             }
10864             
10865             firstpass = FALSE;
10866                 
10867             for (eIndex = 0; eIndex < elementSize; eIndex++)
10868             {
10869                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10870                 if (val != lastVal)
10871                 {
10872                     emitcode("mov", "a, #!constbyte", val);
10873                     lastVal = val;
10874                 }
10875                 
10876                 emitcode("movx", "@dptr, a");
10877                 emitcode("inc", "dptr");
10878             }
10879             
10880             if (count > 1)
10881             {
10882                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10883             }
10884             
10885             ix -= count;
10886         }
10887         
10888         iLoop = iLoop->next;
10889     }
10890     
10891     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10892 }
10893 #endif
10894
10895 /*-----------------------------------------------------------------*/
10896 /* genFarFarAssign - assignment when both are in far space         */
10897 /*-----------------------------------------------------------------*/
10898 static void
10899 genFarFarAssign (operand * result, operand * right, iCode * ic)
10900 {
10901   int size = AOP_SIZE (right);
10902   int offset = 0;
10903   symbol *rSym = NULL;
10904
10905   if (size == 1)
10906   {
10907       /* quick & easy case. */
10908       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10909       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10910       freeAsmop (right, NULL, ic, FALSE);
10911       /* now assign DPTR to result */
10912       _G.accInUse++;
10913       aopOp(result, ic, FALSE, FALSE);
10914       _G.accInUse--;
10915       aopPut(AOP(result), "a", 0);
10916       freeAsmop(result, NULL, ic, FALSE);
10917       return;
10918   }
10919   
10920   /* See if we've got an underlying symbol to abuse. */
10921   if (IS_SYMOP(result) && OP_SYMBOL(result))
10922   {
10923       if (IS_TRUE_SYMOP(result))
10924       {
10925           rSym = OP_SYMBOL(result);
10926       }
10927       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10928       {
10929           rSym = OP_SYMBOL(result)->usl.spillLoc;
10930       }
10931   }
10932              
10933   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10934   {
10935       /* We can use the '390 auto-toggle feature to good effect here. */
10936       
10937       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10938       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10939       emitcode ("mov", "dptr,#%s", rSym->rname); 
10940       /* DP2 = result, DP1 = right, DP1 is current. */
10941       while (size)
10942       {
10943           emitcode("movx", "a,@dptr");
10944           emitcode("movx", "@dptr,a");
10945           if (--size)
10946           {
10947                emitcode("inc", "dptr");
10948                emitcode("inc", "dptr");
10949           }
10950       }
10951       emitcode("mov", "dps,#0");
10952       freeAsmop (right, NULL, ic, FALSE);
10953 #if 0
10954 some alternative code for processors without auto-toggle
10955 no time to test now, so later well put in...kpb
10956         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10957         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10958         emitcode ("mov", "dptr,#%s", rSym->rname); 
10959         /* DP2 = result, DP1 = right, DP1 is current. */
10960         while (size)
10961         {
10962           --size;
10963           emitcode("movx", "a,@dptr");
10964           if (size)
10965             emitcode("inc", "dptr");
10966           emitcode("inc", "dps");
10967           emitcode("movx", "@dptr,a");
10968           if (size)
10969             emitcode("inc", "dptr");
10970           emitcode("inc", "dps");
10971         }
10972         emitcode("mov", "dps,#0");
10973         freeAsmop (right, NULL, ic, FALSE);
10974 #endif
10975   }
10976   else
10977   {
10978       D (emitcode (";", "genFarFarAssign"););
10979       aopOp (result, ic, TRUE, TRUE);
10980
10981       _startLazyDPSEvaluation ();
10982       
10983       while (size--)
10984         {
10985           aopPut (AOP (result),
10986                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10987           offset++;
10988         }
10989       _endLazyDPSEvaluation ();
10990       freeAsmop (result, NULL, ic, FALSE);
10991       freeAsmop (right, NULL, ic, FALSE);
10992   }
10993 }
10994
10995 /*-----------------------------------------------------------------*/
10996 /* genAssign - generate code for assignment                        */
10997 /*-----------------------------------------------------------------*/
10998 static void
10999 genAssign (iCode * ic)
11000 {
11001   operand *result, *right;
11002   int size, offset;
11003   unsigned long lit = 0L;
11004
11005   D (emitcode (";", "genAssign ");
11006     );
11007
11008   result = IC_RESULT (ic);
11009   right = IC_RIGHT (ic);
11010
11011   /* if they are the same */
11012   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11013     return;
11014
11015   aopOp (right, ic, FALSE, FALSE);
11016
11017   emitcode (";", "genAssign: resultIsFar = %s",
11018             isOperandInFarSpace (result) ?
11019             "TRUE" : "FALSE");
11020
11021   /* special case both in far space */
11022   if ((AOP_TYPE (right) == AOP_DPTR ||
11023        AOP_TYPE (right) == AOP_DPTR2) &&
11024   /* IS_TRUE_SYMOP(result)       && */
11025       isOperandInFarSpace (result))
11026     {
11027       genFarFarAssign (result, right, ic);
11028       return;
11029     }
11030
11031   aopOp (result, ic, TRUE, FALSE);
11032
11033   /* if they are the same registers */
11034   if (sameRegs (AOP (right), AOP (result)))
11035     goto release;
11036
11037   /* if the result is a bit */
11038   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11039     {
11040       /* if the right size is a literal then
11041          we know what the value is */
11042       if (AOP_TYPE (right) == AOP_LIT)
11043         {
11044           if (((int) operandLitValue (right)))
11045             aopPut (AOP (result), one, 0);
11046           else
11047             aopPut (AOP (result), zero, 0);
11048           goto release;
11049         }
11050
11051       /* the right is also a bit variable */
11052       if (AOP_TYPE (right) == AOP_CRY)
11053         {
11054           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11055           aopPut (AOP (result), "c", 0);
11056           goto release;
11057         }
11058
11059       /* we need to or */
11060       toBoolean (right);
11061       aopPut (AOP (result), "a", 0);
11062       goto release;
11063     }
11064
11065   /* bit variables done */
11066   /* general case */
11067   size = AOP_SIZE (result);
11068   offset = 0;
11069   if (AOP_TYPE (right) == AOP_LIT)
11070     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11071
11072   if ((size > 1) &&
11073       (AOP_TYPE (result) != AOP_REG) &&
11074       (AOP_TYPE (right) == AOP_LIT) &&
11075       !IS_FLOAT (operandType (right)))
11076     {
11077       _startLazyDPSEvaluation ();
11078       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11079         {
11080           aopPut (AOP (result),
11081                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11082                   offset);
11083           offset++;
11084           size--;
11085         }
11086       /* And now fill the rest with zeros. */
11087       if (size)
11088         {
11089           emitcode ("clr", "a");
11090         }
11091       while (size--)
11092         {
11093           aopPut (AOP (result), "a", offset++);
11094         }
11095       _endLazyDPSEvaluation ();
11096     }
11097   else
11098     {
11099       _startLazyDPSEvaluation ();
11100       while (size--)
11101         {
11102           aopPut (AOP (result),
11103                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11104                   offset);
11105           offset++;
11106         }
11107       _endLazyDPSEvaluation ();
11108     }
11109
11110 release:
11111   freeAsmop (right, NULL, ic, FALSE);
11112   freeAsmop (result, NULL, ic, TRUE);
11113 }
11114
11115 /*-----------------------------------------------------------------*/
11116 /* genJumpTab - generates code for jump table                      */
11117 /*-----------------------------------------------------------------*/
11118 static void
11119 genJumpTab (iCode * ic)
11120 {
11121   symbol *jtab;
11122   char *l;
11123
11124   D (emitcode (";", "genJumpTab ");
11125     );
11126
11127   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11128   /* get the condition into accumulator */
11129   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11130   MOVA (l);
11131   /* multiply by four! */
11132   emitcode ("add", "a,acc");
11133   emitcode ("add", "a,acc");
11134   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11135
11136   jtab = newiTempLabel (NULL);
11137   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11138   emitcode ("jmp", "@a+dptr");
11139   emitcode ("", "!tlabeldef", jtab->key + 100);
11140   /* now generate the jump labels */
11141   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11142        jtab = setNextItem (IC_JTLABELS (ic)))
11143     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11144
11145 }
11146
11147 /*-----------------------------------------------------------------*/
11148 /* genCast - gen code for casting                                  */
11149 /*-----------------------------------------------------------------*/
11150 static void
11151 genCast (iCode * ic)
11152 {
11153   operand *result = IC_RESULT (ic);
11154   sym_link *ctype = operandType (IC_LEFT (ic));
11155   sym_link *rtype = operandType (IC_RIGHT (ic));
11156   operand *right = IC_RIGHT (ic);
11157   int size, offset;
11158
11159   D (emitcode (";", "genCast "););
11160
11161   /* if they are equivalent then do nothing */
11162   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11163     return;
11164
11165   aopOp (right, ic, FALSE, FALSE);
11166   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11167
11168   /* if the result is a bit */
11169   if (IS_BITVAR (OP_SYMBOL (result)->type)
11170       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11171     {
11172       /* if the right size is a literal then
11173          we know what the value is */
11174       if (AOP_TYPE (right) == AOP_LIT)
11175         {
11176           if (((int) operandLitValue (right)))
11177             aopPut (AOP (result), one, 0);
11178           else
11179             aopPut (AOP (result), zero, 0);
11180
11181           goto release;
11182         }
11183
11184       /* the right is also a bit variable */
11185       if (AOP_TYPE (right) == AOP_CRY)
11186         {
11187           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11188           aopPut (AOP (result), "c", 0);
11189           goto release;
11190         }
11191
11192       /* we need to or */
11193       toBoolean (right);
11194       aopPut (AOP (result), "a", 0);
11195       goto release;
11196     }
11197
11198   /* if they are the same size : or less */
11199   if (AOP_SIZE (result) <= AOP_SIZE (right))
11200     {
11201
11202       /* if they are in the same place */
11203       if (sameRegs (AOP (right), AOP (result)))
11204         goto release;
11205
11206       /* if they in different places then copy */
11207       size = AOP_SIZE (result);
11208       offset = 0;
11209       _startLazyDPSEvaluation ();
11210       while (size--)
11211         {
11212           aopPut (AOP (result),
11213                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11214                   offset);
11215           offset++;
11216         }
11217       _endLazyDPSEvaluation ();
11218       goto release;
11219     }
11220
11221
11222   /* if the result is of type pointer */
11223   if (IS_PTR (ctype))
11224     {
11225
11226       int p_type;
11227       sym_link *type = operandType (right);
11228
11229       /* pointer to generic pointer */
11230       if (IS_GENPTR (ctype))
11231         {
11232           if (IS_PTR (type))
11233             {
11234               p_type = DCL_TYPE (type);
11235             }
11236           else
11237             {
11238 #if OLD_CAST_BEHAVIOR
11239               /* KV: we are converting a non-pointer type to
11240                * a generic pointer. This (ifdef'd out) code
11241                * says that the resulting generic pointer
11242                * should have the same class as the storage
11243                * location of the non-pointer variable.
11244                *
11245                * For example, converting an int (which happens
11246                * to be stored in DATA space) to a pointer results
11247                * in a DATA generic pointer; if the original int
11248                * in XDATA space, so will be the resulting pointer.
11249                *
11250                * I don't like that behavior, and thus this change:
11251                * all such conversions will be forced to XDATA and
11252                * throw a warning. If you want some non-XDATA
11253                * type, or you want to suppress the warning, you
11254                * must go through an intermediate cast, like so:
11255                *
11256                * char _generic *gp = (char _xdata *)(intVar);
11257                */
11258               sym_link *etype = getSpec (type);
11259
11260               /* we have to go by the storage class */
11261               if (SPEC_OCLS (etype) != generic)
11262                 {
11263                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11264                 }
11265               else
11266 #endif
11267                 {
11268                   /* Converting unknown class (i.e. register variable)
11269                    * to generic pointer. This is not good, but
11270                    * we'll make a guess (and throw a warning).
11271                    */
11272                   p_type = FPOINTER;
11273                   werror (W_INT_TO_GEN_PTR_CAST);
11274                 }
11275             }
11276
11277           /* the first two bytes are known */
11278           size = GPTRSIZE - 1;
11279           offset = 0;
11280           _startLazyDPSEvaluation ();
11281           while (size--)
11282             {
11283               aopPut (AOP (result),
11284                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11285                       offset);
11286               offset++;
11287             }
11288           _endLazyDPSEvaluation ();
11289
11290           /* the last byte depending on type */
11291             {
11292                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11293                 char gpValStr[10];
11294             
11295                 if (gpVal == -1)
11296                 {
11297                     // pointerTypeToGPByte will have bitched.
11298                     exit(1);
11299                 }
11300             
11301                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11302                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11303             }
11304           goto release;
11305         }
11306
11307       /* just copy the pointers */
11308       size = AOP_SIZE (result);
11309       offset = 0;
11310       _startLazyDPSEvaluation ();
11311       while (size--)
11312         {
11313           aopPut (AOP (result),
11314                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11315                   offset);
11316           offset++;
11317         }
11318       _endLazyDPSEvaluation ();
11319       goto release;
11320     }
11321
11322   /* so we now know that the size of destination is greater
11323      than the size of the source */
11324   /* we move to result for the size of source */
11325   size = AOP_SIZE (right);
11326   offset = 0;
11327   _startLazyDPSEvaluation ();
11328   while (size--)
11329     {
11330       aopPut (AOP (result),
11331               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11332               offset);
11333       offset++;
11334     }
11335   _endLazyDPSEvaluation ();
11336
11337   /* now depending on the sign of the source && destination */
11338   size = AOP_SIZE (result) - AOP_SIZE (right);
11339   /* if unsigned or not an integral type */
11340   /* also, if the source is a bit, we don't need to sign extend, because
11341    * it can't possibly have set the sign bit.
11342    */
11343   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11344     {
11345       while (size--)
11346         {
11347           aopPut (AOP (result), zero, offset++);
11348         }
11349     }
11350   else
11351     {
11352       /* we need to extend the sign :{ */
11353       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11354                         FALSE, FALSE, NULL));
11355       emitcode ("rlc", "a");
11356       emitcode ("subb", "a,acc");
11357       while (size--)
11358         aopPut (AOP (result), "a", offset++);
11359     }
11360
11361   /* we are done hurray !!!! */
11362
11363 release:
11364   freeAsmop (right, NULL, ic, TRUE);
11365   freeAsmop (result, NULL, ic, TRUE);
11366
11367 }
11368
11369 /*-----------------------------------------------------------------*/
11370 /* genDjnz - generate decrement & jump if not zero instrucion      */
11371 /*-----------------------------------------------------------------*/
11372 static int
11373 genDjnz (iCode * ic, iCode * ifx)
11374 {
11375   symbol *lbl, *lbl1;
11376   if (!ifx)
11377     return 0;
11378
11379   /* if the if condition has a false label
11380      then we cannot save */
11381   if (IC_FALSE (ifx))
11382     return 0;
11383
11384   /* if the minus is not of the form
11385      a = a - 1 */
11386   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11387       !IS_OP_LITERAL (IC_RIGHT (ic)))
11388     return 0;
11389
11390   if (operandLitValue (IC_RIGHT (ic)) != 1)
11391     return 0;
11392
11393   /* if the size of this greater than one then no
11394      saving */
11395   if (getSize (operandType (IC_RESULT (ic))) > 1)
11396     return 0;
11397
11398   /* otherwise we can save BIG */
11399   D(emitcode(";", "genDjnz"););
11400
11401   lbl = newiTempLabel (NULL);
11402   lbl1 = newiTempLabel (NULL);
11403
11404   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11405
11406   if (AOP_NEEDSACC(IC_RESULT(ic)))
11407   {
11408       /* If the result is accessed indirectly via
11409        * the accumulator, we must explicitly write
11410        * it back after the decrement.
11411        */
11412       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11413       
11414       if (strcmp(rByte, "a"))
11415       {
11416            /* Something is hopelessly wrong */
11417            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11418                    __FILE__, __LINE__);
11419            /* We can just give up; the generated code will be inefficient,
11420             * but what the hey.
11421             */
11422            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11423            return 0;
11424       }
11425       emitcode ("dec", "%s", rByte);
11426       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11427       emitcode ("jnz", "!tlabel", lbl->key + 100);
11428   }
11429   else if (IS_AOP_PREG (IC_RESULT (ic)))
11430     {
11431       emitcode ("dec", "%s",
11432                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11433       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11434       emitcode ("jnz", "!tlabel", lbl->key + 100);
11435     }
11436   else
11437     {
11438       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11439                 lbl->key + 100);
11440     }
11441   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11442   emitcode ("", "!tlabeldef", lbl->key + 100);
11443   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11444   emitcode ("", "!tlabeldef", lbl1->key + 100);
11445
11446   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11447   ifx->generated = 1;
11448   return 1;
11449 }
11450
11451 /*-----------------------------------------------------------------*/
11452 /* genReceive - generate code for a receive iCode                  */
11453 /*-----------------------------------------------------------------*/
11454 static void
11455 genReceive (iCode * ic)
11456 {
11457     int size = getSize (operandType (IC_RESULT (ic)));
11458     int offset = 0;
11459     int rb1off ;
11460     
11461     D (emitcode (";", "genReceive "););
11462
11463     if (ic->argreg == 1) 
11464     {
11465         /* first parameter */
11466         if (AOP_IS_STR(IC_RESULT(ic)))
11467         {
11468             /* Nothing to do: it's already in the proper place. */
11469             return;
11470         }
11471         else
11472         {
11473             bool useDp2;
11474             
11475             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11476                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11477                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11478             
11479             _G.accInUse++;
11480             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11481             _G.accInUse--; 
11482             
11483             /* Sanity checking... */
11484             if (AOP_USESDPTR(IC_RESULT(ic)))
11485             {
11486                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11487                         "genReceive got unexpected DPTR.");
11488             }
11489             assignResultValue (IC_RESULT (ic));
11490         }
11491     } 
11492     else 
11493     { 
11494         /* second receive onwards */
11495         /* this gets a little tricky since unused recevies will be
11496          eliminated, we have saved the reg in the type field . and
11497          we use that to figure out which register to use */
11498         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11499         rb1off = ic->argreg;
11500         while (size--) 
11501         {
11502             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11503         }
11504     }
11505     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11506 }
11507
11508 /*-----------------------------------------------------------------*/
11509 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11510 /*-----------------------------------------------------------------*/
11511 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11512 {
11513     operand *from , *to , *count;
11514     symbol *lbl;
11515     bitVect *rsave;
11516     int i;
11517
11518     /* we know it has to be 3 parameters */
11519     assert (nparms == 3);
11520     
11521     rsave = newBitVect(16);
11522     /* save DPTR if it needs to be saved */
11523     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11524             if (bitVectBitValue(ic->rMask,i))
11525                     rsave = bitVectSetBit(rsave,i);
11526     }
11527     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11528                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11529     savermask(rsave);
11530     
11531     to = parms[0];
11532     from = parms[1];
11533     count = parms[2];
11534
11535     aopOp (from, ic->next, FALSE, FALSE);
11536
11537     /* get from into DPTR1 */
11538     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11539     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11540     if (options.model == MODEL_FLAT24) {
11541         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11542     }
11543
11544     freeAsmop (from, NULL, ic, FALSE);
11545     aopOp (to, ic, FALSE, FALSE);
11546     /* get "to" into DPTR */
11547     /* if the operand is already in dptr
11548        then we do nothing else we move the value to dptr */
11549     if (AOP_TYPE (to) != AOP_STR) {
11550         /* if already in DPTR then we need to push */
11551         if (AOP_TYPE(to) == AOP_DPTR) {
11552             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11553             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11554             if (options.model == MODEL_FLAT24)
11555                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11556             emitcode ("pop", "dph");
11557             emitcode ("pop", "dpl");        
11558         } else {
11559             _startLazyDPSEvaluation ();
11560             /* if this is remateriazable */
11561             if (AOP_TYPE (to) == AOP_IMMD) {
11562                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11563             } else {                    /* we need to get it byte by byte */
11564                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11565                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11566                 if (options.model == MODEL_FLAT24) {
11567                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11568                 }
11569             }
11570             _endLazyDPSEvaluation ();
11571         }
11572     }
11573     freeAsmop (to, NULL, ic, FALSE);
11574     _G.dptrInUse = _G.dptr1InUse = 1;
11575     aopOp (count, ic->next->next, FALSE,FALSE);
11576     lbl =newiTempLabel(NULL);
11577
11578     /* now for the actual copy */
11579     if (AOP_TYPE(count) == AOP_LIT && 
11580         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11581         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11582         if (fromc) {
11583             emitcode ("lcall","__bi_memcpyc2x_s");
11584         } else {
11585             emitcode ("lcall","__bi_memcpyx2x_s");
11586         }
11587         freeAsmop (count, NULL, ic, FALSE);
11588     } else {
11589         symbol *lbl1 = newiTempLabel(NULL);
11590         
11591         emitcode (";"," Auto increment but no djnz");
11592         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11593         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11594         freeAsmop (count, NULL, ic, FALSE);
11595         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11596         emitcode ("","!tlabeldef",lbl->key+100);
11597         if (fromc) {
11598             emitcode ("clr","a");
11599             emitcode ("movc", "a,@a+dptr");
11600         } else 
11601             emitcode ("movx", "a,@dptr");
11602         emitcode ("movx", "@dptr,a");
11603         emitcode ("inc", "dptr");
11604         emitcode ("inc", "dptr");
11605         emitcode ("mov","a,b");
11606         emitcode ("orl","a,_ap");
11607         emitcode ("jz","!tlabel",lbl1->key+100);
11608         emitcode ("mov","a,_ap");
11609         emitcode ("add","a,#!constbyte",0xFF);
11610         emitcode ("mov","_ap,a");
11611         emitcode ("mov","a,b");
11612         emitcode ("addc","a,#!constbyte",0xFF);
11613         emitcode ("mov","b,a");
11614         emitcode ("sjmp","!tlabel",lbl->key+100);
11615         emitcode ("","!tlabeldef",lbl1->key+100);
11616     }
11617     emitcode ("mov", "dps,#0"); 
11618     _G.dptrInUse = _G.dptr1InUse = 0;
11619     unsavermask(rsave);
11620
11621 }
11622
11623 /*-----------------------------------------------------------------*/
11624 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11625 /*-----------------------------------------------------------------*/
11626 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11627 {
11628     operand *from , *to , *count;
11629     symbol *lbl,*lbl2;
11630     bitVect *rsave;
11631     int i;
11632
11633     /* we know it has to be 3 parameters */
11634     assert (nparms == 3);
11635     
11636     rsave = newBitVect(16);
11637     /* save DPTR if it needs to be saved */
11638     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11639             if (bitVectBitValue(ic->rMask,i))
11640                     rsave = bitVectSetBit(rsave,i);
11641     }
11642     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11643                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11644     savermask(rsave);
11645     
11646     to = parms[0];
11647     from = parms[1];
11648     count = parms[2];
11649
11650     aopOp (from, ic->next, FALSE, FALSE);
11651
11652     /* get from into DPTR1 */
11653     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11654     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11655     if (options.model == MODEL_FLAT24) {
11656         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11657     }
11658
11659     freeAsmop (from, NULL, ic, FALSE);
11660     aopOp (to, ic, FALSE, FALSE);
11661     /* get "to" into DPTR */
11662     /* if the operand is already in dptr
11663        then we do nothing else we move the value to dptr */
11664     if (AOP_TYPE (to) != AOP_STR) {
11665         /* if already in DPTR then we need to push */
11666         if (AOP_TYPE(to) == AOP_DPTR) {
11667             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11668             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11669             if (options.model == MODEL_FLAT24)
11670                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11671             emitcode ("pop", "dph");
11672             emitcode ("pop", "dpl");        
11673         } else {
11674             _startLazyDPSEvaluation ();
11675             /* if this is remateriazable */
11676             if (AOP_TYPE (to) == AOP_IMMD) {
11677                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11678             } else {                    /* we need to get it byte by byte */
11679                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11680                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11681                 if (options.model == MODEL_FLAT24) {
11682                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11683                 }
11684             }
11685             _endLazyDPSEvaluation ();
11686         }
11687     }
11688     freeAsmop (to, NULL, ic, FALSE);
11689     _G.dptrInUse = _G.dptr1InUse = 1;
11690     aopOp (count, ic->next->next, FALSE,FALSE);
11691     lbl =newiTempLabel(NULL);
11692     lbl2 =newiTempLabel(NULL);
11693
11694     /* now for the actual compare */
11695     if (AOP_TYPE(count) == AOP_LIT && 
11696         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11697         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11698         if (fromc)
11699             emitcode("lcall","__bi_memcmpc2x_s");
11700         else
11701             emitcode("lcall","__bi_memcmpx2x_s");
11702         freeAsmop (count, NULL, ic, FALSE);
11703         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11704         aopPut(AOP(IC_RESULT(ic)),"a",0);
11705         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11706     } else {
11707         symbol *lbl1 = newiTempLabel(NULL);
11708
11709         emitcode("push","ar0");         
11710         emitcode (";"," Auto increment but no djnz");
11711         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11712         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11713         freeAsmop (count, NULL, ic, FALSE);
11714         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11715         emitcode ("","!tlabeldef",lbl->key+100);
11716         if (fromc) {
11717             emitcode ("clr","a");
11718             emitcode ("movc", "a,@a+dptr");
11719         } else 
11720             emitcode ("movx", "a,@dptr");
11721         emitcode ("mov","r0,a");
11722         emitcode ("movx", "a,@dptr");
11723         emitcode ("clr","c");
11724         emitcode ("subb","a,r0");
11725         emitcode ("jnz","!tlabel",lbl2->key+100);
11726         emitcode ("inc", "dptr");
11727         emitcode ("inc", "dptr");
11728         emitcode ("mov","a,b");
11729         emitcode ("orl","a,_ap");
11730         emitcode ("jz","!tlabel",lbl1->key+100);
11731         emitcode ("mov","a,_ap");
11732         emitcode ("add","a,#!constbyte",0xFF);
11733         emitcode ("mov","_ap,a");
11734         emitcode ("mov","a,b");
11735         emitcode ("addc","a,#!constbyte",0xFF);
11736         emitcode ("mov","b,a");
11737         emitcode ("sjmp","!tlabel",lbl->key+100);
11738         emitcode ("","!tlabeldef",lbl1->key+100);
11739         emitcode ("clr","a");
11740         emitcode ("","!tlabeldef",lbl2->key+100);
11741         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11742         aopPut(AOP(IC_RESULT(ic)),"a",0);
11743         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11744         emitcode("pop","ar0");
11745         emitcode ("mov", "dps,#0");      
11746     }
11747     _G.dptrInUse = _G.dptr1InUse = 0;
11748     unsavermask(rsave);
11749
11750 }
11751
11752 /*-----------------------------------------------------------------*/
11753 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11754 /* port, first parameter output area second parameter pointer to   */
11755 /* port third parameter count                                      */
11756 /*-----------------------------------------------------------------*/
11757 static void genInp( iCode *ic, int nparms, operand **parms)
11758 {
11759     operand *from , *to , *count;
11760     symbol *lbl;
11761     bitVect *rsave;
11762     int i;
11763
11764     /* we know it has to be 3 parameters */
11765     assert (nparms == 3);
11766     
11767     rsave = newBitVect(16);
11768     /* save DPTR if it needs to be saved */
11769     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11770             if (bitVectBitValue(ic->rMask,i))
11771                     rsave = bitVectSetBit(rsave,i);
11772     }
11773     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11774                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11775     savermask(rsave);
11776     
11777     to = parms[0];
11778     from = parms[1];
11779     count = parms[2];
11780
11781     aopOp (from, ic->next, FALSE, FALSE);
11782
11783     /* get from into DPTR1 */
11784     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11785     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11786     if (options.model == MODEL_FLAT24) {
11787         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11788     }
11789
11790     freeAsmop (from, NULL, ic, FALSE);
11791     aopOp (to, ic, FALSE, FALSE);
11792     /* get "to" into DPTR */
11793     /* if the operand is already in dptr
11794        then we do nothing else we move the value to dptr */
11795     if (AOP_TYPE (to) != AOP_STR) {
11796         /* if already in DPTR then we need to push */
11797         if (AOP_TYPE(to) == AOP_DPTR) {
11798             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11799             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11800             if (options.model == MODEL_FLAT24)
11801                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11802             emitcode ("pop", "dph");
11803             emitcode ("pop", "dpl");        
11804         } else {
11805             _startLazyDPSEvaluation ();
11806             /* if this is remateriazable */
11807             if (AOP_TYPE (to) == AOP_IMMD) {
11808                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11809             } else {                    /* we need to get it byte by byte */
11810                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11811                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11812                 if (options.model == MODEL_FLAT24) {
11813                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11814                 }
11815             }
11816             _endLazyDPSEvaluation ();
11817         }
11818     }
11819     freeAsmop (to, NULL, ic, FALSE);
11820
11821     _G.dptrInUse = _G.dptr1InUse = 1;
11822     aopOp (count, ic->next->next, FALSE,FALSE);
11823     lbl =newiTempLabel(NULL);
11824
11825     /* now for the actual copy */
11826     if (AOP_TYPE(count) == AOP_LIT && 
11827         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11828         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11829         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11830         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11831         freeAsmop (count, NULL, ic, FALSE);
11832         emitcode ("","!tlabeldef",lbl->key+100);
11833         emitcode ("movx", "a,@dptr");   /* read data from port */
11834         emitcode ("dec","dps");         /* switch to DPTR */
11835         emitcode ("movx", "@dptr,a");   /* save into location */
11836         emitcode ("inc", "dptr");       /* point to next area */
11837         emitcode ("inc","dps");         /* switch to DPTR2 */
11838         emitcode ("djnz","b,!tlabel",lbl->key+100);
11839     } else {
11840         symbol *lbl1 = newiTempLabel(NULL);
11841         
11842         emitcode (";"," Auto increment but no djnz");
11843         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11844         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11845         freeAsmop (count, NULL, ic, FALSE);
11846         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11847         emitcode ("","!tlabeldef",lbl->key+100);
11848         emitcode ("movx", "a,@dptr");
11849         emitcode ("dec","dps");         /* switch to DPTR */
11850         emitcode ("movx", "@dptr,a");
11851         emitcode ("inc", "dptr");
11852         emitcode ("inc","dps");         /* switch to DPTR2 */
11853 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11854 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11855         emitcode ("mov","a,b");
11856         emitcode ("orl","a,_ap");
11857         emitcode ("jz","!tlabel",lbl1->key+100);
11858         emitcode ("mov","a,_ap");
11859         emitcode ("add","a,#!constbyte",0xFF);
11860         emitcode ("mov","_ap,a");
11861         emitcode ("mov","a,b");
11862         emitcode ("addc","a,#!constbyte",0xFF);
11863         emitcode ("mov","b,a");
11864         emitcode ("sjmp","!tlabel",lbl->key+100);
11865         emitcode ("","!tlabeldef",lbl1->key+100);
11866     }
11867     emitcode ("mov", "dps,#0"); 
11868     _G.dptrInUse = _G.dptr1InUse = 0;
11869     unsavermask(rsave);
11870
11871 }
11872
11873 /*-----------------------------------------------------------------*/
11874 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11875 /* port, first parameter output area second parameter pointer to   */
11876 /* port third parameter count                                      */
11877 /*-----------------------------------------------------------------*/
11878 static void genOutp( iCode *ic, int nparms, operand **parms)
11879 {
11880     operand *from , *to , *count;
11881     symbol *lbl;
11882     bitVect *rsave;
11883     int i;
11884
11885     /* we know it has to be 3 parameters */
11886     assert (nparms == 3);
11887     
11888     rsave = newBitVect(16);
11889     /* save DPTR if it needs to be saved */
11890     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11891             if (bitVectBitValue(ic->rMask,i))
11892                     rsave = bitVectSetBit(rsave,i);
11893     }
11894     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11895                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11896     savermask(rsave);
11897     
11898     to = parms[0];
11899     from = parms[1];
11900     count = parms[2];
11901
11902     aopOp (from, ic->next, FALSE, FALSE);
11903
11904     /* get from into DPTR1 */
11905     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11906     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11907     if (options.model == MODEL_FLAT24) {
11908         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11909     }
11910
11911     freeAsmop (from, NULL, ic, FALSE);
11912     aopOp (to, ic, FALSE, FALSE);
11913     /* get "to" into DPTR */
11914     /* if the operand is already in dptr
11915        then we do nothing else we move the value to dptr */
11916     if (AOP_TYPE (to) != AOP_STR) {
11917         /* if already in DPTR then we need to push */
11918         if (AOP_TYPE(to) == AOP_DPTR) {
11919             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11920             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11921             if (options.model == MODEL_FLAT24)
11922                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11923             emitcode ("pop", "dph");
11924             emitcode ("pop", "dpl");        
11925         } else {
11926             _startLazyDPSEvaluation ();
11927             /* if this is remateriazable */
11928             if (AOP_TYPE (to) == AOP_IMMD) {
11929                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11930             } else {                    /* we need to get it byte by byte */
11931                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11932                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11933                 if (options.model == MODEL_FLAT24) {
11934                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11935                 }
11936             }
11937             _endLazyDPSEvaluation ();
11938         }
11939     }
11940     freeAsmop (to, NULL, ic, FALSE);
11941
11942     _G.dptrInUse = _G.dptr1InUse = 1;
11943     aopOp (count, ic->next->next, FALSE,FALSE);
11944     lbl =newiTempLabel(NULL);
11945
11946     /* now for the actual copy */
11947     if (AOP_TYPE(count) == AOP_LIT && 
11948         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11950         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11951         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11952         emitcode ("","!tlabeldef",lbl->key+100);
11953         emitcode ("movx", "a,@dptr");   /* read data from port */
11954         emitcode ("inc","dps");         /* switch to DPTR2 */
11955         emitcode ("movx", "@dptr,a");   /* save into location */
11956         emitcode ("inc", "dptr");       /* point to next area */
11957         emitcode ("dec","dps");         /* switch to DPTR */
11958         emitcode ("djnz","b,!tlabel",lbl->key+100);
11959         freeAsmop (count, NULL, ic, FALSE);
11960     } else {
11961         symbol *lbl1 = newiTempLabel(NULL);
11962         
11963         emitcode (";"," Auto increment but no djnz");
11964         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11965         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11966         freeAsmop (count, NULL, ic, FALSE);
11967         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11968         emitcode ("","!tlabeldef",lbl->key+100);
11969         emitcode ("movx", "a,@dptr");
11970         emitcode ("inc", "dptr");
11971         emitcode ("inc","dps");         /* switch to DPTR2 */
11972         emitcode ("movx", "@dptr,a");
11973         emitcode ("dec","dps");         /* switch to DPTR */
11974         emitcode ("mov","a,b");
11975         emitcode ("orl","a,_ap");
11976         emitcode ("jz","!tlabel",lbl1->key+100);
11977         emitcode ("mov","a,_ap");
11978         emitcode ("add","a,#!constbyte",0xFF);
11979         emitcode ("mov","_ap,a");
11980         emitcode ("mov","a,b");
11981         emitcode ("addc","a,#!constbyte",0xFF);
11982         emitcode ("mov","b,a");
11983         emitcode ("sjmp","!tlabel",lbl->key+100);
11984         emitcode ("","!tlabeldef",lbl1->key+100);
11985     }
11986     emitcode ("mov", "dps,#0"); 
11987     _G.dptrInUse = _G.dptr1InUse = 0;
11988     unsavermask(rsave);
11989
11990 }
11991
11992 /*-----------------------------------------------------------------*/
11993 /* genSwapW - swap lower & high order bytes                        */
11994 /*-----------------------------------------------------------------*/
11995 static void genSwapW(iCode *ic, int nparms, operand **parms)
11996 {
11997     operand *dest;
11998     operand *src;
11999     assert (nparms==1);
12000
12001     src = parms[0];
12002     dest=IC_RESULT(ic);
12003
12004     assert(getSize(operandType(src))==2);
12005
12006     aopOp (src, ic, FALSE, FALSE);
12007     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12008     _G.accInUse++;
12009     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12010     _G.accInUse--;
12011     freeAsmop (src, NULL, ic, FALSE);
12012     
12013     aopOp (dest,ic, FALSE, FALSE);
12014     aopPut(AOP(dest),"b",0);
12015     aopPut(AOP(dest),"a",1);
12016     freeAsmop (dest, NULL, ic, FALSE);    
12017 }
12018
12019 /*-----------------------------------------------------------------*/
12020 /* genMemsetX - gencode for memSetX data                           */
12021 /*-----------------------------------------------------------------*/
12022 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12023 {
12024     operand *to , *val , *count;
12025     symbol *lbl;
12026     char *l;
12027     int i;
12028     bitVect *rsave;
12029
12030     /* we know it has to be 3 parameters */
12031     assert (nparms == 3);
12032     
12033     to = parms[0];
12034     val = parms[1];
12035     count = parms[2];
12036         
12037     /* save DPTR if it needs to be saved */
12038     rsave = newBitVect(16);
12039     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12040             if (bitVectBitValue(ic->rMask,i))
12041                     rsave = bitVectSetBit(rsave,i);
12042     }
12043     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12044                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12045     savermask(rsave);
12046
12047     aopOp (to, ic, FALSE, FALSE);
12048     /* get "to" into DPTR */
12049     /* if the operand is already in dptr
12050        then we do nothing else we move the value to dptr */
12051     if (AOP_TYPE (to) != AOP_STR) {
12052         /* if already in DPTR then we need to push */
12053         if (AOP_TYPE(to) == AOP_DPTR) {
12054             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12055             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12056             if (options.model == MODEL_FLAT24)
12057                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12058             emitcode ("pop", "dph");
12059             emitcode ("pop", "dpl");        
12060         } else {
12061             _startLazyDPSEvaluation ();
12062             /* if this is remateriazable */
12063             if (AOP_TYPE (to) == AOP_IMMD) {
12064                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12065             } else {                    /* we need to get it byte by byte */
12066                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12067                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12068                 if (options.model == MODEL_FLAT24) {
12069                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12070                 }
12071             }
12072             _endLazyDPSEvaluation ();
12073         }
12074     }
12075     freeAsmop (to, NULL, ic, FALSE);
12076
12077     aopOp (val, ic->next->next, FALSE,FALSE);
12078     aopOp (count, ic->next->next, FALSE,FALSE);    
12079     lbl =newiTempLabel(NULL);
12080     /* now for the actual copy */
12081     if (AOP_TYPE(count) == AOP_LIT && 
12082         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12083         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12084         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12085         MOVA(l);
12086         emitcode ("","!tlabeldef",lbl->key+100);
12087         emitcode ("movx", "@dptr,a");
12088         emitcode ("inc", "dptr");
12089         emitcode ("djnz","b,!tlabel",lbl->key+100);
12090     } else {
12091         symbol *lbl1 = newiTempLabel(NULL);
12092         
12093         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12094         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12095         emitcode ("","!tlabeldef",lbl->key+100);
12096         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12097         emitcode ("movx", "@dptr,a");
12098         emitcode ("inc", "dptr");
12099         emitcode ("mov","a,b");
12100         emitcode ("orl","a,_ap");
12101         emitcode ("jz","!tlabel",lbl1->key+100);
12102         emitcode ("mov","a,_ap");
12103         emitcode ("add","a,#!constbyte",0xFF);
12104         emitcode ("mov","_ap,a");
12105         emitcode ("mov","a,b");
12106         emitcode ("addc","a,#!constbyte",0xFF);
12107         emitcode ("mov","b,a");
12108         emitcode ("sjmp","!tlabel",lbl->key+100);
12109         emitcode ("","!tlabeldef",lbl1->key+100);
12110     }
12111     freeAsmop (count, NULL, ic, FALSE);
12112     unsavermask(rsave);
12113 }
12114
12115 /*-----------------------------------------------------------------*/
12116 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12117 /*-----------------------------------------------------------------*/
12118 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12119 {
12120         bitVect *rsave ;
12121         operand *pnum, *result;
12122         int i;
12123     
12124         assert (nparms==1);
12125         /* save registers that need to be saved */
12126         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12127                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12128     
12129         pnum = parms[0]; 
12130         aopOp (pnum, ic, FALSE, FALSE);
12131         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12132         freeAsmop (pnum, NULL, ic, FALSE);
12133         emitcode ("lcall","NatLib_LoadPrimitive");
12134         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12135         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12136             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12137                 for (i = (size-1) ; i >= 0 ; i-- ) {
12138                         emitcode ("push","a%s",javaRet[i]);
12139                 }
12140                 for (i=0; i < size ; i++ ) {
12141                         emitcode ("pop","a%s",
12142                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12143                 }
12144         } else {
12145                 for (i = 0 ; i < size ; i++ ) {
12146                         aopPut(AOP(result),javaRet[i],i);
12147                 }
12148         }    
12149         freeAsmop (result, NULL, ic, FALSE);
12150         unsavermask(rsave);
12151 }
12152
12153 /*-----------------------------------------------------------------*/
12154 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12155 /*-----------------------------------------------------------------*/
12156 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12157 {
12158         bitVect *rsave ;
12159         operand *pnum, *result;
12160         int size = 3;
12161         int i;
12162     
12163         assert (nparms==1);
12164         /* save registers that need to be saved */
12165         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12166                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12167     
12168         pnum = parms[0]; 
12169         aopOp (pnum, ic, FALSE, FALSE);
12170         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12171         freeAsmop (pnum, NULL, ic, FALSE);
12172         emitcode ("lcall","NatLib_LoadPointer");
12173         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12174         if (AOP_TYPE(result)!=AOP_STR) {
12175                 for (i = 0 ; i < size ; i++ ) {
12176                         aopPut(AOP(result),fReturn[i],i);
12177                 }
12178         }    
12179         freeAsmop (result, NULL, ic, FALSE);
12180         unsavermask(rsave);
12181 }
12182
12183 /*-----------------------------------------------------------------*/
12184 /* genNatLibInstallStateBlock -                                    */
12185 /*-----------------------------------------------------------------*/
12186 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12187                                        operand **parms, const char *name)
12188 {
12189         bitVect *rsave ;
12190         operand *psb, *handle;
12191         assert (nparms==2);
12192
12193         /* save registers that need to be saved */
12194         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12195                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12196         psb = parms[0];
12197         handle = parms[1];
12198
12199         /* put pointer to state block into DPTR1 */
12200         aopOp (psb, ic, FALSE, FALSE);
12201         if (AOP_TYPE (psb) == AOP_IMMD) {
12202                 emitcode ("mov","dps,#1");
12203                 emitcode ("mov", "dptr,%s",
12204                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12205                 emitcode ("mov","dps,#0");
12206         } else {
12207                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12208                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12209                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12210         }
12211         freeAsmop (psb, NULL, ic, FALSE);
12212
12213         /* put libraryID into DPTR */
12214         emitcode ("mov","dptr,#LibraryID");
12215
12216         /* put handle into r3:r2 */
12217         aopOp (handle, ic, FALSE, FALSE);
12218         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12219                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12220                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12221                 emitcode ("pop","ar3");
12222                 emitcode ("pop","ar2");
12223         } else {        
12224                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12225                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12226         }
12227         freeAsmop (psb, NULL, ic, FALSE);
12228
12229         /* make the call */
12230         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12231
12232         /* put return value into place*/
12233         _G.accInUse++;
12234         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12235         _G.accInUse--;
12236         aopPut(AOP(IC_RESULT(ic)),"a",0);
12237         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12238         unsavermask(rsave);
12239 }
12240
12241 /*-----------------------------------------------------------------*/
12242 /* genNatLibRemoveStateBlock -                                     */
12243 /*-----------------------------------------------------------------*/
12244 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12245 {
12246         bitVect *rsave ;
12247
12248         assert(nparms==0);
12249
12250         /* save registers that need to be saved */
12251         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12252                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12253
12254         /* put libraryID into DPTR */
12255         emitcode ("mov","dptr,#LibraryID");
12256         /* make the call */
12257         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12258         unsavermask(rsave);
12259 }
12260
12261 /*-----------------------------------------------------------------*/
12262 /* genNatLibGetStateBlock -                                        */
12263 /*-----------------------------------------------------------------*/
12264 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12265                                    operand **parms,const char *name)
12266 {
12267         bitVect *rsave ;
12268         symbol *lbl = newiTempLabel(NULL);
12269         
12270         assert(nparms==0);
12271         /* save registers that need to be saved */
12272         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12273                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12274
12275         /* put libraryID into DPTR */
12276         emitcode ("mov","dptr,#LibraryID");
12277         /* make the call */
12278         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12279         emitcode ("jnz","!tlabel",lbl->key+100);
12280
12281         /* put return value into place */
12282         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12283         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12284                 emitcode ("push","ar3");
12285                 emitcode ("push","ar2");
12286                 emitcode ("pop","%s",
12287                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12288                 emitcode ("pop","%s",
12289                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12290         } else {
12291                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12292                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12293         }
12294         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12295         emitcode ("","!tlabeldef",lbl->key+100);
12296         unsavermask(rsave);
12297 }
12298
12299 /*-----------------------------------------------------------------*/
12300 /* genMMMalloc -                                                   */
12301 /*-----------------------------------------------------------------*/
12302 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12303                          int size, const char *name)
12304 {
12305         bitVect *rsave ;
12306         operand *bsize;
12307         symbol *rsym;
12308         symbol *lbl = newiTempLabel(NULL);
12309
12310         assert (nparms == 1);
12311         /* save registers that need to be saved */
12312         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12313                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12314         
12315         bsize=parms[0];
12316         aopOp (bsize,ic,FALSE,FALSE);
12317
12318         /* put the size in R4-R2 */
12319         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12320                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12321                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12322                 if (size==3) {
12323                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12324                         emitcode("pop","ar4");
12325                 }
12326                 emitcode("pop","ar3");
12327                 emitcode("pop","ar2");          
12328         } else {
12329                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12330                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12331                 if (size==3) {
12332                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12333                 }
12334         }
12335         freeAsmop (bsize, NULL, ic, FALSE);
12336
12337         /* make the call */
12338         emitcode ("lcall","MM_%s",name);
12339         emitcode ("jz","!tlabel",lbl->key+100);
12340         emitcode ("mov","r2,#!constbyte",0xff);
12341         emitcode ("mov","r3,#!constbyte",0xff);
12342         emitcode ("","!tlabeldef",lbl->key+100);
12343         /* we don't care about the pointer : we just save the handle */
12344         rsym = OP_SYMBOL(IC_RESULT(ic));
12345         if (rsym->liveFrom != rsym->liveTo) {
12346                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12347                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12348                         emitcode ("push","ar3");
12349                         emitcode ("push","ar2");
12350                         emitcode ("pop","%s",
12351                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12352                         emitcode ("pop","%s",
12353                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12354                 } else {
12355                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12356                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12357                 }
12358                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12359         }
12360         unsavermask(rsave);
12361 }
12362
12363 /*-----------------------------------------------------------------*/
12364 /* genMMDeref -                                                    */
12365 /*-----------------------------------------------------------------*/
12366 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12367 {
12368         bitVect *rsave ;
12369         operand *handle;
12370
12371         assert (nparms == 1);
12372         /* save registers that need to be saved */
12373         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12374                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12375         
12376         handle=parms[0];
12377         aopOp (handle,ic,FALSE,FALSE);
12378
12379         /* put the size in R4-R2 */
12380         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12381                 emitcode("push","%s",
12382                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12383                 emitcode("push","%s",
12384                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12385                 emitcode("pop","ar3");
12386                 emitcode("pop","ar2");          
12387         } else {
12388                 emitcode ("mov","r2,%s",
12389                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12390                 emitcode ("mov","r3,%s",
12391                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12392         }
12393         freeAsmop (handle, NULL, ic, FALSE);
12394
12395         /* make the call */
12396         emitcode ("lcall","MM_Deref");
12397         
12398         {
12399                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12400                 if (rsym->liveFrom != rsym->liveTo) {                   
12401                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12402                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12403                             _startLazyDPSEvaluation ();
12404                             
12405                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12406                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12407                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12408
12409                             _endLazyDPSEvaluation ();
12410                             
12411                         }
12412                 }
12413         }
12414         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12415         unsavermask(rsave);
12416 }
12417
12418 /*-----------------------------------------------------------------*/
12419 /* genMMUnrestrictedPersist -                                      */
12420 /*-----------------------------------------------------------------*/
12421 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12422 {
12423         bitVect *rsave ;
12424         operand *handle;
12425
12426         assert (nparms == 1);
12427         /* save registers that need to be saved */
12428         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12429                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12430         
12431         handle=parms[0];
12432         aopOp (handle,ic,FALSE,FALSE);
12433
12434         /* put the size in R3-R2 */
12435         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12436                 emitcode("push","%s",
12437                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12438                 emitcode("push","%s",
12439                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12440                 emitcode("pop","ar3");
12441                 emitcode("pop","ar2");          
12442         } else {
12443                 emitcode ("mov","r2,%s",
12444                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12445                 emitcode ("mov","r3,%s",
12446                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12447         }
12448         freeAsmop (handle, NULL, ic, FALSE);
12449
12450         /* make the call */
12451         emitcode ("lcall","MM_UnrestrictedPersist");
12452
12453         {
12454                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12455                 if (rsym->liveFrom != rsym->liveTo) {   
12456                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12457                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12458                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12459                 }
12460         }
12461         unsavermask(rsave);
12462 }
12463
12464 /*-----------------------------------------------------------------*/
12465 /* genSystemExecJavaProcess -                                      */
12466 /*-----------------------------------------------------------------*/
12467 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12468 {
12469         bitVect *rsave ;
12470         operand *handle, *pp;
12471
12472         assert (nparms==2);
12473         /* save registers that need to be saved */
12474         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12475                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12476         
12477         pp = parms[0];
12478         handle = parms[1];
12479         
12480         /* put the handle in R3-R2 */
12481         aopOp (handle,ic,FALSE,FALSE);
12482         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12483                 emitcode("push","%s",
12484                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12485                 emitcode("push","%s",
12486                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12487                 emitcode("pop","ar3");
12488                 emitcode("pop","ar2");          
12489         } else {
12490                 emitcode ("mov","r2,%s",
12491                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12492                 emitcode ("mov","r3,%s",
12493                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12494         }
12495         freeAsmop (handle, NULL, ic, FALSE);
12496         
12497         /* put pointer in DPTR */
12498         aopOp (pp,ic,FALSE,FALSE);
12499         if (AOP_TYPE(pp) == AOP_IMMD) {
12500                 emitcode ("mov", "dptr,%s",
12501                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12502         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12503                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12504                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12505                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12506         }
12507         freeAsmop (handle, NULL, ic, FALSE);
12508
12509         /* make the call */
12510         emitcode ("lcall","System_ExecJavaProcess");
12511         
12512         /* put result in place */
12513         {
12514                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12515                 if (rsym->liveFrom != rsym->liveTo) {   
12516                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12517                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12518                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12519                 }
12520         }
12521         
12522         unsavermask(rsave);
12523 }
12524
12525 /*-----------------------------------------------------------------*/
12526 /* genSystemRTCRegisters -                                         */
12527 /*-----------------------------------------------------------------*/
12528 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12529                                   char *name)
12530 {
12531         bitVect *rsave ;
12532         operand *pp;
12533
12534         assert (nparms==1);
12535         /* save registers that need to be saved */
12536         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12537                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12538         
12539         pp=parms[0];
12540         /* put pointer in DPTR */
12541         aopOp (pp,ic,FALSE,FALSE);
12542         if (AOP_TYPE (pp) == AOP_IMMD) {
12543                 emitcode ("mov","dps,#1");
12544                 emitcode ("mov", "dptr,%s", 
12545                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12546                 emitcode ("mov","dps,#0");
12547         } else {
12548                 emitcode ("mov","dpl1,%s",
12549                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12550                 emitcode ("mov","dph1,%s",
12551                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12552                 emitcode ("mov","dpx1,%s",
12553                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12554         }
12555         freeAsmop (pp, NULL, ic, FALSE);
12556
12557         /* make the call */
12558         emitcode ("lcall","System_%sRTCRegisters",name);
12559
12560         unsavermask(rsave);
12561 }
12562
12563 /*-----------------------------------------------------------------*/
12564 /* genSystemThreadSleep -                                          */
12565 /*-----------------------------------------------------------------*/
12566 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12567 {
12568         bitVect *rsave ;
12569         operand *to, *s;
12570
12571         assert (nparms==1);
12572         /* save registers that need to be saved */
12573         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12574                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12575
12576         to = parms[0];
12577         aopOp(to,ic,FALSE,FALSE);
12578         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12579             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12580                 emitcode ("push","%s",
12581                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12582                 emitcode ("push","%s",
12583                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12584                 emitcode ("push","%s",
12585                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12586                 emitcode ("push","%s",
12587                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12588                 emitcode ("pop","ar3");
12589                 emitcode ("pop","ar2");
12590                 emitcode ("pop","ar1");
12591                 emitcode ("pop","ar0");
12592         } else {
12593                 emitcode ("mov","r0,%s",
12594                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12595                 emitcode ("mov","r1,%s",
12596                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12597                 emitcode ("mov","r2,%s",
12598                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12599                 emitcode ("mov","r3,%s",
12600                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12601         }
12602         freeAsmop (to, NULL, ic, FALSE);
12603
12604         /* suspend in acc */
12605         s = parms[1];
12606         aopOp(s,ic,FALSE,FALSE);
12607         emitcode ("mov","a,%s",
12608                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12609         freeAsmop (s, NULL, ic, FALSE);
12610
12611         /* make the call */
12612         emitcode ("lcall","System_%s",name);
12613
12614         unsavermask(rsave);
12615 }
12616
12617 /*-----------------------------------------------------------------*/
12618 /* genSystemThreadResume -                                         */
12619 /*-----------------------------------------------------------------*/
12620 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12621 {
12622         bitVect *rsave ;
12623         operand *tid,*pid;
12624
12625         assert (nparms==2);
12626         /* save registers that need to be saved */
12627         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12628                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12629         
12630         tid = parms[0];
12631         pid = parms[1];
12632         
12633         /* PID in R0 */
12634         aopOp(pid,ic,FALSE,FALSE);
12635         emitcode ("mov","r0,%s",
12636                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12637         freeAsmop (pid, NULL, ic, FALSE);
12638         
12639         /* tid into ACC */
12640         aopOp(tid,ic,FALSE,FALSE);
12641         emitcode ("mov","a,%s",
12642                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12643         freeAsmop (tid, NULL, ic, FALSE);
12644         
12645         emitcode ("lcall","System_ThreadResume");
12646
12647         /* put result into place */
12648         {
12649                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12650                 if (rsym->liveFrom != rsym->liveTo) {   
12651                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12652                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12653                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12654                 }
12655         }
12656         unsavermask(rsave);
12657 }
12658
12659 /*-----------------------------------------------------------------*/
12660 /* genSystemProcessResume -                                        */
12661 /*-----------------------------------------------------------------*/
12662 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12663 {
12664         bitVect *rsave ;
12665         operand *pid;
12666
12667         assert (nparms==1);
12668         /* save registers that need to be saved */
12669         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12670                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12671         
12672         pid = parms[0];
12673         
12674         /* pid into ACC */
12675         aopOp(pid,ic,FALSE,FALSE);
12676         emitcode ("mov","a,%s",
12677                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12678         freeAsmop (pid, NULL, ic, FALSE);
12679         
12680         emitcode ("lcall","System_ProcessResume");
12681
12682         unsavermask(rsave);
12683 }
12684
12685 /*-----------------------------------------------------------------*/
12686 /* genSystem -                                                     */
12687 /*-----------------------------------------------------------------*/
12688 static void genSystem (iCode *ic,int nparms,char *name)
12689 {
12690         assert(nparms == 0);
12691
12692         emitcode ("lcall","System_%s",name);
12693 }
12694
12695 /*-----------------------------------------------------------------*/
12696 /* genSystemPoll -                                                  */
12697 /*-----------------------------------------------------------------*/
12698 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12699 {
12700         bitVect *rsave ;
12701         operand *fp;
12702
12703         assert (nparms==1);
12704         /* save registers that need to be saved */
12705         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12706                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12707
12708         fp = parms[0];
12709         aopOp (fp,ic,FALSE,FALSE);
12710         if (AOP_TYPE (fp) == AOP_IMMD) {
12711                 emitcode ("mov", "dptr,%s", 
12712                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12713         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12714                 emitcode ("mov","dpl,%s",
12715                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12716                 emitcode ("mov","dph,%s",
12717                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12718                 emitcode ("mov","dpx,%s",
12719                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12720         }
12721         freeAsmop (fp, NULL, ic, FALSE);
12722
12723         emitcode ("lcall","System_%sPoll",name);
12724
12725         /* put result into place */
12726         {
12727                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12728                 if (rsym->liveFrom != rsym->liveTo) {   
12729                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12730                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12731                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12732                 }
12733         }
12734         unsavermask(rsave);
12735 }
12736
12737 /*-----------------------------------------------------------------*/
12738 /* genSystemGetCurrentID -                                         */
12739 /*-----------------------------------------------------------------*/
12740 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12741 {
12742         assert (nparms==0);
12743
12744         emitcode ("lcall","System_GetCurrent%sId",name);
12745         /* put result into place */
12746         {
12747                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12748                 if (rsym->liveFrom != rsym->liveTo) {   
12749                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12750                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12751                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12752                 }
12753         }
12754 }
12755
12756 /*-----------------------------------------------------------------*/
12757 /* genDummyRead - generate code for dummy read of volatiles        */
12758 /*-----------------------------------------------------------------*/
12759 static void
12760 genDummyRead (iCode * ic)
12761 {
12762   operand *op;
12763   int size, offset;
12764
12765   D(emitcode(";     genDummyRead",""));
12766
12767   op = IC_RIGHT (ic);
12768   if (op && IS_SYMOP (op))
12769     {
12770       aopOp (op, ic, FALSE, FALSE);
12771
12772       /* if the result is a bit */
12773       if (AOP_TYPE (op) == AOP_CRY)
12774         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12775       else
12776         {
12777           /* bit variables done */
12778           /* general case */
12779           size = AOP_SIZE (op);
12780           offset = 0;
12781           while (size--)
12782           {
12783             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12784             offset++;
12785           }
12786         }
12787
12788       freeAsmop (op, NULL, ic, TRUE);
12789     }
12790
12791   op = IC_LEFT (ic);
12792   if (op && IS_SYMOP (op))
12793     {
12794       aopOp (op, ic, FALSE, FALSE);
12795
12796       /* if the result is a bit */
12797       if (AOP_TYPE (op) == AOP_CRY)
12798         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12799       else
12800         {
12801           /* bit variables done */
12802           /* general case */
12803           size = AOP_SIZE (op);
12804           offset = 0;
12805           while (size--)
12806           {
12807             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12808             offset++;
12809           }
12810         }
12811
12812       freeAsmop (op, NULL, ic, TRUE);
12813     }
12814     
12815 }
12816
12817 /*-----------------------------------------------------------------*/
12818 /* genCritical - generate code for start of a critical sequence    */
12819 /*-----------------------------------------------------------------*/
12820 static void
12821 genCritical (iCode *ic)
12822 {
12823   symbol *tlbl = newiTempLabel (NULL);
12824
12825   D(emitcode(";     genCritical",""));
12826   
12827   if (IC_RESULT (ic))
12828     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12829
12830   emitcode ("setb", "c");
12831   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12832   emitcode ("clr", "c");
12833   emitcode ("", "%05d$:", (tlbl->key + 100));
12834
12835   if (IC_RESULT (ic))
12836     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12837   else
12838     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12839
12840   if (IC_RESULT (ic))
12841     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12842 }
12843
12844 /*-----------------------------------------------------------------*/
12845 /* genEndCritical - generate code for end of a critical sequence   */
12846 /*-----------------------------------------------------------------*/
12847 static void
12848 genEndCritical (iCode *ic)
12849 {
12850   D(emitcode(";     genEndCritical",""));
12851   
12852   if (IC_RIGHT (ic))
12853     {
12854       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12855       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12856         {
12857           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12858           emitcode ("mov", "ea,c");
12859         }
12860       else
12861         {
12862           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12863           emitcode ("rrc", "a");
12864           emitcode ("mov", "ea,c");
12865         }
12866       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12867     }
12868   else
12869     {
12870       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12871       emitcode ("mov", "ea,c");
12872     }
12873 }
12874
12875
12876
12877 /*-----------------------------------------------------------------*/
12878 /* genBuiltIn - calls the appropriate function to  generating code */
12879 /* for a built in function                                         */
12880 /*-----------------------------------------------------------------*/
12881 static void genBuiltIn (iCode *ic)
12882 {
12883         operand *bi_parms[MAX_BUILTIN_ARGS];
12884         int nbi_parms;
12885         iCode *bi_iCode;
12886         symbol *bif;
12887
12888         /* get all the arguments for a built in function */
12889         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12890
12891         /* which function is it */
12892         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12893         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12894                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12895         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12896                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12897         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12898                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12899         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12900                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12901         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12902                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12903         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12904                 genInp(bi_iCode,nbi_parms,bi_parms);
12905         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12906                 genOutp(bi_iCode,nbi_parms,bi_parms);
12907         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12908                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12909                 /* JavaNative builtIns */               
12910         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12911                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12912         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12913                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12914         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12915                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12916         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12917                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12918         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12919                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12920         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12921                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12922         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12923                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12924         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12925                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12926         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12927                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12928         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12929                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12930         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12931                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12932         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12933                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12934         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12935                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12936         } else if (strcmp(bif->name,"MM_Free")==0) {
12937                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12938         } else if (strcmp(bif->name,"MM_Deref")==0) {
12939                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12940         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12941                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12942         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12943                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12944         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12945                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12946         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12947                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12948         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12949                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12950         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12951                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12952         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12953                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12954         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12955                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12956         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12957                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12958         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12959                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12960         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12961                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12962         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12963                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12964         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12965                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12966         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12967                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12968         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12969                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12970         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12971                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12972         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12973                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12974         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12975                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12976         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12977                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12978         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12979                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12980         } else {
12981                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12982                 return ;
12983         }
12984         return ;    
12985 }
12986
12987 /*-----------------------------------------------------------------*/
12988 /* gen390Code - generate code for Dallas 390 based controllers     */
12989 /*-----------------------------------------------------------------*/
12990 void
12991 gen390Code (iCode * lic)
12992 {
12993   iCode *ic;
12994   int cln = 0;
12995
12996   lineHead = lineCurr = NULL;
12997   dptrn[1][0] = "dpl1";
12998   dptrn[1][1] = "dph1";
12999   dptrn[1][2] = "dpx1";
13000   
13001   if (options.model == MODEL_FLAT24) {
13002     fReturnSizeDS390 = 5;
13003     fReturn = fReturn24;
13004   } else {
13005     fReturnSizeDS390 = 4;
13006     fReturn = fReturn16;
13007     options.stack10bit=0;
13008   }
13009 #if 1
13010   /* print the allocation information */
13011   if (allocInfo && currFunc)
13012     printAllocInfo (currFunc, codeOutFile);
13013 #endif
13014   /* if debug information required */
13015   if (options.debug && currFunc)
13016     {
13017       debugFile->writeFunction(currFunc);
13018       _G.debugLine = 1;
13019       if (IS_STATIC (currFunc->etype))
13020         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13021       else
13022         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13023       _G.debugLine = 0;
13024     }
13025   /* stack pointer name */
13026   if (options.useXstack)
13027     spname = "_spx";
13028   else
13029     spname = "sp";
13030
13031
13032   for (ic = lic; ic; ic = ic->next)
13033     {
13034
13035       if (ic->lineno && cln != ic->lineno)
13036         {
13037           if (options.debug)
13038             {
13039               _G.debugLine = 1;
13040               emitcode ("", "C$%s$%d$%d$%d ==.",
13041                         FileBaseName (ic->filename), ic->lineno,
13042                         ic->level, ic->block);
13043               _G.debugLine = 0;
13044             }
13045           if (!options.noCcodeInAsm) {
13046             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13047                       printCLine(ic->filename, ic->lineno));
13048           }
13049           cln = ic->lineno;
13050         }
13051       if (options.iCodeInAsm) {
13052         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13053       }
13054       /* if the result is marked as
13055          spilt and rematerializable or code for
13056          this has already been generated then
13057          do nothing */
13058       if (resultRemat (ic) || ic->generated)
13059         continue;
13060
13061       /* depending on the operation */
13062       switch (ic->op)
13063         {
13064         case '!':
13065           genNot (ic);
13066           break;
13067
13068         case '~':
13069           genCpl (ic);
13070           break;
13071
13072         case UNARYMINUS:
13073           genUminus (ic);
13074           break;
13075
13076         case IPUSH:
13077           genIpush (ic);
13078           break;
13079
13080         case IPOP:
13081           /* IPOP happens only when trying to restore a
13082              spilt live range, if there is an ifx statement
13083              following this pop then the if statement might
13084              be using some of the registers being popped which
13085              would destory the contents of the register so
13086              we need to check for this condition and handle it */
13087           if (ic->next &&
13088               ic->next->op == IFX &&
13089               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13090             genIfx (ic->next, ic);
13091           else
13092             genIpop (ic);
13093           break;
13094
13095         case CALL:
13096           genCall (ic);
13097           break;
13098
13099         case PCALL:
13100           genPcall (ic);
13101           break;
13102
13103         case FUNCTION:
13104           genFunction (ic);
13105           break;
13106
13107         case ENDFUNCTION:
13108           genEndFunction (ic);
13109           break;
13110
13111         case RETURN:
13112           genRet (ic);
13113           break;
13114
13115         case LABEL:
13116           genLabel (ic);
13117           break;
13118
13119         case GOTO:
13120           genGoto (ic);
13121           break;
13122
13123         case '+':
13124           genPlus (ic);
13125           break;
13126
13127         case '-':
13128           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13129             genMinus (ic);
13130           break;
13131
13132         case '*':
13133           genMult (ic);
13134           break;
13135
13136         case '/':
13137           genDiv (ic);
13138           break;
13139
13140         case '%':
13141           genMod (ic);
13142           break;
13143
13144         case '>':
13145           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13146           break;
13147
13148         case '<':
13149           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13150           break;
13151
13152         case LE_OP:
13153         case GE_OP:
13154         case NE_OP:
13155
13156           /* note these two are xlated by algebraic equivalence
13157              during parsing SDCC.y */
13158           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13159                   "got '>=' or '<=' shouldn't have come here");
13160           break;
13161
13162         case EQ_OP:
13163           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13164           break;
13165
13166         case AND_OP:
13167           genAndOp (ic);
13168           break;
13169
13170         case OR_OP:
13171           genOrOp (ic);
13172           break;
13173
13174         case '^':
13175           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13176           break;
13177
13178         case '|':
13179           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13180           break;
13181
13182         case BITWISEAND:
13183           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13184           break;
13185
13186         case INLINEASM:
13187           genInline (ic);
13188           break;
13189
13190         case RRC:
13191           genRRC (ic);
13192           break;
13193
13194         case RLC:
13195           genRLC (ic);
13196           break;
13197
13198         case GETHBIT:
13199           genGetHbit (ic);
13200           break;
13201
13202         case LEFT_OP:
13203           genLeftShift (ic);
13204           break;
13205
13206         case RIGHT_OP:
13207           genRightShift (ic);
13208           break;
13209
13210         case GET_VALUE_AT_ADDRESS:
13211           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13212           break;
13213
13214         case '=':
13215           if (POINTER_SET (ic))
13216             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13217           else
13218             genAssign (ic);
13219           break;
13220
13221         case IFX:
13222           genIfx (ic, NULL);
13223           break;
13224
13225         case ADDRESS_OF:
13226           genAddrOf (ic);
13227           break;
13228
13229         case JUMPTABLE:
13230           genJumpTab (ic);
13231           break;
13232
13233         case CAST:
13234           genCast (ic);
13235           break;
13236
13237         case RECEIVE:
13238           genReceive (ic);
13239           break;
13240
13241         case SEND:
13242           if (ic->builtinSEND) genBuiltIn(ic);
13243           else addSet (&_G.sendSet, ic);
13244           break;
13245
13246         case DUMMY_READ_VOLATILE:
13247           genDummyRead (ic);
13248           break;
13249
13250         case CRITICAL:
13251           genCritical (ic);
13252           break;
13253
13254         case ENDCRITICAL:
13255           genEndCritical (ic);
13256           break;
13257         
13258         case SWAP:
13259           genSwap (ic);
13260           break;
13261           
13262 #if 0 // obsolete, and buggy for != xdata
13263         case ARRAYINIT:
13264             genArrayInit(ic);
13265             break;
13266 #endif
13267             
13268         default:
13269           ic = ic;
13270         }
13271     }
13272
13273
13274   /* now we are ready to call the
13275      peep hole optimizer */
13276   if (!options.nopeep)
13277     peepHole (&lineHead);
13278
13279   /* now do the actual printing */
13280   printLine (lineHead, codeOutFile);
13281   return;
13282 }