* src/ds390/gen.c (aopOp3): fixed the assignment of different dptrs to
[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       {
3959         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3960         return TRUE;
3961       }
3962     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3963       {
3964 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3965         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3966         return TRUE;
3967       }
3968     
3969     // Operands may be equivalent (but not equal) if they share a spill location. If
3970     // so, use the same DPTR or DPTR2.
3971     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
3972       {
3973         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
3974         return TRUE;
3975       }
3976     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
3977       {
3978         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
3979         return TRUE;
3980       }
3981     
3982     // Note which dptrs are currently in use.
3983     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3984     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3985     
3986     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3987     // generate it.
3988     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3989     {
3990         return FALSE;
3991     }
3992     
3993     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3994     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3995     {
3996         return FALSE;
3997     }
3998     
3999     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
4000     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4001     {
4002         return FALSE;
4003     }
4004
4005     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4006
4007     // Some sanity checking...
4008     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4009     {
4010         fprintf(stderr,
4011                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4012                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4013         emitcode(";", ">>> unexpected DPTR here.");
4014     }
4015     
4016     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4017     {
4018         fprintf(stderr,
4019                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4020                 __FILE__, __LINE__, ic->filename, ic->lineno);  
4021         emitcode(";", ">>> unexpected DPTR2 here.");
4022     }    
4023     
4024     return TRUE;
4025 }
4026
4027 // Macro to aopOp all three operands of an ic. If this cannot be done, 
4028 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4029 // will be set TRUE. The caller must then handle the case specially, noting
4030 // that the IC_RESULT operand is not aopOp'd.
4031 // 
4032 #define AOP_OP_3_NOFATAL(ic, rc) \
4033             do { rc = !aopOp3(ic); } while (0)
4034
4035 // aopOp the left & right operands of an ic.
4036 #define AOP_OP_2(ic) \
4037     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4038     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4039
4040 // convienience macro.
4041 #define AOP_SET_LOCALS(ic) \
4042     left = IC_LEFT(ic); \
4043     right = IC_RIGHT(ic); \
4044     result = IC_RESULT(ic);
4045
4046
4047 // Given an integer value of pushedSize bytes on the stack,
4048 // adjust it to be resultSize bytes, either by discarding
4049 // the most significant bytes or by zero-padding.
4050 //
4051 // On exit from this macro, pushedSize will have been adjusted to
4052 // equal resultSize, and ACC may be trashed.
4053 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4054       /* If the pushed data is bigger than the result,          \
4055        * simply discard unused bytes. Icky, but works.          \
4056        */                                                       \
4057       while (pushedSize > resultSize)                           \
4058       {                                                         \
4059           D (emitcode (";", "discarding unused result byte."););\
4060           emitcode ("pop", "acc");                              \
4061           pushedSize--;                                         \
4062       }                                                         \
4063       if (pushedSize < resultSize)                              \
4064       {                                                         \
4065           emitcode ("clr", "a");                                \
4066           /* Conversly, we haven't pushed enough here.          \
4067            * just zero-pad, and all is well.                    \
4068            */                                                   \
4069           while (pushedSize < resultSize)                       \
4070           {                                                     \
4071               emitcode("push", "acc");                          \
4072               pushedSize++;                                     \
4073           }                                                     \
4074       }                                                         \
4075       assert(pushedSize == resultSize);
4076
4077 /*-----------------------------------------------------------------*/
4078 /* genPlus - generates code for addition                           */
4079 /*-----------------------------------------------------------------*/
4080 static void
4081 genPlus (iCode * ic)
4082 {
4083   int size, offset = 0;
4084   bool pushResult;
4085   int rSize;
4086
4087   D (emitcode (";", "genPlus "););
4088
4089   /* special cases :- */
4090   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4091       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4092       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4093       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4094       if (size <= 9) {
4095           while (size--) emitcode ("inc","dptr");
4096       } else {
4097           emitcode ("mov","a,dpl");
4098           emitcode ("add","a,#!constbyte",size & 0xff);
4099           emitcode ("mov","dpl,a");
4100           emitcode ("mov","a,dph");
4101           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4102           emitcode ("mov","dph,a");
4103           emitcode ("mov","a,dpx");
4104           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4105           emitcode ("mov","dpx,a");
4106       }
4107       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4108       return ;
4109   }
4110   if ( IS_SYMOP(IC_LEFT(ic)) && 
4111        OP_SYMBOL(IC_LEFT(ic))->remat &&
4112        isOperandInFarSpace(IC_RIGHT(ic))) {
4113       operand *op = IC_RIGHT(ic);
4114       IC_RIGHT(ic) = IC_LEFT(ic);
4115       IC_LEFT(ic) = op;
4116   }
4117                 
4118   AOP_OP_3_NOFATAL (ic, pushResult);
4119     
4120   if (pushResult)
4121     {
4122       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4123     }
4124
4125   if (!pushResult)
4126     {
4127       /* if literal, literal on the right or
4128          if left requires ACC or right is already
4129          in ACC */
4130       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4131        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4132           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4133         {
4134           operand *t = IC_RIGHT (ic);
4135           IC_RIGHT (ic) = IC_LEFT (ic);
4136           IC_LEFT (ic) = t;
4137           emitcode (";", "Swapped plus args.");
4138         }
4139
4140       /* if both left & right are in bit
4141          space */
4142       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4143           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4144         {
4145           genPlusBits (ic);
4146           goto release;
4147         }
4148
4149       /* if left in bit space & right literal */
4150       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4151           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4152         {
4153           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4154           /* if result in bit space */
4155           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4156             {
4157               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4158                 emitcode ("cpl", "c");
4159               outBitC (IC_RESULT (ic));
4160             }
4161           else
4162             {
4163               size = getDataSize (IC_RESULT (ic));
4164               _startLazyDPSEvaluation ();
4165               while (size--)
4166                 {
4167                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4168                   emitcode ("addc", "a,#0");
4169                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4170                 }
4171               _endLazyDPSEvaluation ();
4172             }
4173           goto release;
4174         }
4175
4176       /* if I can do an increment instead
4177          of add then GOOD for ME */
4178       if (genPlusIncr (ic) == TRUE)
4179         {
4180           emitcode (";", "did genPlusIncr");
4181           goto release;
4182         }
4183
4184     }
4185   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4186
4187   _startLazyDPSEvaluation ();
4188   while (size--)
4189     {
4190       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4191         {
4192           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4193           if (offset == 0)
4194             emitcode ("add", "a,%s",
4195                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4196           else
4197             emitcode ("addc", "a,%s",
4198                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4199         }
4200       else
4201         {
4202           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4203           {
4204               /* right is going to use ACC or we would have taken the
4205                * above branch.
4206                */
4207               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4208        TR_AP("#3");
4209               D(emitcode(";", "+ AOP_ACC special case."););
4210               emitcode("xch", "a, %s", DP2_RESULT_REG);
4211           }
4212           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4213           if (offset == 0)
4214           {
4215             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4216             {
4217          TR_AP("#4");
4218                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4219             }
4220             else
4221             {
4222                 emitcode ("add", "a,%s",
4223                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4224                                   DP2_RESULT_REG));
4225             }
4226           }
4227           else
4228           {
4229             emitcode ("addc", "a,%s",
4230                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4231                           DP2_RESULT_REG));
4232           }
4233         }
4234       if (!pushResult)
4235         {
4236           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4237         }
4238       else
4239         {
4240           emitcode ("push", "acc");
4241         }
4242       offset++;
4243     }
4244   _endLazyDPSEvaluation ();
4245
4246   if (pushResult)
4247     {
4248       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4249
4250       size = getDataSize (IC_LEFT (ic));
4251       rSize = getDataSize (IC_RESULT (ic));
4252
4253       ADJUST_PUSHED_RESULT(size, rSize);
4254
4255       _startLazyDPSEvaluation ();
4256       while (size--)
4257         {
4258           emitcode ("pop", "acc");
4259           aopPut (AOP (IC_RESULT (ic)), "a", size);
4260         }
4261       _endLazyDPSEvaluation ();
4262     }
4263
4264   adjustArithmeticResult (ic);
4265
4266 release:
4267   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4270 }
4271
4272 /*-----------------------------------------------------------------*/
4273 /* genMinusDec :- does subtraction with deccrement if possible     */
4274 /*-----------------------------------------------------------------*/
4275 static bool
4276 genMinusDec (iCode * ic)
4277 {
4278   unsigned int icount;
4279   unsigned int size = getDataSize (IC_RESULT (ic));
4280
4281   /* will try to generate an increment */
4282   /* if the right side is not a literal
4283      we cannot */
4284   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4285     return FALSE;
4286
4287   /* if the literal value of the right hand side
4288      is greater than 4 then it is not worth it */
4289   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4290     return FALSE;
4291
4292   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4293       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4294       while (icount--) {
4295           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4296       }
4297       return TRUE;
4298   }
4299   /* if decrement 16 bits in register */
4300   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4301       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4302       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4303       (size > 1) &&
4304       (icount == 1))
4305     {
4306       symbol *tlbl;
4307       int    emitTlbl;
4308       int    labelRange;
4309       char   *l;
4310
4311       /* If the next instruction is a goto and the goto target
4312          * is <= 5 instructions previous to this, we can generate
4313          * jumps straight to that target.
4314        */
4315       if (ic->next && ic->next->op == GOTO
4316           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4317           && labelRange <= 5)
4318         {
4319           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4320           tlbl = IC_LABEL (ic->next);
4321           emitTlbl = 0;
4322         }
4323       else
4324         {
4325           tlbl = newiTempLabel (NULL);
4326           emitTlbl = 1;
4327         }
4328
4329       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4330       emitcode ("dec", "%s", l);
4331  
4332       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4333           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4334           IS_AOP_PREG (IC_RESULT (ic)))
4335       {     
4336           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4337       }
4338       else
4339       {
4340           emitcode ("mov", "a,#!constbyte",0xff);
4341           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4342       }
4343       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4344       emitcode ("dec", "%s", l);
4345       if (size > 2)
4346         {
4347             if (!strcmp(l, "acc"))
4348             {
4349                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4350             }
4351             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4352                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4353                      IS_AOP_PREG (IC_RESULT (ic)))
4354             {       
4355                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4356             }
4357             else
4358             {
4359                 emitcode ("mov", "a,#!constbyte",0xff);
4360                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4361             }
4362             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4363             emitcode ("dec", "%s", l);
4364         }
4365       if (size > 3)
4366         {
4367             if (!strcmp(l, "acc"))
4368             {
4369                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4370             }
4371             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4372                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4373                      IS_AOP_PREG (IC_RESULT (ic)))
4374             {       
4375                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4376             }
4377             else
4378             {
4379                 emitcode ("mov", "a,#!constbyte",0xff);
4380                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4381             }       
4382             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4383             emitcode ("dec", "%s", l);
4384         }
4385       if (emitTlbl)
4386         {
4387           emitcode ("", "!tlabeldef", tlbl->key + 100);
4388         }
4389       return TRUE;
4390     }
4391
4392   /* if the sizes are greater than 1 then we cannot */
4393   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4394       AOP_SIZE (IC_LEFT (ic)) > 1)
4395     return FALSE;
4396
4397   /* we can if the aops of the left & result match or
4398      if they are in registers and the registers are the
4399      same */
4400   if (
4401        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4402        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4403        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4404     {
4405
4406       _startLazyDPSEvaluation ();
4407       while (icount--)
4408         {
4409           emitcode ("dec", "%s",
4410                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4411         }
4412       _endLazyDPSEvaluation ();
4413
4414       return TRUE;
4415     }
4416
4417   return FALSE;
4418 }
4419
4420 /*-----------------------------------------------------------------*/
4421 /* addSign - complete with sign                                    */
4422 /*-----------------------------------------------------------------*/
4423 static void
4424 addSign (operand * result, int offset, int sign)
4425 {
4426   int size = (getDataSize (result) - offset);
4427   if (size > 0)
4428     {
4429       _startLazyDPSEvaluation();
4430       if (sign)
4431         {
4432           emitcode ("rlc", "a");
4433           emitcode ("subb", "a,acc");
4434           while (size--)
4435           {
4436             aopPut (AOP (result), "a", offset++);
4437           }
4438         }
4439       else
4440       {
4441         while (size--)
4442         {
4443           aopPut (AOP (result), zero, offset++);
4444         }
4445       }
4446       _endLazyDPSEvaluation();
4447     }
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genMinusBits - generates code for subtraction  of two bits      */
4452 /*-----------------------------------------------------------------*/
4453 static void
4454 genMinusBits (iCode * ic)
4455 {
4456   symbol *lbl = newiTempLabel (NULL);
4457
4458   D (emitcode (";", "genMinusBits "););
4459
4460   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4461     {
4462       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4463       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4464       emitcode ("cpl", "c");
4465       emitcode ("", "!tlabeldef", (lbl->key + 100));
4466       outBitC (IC_RESULT (ic));
4467     }
4468   else
4469     {
4470       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4471       emitcode ("subb", "a,acc");
4472       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4473       emitcode ("inc", "a");
4474       emitcode ("", "!tlabeldef", (lbl->key + 100));
4475       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4476       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4477     }
4478 }
4479
4480 /*-----------------------------------------------------------------*/
4481 /* genMinus - generates code for subtraction                       */
4482 /*-----------------------------------------------------------------*/
4483 static void
4484 genMinus (iCode * ic)
4485 {
4486     int size, offset = 0;
4487     int rSize;
4488     long lit = 0L;
4489     bool pushResult;
4490
4491     D (emitcode (";", "genMinus "););
4492
4493     AOP_OP_3_NOFATAL(ic, pushResult);   
4494
4495     if (!pushResult)
4496     {
4497       /* special cases :- */
4498       /* if both left & right are in bit space */
4499       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4500           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4501         {
4502           genMinusBits (ic);
4503           goto release;
4504         }
4505
4506       /* if I can do an decrement instead
4507          of subtract then GOOD for ME */
4508       if (genMinusDec (ic) == TRUE)
4509         goto release;
4510
4511     }
4512
4513   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4514
4515   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4516     {
4517       CLRC;
4518     }
4519   else
4520     {
4521       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4522       lit = -lit;
4523     }
4524
4525
4526   /* if literal, add a,#-lit, else normal subb */
4527   _startLazyDPSEvaluation ();
4528   while (size--) {
4529       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4530           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4531               emitcode ("mov","b,%s",
4532                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4533               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4534               emitcode ("subb","a,b");
4535           } else {
4536               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4537               emitcode ("subb", "a,%s",
4538                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4539                                 DP2_RESULT_REG));
4540           }
4541       } else {
4542           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4543           /* first add without previous c */
4544           if (!offset) {
4545               if (!size && lit==-1) {
4546                   emitcode ("dec", "a");
4547               } else {
4548                   emitcode ("add", "a,#!constbyte",
4549                             (unsigned int) (lit & 0x0FFL));
4550               }
4551           } else {
4552               emitcode ("addc", "a,#!constbyte",
4553                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4554           }
4555       }
4556       
4557       if (pushResult) {
4558           emitcode ("push", "acc");
4559       } else {
4560           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4561       }
4562       offset++;
4563   }
4564   _endLazyDPSEvaluation ();
4565   
4566   if (pushResult)
4567     {
4568       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4569
4570       size = getDataSize (IC_LEFT (ic));
4571       rSize = getDataSize (IC_RESULT (ic));
4572
4573       ADJUST_PUSHED_RESULT(size, rSize);
4574
4575       _startLazyDPSEvaluation ();
4576       while (size--)
4577         {
4578           emitcode ("pop", "acc");
4579           aopPut (AOP (IC_RESULT (ic)), "a", size);
4580         }
4581       _endLazyDPSEvaluation ();
4582     }
4583
4584   adjustArithmeticResult (ic);
4585
4586 release:
4587   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4588   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4590 }
4591
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genMultbits :- multiplication of bits                           */
4595 /*-----------------------------------------------------------------*/
4596 static void
4597 genMultbits (operand * left,
4598              operand * right,
4599              operand * result,
4600              iCode   * ic)
4601 {
4602   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4603   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4604   aopOp(result, ic, TRUE, FALSE);
4605   outBitC (result);
4606 }
4607
4608
4609 /*-----------------------------------------------------------------*/
4610 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4611 /*-----------------------------------------------------------------*/
4612 static void
4613 genMultOneByte (operand * left,
4614                 operand * right,
4615                 operand * result,
4616                 iCode   * ic)
4617 {
4618   sym_link *opetype = operandType (result);
4619   symbol *lbl;
4620
4621
4622   /* (if two literals: the value is computed before) */
4623   /* if one literal, literal on the right */
4624   if (AOP_TYPE (left) == AOP_LIT)
4625     {
4626       operand *t = right;
4627       right = left;
4628       left = t;
4629       emitcode (";", "swapped left and right");
4630     }
4631
4632   if (SPEC_USIGN(opetype)
4633       // ignore the sign of left and right, what else can we do?
4634       || (SPEC_USIGN(operandType(left)) && 
4635           SPEC_USIGN(operandType(right)))) {
4636     // just an unsigned 8*8=8/16 multiply
4637     //emitcode (";","unsigned");
4638     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4639     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4640     emitcode ("mul", "ab");
4641    
4642     _G.accInUse++; _G.bInUse++;
4643     aopOp(result, ic, TRUE, FALSE);
4644       
4645       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4646       {
4647           // this should never happen
4648           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4649                    AOP_SIZE(result), __FILE__, lineno);
4650           exit (1);
4651       }      
4652       
4653     aopPut (AOP (result), "a", 0);
4654     _G.accInUse--; _G.bInUse--;
4655     if (AOP_SIZE(result)==2) 
4656     {
4657       aopPut (AOP (result), "b", 1);
4658     }
4659     return;
4660   }
4661
4662   // we have to do a signed multiply
4663
4664   emitcode (";", "signed");
4665   emitcode ("clr", "F0"); // reset sign flag
4666   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4667
4668   lbl=newiTempLabel(NULL);
4669   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4670   // left side is negative, 8-bit two's complement, this fails for -128
4671   emitcode ("setb", "F0"); // set sign flag
4672   emitcode ("cpl", "a");
4673   emitcode ("inc", "a");
4674
4675   emitcode ("", "!tlabeldef", lbl->key+100);
4676
4677   /* if literal */
4678   if (AOP_TYPE(right)==AOP_LIT) {
4679     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4680     /* AND literal negative */
4681     if ((int) val < 0) {
4682       emitcode ("cpl", "F0"); // complement sign flag
4683       emitcode ("mov", "b,#!constbyte", -val);
4684     } else {
4685       emitcode ("mov", "b,#!constbyte", val);
4686     }
4687   } else {
4688     lbl=newiTempLabel(NULL);
4689     emitcode ("mov", "b,a");
4690     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4691     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4692     // right side is negative, 8-bit two's complement
4693     emitcode ("cpl", "F0"); // complement sign flag
4694     emitcode ("cpl", "a");
4695     emitcode ("inc", "a");
4696     emitcode ("", "!tlabeldef", lbl->key+100);
4697   }
4698   emitcode ("mul", "ab");
4699     
4700   _G.accInUse++;_G.bInUse++;
4701   aopOp(result, ic, TRUE, FALSE);
4702     
4703   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4704   {
4705     // this should never happen
4706       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4707                AOP_SIZE(result), __FILE__, lineno);
4708       exit (1);
4709   }    
4710     
4711   lbl=newiTempLabel(NULL);
4712   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4713   // only ONE op was negative, we have to do a 8/16-bit two's complement
4714   emitcode ("cpl", "a"); // lsb
4715   if (AOP_SIZE(result)==1) {
4716     emitcode ("inc", "a");
4717   } else {
4718     emitcode ("add", "a,#1");
4719     emitcode ("xch", "a,b");
4720     emitcode ("cpl", "a"); // msb
4721     emitcode ("addc", "a,#0");
4722     emitcode ("xch", "a,b");
4723   }
4724
4725   emitcode ("", "!tlabeldef", lbl->key+100);
4726   aopPut (AOP (result), "a", 0);
4727   _G.accInUse--;_G.bInUse--;
4728   if (AOP_SIZE(result)==2) {
4729     aopPut (AOP (result), "b", 1);
4730   }
4731 }
4732
4733 /*-----------------------------------------------------------------*/
4734 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4735 /*-----------------------------------------------------------------*/
4736 static void genMultTwoByte (operand *left, operand *right, 
4737                             operand *result, iCode *ic)
4738 {
4739         sym_link *retype = getSpec(operandType(right));
4740         sym_link *letype = getSpec(operandType(left));
4741         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4742         symbol *lbl;
4743
4744         if (AOP_TYPE (left) == AOP_LIT) {
4745                 operand *t = right;
4746                 right = left;
4747                 left = t;
4748         }
4749         /* save EA bit in F1 */
4750         lbl = newiTempLabel(NULL);
4751         emitcode ("setb","F1");
4752         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4753         emitcode ("clr","F1");
4754         emitcode("","!tlabeldef",lbl->key+100);
4755
4756         /* load up MB with right */
4757         if (!umult) {
4758                 emitcode("clr","F0");
4759                 if (AOP_TYPE(right) == AOP_LIT) {
4760                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4761                         if (val < 0) {
4762                                 emitcode("setb","F0");
4763                                 val = -val;
4764                         }
4765                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4766                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4767                 } else {
4768                         lbl = newiTempLabel(NULL);
4769                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4770                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4771                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4772                         emitcode ("xch", "a,b");
4773                         emitcode ("cpl","a");
4774                         emitcode ("add", "a,#1");
4775                         emitcode ("xch", "a,b");
4776                         emitcode ("cpl", "a"); // msb
4777                         emitcode ("addc", "a,#0");
4778                         emitcode ("setb","F0");
4779                         emitcode ("","!tlabeldef",lbl->key+100);
4780                         emitcode ("mov","mb,b");
4781                         emitcode ("mov","mb,a");
4782                 }
4783         } else {
4784                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4785                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4786         }
4787         /* load up MA with left */
4788         if (!umult) {
4789                 lbl = newiTempLabel(NULL);
4790                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4791                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4792                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4793                 emitcode ("xch", "a,b");
4794                 emitcode ("cpl","a");
4795                 emitcode ("add", "a,#1");
4796                 emitcode ("xch", "a,b");
4797                 emitcode ("cpl", "a"); // msb
4798                 emitcode ("addc","a,#0");
4799                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4800                 emitcode ("setb","F0");
4801                 emitcode ("","!tlabeldef",lbl->key+100);
4802                 emitcode ("mov","ma,b");
4803                 emitcode ("mov","ma,a");
4804         } else {
4805                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4806                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4807         }
4808         /* wait for multiplication to finish */
4809         lbl = newiTempLabel(NULL);
4810         emitcode("","!tlabeldef", lbl->key+100);
4811         emitcode("mov","a,mcnt1");
4812         emitcode("anl","a,#!constbyte",0x80);
4813         emitcode("jnz","!tlabel",lbl->key+100);
4814         
4815         freeAsmop (left, NULL, ic, TRUE);
4816         freeAsmop (right, NULL, ic,TRUE);
4817         aopOp(result, ic, TRUE, FALSE);
4818
4819         /* if unsigned then simple */   
4820         if (umult) {
4821                 emitcode ("mov","a,ma");
4822                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4823                 emitcode ("mov","a,ma");
4824                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4825                 aopPut(AOP(result),"ma",1);
4826                 aopPut(AOP(result),"ma",0);
4827         } else {
4828                 emitcode("push","ma");
4829                 emitcode("push","ma");
4830                 emitcode("push","ma");
4831                 MOVA("ma");
4832                 /* negate result if needed */
4833                 lbl = newiTempLabel(NULL);      
4834                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4835                 emitcode("cpl","a");
4836                 emitcode("add","a,#1");
4837                 emitcode("","!tlabeldef", lbl->key+100);
4838                 if (AOP_TYPE(result) == AOP_ACC)
4839                 {
4840                     D(emitcode(";", "ACC special case."););
4841                     /* We know result is the only live aop, and 
4842                      * it's obviously not a DPTR2, so AP is available.
4843                      */
4844                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4845                 }
4846                 else
4847                 {
4848                     aopPut(AOP(result),"a",0);
4849                 }
4850             
4851                 emitcode("pop","acc");
4852                 lbl = newiTempLabel(NULL);      
4853                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4854                 emitcode("cpl","a");
4855                 emitcode("addc","a,#0");
4856                 emitcode("","!tlabeldef", lbl->key+100);
4857                 aopPut(AOP(result),"a",1);
4858                 emitcode("pop","acc");
4859                 if (AOP_SIZE(result) >= 3) {
4860                         lbl = newiTempLabel(NULL);      
4861                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4862                         emitcode("cpl","a");
4863                         emitcode("addc","a,#0");                        
4864                         emitcode("","!tlabeldef", lbl->key+100);
4865                         aopPut(AOP(result),"a",2);
4866                 }
4867                 emitcode("pop","acc");
4868                 if (AOP_SIZE(result) >= 4) {
4869                         lbl = newiTempLabel(NULL);      
4870                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4871                         emitcode("cpl","a");
4872                         emitcode("addc","a,#0");                        
4873                         emitcode("","!tlabeldef", lbl->key+100);
4874                         aopPut(AOP(result),"a",3);
4875                 }
4876                 if (AOP_TYPE(result) == AOP_ACC)
4877                 {
4878                     /* We stashed the result away above. */
4879                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4880                 }           
4881                 
4882         }
4883         freeAsmop (result, NULL, ic, TRUE);
4884
4885         /* restore EA bit in F1 */
4886         lbl = newiTempLabel(NULL);
4887         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4888         emitcode ("setb","EA");
4889         emitcode("","!tlabeldef",lbl->key+100);
4890         return ;
4891 }
4892
4893 /*-----------------------------------------------------------------*/
4894 /* genMult - generates code for multiplication                     */
4895 /*-----------------------------------------------------------------*/
4896 static void
4897 genMult (iCode * ic)
4898 {
4899   operand *left = IC_LEFT (ic);
4900   operand *right = IC_RIGHT (ic);
4901   operand *result = IC_RESULT (ic);
4902
4903   D (emitcode (";", "genMult "););
4904
4905   /* assign the amsops */
4906   AOP_OP_2 (ic);
4907
4908   /* special cases first */
4909   /* both are bits */
4910   if (AOP_TYPE (left) == AOP_CRY &&
4911       AOP_TYPE (right) == AOP_CRY)
4912     {
4913       genMultbits (left, right, result, ic);
4914       goto release;
4915     }
4916
4917   /* if both are of size == 1 */
4918   if (AOP_SIZE (left) == 1 &&
4919       AOP_SIZE (right) == 1)
4920     {
4921       genMultOneByte (left, right, result, ic);
4922       goto release;
4923     }
4924
4925   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4926           /* use the ds390 ARITHMETIC accel UNIT */
4927           genMultTwoByte (left, right, result, ic);
4928           return ;
4929   }
4930   /* should have been converted to function call */
4931   assert (0);
4932
4933 release:
4934   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4935   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936   freeAsmop (result, NULL, ic, TRUE);
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /* genDivbits :- division of bits                                  */
4941 /*-----------------------------------------------------------------*/
4942 static void
4943 genDivbits (operand * left,
4944             operand * right,
4945             operand * result,
4946             iCode   * ic)
4947 {
4948
4949   char *l;
4950
4951   /* the result must be bit */
4952   LOAD_AB_FOR_DIV (left, right, l);
4953   emitcode ("div", "ab");
4954   emitcode ("rrc", "a");
4955   aopOp(result, ic, TRUE, FALSE);
4956     
4957   aopPut (AOP (result), "c", 0);
4958 }
4959
4960 /*-----------------------------------------------------------------*/
4961 /* genDivOneByte : 8 bit division                                  */
4962 /*-----------------------------------------------------------------*/
4963 static void
4964 genDivOneByte (operand * left,
4965                operand * right,
4966                operand * result,
4967                iCode   * ic)
4968 {
4969   sym_link *opetype = operandType (result);
4970   char *l;
4971   symbol *lbl;
4972   int size, offset;
4973
4974   offset = 1;
4975   /* signed or unsigned */
4976   if (SPEC_USIGN (opetype))
4977     {
4978         /* unsigned is easy */
4979         LOAD_AB_FOR_DIV (left, right, l);
4980         emitcode ("div", "ab");
4981
4982         _G.accInUse++;
4983         aopOp(result, ic, TRUE, FALSE);
4984         aopPut (AOP (result), "a", 0);
4985         _G.accInUse--;
4986
4987         size = AOP_SIZE (result) - 1;
4988         
4989         while (size--)
4990         {
4991             aopPut (AOP (result), zero, offset++);
4992         }
4993       return;
4994     }
4995
4996   /* signed is a little bit more difficult */
4997
4998   /* save the signs of the operands */
4999   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5000   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
5001   emitcode ("push", "acc");     /* save it on the stack */
5002
5003   /* now sign adjust for both left & right */
5004   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5005   lbl = newiTempLabel (NULL);
5006   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5007   emitcode ("cpl", "a");
5008   emitcode ("inc", "a");
5009   emitcode ("", "!tlabeldef", (lbl->key + 100));
5010   emitcode ("mov", "b,a");
5011
5012   /* sign adjust left side */
5013   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5014
5015   lbl = newiTempLabel (NULL);
5016   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5017   emitcode ("cpl", "a");
5018   emitcode ("inc", "a");
5019   emitcode ("", "!tlabeldef", (lbl->key + 100));
5020
5021   /* now the division */
5022   emitcode ("nop", "; workaround for DS80C390 div bug.");
5023   emitcode ("div", "ab");
5024   /* we are interested in the lower order
5025      only */
5026   emitcode ("mov", "b,a");
5027   lbl = newiTempLabel (NULL);
5028   emitcode ("pop", "acc");
5029   /* if there was an over flow we don't
5030      adjust the sign of the result */
5031   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5032   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5033   CLRC;
5034   emitcode ("clr", "a");
5035   emitcode ("subb", "a,b");
5036   emitcode ("mov", "b,a");
5037   emitcode ("", "!tlabeldef", (lbl->key + 100));
5038
5039   /* now we are done */
5040   _G.accInUse++;     _G.bInUse++;
5041     aopOp(result, ic, TRUE, FALSE);
5042     
5043     aopPut (AOP (result), "b", 0);
5044     
5045     size = AOP_SIZE (result) - 1;
5046     
5047     if (size > 0)
5048     {
5049       emitcode ("mov", "c,b.7");
5050       emitcode ("subb", "a,acc");
5051     }
5052     while (size--)
5053     {
5054         aopPut (AOP (result), "a", offset++);
5055     }
5056     _G.accInUse--;     _G.bInUse--;
5057
5058 }
5059
5060 /*-----------------------------------------------------------------*/
5061 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5062 /*-----------------------------------------------------------------*/
5063 static void genDivTwoByte (operand *left, operand *right, 
5064                             operand *result, iCode *ic)
5065 {
5066         sym_link *retype = getSpec(operandType(right));
5067         sym_link *letype = getSpec(operandType(left));
5068         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5069         symbol *lbl;
5070
5071         /* save EA bit in F1 */
5072         lbl = newiTempLabel(NULL);
5073         emitcode ("setb","F1");
5074         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5075         emitcode ("clr","F1");
5076         emitcode("","!tlabeldef",lbl->key+100);
5077
5078         /* load up MA with left */
5079         if (!umult) {
5080                 emitcode("clr","F0");
5081                 lbl = newiTempLabel(NULL);
5082                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5083                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5084                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5085                 emitcode ("xch", "a,b");
5086                 emitcode ("cpl","a");
5087                 emitcode ("add", "a,#1");
5088                 emitcode ("xch", "a,b");
5089                 emitcode ("cpl", "a"); // msb
5090                 emitcode ("addc","a,#0");
5091                 emitcode ("setb","F0");
5092                 emitcode ("","!tlabeldef",lbl->key+100);
5093                 emitcode ("mov","ma,b");
5094                 emitcode ("mov","ma,a");
5095         } else {
5096                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5097                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5098         }
5099
5100         /* load up MB with right */
5101         if (!umult) {
5102                 if (AOP_TYPE(right) == AOP_LIT) {
5103                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5104                         if (val < 0) {
5105                                 lbl = newiTempLabel(NULL);
5106                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5107                                 emitcode("setb","F0");
5108                                 emitcode ("","!tlabeldef",lbl->key+100);
5109                                 val = -val;
5110                         } 
5111                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5112                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5113                 } else {
5114                         lbl = newiTempLabel(NULL);
5115                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5116                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5117                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5118                         emitcode ("xch", "a,b");
5119                         emitcode ("cpl","a");
5120                         emitcode ("add", "a,#1");
5121                         emitcode ("xch", "a,b");
5122                         emitcode ("cpl", "a"); // msb
5123                         emitcode ("addc", "a,#0");
5124                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5125                         emitcode ("setb","F0");
5126                         emitcode ("","!tlabeldef",lbl->key+100);
5127                         emitcode ("mov","mb,b");
5128                         emitcode ("mov","mb,a");
5129                 }
5130         } else {
5131                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5132                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5133         }
5134
5135         /* wait for multiplication to finish */
5136         lbl = newiTempLabel(NULL);
5137         emitcode("","!tlabeldef", lbl->key+100);
5138         emitcode("mov","a,mcnt1");
5139         emitcode("anl","a,#!constbyte",0x80);
5140         emitcode("jnz","!tlabel",lbl->key+100);
5141         
5142         freeAsmop (left, NULL, ic, TRUE);
5143         freeAsmop (right, NULL, ic,TRUE);
5144         aopOp(result, ic, TRUE, FALSE);
5145
5146         /* if unsigned then simple */   
5147         if (umult) {
5148                 aopPut(AOP(result),"ma",1);
5149                 aopPut(AOP(result),"ma",0);
5150         } else {
5151                 emitcode("push","ma");
5152                 MOVA("ma");
5153                 /* negate result if needed */
5154                 lbl = newiTempLabel(NULL);      
5155                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5156                 emitcode("cpl","a");
5157                 emitcode("add","a,#1");
5158                 emitcode("","!tlabeldef", lbl->key+100);
5159                 aopPut(AOP(result),"a",0);
5160                 emitcode("pop","acc");
5161                 lbl = newiTempLabel(NULL);      
5162                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5163                 emitcode("cpl","a");
5164                 emitcode("addc","a,#0");
5165                 emitcode("","!tlabeldef", lbl->key+100);
5166                 aopPut(AOP(result),"a",1);
5167         }
5168         freeAsmop (result, NULL, ic, TRUE);
5169         /* restore EA bit in F1 */
5170         lbl = newiTempLabel(NULL);
5171         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5172         emitcode ("setb","EA");
5173         emitcode("","!tlabeldef",lbl->key+100);
5174         return ;
5175 }
5176
5177 /*-----------------------------------------------------------------*/
5178 /* genDiv - generates code for division                            */
5179 /*-----------------------------------------------------------------*/
5180 static void
5181 genDiv (iCode * ic)
5182 {
5183   operand *left = IC_LEFT (ic);
5184   operand *right = IC_RIGHT (ic);
5185   operand *result = IC_RESULT (ic);
5186
5187   D (emitcode (";", "genDiv "););
5188
5189   /* assign the amsops */
5190   AOP_OP_2 (ic);
5191
5192   /* special cases first */
5193   /* both are bits */
5194   if (AOP_TYPE (left) == AOP_CRY &&
5195       AOP_TYPE (right) == AOP_CRY)
5196     {
5197       genDivbits (left, right, result, ic);
5198       goto release;
5199     }
5200
5201   /* if both are of size == 1 */
5202   if (AOP_SIZE (left) == 1 &&
5203       AOP_SIZE (right) == 1)
5204     {
5205       genDivOneByte (left, right, result, ic);
5206       goto release;
5207     }
5208
5209   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5210           /* use the ds390 ARITHMETIC accel UNIT */
5211           genDivTwoByte (left, right, result, ic);
5212           return ;
5213   }
5214   /* should have been converted to function call */
5215   assert (0);
5216 release:
5217   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219   freeAsmop (result, NULL, ic, TRUE);
5220 }
5221
5222 /*-----------------------------------------------------------------*/
5223 /* genModbits :- modulus of bits                                   */
5224 /*-----------------------------------------------------------------*/
5225 static void
5226 genModbits (operand * left,
5227             operand * right,
5228             operand * result,
5229             iCode   * ic)
5230 {
5231
5232   char *l;
5233
5234   /* the result must be bit */
5235   LOAD_AB_FOR_DIV (left, right, l);
5236   emitcode ("div", "ab");
5237   emitcode ("mov", "a,b");
5238   emitcode ("rrc", "a");
5239   aopOp(result, ic, TRUE, FALSE);
5240   aopPut (AOP (result), "c", 0);
5241 }
5242
5243 /*-----------------------------------------------------------------*/
5244 /* genModOneByte : 8 bit modulus                                   */
5245 /*-----------------------------------------------------------------*/
5246 static void
5247 genModOneByte (operand * left,
5248                operand * right,
5249                operand * result,
5250                iCode   * ic)
5251 {
5252   sym_link *opetype = operandType (result);
5253   char *l;
5254   symbol *lbl;
5255
5256   /* signed or unsigned */
5257   if (SPEC_USIGN (opetype))
5258     {
5259       /* unsigned is easy */
5260       LOAD_AB_FOR_DIV (left, right, l);
5261       emitcode ("div", "ab");
5262       aopOp(result, ic, TRUE, FALSE);   
5263       aopPut (AOP (result), "b", 0);
5264       return;
5265     }
5266
5267   /* signed is a little bit more difficult */
5268
5269   /* save the signs of the operands */
5270   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5271
5272   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5273   emitcode ("push", "acc");     /* save it on the stack */
5274
5275   /* now sign adjust for both left & right */
5276   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5277
5278   lbl = newiTempLabel (NULL);
5279   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5280   emitcode ("cpl", "a");
5281   emitcode ("inc", "a");
5282   emitcode ("", "!tlabeldef", (lbl->key + 100));
5283   emitcode ("mov", "b,a");
5284
5285   /* sign adjust left side */
5286   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5287
5288   lbl = newiTempLabel (NULL);
5289   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5290   emitcode ("cpl", "a");
5291   emitcode ("inc", "a");
5292   emitcode ("", "!tlabeldef", (lbl->key + 100));
5293
5294   /* now the multiplication */
5295   emitcode ("nop", "; workaround for DS80C390 div bug.");
5296   emitcode ("div", "ab");
5297   /* we are interested in the lower order
5298      only */
5299   lbl = newiTempLabel (NULL);
5300   emitcode ("pop", "acc");
5301   /* if there was an over flow we don't
5302      adjust the sign of the result */
5303   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5304   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5305   CLRC;
5306   emitcode ("clr", "a");
5307   emitcode ("subb", "a,b");
5308   emitcode ("mov", "b,a");
5309   emitcode ("", "!tlabeldef", (lbl->key + 100));
5310   
5311   _G.bInUse++;
5312   /* now we are done */
5313   aopOp(result, ic, TRUE, FALSE);    
5314   aopPut (AOP (result), "b", 0);
5315   _G.bInUse--;
5316
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5321 /*-----------------------------------------------------------------*/
5322 static void genModTwoByte (operand *left, operand *right, 
5323                             operand *result, iCode *ic)
5324 {
5325         sym_link *retype = getSpec(operandType(right));
5326         sym_link *letype = getSpec(operandType(left));
5327         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5328         symbol *lbl;
5329
5330         /* load up MA with left */
5331         /* save EA bit in F1 */
5332         lbl = newiTempLabel(NULL);
5333         emitcode ("setb","F1");
5334         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5335         emitcode ("clr","F1");
5336         emitcode("","!tlabeldef",lbl->key+100);
5337
5338         if (!umult) {
5339                 lbl = newiTempLabel(NULL);
5340                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5341                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5342                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5343                 emitcode ("xch", "a,b");
5344                 emitcode ("cpl","a");
5345                 emitcode ("add", "a,#1");
5346                 emitcode ("xch", "a,b");
5347                 emitcode ("cpl", "a"); // msb
5348                 emitcode ("addc","a,#0");
5349                 emitcode ("","!tlabeldef",lbl->key+100);
5350                 emitcode ("mov","ma,b");
5351                 emitcode ("mov","ma,a");
5352         } else {
5353                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5354                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5355         }
5356
5357         /* load up MB with right */
5358         if (!umult) {
5359                 if (AOP_TYPE(right) == AOP_LIT) {
5360                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5361                         if (val < 0) {
5362                                 val = -val;
5363                         } 
5364                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5365                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5366                 } else {
5367                         lbl = newiTempLabel(NULL);
5368                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5369                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5370                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5371                         emitcode ("xch", "a,b");
5372                         emitcode ("cpl","a");
5373                         emitcode ("add", "a,#1");
5374                         emitcode ("xch", "a,b");
5375                         emitcode ("cpl", "a"); // msb
5376                         emitcode ("addc", "a,#0");
5377                         emitcode ("","!tlabeldef",lbl->key+100);
5378                         emitcode ("mov","mb,b");
5379                         emitcode ("mov","mb,a");
5380                 }
5381         } else {
5382                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5383                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5384         }
5385
5386         /* wait for multiplication to finish */
5387         lbl = newiTempLabel(NULL);
5388         emitcode("","!tlabeldef", lbl->key+100);
5389         emitcode("mov","a,mcnt1");
5390         emitcode("anl","a,#!constbyte",0x80);
5391         emitcode("jnz","!tlabel",lbl->key+100);
5392         
5393         freeAsmop (left, NULL, ic, TRUE);
5394         freeAsmop (right, NULL, ic,TRUE);
5395         aopOp(result, ic, TRUE, FALSE);
5396
5397         aopPut(AOP(result),"mb",1);
5398         aopPut(AOP(result),"mb",0);
5399         freeAsmop (result, NULL, ic, TRUE);
5400
5401         /* restore EA bit in F1 */
5402         lbl = newiTempLabel(NULL);
5403         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5404         emitcode ("setb","EA");
5405         emitcode("","!tlabeldef",lbl->key+100);
5406         return ;
5407 }
5408
5409 /*-----------------------------------------------------------------*/
5410 /* genMod - generates code for division                            */
5411 /*-----------------------------------------------------------------*/
5412 static void
5413 genMod (iCode * ic)
5414 {
5415   operand *left = IC_LEFT (ic);
5416   operand *right = IC_RIGHT (ic);
5417   operand *result = IC_RESULT (ic);
5418
5419   D (emitcode (";", "genMod "); );
5420
5421   /* assign the amsops */
5422   AOP_OP_2 (ic);
5423
5424   /* special cases first */
5425   /* both are bits */
5426   if (AOP_TYPE (left) == AOP_CRY &&
5427       AOP_TYPE (right) == AOP_CRY)
5428     {
5429       genModbits (left, right, result, ic);
5430       goto release;
5431     }
5432
5433   /* if both are of size == 1 */
5434   if (AOP_SIZE (left) == 1 &&
5435       AOP_SIZE (right) == 1)
5436     {
5437       genModOneByte (left, right, result, ic);
5438       goto release;
5439     }
5440
5441   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5442           /* use the ds390 ARITHMETIC accel UNIT */
5443           genModTwoByte (left, right, result, ic);
5444           return ;
5445   }
5446
5447   /* should have been converted to function call */
5448   assert (0);
5449
5450 release:
5451   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5452   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5453   freeAsmop (result, NULL, ic, TRUE);
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* genIfxJump :- will create a jump depending on the ifx           */
5458 /*-----------------------------------------------------------------*/
5459 static void
5460 genIfxJump (iCode * ic, char *jval)
5461 {
5462   symbol *jlbl;
5463   symbol *tlbl = newiTempLabel (NULL);
5464   char *inst;
5465
5466   D (emitcode (";", "genIfxJump"););
5467
5468   /* if true label then we jump if condition
5469      supplied is true */
5470   if (IC_TRUE (ic))
5471     {
5472       jlbl = IC_TRUE (ic);
5473       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5474                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5475     }
5476   else
5477     {
5478       /* false label is present */
5479       jlbl = IC_FALSE (ic);
5480       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5481                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5482     }
5483   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5484     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5485   else
5486     emitcode (inst, "!tlabel", tlbl->key + 100);
5487   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5488   emitcode ("", "!tlabeldef", tlbl->key + 100);
5489
5490   /* mark the icode as generated */
5491   ic->generated = 1;
5492 }
5493
5494 /*-----------------------------------------------------------------*/
5495 /* genCmp :- greater or less than comparison                       */
5496 /*-----------------------------------------------------------------*/
5497 static void
5498 genCmp (operand * left, operand * right,
5499         iCode * ic, iCode * ifx, int sign)
5500 {
5501   int size, offset = 0;
5502   unsigned long lit = 0L;
5503   operand *result;
5504
5505   D (emitcode (";", "genCmp"););
5506
5507   result = IC_RESULT (ic);
5508
5509   /* if left & right are bit variables */
5510   if (AOP_TYPE (left) == AOP_CRY &&
5511       AOP_TYPE (right) == AOP_CRY)
5512     {
5513       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5514       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5515     }
5516   else
5517     {
5518       /* subtract right from left if at the
5519          end the carry flag is set then we know that
5520          left is greater than right */
5521       size = max (AOP_SIZE (left), AOP_SIZE (right));
5522
5523       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5524       if ((size == 1) && !sign 
5525           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5526         {
5527           symbol *lbl = newiTempLabel (NULL);
5528           emitcode ("cjne", "%s,%s,!tlabel",
5529                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5530                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5531                     lbl->key + 100);
5532           emitcode ("", "!tlabeldef", lbl->key + 100);
5533         }
5534       else
5535         {
5536           if (AOP_TYPE (right) == AOP_LIT)
5537             {
5538               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5539               /* optimize if(x < 0) or if(x >= 0) */
5540               if (lit == 0L)
5541                 {
5542                   if (!sign)
5543                     {
5544                       CLRC;
5545                     }
5546                   else
5547                     {
5548                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5549
5550                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5551                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5552
5553                       aopOp (result, ic, FALSE, FALSE);
5554
5555                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5556                         {
5557                           freeAsmop (result, NULL, ic, TRUE);
5558                           genIfxJump (ifx, "acc.7");
5559                           return;
5560                         }
5561                       else
5562                         {
5563                           emitcode ("rlc", "a");
5564                         }
5565                       goto release_freedLR;
5566                     }
5567                   goto release;
5568                 }
5569             }
5570           CLRC;
5571           while (size--)
5572             {
5573               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5574               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5575               // emitcode (";", "genCmp #2");
5576               if (sign && (size == 0))
5577                 {
5578                   // emitcode (";", "genCmp #3");
5579                   emitcode ("xrl", "a,#!constbyte",0x80);
5580                   if (AOP_TYPE (right) == AOP_LIT)
5581                     {
5582                       unsigned long lit = (unsigned long)
5583                       floatFromVal (AOP (right)->aopu.aop_lit);
5584                       // emitcode (";", "genCmp #3.1");
5585                       emitcode ("subb", "a,#!constbyte",
5586                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5587                     }
5588                   else
5589                     {
5590                       // emitcode (";", "genCmp #3.2");
5591                       saveAccWarn = 0;  
5592                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5593                       saveAccWarn = DEFAULT_ACC_WARNING;
5594                       emitcode ("xrl", "b,#!constbyte",0x80);
5595                       emitcode ("subb", "a,b");
5596                     }
5597                 }
5598               else
5599                 {
5600                   const char *s;
5601
5602                   // emitcode (";", "genCmp #4");
5603                   saveAccWarn = 0;
5604                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5605                   saveAccWarn = DEFAULT_ACC_WARNING;
5606
5607                   emitcode ("subb", "a,%s", s);
5608                 }
5609             }
5610         }
5611     }
5612
5613 release:
5614 /* Don't need the left & right operands any more; do need the result. */
5615   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5616   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5617
5618   aopOp (result, ic, FALSE, FALSE);
5619
5620 release_freedLR:
5621
5622   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5623     {
5624       outBitC (result);
5625     }
5626   else
5627     {
5628       /* if the result is used in the next
5629          ifx conditional branch then generate
5630          code a little differently */
5631       if (ifx)
5632         {
5633           genIfxJump (ifx, "c");
5634         }
5635       else
5636         {
5637           outBitC (result);
5638         }
5639       /* leave the result in acc */
5640     }
5641   freeAsmop (result, NULL, ic, TRUE);
5642 }
5643
5644 /*-----------------------------------------------------------------*/
5645 /* genCmpGt :- greater than comparison                             */
5646 /*-----------------------------------------------------------------*/
5647 static void
5648 genCmpGt (iCode * ic, iCode * ifx)
5649 {
5650   operand *left, *right;
5651   sym_link *letype, *retype;
5652   int sign;
5653
5654   D (emitcode (";", "genCmpGt ");
5655     );
5656
5657   left = IC_LEFT (ic);
5658   right = IC_RIGHT (ic);
5659
5660   letype = getSpec (operandType (left));
5661   retype = getSpec (operandType (right));
5662   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5663
5664   /* assign the left & right amsops */
5665   AOP_OP_2 (ic);
5666
5667   genCmp (right, left, ic, ifx, sign);
5668 }
5669
5670 /*-----------------------------------------------------------------*/
5671 /* genCmpLt - less than comparisons                                */
5672 /*-----------------------------------------------------------------*/
5673 static void
5674 genCmpLt (iCode * ic, iCode * ifx)
5675 {
5676   operand *left, *right;
5677   sym_link *letype, *retype;
5678   int sign;
5679
5680   D (emitcode (";", "genCmpLt "););
5681
5682   left = IC_LEFT (ic);
5683   right = IC_RIGHT (ic);
5684
5685   letype = getSpec (operandType (left));
5686   retype = getSpec (operandType (right));
5687   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5688
5689   /* assign the left & right amsops */
5690   AOP_OP_2 (ic);
5691
5692   genCmp (left, right, ic, ifx, sign);
5693 }
5694
5695 /*-----------------------------------------------------------------*/
5696 /* gencjneshort - compare and jump if not equal                    */
5697 /*-----------------------------------------------------------------*/
5698 static void
5699 gencjneshort (operand * left, operand * right, symbol * lbl)
5700 {
5701   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5702   int offset = 0;
5703   unsigned long lit = 0L;
5704
5705   D (emitcode (";", "gencjneshort");
5706     );
5707
5708   /* if the left side is a literal or
5709      if the right is in a pointer register and left
5710      is not */
5711   if ((AOP_TYPE (left) == AOP_LIT) ||
5712       (AOP_TYPE (left) == AOP_IMMD) ||
5713       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5714     {
5715       operand *t = right;
5716       right = left;
5717       left = t;
5718     }
5719
5720   if (AOP_TYPE (right) == AOP_LIT)
5721     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5722
5723   if (opIsGptr (left) || opIsGptr (right))
5724     {
5725       /* We are comparing a generic pointer to something.
5726        * Exclude the generic type byte from the comparison.
5727        */
5728       size--;
5729       D (emitcode (";", "cjneshort: generic ptr special case."););
5730     }
5731
5732
5733   /* if the right side is a literal then anything goes */
5734   if (AOP_TYPE (right) == AOP_LIT &&
5735       AOP_TYPE (left) != AOP_DIR)
5736     {
5737       while (size--)
5738         {
5739           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5740           emitcode ("cjne", "a,%s,!tlabel",
5741                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5742                     lbl->key + 100);
5743           offset++;
5744         }
5745     }
5746
5747   /* if the right side is in a register or in direct space or
5748      if the left is a pointer register & right is not */
5749   else if (AOP_TYPE (right) == AOP_REG ||
5750            AOP_TYPE (right) == AOP_DIR ||
5751            AOP_TYPE (right) == AOP_LIT ||
5752            AOP_TYPE (right) == AOP_IMMD ||
5753            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5754            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5755     {
5756       while (size--)
5757         {
5758           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5759           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5760               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5761             emitcode ("jnz", "!tlabel", lbl->key + 100);
5762           else
5763             emitcode ("cjne", "a,%s,!tlabel",
5764                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5765                       lbl->key + 100);
5766           offset++;
5767         }
5768     }
5769   else
5770     {
5771       /* right is a pointer reg need both a & b */
5772       while (size--)
5773         {
5774           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5775           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5776           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5777           offset++;
5778         }
5779     }
5780 }
5781
5782 /*-----------------------------------------------------------------*/
5783 /* gencjne - compare and jump if not equal                         */
5784 /*-----------------------------------------------------------------*/
5785 static void
5786 gencjne (operand * left, operand * right, symbol * lbl)
5787 {
5788   symbol *tlbl = newiTempLabel (NULL);
5789
5790   D (emitcode (";", "gencjne");
5791     );
5792
5793   gencjneshort (left, right, lbl);
5794
5795   emitcode ("mov", "a,%s", one);
5796   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5797   emitcode ("", "!tlabeldef", lbl->key + 100);
5798   emitcode ("clr", "a");
5799   emitcode ("", "!tlabeldef", tlbl->key + 100);
5800 }
5801
5802 /*-----------------------------------------------------------------*/
5803 /* genCmpEq - generates code for equal to                          */
5804 /*-----------------------------------------------------------------*/
5805 static void
5806 genCmpEq (iCode * ic, iCode * ifx)
5807 {
5808   operand *left, *right, *result;
5809
5810   D (emitcode (";", "genCmpEq ");
5811     );
5812
5813   AOP_OP_2 (ic);
5814   AOP_SET_LOCALS (ic);
5815
5816   /* if literal, literal on the right or
5817      if the right is in a pointer register and left
5818      is not */
5819   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5820       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5821     {
5822       operand *t = IC_RIGHT (ic);
5823       IC_RIGHT (ic) = IC_LEFT (ic);
5824       IC_LEFT (ic) = t;
5825     }
5826
5827   if (ifx &&                    /* !AOP_SIZE(result) */
5828       OP_SYMBOL (result) &&
5829       OP_SYMBOL (result)->regType == REG_CND)
5830     {
5831       symbol *tlbl;
5832       /* if they are both bit variables */
5833       if (AOP_TYPE (left) == AOP_CRY &&
5834           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5835         {
5836           if (AOP_TYPE (right) == AOP_LIT)
5837             {
5838               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5839               if (lit == 0L)
5840                 {
5841                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5842                   emitcode ("cpl", "c");
5843                 }
5844               else if (lit == 1L)
5845                 {
5846                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5847                 }
5848               else
5849                 {
5850                   emitcode ("clr", "c");
5851                 }
5852               /* AOP_TYPE(right) == AOP_CRY */
5853             }
5854           else
5855             {
5856               symbol *lbl = newiTempLabel (NULL);
5857               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5858               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5859               emitcode ("cpl", "c");
5860               emitcode ("", "!tlabeldef", (lbl->key + 100));
5861             }
5862           /* if true label then we jump if condition
5863              supplied is true */
5864           tlbl = newiTempLabel (NULL);
5865           if (IC_TRUE (ifx))
5866             {
5867               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5868               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5869             }
5870           else
5871             {
5872               emitcode ("jc", "!tlabel", tlbl->key + 100);
5873               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5874             }
5875           emitcode ("", "!tlabeldef", tlbl->key + 100);
5876         }
5877       else
5878         {
5879           tlbl = newiTempLabel (NULL);
5880           gencjneshort (left, right, tlbl);
5881           if (IC_TRUE (ifx))
5882             {
5883               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5884               emitcode ("", "!tlabeldef", tlbl->key + 100);
5885             }
5886           else
5887             {
5888               symbol *lbl = newiTempLabel (NULL);
5889               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5890               emitcode ("", "!tlabeldef", tlbl->key + 100);
5891               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5892               emitcode ("", "!tlabeldef", lbl->key + 100);
5893             }
5894         }
5895       /* mark the icode as generated */
5896       ifx->generated = 1;
5897
5898       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5899       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5900       return;
5901     }
5902
5903   /* if they are both bit variables */
5904   if (AOP_TYPE (left) == AOP_CRY &&
5905       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5906     {
5907       if (AOP_TYPE (right) == AOP_LIT)
5908         {
5909           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5910           if (lit == 0L)
5911             {
5912               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5913               emitcode ("cpl", "c");
5914             }
5915           else if (lit == 1L)
5916             {
5917               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5918             }
5919           else
5920             {
5921               emitcode ("clr", "c");
5922             }
5923           /* AOP_TYPE(right) == AOP_CRY */
5924         }
5925       else
5926         {
5927           symbol *lbl = newiTempLabel (NULL);
5928           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5929           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5930           emitcode ("cpl", "c");
5931           emitcode ("", "!tlabeldef", (lbl->key + 100));
5932         }
5933
5934       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5936
5937       aopOp (result, ic, TRUE, FALSE);
5938
5939       /* c = 1 if egal */
5940       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5941         {
5942           outBitC (result);
5943           goto release;
5944         }
5945       if (ifx)
5946         {
5947           genIfxJump (ifx, "c");
5948           goto release;
5949         }
5950       /* if the result is used in an arithmetic operation
5951          then put the result in place */
5952       outBitC (result);
5953     }
5954   else
5955     {
5956       gencjne (left, right, newiTempLabel (NULL));
5957
5958       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5960
5961       aopOp (result, ic, TRUE, FALSE);
5962
5963       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5964         {
5965           aopPut (AOP (result), "a", 0);
5966           goto release;
5967         }
5968       if (ifx)
5969         {
5970           genIfxJump (ifx, "a");
5971           goto release;
5972         }
5973       /* if the result is used in an arithmetic operation
5974          then put the result in place */
5975       if (AOP_TYPE (result) != AOP_CRY)
5976         outAcc (result);
5977       /* leave the result in acc */
5978     }
5979
5980 release:
5981   freeAsmop (result, NULL, ic, TRUE);
5982 }
5983
5984 /*-----------------------------------------------------------------*/
5985 /* ifxForOp - returns the icode containing the ifx for operand     */
5986 /*-----------------------------------------------------------------*/
5987 static iCode *
5988 ifxForOp (operand * op, iCode * ic)
5989 {
5990   /* if true symbol then needs to be assigned */
5991   if (IS_TRUE_SYMOP (op))
5992     return NULL;
5993
5994   /* if this has register type condition and
5995      the next instruction is ifx with the same operand
5996      and live to of the operand is upto the ifx only then */
5997   if (ic->next &&
5998       ic->next->op == IFX &&
5999       IC_COND (ic->next)->key == op->key &&
6000       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6001     return ic->next;
6002
6003   return NULL;
6004 }
6005 /*-----------------------------------------------------------------*/
6006 /* hasInc - operand is incremented before any other use            */
6007 /*-----------------------------------------------------------------*/
6008 static iCode *
6009 hasInc (operand *op, iCode *ic, int osize)
6010 {
6011   sym_link *type = operandType(op);
6012   sym_link *retype = getSpec (type);
6013   iCode *lic = ic->next;
6014   int isize ;
6015   
6016   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6017   if (!IS_SYMOP(op)) return NULL;
6018
6019   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6020   if (IS_AGGREGATE(type->next)) return NULL;
6021   if (osize != (isize = getSize(type->next))) return NULL;
6022
6023   while (lic) {
6024       /* if operand of the form op = op + <sizeof *op> */
6025       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6026           isOperandEqual(IC_RESULT(lic),op) && 
6027           isOperandLiteral(IC_RIGHT(lic)) &&
6028           operandLitValue(IC_RIGHT(lic)) == isize) {
6029           return lic;
6030       }
6031       /* if the operand used or deffed */
6032       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
6033           return NULL;
6034       }
6035       /* if GOTO or IFX */
6036       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6037       lic = lic->next;
6038   }
6039   return NULL;
6040 }
6041
6042 /*-----------------------------------------------------------------*/
6043 /* genAndOp - for && operation                                     */
6044 /*-----------------------------------------------------------------*/
6045 static void
6046 genAndOp (iCode * ic)
6047 {
6048   operand *left, *right, *result;
6049   symbol *tlbl;
6050
6051   D (emitcode (";", "genAndOp "););
6052
6053   /* note here that && operations that are in an
6054      if statement are taken away by backPatchLabels
6055      only those used in arthmetic operations remain */
6056   AOP_OP_2 (ic);
6057   AOP_SET_LOCALS (ic);
6058
6059   /* if both are bit variables */
6060   if (AOP_TYPE (left) == AOP_CRY &&
6061       AOP_TYPE (right) == AOP_CRY)
6062     {
6063       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6064       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6065       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6066       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6067   
6068       aopOp (result,ic,FALSE, FALSE);
6069       outBitC (result);
6070     }
6071   else
6072     {
6073       tlbl = newiTempLabel (NULL);
6074       toBoolean (left);
6075       emitcode ("jz", "!tlabel", tlbl->key + 100);
6076       toBoolean (right);
6077       emitcode ("", "!tlabeldef", tlbl->key + 100);
6078       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6079       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6080   
6081       aopOp (result,ic,FALSE, FALSE);
6082       outBitAcc (result);
6083     }
6084     freeAsmop (result, NULL, ic, TRUE);
6085 }
6086
6087
6088 /*-----------------------------------------------------------------*/
6089 /* genOrOp - for || operation                                      */
6090 /*-----------------------------------------------------------------*/
6091 static void
6092 genOrOp (iCode * ic)
6093 {
6094   operand *left, *right, *result;
6095   symbol *tlbl;
6096
6097   D (emitcode (";", "genOrOp "););
6098
6099   /* note here that || operations that are in an
6100      if statement are taken away by backPatchLabels
6101      only those used in arthmetic operations remain */
6102   AOP_OP_2 (ic);
6103   AOP_SET_LOCALS (ic);
6104
6105   /* if both are bit variables */
6106   if (AOP_TYPE (left) == AOP_CRY &&
6107       AOP_TYPE (right) == AOP_CRY)
6108     {
6109       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6110       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6111       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6112       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6113   
6114       aopOp (result,ic,FALSE, FALSE);
6115       
6116       outBitC (result);
6117     }
6118   else
6119     {
6120       tlbl = newiTempLabel (NULL);
6121       toBoolean (left);
6122       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6123       toBoolean (right);
6124       emitcode ("", "!tlabeldef", tlbl->key + 100);
6125       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6126       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6127   
6128       aopOp (result,ic,FALSE, FALSE);
6129       
6130       outBitAcc (result);
6131     }
6132
6133   freeAsmop (result, NULL, ic, TRUE);
6134 }
6135
6136 /*-----------------------------------------------------------------*/
6137 /* isLiteralBit - test if lit == 2^n                               */
6138 /*-----------------------------------------------------------------*/
6139 static int
6140 isLiteralBit (unsigned long lit)
6141 {
6142   unsigned long pw[32] =
6143   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6144    0x100L, 0x200L, 0x400L, 0x800L,
6145    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6146    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6147    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6148    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6149    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6150   int idx;
6151
6152   for (idx = 0; idx < 32; idx++)
6153     if (lit == pw[idx])
6154       return idx + 1;
6155   return 0;
6156 }
6157
6158 /*-----------------------------------------------------------------*/
6159 /* continueIfTrue -                                                */
6160 /*-----------------------------------------------------------------*/
6161 static void
6162 continueIfTrue (iCode * ic)
6163 {
6164   if (IC_TRUE (ic))
6165     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6166   ic->generated = 1;
6167 }
6168
6169 /*-----------------------------------------------------------------*/
6170 /* jmpIfTrue -                                                     */
6171 /*-----------------------------------------------------------------*/
6172 static void
6173 jumpIfTrue (iCode * ic)
6174 {
6175   if (!IC_TRUE (ic))
6176     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6177   ic->generated = 1;
6178 }
6179
6180 /*-----------------------------------------------------------------*/
6181 /* jmpTrueOrFalse -                                                */
6182 /*-----------------------------------------------------------------*/
6183 static void
6184 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6185 {
6186   // ugly but optimized by peephole
6187   if (IC_TRUE (ic))
6188     {
6189       symbol *nlbl = newiTempLabel (NULL);
6190       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6191       emitcode ("", "!tlabeldef", tlbl->key + 100);
6192       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6193       emitcode ("", "!tlabeldef", nlbl->key + 100);
6194     }
6195   else
6196     {
6197       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6198       emitcode ("", "!tlabeldef", tlbl->key + 100);
6199     }
6200   ic->generated = 1;
6201 }
6202
6203 // Generate code to perform a bit-wise logic operation
6204 // on two operands in far space (assumed to already have been 
6205 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6206 // in far space. This requires pushing the result on the stack
6207 // then popping it into the result.
6208 static void
6209 genFarFarLogicOp(iCode *ic, char *logicOp)
6210 {
6211       int size, resultSize, compSize;
6212       int offset = 0;
6213       
6214       TR_AP("#5");
6215       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6216       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6217                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6218       
6219       _startLazyDPSEvaluation();
6220       for (size = compSize; (size--); offset++)
6221       {
6222           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6223           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6224           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6225           
6226           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6227           emitcode ("push", "acc");
6228       }
6229       _endLazyDPSEvaluation();
6230      
6231       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6232       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6233       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6234      
6235       resultSize = AOP_SIZE(IC_RESULT(ic));
6236
6237       ADJUST_PUSHED_RESULT(compSize, resultSize);
6238
6239       _startLazyDPSEvaluation();
6240       while (compSize--)
6241       {
6242           emitcode ("pop", "acc");
6243           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6244       }
6245       _endLazyDPSEvaluation();
6246       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6247 }
6248
6249
6250 /*-----------------------------------------------------------------*/
6251 /* genAnd  - code for and                                          */
6252 /*-----------------------------------------------------------------*/
6253 static void
6254 genAnd (iCode * ic, iCode * ifx)
6255 {
6256   operand *left, *right, *result;
6257   int size, offset = 0;
6258   unsigned long lit = 0L;
6259   int bytelit;
6260   char buff[10];
6261   bool pushResult;
6262
6263   D (emitcode (";", "genAnd "););
6264
6265   AOP_OP_3_NOFATAL (ic, pushResult);
6266   AOP_SET_LOCALS (ic);
6267
6268   if (pushResult)
6269   {
6270       genFarFarLogicOp(ic, "anl");
6271       return;
6272   }  
6273
6274 #ifdef DEBUG_TYPE
6275   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6276             AOP_TYPE (result),
6277             AOP_TYPE (left), AOP_TYPE (right));
6278   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6279             AOP_SIZE (result),
6280             AOP_SIZE (left), AOP_SIZE (right));
6281 #endif
6282
6283   /* if left is a literal & right is not then exchange them */
6284   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6285 #ifdef LOGIC_OPS_BROKEN      
6286     ||  AOP_NEEDSACC (left)
6287 #endif
6288     )
6289     {
6290       operand *tmp = right;
6291       right = left;
6292       left = tmp;
6293     }
6294
6295   /* if result = right then exchange them */
6296   if (sameRegs (AOP (result), AOP (right)))
6297     {
6298       operand *tmp = right;
6299       right = left;
6300       left = tmp;
6301     }
6302
6303   /* if right is bit then exchange them */
6304   if (AOP_TYPE (right) == AOP_CRY &&
6305       AOP_TYPE (left) != AOP_CRY)
6306     {
6307       operand *tmp = right;
6308       right = left;
6309       left = tmp;
6310     }
6311   if (AOP_TYPE (right) == AOP_LIT)
6312     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6313
6314   size = AOP_SIZE (result);
6315
6316   // if(bit & yy)
6317   // result = bit & yy;
6318   if (AOP_TYPE (left) == AOP_CRY)
6319     {
6320       // c = bit & literal;
6321       if (AOP_TYPE (right) == AOP_LIT)
6322         {
6323           if (lit & 1)
6324             {
6325               if (size && sameRegs (AOP (result), AOP (left)))
6326                 // no change
6327                 goto release;
6328               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6329             }
6330           else
6331             {
6332               // bit(result) = 0;
6333               if (size && (AOP_TYPE (result) == AOP_CRY))
6334                 {
6335                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6336                   goto release;
6337                 }
6338               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6339                 {
6340                   jumpIfTrue (ifx);
6341                   goto release;
6342                 }
6343               emitcode ("clr", "c");
6344             }
6345         }
6346       else
6347         {
6348           if (AOP_TYPE (right) == AOP_CRY)
6349             {
6350               // c = bit & bit;
6351               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6352               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6353             }
6354           else
6355             {
6356               // c = bit & val;
6357               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6358               // c = lsb
6359               emitcode ("rrc", "a");
6360               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6361             }
6362         }
6363       // bit = c
6364       // val = c
6365       if (size)
6366         outBitC (result);
6367       // if(bit & ...)
6368       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6369         genIfxJump (ifx, "c");
6370       goto release;
6371     }
6372
6373   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6374   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6375   if ((AOP_TYPE (right) == AOP_LIT) &&
6376       (AOP_TYPE (result) == AOP_CRY) &&
6377       (AOP_TYPE (left) != AOP_CRY))
6378     {
6379       int posbit = isLiteralBit (lit);
6380       /* left &  2^n */
6381       if (posbit)
6382         {
6383           posbit--;
6384           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6385           // bit = left & 2^n
6386           if (size)
6387             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6388           // if(left &  2^n)
6389           else
6390             {
6391               if (ifx)
6392                 {
6393                   SNPRINTF (buff, sizeof(buff), 
6394                             "acc.%d", posbit & 0x07);
6395                   genIfxJump (ifx, buff);
6396                 }
6397               else 
6398                   {
6399                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6400                   }
6401               goto release;
6402             }
6403         }
6404       else
6405         {
6406           symbol *tlbl = newiTempLabel (NULL);
6407           int sizel = AOP_SIZE (left);
6408           if (size)
6409             emitcode ("setb", "c");
6410           while (sizel--)
6411             {
6412               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6413                 {
6414                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6415                   // byte ==  2^n ?
6416                   if ((posbit = isLiteralBit (bytelit)) != 0)
6417                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6418                   else
6419                     {
6420                       if (bytelit != 0x0FFL)
6421                         emitcode ("anl", "a,%s",
6422                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6423                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6424                     }
6425                 }
6426               offset++;
6427             }
6428           // bit = left & literal
6429           if (size)
6430             {
6431               emitcode ("clr", "c");
6432               emitcode ("", "!tlabeldef", tlbl->key + 100);
6433             }
6434           // if(left & literal)
6435           else
6436             {
6437               if (ifx)
6438                 jmpTrueOrFalse (ifx, tlbl);
6439               else
6440                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6441               goto release;
6442             }
6443         }
6444       outBitC (result);
6445       goto release;
6446     }
6447
6448   /* if left is same as result */
6449   if (sameRegs (AOP (result), AOP (left)))
6450     {
6451       for (; size--; offset++)
6452         {
6453           if (AOP_TYPE (right) == AOP_LIT)
6454             {
6455               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6456                 continue;
6457               else if (bytelit == 0)
6458                 aopPut (AOP (result), zero, offset);
6459               else if (IS_AOP_PREG (result))
6460                 {
6461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462                   emitcode ("anl", "a,%s",
6463                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6464                   aopPut (AOP (result), "a", offset);
6465                 }
6466               else
6467                 emitcode ("anl", "%s,%s",
6468                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6469                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6470             }
6471           else
6472             {
6473               if (AOP_TYPE (left) == AOP_ACC)
6474                 emitcode ("anl", "a,%s",
6475                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6476               else
6477                 {
6478                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6479                   if (IS_AOP_PREG (result))
6480                     {
6481                       emitcode ("anl", "a,%s",
6482                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6483                       aopPut (AOP (result), "a", offset);
6484                     }
6485                   else
6486                     emitcode ("anl", "%s,a",
6487                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6488                 }
6489             }
6490         }
6491     }
6492   else
6493     {
6494       // left & result in different registers
6495       if (AOP_TYPE (result) == AOP_CRY)
6496         {
6497           // result = bit
6498           // if(size), result in bit
6499           // if(!size && ifx), conditional oper: if(left & right)
6500           symbol *tlbl = newiTempLabel (NULL);
6501           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6502           if (size)
6503             emitcode ("setb", "c");
6504           while (sizer--)
6505             {
6506               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6507                 emitcode ("anl", "a,%s",
6508                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6509               } else {
6510                 if (AOP_TYPE(left)==AOP_ACC) {
6511                   emitcode("mov", "b,a");
6512                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6513                   emitcode("anl", "a,b");
6514                 }else {
6515                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6516                   emitcode ("anl", "a,%s",
6517                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6518                 }
6519               }
6520               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6521               offset++;
6522             }
6523           if (size)
6524             {
6525               CLRC;
6526               emitcode ("", "!tlabeldef", tlbl->key + 100);
6527               outBitC (result);
6528             }
6529           else if (ifx)
6530             jmpTrueOrFalse (ifx, tlbl);
6531           else
6532             emitcode ("", "!tlabeldef", tlbl->key + 100);
6533         }
6534       else
6535         {
6536           for (; (size--); offset++)
6537             {
6538               // normal case
6539               // result = left & right
6540               if (AOP_TYPE (right) == AOP_LIT)
6541                 {
6542                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6543                     {
6544                       aopPut (AOP (result),
6545                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6546                               offset);
6547                       continue;
6548                     }
6549                   else if (bytelit == 0)
6550                     {
6551                       aopPut (AOP (result), zero, offset);
6552                       continue;
6553                     }
6554                   D (emitcode (";", "better literal AND."););
6555                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6556                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6557                                                     FALSE, FALSE, DP2_RESULT_REG));
6558
6559                 }
6560               else
6561                 {
6562                   // faster than result <- left, anl result,right
6563                   // and better if result is SFR
6564                   if (AOP_TYPE (left) == AOP_ACC)
6565                     {
6566                       emitcode ("anl", "a,%s", 
6567                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6568                     }
6569                   else
6570                     {
6571                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6572                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6573                       {
6574                           emitcode("mov", "b,a");
6575                           rOp = "b";
6576                       }
6577                         
6578                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6579                       emitcode ("anl", "a,%s", rOp);
6580                     }                   
6581                 }
6582               aopPut (AOP (result), "a", offset);
6583             }
6584         }
6585     }
6586
6587 release:
6588   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6589   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6590   freeAsmop (result, NULL, ic, TRUE);
6591 }
6592
6593
6594 /*-----------------------------------------------------------------*/
6595 /* genOr  - code for or                                            */
6596 /*-----------------------------------------------------------------*/
6597 static void
6598 genOr (iCode * ic, iCode * ifx)
6599 {
6600   operand *left, *right, *result;
6601   int size, offset = 0;
6602   unsigned long lit = 0L;
6603   bool     pushResult;
6604
6605   D (emitcode (";", "genOr "););
6606
6607   AOP_OP_3_NOFATAL (ic, pushResult);
6608   AOP_SET_LOCALS (ic);
6609
6610   if (pushResult)
6611   {
6612       genFarFarLogicOp(ic, "orl");
6613       return;
6614   }
6615
6616
6617 #ifdef DEBUG_TYPE
6618   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6619             AOP_TYPE (result),
6620             AOP_TYPE (left), AOP_TYPE (right));
6621   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6622             AOP_SIZE (result),
6623             AOP_SIZE (left), AOP_SIZE (right));
6624 #endif
6625
6626   /* if left is a literal & right is not then exchange them */
6627   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6628 #ifdef LOGIC_OPS_BROKEN
6629    || AOP_NEEDSACC (left) // I think this is a net loss now.
6630 #endif      
6631       )
6632     {
6633       operand *tmp = right;
6634       right = left;
6635       left = tmp;
6636     }
6637
6638   /* if result = right then exchange them */
6639   if (sameRegs (AOP (result), AOP (right)))
6640     {
6641       operand *tmp = right;
6642       right = left;
6643       left = tmp;
6644     }
6645
6646   /* if right is bit then exchange them */
6647   if (AOP_TYPE (right) == AOP_CRY &&
6648       AOP_TYPE (left) != AOP_CRY)
6649     {
6650       operand *tmp = right;
6651       right = left;
6652       left = tmp;
6653     }
6654   if (AOP_TYPE (right) == AOP_LIT)
6655     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6656
6657   size = AOP_SIZE (result);
6658
6659   // if(bit | yy)
6660   // xx = bit | yy;
6661   if (AOP_TYPE (left) == AOP_CRY)
6662     {
6663       if (AOP_TYPE (right) == AOP_LIT)
6664         {
6665           // c = bit & literal;
6666           if (lit)
6667             {
6668               // lit != 0 => result = 1
6669               if (AOP_TYPE (result) == AOP_CRY)
6670                 {
6671                   if (size)
6672                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6673                   else if (ifx)
6674                     continueIfTrue (ifx);
6675                   goto release;
6676                 }
6677               emitcode ("setb", "c");
6678             }
6679           else
6680             {
6681               // lit == 0 => result = left
6682               if (size && sameRegs (AOP (result), AOP (left)))
6683                 goto release;
6684               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6685             }
6686         }
6687       else
6688         {
6689           if (AOP_TYPE (right) == AOP_CRY)
6690             {
6691               // c = bit | bit;
6692               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6693               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6694             }
6695           else
6696             {
6697               // c = bit | val;
6698               symbol *tlbl = newiTempLabel (NULL);
6699               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6700                 emitcode ("setb", "c");
6701               emitcode ("jb", "%s,!tlabel",
6702                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6703               toBoolean (right);
6704               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6705               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6706                 {
6707                   jmpTrueOrFalse (ifx, tlbl);
6708                   goto release;
6709                 }
6710               else
6711                 {
6712                   CLRC;
6713                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6714                 }
6715             }
6716         }
6717       // bit = c
6718       // val = c
6719       if (size)
6720         outBitC (result);
6721       // if(bit | ...)
6722       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6723            genIfxJump (ifx, "c");
6724       goto release;
6725     }
6726
6727   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6728   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6729   if ((AOP_TYPE (right) == AOP_LIT) &&
6730       (AOP_TYPE (result) == AOP_CRY) &&
6731       (AOP_TYPE (left) != AOP_CRY))
6732     {
6733       if (lit)
6734         {
6735           // result = 1
6736           if (size)
6737             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6738           else
6739             continueIfTrue (ifx);
6740           goto release;
6741         }
6742       else
6743         {
6744           // lit = 0, result = boolean(left)
6745           if (size)
6746             emitcode ("setb", "c");
6747           toBoolean (right);
6748           if (size)
6749             {
6750               symbol *tlbl = newiTempLabel (NULL);
6751               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6752               CLRC;
6753               emitcode ("", "!tlabeldef", tlbl->key + 100);
6754             }
6755           else
6756             {
6757               genIfxJump (ifx, "a");
6758               goto release;
6759             }
6760         }
6761       outBitC (result);
6762       goto release;
6763     }
6764
6765   /* if left is same as result */
6766   if (sameRegs (AOP (result), AOP (left)))
6767     {
6768       for (; size--; offset++)
6769         {
6770           if (AOP_TYPE (right) == AOP_LIT)
6771             {
6772               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6773                 {
6774                   continue;
6775                 }
6776               else
6777                 {
6778                   if (IS_AOP_PREG (left))
6779                     {
6780                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6781                       emitcode ("orl", "a,%s",
6782                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6783                       aopPut (AOP (result), "a", offset);
6784                     }
6785                   else
6786                     {
6787                       emitcode ("orl", "%s,%s",
6788                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6789                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6790                     }
6791                 }
6792             }
6793           else
6794             {
6795               if (AOP_TYPE (left) == AOP_ACC)
6796                 {
6797                   emitcode ("orl", "a,%s",
6798                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6799                 }
6800               else
6801                 {
6802                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6803                   if (IS_AOP_PREG (left))
6804                     {
6805                       emitcode ("orl", "a,%s", 
6806                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6807                       aopPut (AOP (result), "a", offset);
6808                     }
6809                   else
6810                     {
6811                       emitcode ("orl", "%s,a",
6812                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6813                     }
6814                 }
6815             }
6816         }
6817     }
6818   else
6819     {
6820       // left & result in different registers
6821       if (AOP_TYPE (result) == AOP_CRY)
6822         {
6823           // result = bit
6824           // if(size), result in bit
6825           // if(!size && ifx), conditional oper: if(left | right)
6826           symbol *tlbl = newiTempLabel (NULL);
6827           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6828           if (size)
6829             emitcode ("setb", "c");
6830           while (sizer--)
6831             {
6832               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6833                 emitcode ("orl", "a,%s",
6834                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6835               } else {
6836                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6837                 emitcode ("orl", "a,%s",
6838                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6839               }
6840               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6841               offset++;
6842             }
6843           if (size)
6844             {
6845               CLRC;
6846               emitcode ("", "!tlabeldef", tlbl->key + 100);
6847               outBitC (result);
6848             }
6849           else if (ifx)
6850             jmpTrueOrFalse (ifx, tlbl);
6851           else
6852             emitcode ("", "!tlabeldef", tlbl->key + 100);
6853         }
6854       else
6855         {
6856             _startLazyDPSEvaluation();
6857           for (; (size--); offset++)
6858             {
6859               // normal case
6860               // result = left & right
6861               if (AOP_TYPE (right) == AOP_LIT)
6862                 {
6863                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6864                     {
6865                       aopPut (AOP (result),
6866                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6867                               offset);
6868                       continue;
6869                     }
6870                   D (emitcode (";", "better literal OR."););
6871                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6872                   emitcode ("orl", "a, %s",
6873                             aopGet (AOP (right), offset,
6874                                     FALSE, FALSE, DP2_RESULT_REG));
6875
6876                 }
6877               else
6878                 {
6879                   // faster than result <- left, anl result,right
6880                   // and better if result is SFR
6881                   if (AOP_TYPE (left) == AOP_ACC)
6882                     {
6883                       emitcode ("orl", "a,%s",
6884                                 aopGet (AOP (right), offset,
6885                                         FALSE, FALSE, DP2_RESULT_REG));
6886                     }
6887                   else
6888                     {
6889                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6890                         
6891                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6892                       {
6893                           emitcode("mov", "b,a");
6894                           rOp = "b";
6895                       }
6896                         
6897                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6898                       emitcode ("orl", "a,%s", rOp);
6899                     }
6900                 }
6901               aopPut (AOP (result), "a", offset);
6902             }
6903             _endLazyDPSEvaluation();
6904         }
6905     }
6906
6907 release:
6908   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6909   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6910   freeAsmop (result, NULL, ic, TRUE);
6911 }
6912
6913 /*-----------------------------------------------------------------*/
6914 /* genXor - code for xclusive or                                   */
6915 /*-----------------------------------------------------------------*/
6916 static void
6917 genXor (iCode * ic, iCode * ifx)
6918 {
6919   operand *left, *right, *result;
6920   int size, offset = 0;
6921   unsigned long lit = 0L;
6922   bool pushResult;
6923
6924   D (emitcode (";", "genXor "););
6925
6926   AOP_OP_3_NOFATAL (ic, pushResult);
6927   AOP_SET_LOCALS (ic);
6928
6929   if (pushResult)
6930   {
6931       genFarFarLogicOp(ic, "xrl");
6932       return;
6933   }  
6934
6935 #ifdef DEBUG_TYPE
6936   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6937             AOP_TYPE (result),
6938             AOP_TYPE (left), AOP_TYPE (right));
6939   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6940             AOP_SIZE (result),
6941             AOP_SIZE (left), AOP_SIZE (right));
6942 #endif
6943
6944   /* if left is a literal & right is not ||
6945      if left needs acc & right does not */
6946   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6947 #ifdef LOGIC_OPS_BROKEN      
6948       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6949 #endif
6950      )
6951     {
6952       operand *tmp = right;
6953       right = left;
6954       left = tmp;
6955     }
6956
6957   /* if result = right then exchange them */
6958   if (sameRegs (AOP (result), AOP (right)))
6959     {
6960       operand *tmp = right;
6961       right = left;
6962       left = tmp;
6963     }
6964
6965   /* if right is bit then exchange them */
6966   if (AOP_TYPE (right) == AOP_CRY &&
6967       AOP_TYPE (left) != AOP_CRY)
6968     {
6969       operand *tmp = right;
6970       right = left;
6971       left = tmp;
6972     }
6973   if (AOP_TYPE (right) == AOP_LIT)
6974     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6975
6976   size = AOP_SIZE (result);
6977
6978   // if(bit ^ yy)
6979   // xx = bit ^ yy;
6980   if (AOP_TYPE (left) == AOP_CRY)
6981     {
6982       if (AOP_TYPE (right) == AOP_LIT)
6983         {
6984           // c = bit & literal;
6985           if (lit >> 1)
6986             {
6987               // lit>>1  != 0 => result = 1
6988               if (AOP_TYPE (result) == AOP_CRY)
6989                 {
6990                   if (size)
6991                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6992                   else if (ifx)
6993                     continueIfTrue (ifx);
6994                   goto release;
6995                 }
6996               emitcode ("setb", "c");
6997             }
6998           else
6999             {
7000               // lit == (0 or 1)
7001               if (lit == 0)
7002                 {
7003                   // lit == 0, result = left
7004                   if (size && sameRegs (AOP (result), AOP (left)))
7005                     goto release;
7006                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7007                 }
7008               else
7009                 {
7010                   // lit == 1, result = not(left)
7011                   if (size && sameRegs (AOP (result), AOP (left)))
7012                     {
7013                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7014                       goto release;
7015                     }
7016                   else
7017                     {
7018                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7019                       emitcode ("cpl", "c");
7020                     }
7021                 }
7022             }
7023
7024         }
7025       else
7026         {
7027           // right != literal
7028           symbol *tlbl = newiTempLabel (NULL);
7029           if (AOP_TYPE (right) == AOP_CRY)
7030             {
7031               // c = bit ^ bit;
7032               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7033             }
7034           else
7035             {
7036               int sizer = AOP_SIZE (right);
7037               // c = bit ^ val
7038               // if val>>1 != 0, result = 1
7039               emitcode ("setb", "c");
7040               while (sizer)
7041                 {
7042                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7043                   if (sizer == 1)
7044                     // test the msb of the lsb
7045                     emitcode ("anl", "a,#!constbyte",0xfe);
7046                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7047                   sizer--;
7048                 }
7049               // val = (0,1)
7050               emitcode ("rrc", "a");
7051             }
7052           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7053           emitcode ("cpl", "c");
7054           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7055         }
7056       // bit = c
7057       // val = c
7058       if (size)
7059         outBitC (result);
7060       // if(bit | ...)
7061       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7062         genIfxJump (ifx, "c");
7063       goto release;
7064     }
7065
7066   if (sameRegs (AOP (result), AOP (left)))
7067     {
7068       /* if left is same as result */
7069       for (; size--; offset++)
7070         {
7071           if (AOP_TYPE (right) == AOP_LIT)
7072             {
7073               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7074                 continue;
7075               else if (IS_AOP_PREG (left))
7076                 {
7077                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7078                   emitcode ("xrl", "a,%s",
7079                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7080                   aopPut (AOP (result), "a", offset);
7081                 }
7082               else
7083                 emitcode ("xrl", "%s,%s",
7084                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7085                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7086             }
7087           else
7088             {
7089               if (AOP_TYPE (left) == AOP_ACC)
7090                 emitcode ("xrl", "a,%s",
7091                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7092               else
7093                 {
7094                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7095                   if (IS_AOP_PREG (left))
7096                     {
7097                       emitcode ("xrl", "a,%s",
7098                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7099                       aopPut (AOP (result), "a", offset);
7100                     }
7101                   else
7102                     emitcode ("xrl", "%s,a",
7103                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7104                 }
7105             }
7106         }
7107     }
7108   else
7109     {
7110       // left & result in different registers
7111       if (AOP_TYPE (result) == AOP_CRY)
7112         {
7113           // result = bit
7114           // if(size), result in bit
7115           // if(!size && ifx), conditional oper: if(left ^ right)
7116           symbol *tlbl = newiTempLabel (NULL);
7117           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7118                   
7119           if (size)
7120             emitcode ("setb", "c");
7121           while (sizer--)
7122             {
7123               if ((AOP_TYPE (right) == AOP_LIT) &&
7124                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7125                 {
7126                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7127                 }
7128               else
7129                 {
7130                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7131                     emitcode ("xrl", "a,%s",
7132                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7133                   } else {
7134                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7136                       {
7137                           emitcode("mov", "b,a");
7138                           rOp = "b";
7139                       }
7140                         
7141                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142                       emitcode ("xrl", "a,%s", rOp);                  
7143                   }
7144                 }
7145               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7146               offset++;
7147             }
7148           if (size)
7149             {
7150               CLRC;
7151               emitcode ("", "!tlabeldef", tlbl->key + 100);
7152               outBitC (result);
7153             }
7154           else if (ifx)
7155             jmpTrueOrFalse (ifx, tlbl);
7156         }
7157       else
7158         {
7159         for (; (size--); offset++)
7160           {
7161             // normal case
7162             // result = left & right
7163             if (AOP_TYPE (right) == AOP_LIT)
7164               {
7165                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7166                   {
7167                     aopPut (AOP (result),
7168                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7169                             offset);
7170                     continue;
7171                   }
7172                 D (emitcode (";", "better literal XOR."););
7173                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7174                 emitcode ("xrl", "a, %s",
7175                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7176               }
7177             else
7178               {
7179                 // faster than result <- left, anl result,right
7180                 // and better if result is SFR
7181                 if (AOP_TYPE (left) == AOP_ACC)
7182                   {
7183                     emitcode ("xrl", "a,%s",
7184                               aopGet (AOP (right), offset,
7185                                       FALSE, FALSE, DP2_RESULT_REG));
7186                   }
7187                 else
7188                   {
7189                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7190                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7191                       {
7192                           emitcode("mov", "b,a");
7193                           rOp = "b";
7194                       }
7195                         
7196                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7197                       emitcode ("xrl", "a,%s", rOp);
7198                   }
7199               }
7200             aopPut (AOP (result), "a", offset);
7201           }
7202         }
7203         
7204     }
7205
7206 release:
7207   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7208   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7209   freeAsmop (result, NULL, ic, TRUE);
7210 }
7211
7212 /*-----------------------------------------------------------------*/
7213 /* genInline - write the inline code out                           */
7214 /*-----------------------------------------------------------------*/
7215 static void
7216 genInline (iCode * ic)
7217 {
7218   char *buffer, *bp, *bp1;
7219
7220   D (emitcode (";", "genInline "); );
7221
7222   _G.inLine += (!options.asmpeep);
7223
7224   buffer = Safe_strdup(IC_INLINE(ic));
7225   bp = buffer;
7226   bp1 = buffer;
7227
7228   /* emit each line as a code */
7229   while (*bp)
7230     {
7231       if (*bp == '\n')
7232         {
7233           *bp++ = '\0';
7234           emitcode (bp1, "");
7235           bp1 = bp;
7236         }
7237       else
7238         {
7239           if (*bp == ':')
7240             {
7241               bp++;
7242               *bp = '\0';
7243               bp++;
7244               emitcode (bp1, "");
7245               bp1 = bp;
7246             }
7247           else
7248             bp++;
7249         }
7250     }
7251   if (bp1 != bp)
7252     emitcode (bp1, "");
7253   /*     emitcode("",buffer); */
7254   _G.inLine -= (!options.asmpeep);
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genRRC - rotate right with carry                                */
7259 /*-----------------------------------------------------------------*/
7260 static void
7261 genRRC (iCode * ic)
7262 {
7263   operand *left, *result;
7264   int     size, offset;
7265
7266   D (emitcode (";", "genRRC "););
7267
7268   /* rotate right with carry */
7269   left = IC_LEFT (ic);
7270   result = IC_RESULT (ic);
7271   aopOp (left, ic, FALSE, FALSE);
7272   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7273
7274   /* move it to the result */
7275   size = AOP_SIZE (result);
7276   offset = size - 1;
7277   CLRC;
7278
7279   _startLazyDPSEvaluation ();
7280   while (size--)
7281     {
7282       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7283       emitcode ("rrc", "a");
7284       if (AOP_SIZE (result) > 1)
7285         aopPut (AOP (result), "a", offset--);
7286     }
7287   _endLazyDPSEvaluation ();
7288
7289   /* now we need to put the carry into the
7290      highest order byte of the result */
7291   if (AOP_SIZE (result) > 1)
7292     {
7293       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7294     }
7295   emitcode ("mov", "acc.7,c");
7296   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7297   freeAsmop (left, NULL, ic, TRUE);
7298   freeAsmop (result, NULL, ic, TRUE);
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* genRLC - generate code for rotate left with carry               */
7303 /*-----------------------------------------------------------------*/
7304 static void
7305 genRLC (iCode * ic)
7306 {
7307   operand *left, *result;
7308   int size, offset;
7309   char *l;
7310
7311   D (emitcode (";", "genRLC "););
7312
7313   /* rotate right with carry */
7314   left = IC_LEFT (ic);
7315   result = IC_RESULT (ic);
7316   aopOp (left, ic, FALSE, FALSE);
7317   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7318
7319   /* move it to the result */
7320   size = AOP_SIZE (result);
7321   offset = 0;
7322   if (size--)
7323     {
7324       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7325       MOVA (l);
7326       emitcode ("add", "a,acc");
7327       if (AOP_SIZE (result) > 1)
7328         {
7329           aopPut (AOP (result), "a", offset++);
7330         }
7331
7332       _startLazyDPSEvaluation ();
7333       while (size--)
7334         {
7335           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7336           MOVA (l);
7337           emitcode ("rlc", "a");
7338           if (AOP_SIZE (result) > 1)
7339             aopPut (AOP (result), "a", offset++);
7340         }
7341       _endLazyDPSEvaluation ();
7342     }
7343   /* now we need to put the carry into the
7344      highest order byte of the result */
7345   if (AOP_SIZE (result) > 1)
7346     {
7347       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7348       MOVA (l);
7349     }
7350   emitcode ("mov", "acc.0,c");
7351   aopPut (AOP (result), "a", 0);
7352   freeAsmop (left, NULL, ic, TRUE);
7353   freeAsmop (result, NULL, ic, TRUE);
7354 }
7355
7356 /*-----------------------------------------------------------------*/
7357 /* genGetHbit - generates code get highest order bit               */
7358 /*-----------------------------------------------------------------*/
7359 static void
7360 genGetHbit (iCode * ic)
7361 {
7362   operand *left, *result;
7363   left = IC_LEFT (ic);
7364   result = IC_RESULT (ic);
7365   aopOp (left, ic, FALSE, FALSE);
7366   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7367
7368   D (emitcode (";", "genGetHbit "););
7369
7370   /* get the highest order byte into a */
7371   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7372   if (AOP_TYPE (result) == AOP_CRY)
7373     {
7374       emitcode ("rlc", "a");
7375       outBitC (result);
7376     }
7377   else
7378     {
7379       emitcode ("rl", "a");
7380       emitcode ("anl", "a,#1");
7381       outAcc (result);
7382     }
7383
7384
7385   freeAsmop (left, NULL, ic, TRUE);
7386   freeAsmop (result, NULL, ic, TRUE);
7387 }
7388
7389 /*-----------------------------------------------------------------*/
7390 /* genSwap - generates code to swap nibbles or bytes               */
7391 /*-----------------------------------------------------------------*/
7392 static void
7393 genSwap (iCode * ic)
7394 {
7395   operand *left, *result;
7396
7397   D(emitcode (";     genSwap",""));
7398
7399   left = IC_LEFT (ic);
7400   result = IC_RESULT (ic);
7401   aopOp (left, ic, FALSE, FALSE);
7402   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7403   
7404   _startLazyDPSEvaluation ();
7405   switch (AOP_SIZE (left))
7406     {
7407     case 1: /* swap nibbles in byte */
7408       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7409       emitcode ("swap", "a");
7410       aopPut (AOP (result), "a", 0);
7411       break;
7412     case 2: /* swap bytes in word */
7413       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7414         {
7415           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7416           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7417           aopPut (AOP (result), "a", 1);
7418         }
7419       else if (operandsEqu (left, result))
7420         {
7421           char * reg = "a";
7422           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7423           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7424             {
7425               emitcode ("mov", "b,a");
7426               reg = "b";
7427               _G.bInUse=1;
7428             }
7429           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7430           aopPut (AOP (result), reg, 1);
7431           _G.bInUse=0;
7432         }
7433       else
7434         {
7435           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7436           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7437         }
7438       break;
7439     default:
7440       wassertl(FALSE, "unsupported SWAP operand size");
7441     }
7442   _endLazyDPSEvaluation ();
7443   
7444   freeAsmop (left, NULL, ic, TRUE);
7445   freeAsmop (result, NULL, ic, TRUE);
7446 }
7447
7448 /*-----------------------------------------------------------------*/
7449 /* AccRol - rotate left accumulator by known count                 */
7450 /*-----------------------------------------------------------------*/
7451 static void
7452 AccRol (int shCount)
7453 {
7454   shCount &= 0x0007;            // shCount : 0..7
7455
7456   switch (shCount)
7457     {
7458     case 0:
7459       break;
7460     case 1:
7461       emitcode ("rl", "a");
7462       break;
7463     case 2:
7464       emitcode ("rl", "a");
7465       emitcode ("rl", "a");
7466       break;
7467     case 3:
7468       emitcode ("swap", "a");
7469       emitcode ("rr", "a");
7470       break;
7471     case 4:
7472       emitcode ("swap", "a");
7473       break;
7474     case 5:
7475       emitcode ("swap", "a");
7476       emitcode ("rl", "a");
7477       break;
7478     case 6:
7479       emitcode ("rr", "a");
7480       emitcode ("rr", "a");
7481       break;
7482     case 7:
7483       emitcode ("rr", "a");
7484       break;
7485     }
7486 }
7487
7488 /*-----------------------------------------------------------------*/
7489 /* AccLsh - left shift accumulator by known count                  */
7490 /*-----------------------------------------------------------------*/
7491 static void
7492 AccLsh (int shCount)
7493 {
7494   if (shCount != 0)
7495     {
7496       if (shCount == 1)
7497         emitcode ("add", "a,acc");
7498       else if (shCount == 2)
7499         {
7500           emitcode ("add", "a,acc");
7501           emitcode ("add", "a,acc");
7502         }
7503       else
7504         {
7505           /* rotate left accumulator */
7506           AccRol (shCount);
7507           /* and kill the lower order bits */
7508           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7509         }
7510     }
7511 }
7512
7513 /*-----------------------------------------------------------------*/
7514 /* AccRsh - right shift accumulator by known count                 */
7515 /*-----------------------------------------------------------------*/
7516 static void
7517 AccRsh (int shCount)
7518 {
7519   if (shCount != 0)
7520     {
7521       if (shCount == 1)
7522         {
7523           CLRC;
7524           emitcode ("rrc", "a");
7525         }
7526       else
7527         {
7528           /* rotate right accumulator */
7529           AccRol (8 - shCount);
7530           /* and kill the higher order bits */
7531           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7532         }
7533     }
7534 }
7535
7536 #ifdef BETTER_LITERAL_SHIFT
7537 /*-----------------------------------------------------------------*/
7538 /* AccSRsh - signed right shift accumulator by known count                 */
7539 /*-----------------------------------------------------------------*/
7540 static void
7541 AccSRsh (int shCount)
7542 {
7543   symbol *tlbl;
7544   if (shCount != 0)
7545     {
7546       if (shCount == 1)
7547         {
7548           emitcode ("mov", "c,acc.7");
7549           emitcode ("rrc", "a");
7550         }
7551       else if (shCount == 2)
7552         {
7553           emitcode ("mov", "c,acc.7");
7554           emitcode ("rrc", "a");
7555           emitcode ("mov", "c,acc.7");
7556           emitcode ("rrc", "a");
7557         }
7558       else
7559         {
7560           tlbl = newiTempLabel (NULL);
7561           /* rotate right accumulator */
7562           AccRol (8 - shCount);
7563           /* and kill the higher order bits */
7564           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7565           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7566           emitcode ("orl", "a,#!constbyte",
7567                     (unsigned char) ~SRMask[shCount]);
7568           emitcode ("", "!tlabeldef", tlbl->key + 100);
7569         }
7570     }
7571 }
7572 #endif
7573
7574 #ifdef BETTER_LITERAL_SHIFT
7575 /*-----------------------------------------------------------------*/
7576 /* shiftR1Left2Result - shift right one byte from left to result   */
7577 /*-----------------------------------------------------------------*/
7578 static void
7579 shiftR1Left2Result (operand * left, int offl,
7580                     operand * result, int offr,
7581                     int shCount, int sign)
7582 {
7583   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7584   /* shift right accumulator */
7585   if (sign)
7586     AccSRsh (shCount);
7587   else
7588     AccRsh (shCount);
7589   aopPut (AOP (result), "a", offr);
7590 }
7591 #endif
7592
7593 #ifdef BETTER_LITERAL_SHIFT
7594 /*-----------------------------------------------------------------*/
7595 /* shiftL1Left2Result - shift left one byte from left to result    */
7596 /*-----------------------------------------------------------------*/
7597 static void
7598 shiftL1Left2Result (operand * left, int offl,
7599                     operand * result, int offr, int shCount)
7600 {
7601   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7602   /* shift left accumulator */
7603   AccLsh (shCount);
7604   aopPut (AOP (result), "a", offr);
7605 }
7606 #endif
7607
7608 #ifdef BETTER_LITERAL_SHIFT
7609 /*-----------------------------------------------------------------*/
7610 /* movLeft2Result - move byte from left to result                  */
7611 /*-----------------------------------------------------------------*/
7612 static void
7613 movLeft2Result (operand * left, int offl,
7614                 operand * result, int offr, int sign)
7615 {
7616   char *l;
7617   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7618   {
7619       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7620
7621       if (*l == '@' && (IS_AOP_PREG (result)))
7622       {
7623           emitcode ("mov", "a,%s", l);
7624           aopPut (AOP (result), "a", offr);
7625       }
7626       else
7627       {
7628           if (!sign)
7629           {
7630             aopPut (AOP (result), l, offr);
7631           }
7632           else
7633             {
7634               /* MSB sign in acc.7 ! */
7635               if (getDataSize (left) == offl + 1)
7636                 {
7637                   emitcode ("mov", "a,%s", l);
7638                   aopPut (AOP (result), "a", offr);
7639                 }
7640             }
7641       }
7642   }
7643 }
7644 #endif
7645
7646 #ifdef BETTER_LITERAL_SHIFT
7647 /*-----------------------------------------------------------------*/
7648 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7649 /*-----------------------------------------------------------------*/
7650 static void
7651 AccAXRrl1 (char *x)
7652 {
7653   emitcode ("rrc", "a");
7654   emitcode ("xch", "a,%s", x);
7655   emitcode ("rrc", "a");
7656   emitcode ("xch", "a,%s", x);
7657 }
7658 #endif
7659
7660 #ifdef BETTER_LITERAL_SHIFT
7661 //REMOVE ME!!!
7662 /*-----------------------------------------------------------------*/
7663 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7664 /*-----------------------------------------------------------------*/
7665 static void
7666 AccAXLrl1 (char *x)
7667 {
7668   emitcode ("xch", "a,%s", x);
7669   emitcode ("rlc", "a");
7670   emitcode ("xch", "a,%s", x);
7671   emitcode ("rlc", "a");
7672 }
7673 #endif
7674
7675 #ifdef BETTER_LITERAL_SHIFT
7676 /*-----------------------------------------------------------------*/
7677 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7678 /*-----------------------------------------------------------------*/
7679 static void
7680 AccAXLsh1 (char *x)
7681 {
7682   emitcode ("xch", "a,%s", x);
7683   emitcode ("add", "a,acc");
7684   emitcode ("xch", "a,%s", x);
7685   emitcode ("rlc", "a");
7686 }
7687 #endif
7688
7689 #ifdef BETTER_LITERAL_SHIFT
7690 /*-----------------------------------------------------------------*/
7691 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7692 /*-----------------------------------------------------------------*/
7693 static void
7694 AccAXLsh (char *x, int shCount)
7695 {
7696   switch (shCount)
7697     {
7698     case 0:
7699       break;
7700     case 1:
7701       AccAXLsh1 (x);
7702       break;
7703     case 2:
7704       AccAXLsh1 (x);
7705       AccAXLsh1 (x);
7706       break;
7707     case 3:
7708     case 4:
7709     case 5:                     // AAAAABBB:CCCCCDDD
7710
7711       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7712
7713       emitcode ("anl", "a,#!constbyte",
7714                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7715
7716       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7717
7718       AccRol (shCount);         // DDDCCCCC:BBB00000
7719
7720       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7721
7722       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7723
7724       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7725
7726       emitcode ("anl", "a,#!constbyte",
7727                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7728
7729       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7730
7731       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7732
7733       break;
7734     case 6:                     // AAAAAABB:CCCCCCDD
7735       emitcode ("anl", "a,#!constbyte",
7736                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7737       emitcode ("mov", "c,acc.0");      // c = B
7738       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7739 #if 0
7740       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7741       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7742 #else
7743       emitcode("rrc","a"); 
7744       emitcode("xch","a,%s", x); 
7745       emitcode("rrc","a"); 
7746       emitcode("mov","c,acc.0"); //<< get correct bit 
7747       emitcode("xch","a,%s", x); 
7748
7749       emitcode("rrc","a"); 
7750       emitcode("xch","a,%s", x); 
7751       emitcode("rrc","a"); 
7752       emitcode("xch","a,%s", x); 
7753 #endif
7754       break;
7755     case 7:                     // a:x <<= 7
7756
7757       emitcode ("anl", "a,#!constbyte",
7758                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7759
7760       emitcode ("mov", "c,acc.0");      // c = B
7761
7762       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7763
7764       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7765
7766       break;
7767     default:
7768       break;
7769     }
7770 }
7771 #endif
7772
7773 #ifdef BETTER_LITERAL_SHIFT
7774 //REMOVE ME!!!
7775 /*-----------------------------------------------------------------*/
7776 /* AccAXRsh - right shift a:x known count (0..7)                   */
7777 /*-----------------------------------------------------------------*/
7778 static void
7779 AccAXRsh (char *x, int shCount)
7780 {
7781   switch (shCount)
7782     {
7783     case 0:
7784       break;
7785     case 1:
7786       CLRC;
7787       AccAXRrl1 (x);            // 0->a:x
7788
7789       break;
7790     case 2:
7791       CLRC;
7792       AccAXRrl1 (x);            // 0->a:x
7793
7794       CLRC;
7795       AccAXRrl1 (x);            // 0->a:x
7796
7797       break;
7798     case 3:
7799     case 4:
7800     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7801
7802       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7803
7804       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7805
7806       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7807
7808       emitcode ("anl", "a,#!constbyte",
7809                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7810
7811       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7812
7813       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7814
7815       emitcode ("anl", "a,#!constbyte",
7816                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7817
7818       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7819
7820       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7821
7822       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7823
7824       break;
7825     case 6:                     // AABBBBBB:CCDDDDDD
7826
7827       emitcode ("mov", "c,acc.7");
7828       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7829
7830       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7831
7832       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7833
7834       emitcode ("anl", "a,#!constbyte",
7835                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7836
7837       break;
7838     case 7:                     // ABBBBBBB:CDDDDDDD
7839
7840       emitcode ("mov", "c,acc.7");      // c = A
7841
7842       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7843
7844       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7845
7846       emitcode ("anl", "a,#!constbyte",
7847                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7848
7849       break;
7850     default:
7851       break;
7852     }
7853 }
7854 #endif
7855
7856 #ifdef BETTER_LITERAL_SHIFT
7857 /*-----------------------------------------------------------------*/
7858 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7859 /*-----------------------------------------------------------------*/
7860 static void
7861 AccAXRshS (char *x, int shCount)
7862 {
7863   symbol *tlbl;
7864   switch (shCount)
7865     {
7866     case 0:
7867       break;
7868     case 1:
7869       emitcode ("mov", "c,acc.7");
7870       AccAXRrl1 (x);            // s->a:x
7871
7872       break;
7873     case 2:
7874       emitcode ("mov", "c,acc.7");
7875       AccAXRrl1 (x);            // s->a:x
7876
7877       emitcode ("mov", "c,acc.7");
7878       AccAXRrl1 (x);            // s->a:x
7879
7880       break;
7881     case 3:
7882     case 4:
7883     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7884
7885       tlbl = newiTempLabel (NULL);
7886       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7887
7888       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7889
7890       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7891
7892       emitcode ("anl", "a,#!constbyte",
7893                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7894
7895       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7896
7897       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7898
7899       emitcode ("anl", "a,#!constbyte",
7900                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7901
7902       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7903
7904       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7905
7906       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7907
7908       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7909       emitcode ("orl", "a,#!constbyte",
7910                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7911
7912       emitcode ("", "!tlabeldef", tlbl->key + 100);
7913       break;                    // SSSSAAAA:BBBCCCCC
7914
7915     case 6:                     // AABBBBBB:CCDDDDDD
7916
7917       tlbl = newiTempLabel (NULL);
7918       emitcode ("mov", "c,acc.7");
7919       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7920
7921       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7922
7923       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7924
7925       emitcode ("anl", "a,#!constbyte",
7926                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7927
7928       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7929       emitcode ("orl", "a,#!constbyte",
7930                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7931
7932       emitcode ("", "!tlabeldef", tlbl->key + 100);
7933       break;
7934     case 7:                     // ABBBBBBB:CDDDDDDD
7935
7936       tlbl = newiTempLabel (NULL);
7937       emitcode ("mov", "c,acc.7");      // c = A
7938
7939       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7940
7941       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7942
7943       emitcode ("anl", "a,#!constbyte",
7944                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7945
7946       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7947       emitcode ("orl", "a,#!constbyte",
7948                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7949
7950       emitcode ("", "!tlabeldef", tlbl->key + 100);
7951       break;
7952     default:
7953       break;
7954     }
7955 }
7956 #endif
7957
7958 #ifdef BETTER_LITERAL_SHIFT
7959 static void
7960 _loadLeftIntoAx(char    **lsb, 
7961                 operand *left, 
7962                 operand *result,
7963                 int     offl,
7964                 int     offr)
7965 {
7966   // Get the initial value from left into a pair of registers.
7967   // MSB must be in A, LSB can be any register.
7968   //
7969   // If the result is held in registers, it is an optimization
7970   // if the LSB can be held in the register which will hold the,
7971   // result LSB since this saves us from having to copy it into
7972   // the result following AccAXLsh.
7973   //
7974   // If the result is addressed indirectly, this is not a gain.
7975   if (AOP_NEEDSACC(result))
7976   {
7977        char *leftByte;
7978        
7979        _startLazyDPSEvaluation();
7980       if (AOP_TYPE(left) == AOP_DPTR2)
7981        {
7982            // Get MSB in A.
7983            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7984            // get LSB in DP2_RESULT_REG.
7985            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7986            assert(!strcmp(leftByte, DP2_RESULT_REG));
7987        }
7988        else
7989        {
7990            // get LSB into DP2_RESULT_REG
7991            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7992            if (strcmp(leftByte, DP2_RESULT_REG))
7993            {
7994                TR_AP("#7");
7995                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7996            }
7997            // And MSB in A.
7998            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7999            assert(strcmp(leftByte, DP2_RESULT_REG));
8000            MOVA(leftByte);
8001        }
8002        _endLazyDPSEvaluation();
8003        *lsb = DP2_RESULT_REG;
8004   }
8005   else
8006   {
8007       if (sameRegs (AOP (result), AOP (left)) &&
8008         ((offl + MSB16) == offr))
8009       {
8010           /* don't crash result[offr] */
8011           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8012           emitcode ("xch", "a,%s", 
8013                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8014       }
8015       else
8016       {
8017           movLeft2Result (left, offl, result, offr, 0);
8018           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8019       }
8020       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8021       assert(strcmp(*lsb,"a"));      
8022   }
8023 }
8024
8025 static void
8026 _storeAxResults(char    *lsb,
8027                 operand *result,
8028                 int     offr)
8029 {
8030   _startLazyDPSEvaluation();
8031   if (AOP_NEEDSACC(result))
8032   {
8033       /* We have to explicitly update the result LSB.
8034        */
8035       emitcode("xch","a,%s", lsb);
8036       aopPut(AOP(result), "a", offr);
8037       emitcode("mov","a,%s", lsb);
8038   }
8039   if (getDataSize (result) > 1)
8040   {
8041       aopPut (AOP (result), "a", offr + MSB16);
8042   }
8043   _endLazyDPSEvaluation();
8044 }
8045
8046 /*-----------------------------------------------------------------*/
8047 /* shiftL2Left2Result - shift left two bytes from left to result   */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 shiftL2Left2Result (operand * left, int offl,
8051                     operand * result, int offr, int shCount)
8052 {
8053   char *lsb;
8054
8055   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8056   
8057   AccAXLsh (lsb, shCount);
8058   
8059   _storeAxResults(lsb, result, offr);
8060 }
8061 #endif
8062
8063 #ifdef BETTER_LITERAL_SHIFT
8064 /*-----------------------------------------------------------------*/
8065 /* shiftR2Left2Result - shift right two bytes from left to result  */
8066 /*-----------------------------------------------------------------*/
8067 static void
8068 shiftR2Left2Result (operand * left, int offl,
8069                     operand * result, int offr,
8070                     int shCount, int sign)
8071 {
8072   char *lsb;
8073   
8074   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8075   
8076   /* a:x >> shCount (x = lsb(result)) */
8077   if (sign)
8078   {
8079      AccAXRshS(lsb, shCount);
8080   }
8081   else
8082   {
8083     AccAXRsh(lsb, shCount);
8084   }
8085   
8086   _storeAxResults(lsb, result, offr);
8087 }
8088 #endif
8089
8090 /*-----------------------------------------------------------------*/
8091 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8092 /*-----------------------------------------------------------------*/
8093 static void
8094 shiftLLeftOrResult (operand * left, int offl,
8095                     operand * result, int offr, int shCount)
8096 {
8097   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8098   /* shift left accumulator */
8099   AccLsh (shCount);
8100   /* or with result */
8101   emitcode ("orl", "a,%s",
8102             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8103   /* back to result */
8104   aopPut (AOP (result), "a", offr);
8105 }
8106
8107 #if 0
8108 //REMOVE ME!!!
8109 /*-----------------------------------------------------------------*/
8110 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8111 /*-----------------------------------------------------------------*/
8112 static void
8113 shiftRLeftOrResult (operand * left, int offl,
8114                     operand * result, int offr, int shCount)
8115 {
8116   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8117   /* shift right accumulator */
8118   AccRsh (shCount);
8119   /* or with result */
8120   emitcode ("orl", "a,%s",
8121             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8122   /* back to result */
8123   aopPut (AOP (result), "a", offr);
8124 }
8125 #endif
8126
8127 #ifdef BETTER_LITERAL_SHIFT
8128 /*-----------------------------------------------------------------*/
8129 /* genlshOne - left shift a one byte quantity by known count       */
8130 /*-----------------------------------------------------------------*/
8131 static void
8132 genlshOne (operand * result, operand * left, int shCount)
8133 {
8134   D (emitcode (";", "genlshOne "););
8135   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8136 }
8137 #endif
8138
8139 #ifdef BETTER_LITERAL_SHIFT
8140 /*-----------------------------------------------------------------*/
8141 /* genlshTwo - left shift two bytes by known amount != 0           */
8142 /*-----------------------------------------------------------------*/
8143 static void
8144 genlshTwo (operand * result, operand * left, int shCount)
8145 {
8146   int size;
8147
8148   D (emitcode (";", "genlshTwo "););
8149
8150   size = getDataSize (result);
8151
8152   /* if shCount >= 8 */
8153   if (shCount >= 8)
8154   {
8155       shCount -= 8;
8156
8157       _startLazyDPSEvaluation();
8158
8159       if (size > 1)
8160         {
8161           if (shCount)
8162           {
8163             _endLazyDPSEvaluation();
8164             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8165             aopPut (AOP (result), zero, LSB);       
8166           }
8167           else
8168           {
8169             movLeft2Result (left, LSB, result, MSB16, 0);
8170             aopPut (AOP (result), zero, LSB);
8171             _endLazyDPSEvaluation();
8172           }
8173         }
8174         else
8175         {
8176           aopPut (AOP (result), zero, LSB);
8177           _endLazyDPSEvaluation();
8178         }
8179   }
8180
8181   /*  1 <= shCount <= 7 */
8182   else
8183     {
8184       if (size == 1)
8185       {
8186         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8187       }
8188       else
8189       {
8190         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8191       }
8192     }
8193 }
8194 #endif
8195
8196 #if 0
8197 //REMOVE ME!!!
8198 /*-----------------------------------------------------------------*/
8199 /* shiftLLong - shift left one long from left to result            */
8200 /* offl = LSB or MSB16                                             */
8201 /*-----------------------------------------------------------------*/
8202 static void
8203 shiftLLong (operand * left, operand * result, int offr)
8204 {
8205   char *l;
8206   int size = AOP_SIZE (result);
8207
8208   if (size >= LSB + offr)
8209     {
8210       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8211       MOVA (l);
8212       emitcode ("add", "a,acc");
8213       if (sameRegs (AOP (left), AOP (result)) &&
8214           size >= MSB16 + offr && offr != LSB)
8215         emitcode ("xch", "a,%s",
8216                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8217       else
8218         aopPut (AOP (result), "a", LSB + offr);
8219     }
8220
8221   if (size >= MSB16 + offr)
8222     {
8223       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8224         {
8225           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8226         }
8227       emitcode ("rlc", "a");
8228       if (sameRegs (AOP (left), AOP (result)) &&
8229           size >= MSB24 + offr && offr != LSB)
8230         emitcode ("xch", "a,%s",
8231                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8232       else
8233         aopPut (AOP (result), "a", MSB16 + offr);
8234     }
8235
8236   if (size >= MSB24 + offr)
8237     {
8238       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8239         {
8240           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8241         }
8242       emitcode ("rlc", "a");
8243       if (sameRegs (AOP (left), AOP (result)) &&
8244           size >= MSB32 + offr && offr != LSB)
8245         emitcode ("xch", "a,%s",
8246                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8247       else
8248         aopPut (AOP (result), "a", MSB24 + offr);
8249     }
8250
8251   if (size > MSB32 + offr)
8252     {
8253       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8254         {
8255           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8256         }
8257       emitcode ("rlc", "a");
8258       aopPut (AOP (result), "a", MSB32 + offr);
8259     }
8260   if (offr != LSB)
8261     aopPut (AOP (result), zero, LSB);
8262 }
8263 #endif
8264
8265 #if 0
8266 //REMOVE ME!!!
8267 /*-----------------------------------------------------------------*/
8268 /* genlshFour - shift four byte by a known amount != 0             */
8269 /*-----------------------------------------------------------------*/
8270 static void
8271 genlshFour (operand * result, operand * left, int shCount)
8272 {
8273   int size;
8274
8275   D (emitcode (";", "genlshFour ");
8276     );
8277
8278   size = AOP_SIZE (result);
8279
8280   /* if shifting more that 3 bytes */
8281   if (shCount >= 24)
8282     {
8283       shCount -= 24;
8284       if (shCount)
8285         /* lowest order of left goes to the highest
8286            order of the destination */
8287         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8288       else
8289         movLeft2Result (left, LSB, result, MSB32, 0);
8290       aopPut (AOP (result), zero, LSB);
8291       aopPut (AOP (result), zero, MSB16);
8292       aopPut (AOP (result), zero, MSB24);
8293       return;
8294     }
8295
8296   /* more than two bytes */
8297   else if (shCount >= 16)
8298     {
8299       /* lower order two bytes goes to higher order two bytes */
8300       shCount -= 16;
8301       /* if some more remaining */
8302       if (shCount)
8303         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8304       else
8305         {
8306           movLeft2Result (left, MSB16, result, MSB32, 0);
8307           movLeft2Result (left, LSB, result, MSB24, 0);
8308         }
8309       aopPut (AOP (result), zero, MSB16);
8310       aopPut (AOP (result), zero, LSB);
8311       return;
8312     }
8313
8314   /* if more than 1 byte */
8315   else if (shCount >= 8)
8316     {
8317       /* lower order three bytes goes to higher order  three bytes */
8318       shCount -= 8;
8319       if (size == 2)
8320         {
8321           if (shCount)
8322             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8323           else
8324             movLeft2Result (left, LSB, result, MSB16, 0);
8325         }
8326       else
8327         {                       /* size = 4 */
8328           if (shCount == 0)
8329             {
8330               movLeft2Result (left, MSB24, result, MSB32, 0);
8331               movLeft2Result (left, MSB16, result, MSB24, 0);
8332               movLeft2Result (left, LSB, result, MSB16, 0);
8333               aopPut (AOP (result), zero, LSB);
8334             }
8335           else if (shCount == 1)
8336             shiftLLong (left, result, MSB16);
8337           else
8338             {
8339               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8340               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8341               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8342               aopPut (AOP (result), zero, LSB);
8343             }
8344         }
8345     }
8346
8347   /* 1 <= shCount <= 7 */
8348   else if (shCount <= 2)
8349     {
8350       shiftLLong (left, result, LSB);
8351       if (shCount == 2)
8352         shiftLLong (result, result, LSB);
8353     }
8354   /* 3 <= shCount <= 7, optimize */
8355   else
8356     {
8357       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8358       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8359       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8360     }
8361 }
8362 #endif
8363
8364 #ifdef BETTER_LITERAL_SHIFT
8365 /*-----------------------------------------------------------------*/
8366 /* genLeftShiftLiteral - left shifting by known count              */
8367 /*-----------------------------------------------------------------*/
8368 static bool
8369 genLeftShiftLiteral (operand * left,
8370                      operand * right,
8371                      operand * result,
8372                      iCode * ic)
8373 {
8374   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8375   int size;
8376
8377   size = getSize (operandType (result));
8378
8379   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8380
8381   /* We only handle certain easy cases so far. */
8382   if ((shCount != 0)
8383    && (shCount < (size * 8))
8384    && (size != 1)
8385    && (size != 2))
8386   {
8387       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8388       return FALSE;
8389   }
8390
8391   freeAsmop (right, NULL, ic, TRUE);
8392
8393   aopOp(left, ic, FALSE, FALSE);
8394   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8395
8396 #if 0 // debug spew
8397   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8398   {
8399         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8400         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8401         {
8402            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8403         }
8404   }
8405   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8406   {
8407         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8408         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8409         {
8410            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8411         }       
8412   }  
8413 #endif
8414   
8415 #if VIEW_SIZE
8416   emitcode ("; shift left ", "result %d, left %d", size,
8417             AOP_SIZE (left));
8418 #endif
8419
8420   /* I suppose that the left size >= result size */
8421   if (shCount == 0)
8422   {
8423         _startLazyDPSEvaluation();
8424         while (size--)
8425         {
8426           movLeft2Result (left, size, result, size, 0);
8427         }
8428         _endLazyDPSEvaluation();
8429   }
8430   else if (shCount >= (size * 8))
8431   {
8432     _startLazyDPSEvaluation();
8433     while (size--)
8434     {
8435       aopPut (AOP (result), zero, size);
8436     }
8437     _endLazyDPSEvaluation();
8438   }
8439   else
8440   {
8441       switch (size)
8442         {
8443         case 1:
8444           genlshOne (result, left, shCount);
8445           break;
8446
8447         case 2:
8448           genlshTwo (result, left, shCount);
8449           break;
8450 #if 0
8451         case 4:
8452           genlshFour (result, left, shCount);
8453           break;
8454 #endif
8455         default:
8456           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8457           break;
8458         }
8459     }
8460   freeAsmop (left, NULL, ic, TRUE);
8461   freeAsmop (result, NULL, ic, TRUE);
8462   return TRUE;
8463 }
8464 #endif
8465
8466 /*-----------------------------------------------------------------*/
8467 /* genLeftShift - generates code for left shifting                 */
8468 /*-----------------------------------------------------------------*/
8469 static void
8470 genLeftShift (iCode * ic)
8471 {
8472   operand *left, *right, *result;
8473   int size, offset;
8474   char *l;
8475   symbol *tlbl, *tlbl1;
8476
8477   D (emitcode (";", "genLeftShift "););
8478
8479   right = IC_RIGHT (ic);
8480   left = IC_LEFT (ic);
8481   result = IC_RESULT (ic);
8482
8483   aopOp (right, ic, FALSE, FALSE);
8484
8485
8486 #ifdef BETTER_LITERAL_SHIFT
8487   /* if the shift count is known then do it
8488      as efficiently as possible */
8489   if (AOP_TYPE (right) == AOP_LIT)
8490     {
8491       if (genLeftShiftLiteral (left, right, result, ic))
8492       {
8493         return;
8494       }
8495     }
8496 #endif
8497
8498   /* shift count is unknown then we have to form
8499      a loop get the loop count in B : Note: we take
8500      only the lower order byte since shifting
8501      more that 32 bits make no sense anyway, ( the
8502      largest size of an object can be only 32 bits ) */
8503
8504   if (AOP_TYPE (right) == AOP_LIT)
8505   {
8506       /* Really should be handled by genLeftShiftLiteral,
8507        * but since I'm too lazy to fix that today, at least we can make
8508        * some small improvement.
8509        */
8510        emitcode("mov", "b,#!constbyte",
8511                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8512   }
8513   else
8514   {
8515       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8516       emitcode ("inc", "b");
8517   }
8518   freeAsmop (right, NULL, ic, TRUE);
8519   aopOp (left, ic, FALSE, FALSE);
8520   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8521
8522   /* now move the left to the result if they are not the
8523      same */
8524   if (!sameRegs (AOP (left), AOP (result)) &&
8525       AOP_SIZE (result) > 1)
8526     {
8527
8528       size = AOP_SIZE (result);
8529       offset = 0;
8530       _startLazyDPSEvaluation ();
8531       while (size--)
8532         {
8533           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8534           if (*l == '@' && (IS_AOP_PREG (result)))
8535             {
8536
8537               emitcode ("mov", "a,%s", l);
8538               aopPut (AOP (result), "a", offset);
8539             }
8540           else
8541             aopPut (AOP (result), l, offset);
8542           offset++;
8543         }
8544       _endLazyDPSEvaluation ();
8545     }
8546
8547   tlbl = newiTempLabel (NULL);
8548   size = AOP_SIZE (result);
8549   offset = 0;
8550   tlbl1 = newiTempLabel (NULL);
8551
8552   /* if it is only one byte then */
8553   if (size == 1)
8554     {
8555       symbol *tlbl1 = newiTempLabel (NULL);
8556
8557       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8558       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8559       emitcode ("", "!tlabeldef", tlbl->key + 100);
8560       emitcode ("add", "a,acc");
8561       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8562       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8563       aopPut (AOP (result), "a", 0);
8564       goto release;
8565     }
8566
8567   reAdjustPreg (AOP (result));
8568
8569   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8570   emitcode ("", "!tlabeldef", tlbl->key + 100);
8571   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8572   emitcode ("add", "a,acc");
8573   aopPut (AOP (result), "a", offset++);
8574   _startLazyDPSEvaluation ();
8575   while (--size)
8576     {
8577       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8578       emitcode ("rlc", "a");
8579       aopPut (AOP (result), "a", offset++);
8580     }
8581   _endLazyDPSEvaluation ();
8582   reAdjustPreg (AOP (result));
8583
8584   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8585   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8586 release:
8587   freeAsmop (left, NULL, ic, TRUE);
8588   freeAsmop (result, NULL, ic, TRUE);
8589 }
8590
8591 #ifdef BETTER_LITERAL_SHIFT
8592 /*-----------------------------------------------------------------*/
8593 /* genrshOne - right shift a one byte quantity by known count      */
8594 /*-----------------------------------------------------------------*/
8595 static void
8596 genrshOne (operand * result, operand * left,
8597            int shCount, int sign)
8598 {
8599   D (emitcode (";", "genrshOne"););
8600   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8601 }
8602 #endif
8603
8604 #ifdef BETTER_LITERAL_SHIFT
8605 /*-----------------------------------------------------------------*/
8606 /* genrshTwo - right shift two bytes by known amount != 0          */
8607 /*-----------------------------------------------------------------*/
8608 static void
8609 genrshTwo (operand * result, operand * left,
8610            int shCount, int sign)
8611 {
8612   D (emitcode (";", "genrshTwo"););
8613
8614   /* if shCount >= 8 */
8615   if (shCount >= 8)
8616     {
8617       shCount -= 8;
8618       _startLazyDPSEvaluation();
8619       if (shCount)
8620       {
8621         shiftR1Left2Result (left, MSB16, result, LSB,
8622                             shCount, sign);
8623       }                     
8624       else
8625       {
8626         movLeft2Result (left, MSB16, result, LSB, sign);
8627       }
8628       addSign (result, MSB16, sign);
8629       _endLazyDPSEvaluation();
8630     }
8631
8632   /*  1 <= shCount <= 7 */
8633   else
8634   {
8635     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8636   }
8637 }
8638 #endif
8639
8640 /*-----------------------------------------------------------------*/
8641 /* shiftRLong - shift right one long from left to result           */
8642 /* offl = LSB or MSB16                                             */
8643 /*-----------------------------------------------------------------*/
8644 static void
8645 shiftRLong (operand * left, int offl,
8646             operand * result, int sign)
8647 {
8648   int isSameRegs=sameRegs(AOP(left),AOP(result));
8649
8650   if (isSameRegs && offl>1) {
8651     // we are in big trouble, but this shouldn't happen
8652     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8653   }
8654
8655   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8656   
8657   if (offl==MSB16) {
8658     // shift is > 8
8659     if (sign) {
8660       emitcode ("rlc", "a");
8661       emitcode ("subb", "a,acc");
8662       emitcode ("xch", "a,%s",
8663                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8664     } else {
8665       aopPut (AOP(result), zero, MSB32);
8666     }
8667   }
8668
8669   if (!sign) {
8670     emitcode ("clr", "c");
8671   } else {
8672     emitcode ("mov", "c,acc.7");
8673   }
8674
8675   emitcode ("rrc", "a");
8676
8677   if (isSameRegs && offl==MSB16) {
8678     emitcode ("xch",
8679               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8680   } else {
8681     aopPut (AOP (result), "a", MSB32);
8682     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8683   }
8684
8685   emitcode ("rrc", "a");
8686   if (isSameRegs && offl==1) {
8687     emitcode ("xch", "a,%s",
8688               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8689   } else {
8690     aopPut (AOP (result), "a", MSB24);
8691     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8692   }
8693   emitcode ("rrc", "a");
8694   aopPut (AOP (result), "a", MSB16 - offl);
8695
8696   if (offl == LSB)
8697     {
8698       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8699       emitcode ("rrc", "a");
8700       aopPut (AOP (result), "a", LSB);
8701     }
8702 }
8703
8704 /*-----------------------------------------------------------------*/
8705 /* genrshFour - shift four byte by a known amount != 0             */
8706 /*-----------------------------------------------------------------*/
8707 static void
8708 genrshFour (operand * result, operand * left,
8709             int shCount, int sign)
8710 {
8711   D (emitcode (";", "genrshFour"););
8712
8713   /* if shifting more that 3 bytes */
8714   if (shCount >= 24)
8715     {
8716       shCount -= 24;
8717       _startLazyDPSEvaluation();
8718       if (shCount)
8719         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8720       else
8721         movLeft2Result (left, MSB32, result, LSB, sign);
8722       addSign (result, MSB16, sign);
8723       _endLazyDPSEvaluation();
8724     }
8725   else if (shCount >= 16)
8726     {
8727       shCount -= 16;
8728       _startLazyDPSEvaluation();
8729       if (shCount)
8730         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8731       else
8732         {
8733           movLeft2Result (left, MSB24, result, LSB, 0);
8734           movLeft2Result (left, MSB32, result, MSB16, sign);
8735         }
8736       addSign (result, MSB24, sign);
8737       _endLazyDPSEvaluation();
8738     }
8739   else if (shCount >= 8)
8740     {
8741       shCount -= 8;
8742       _startLazyDPSEvaluation();
8743       if (shCount == 1)
8744         {
8745             shiftRLong (left, MSB16, result, sign);
8746         }
8747       else if (shCount == 0)
8748         {
8749           movLeft2Result (left, MSB16, result, LSB, 0);
8750           movLeft2Result (left, MSB24, result, MSB16, 0);
8751           movLeft2Result (left, MSB32, result, MSB24, sign);
8752           addSign (result, MSB32, sign);
8753         }
8754       else
8755         {
8756           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8757           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8758           /* the last shift is signed */
8759           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8760           addSign (result, MSB32, sign);
8761         }
8762         _endLazyDPSEvaluation();
8763     }
8764   else
8765     {   
8766         /* 1 <= shCount <= 7 */
8767       if (shCount <= 2)
8768         {
8769           shiftRLong (left, LSB, result, sign);
8770           if (shCount == 2)
8771             shiftRLong (result, LSB, result, sign);
8772         }
8773       else
8774         {
8775           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8776           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8777           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8778         }
8779     }
8780 }
8781
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* genRightShiftLiteral - right shifting by known count            */
8785 /*-----------------------------------------------------------------*/
8786 static bool
8787 genRightShiftLiteral (operand * left,
8788                       operand * right,
8789                       operand * result,
8790                       iCode * ic,
8791                       int sign)
8792 {
8793   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8794   int size;
8795
8796   size = getSize (operandType (result));
8797
8798   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8799
8800   /* We only handle certain easy cases so far. */
8801   if ((shCount != 0)
8802    && (shCount < (size * 8))
8803    && (size != 1)
8804    && (size != 2)
8805    && (size != 4))
8806   {
8807       D(emitcode (";", "genRightShiftLiteral wimping out"););
8808       return FALSE;
8809   }
8810
8811   freeAsmop (right, NULL, ic, TRUE);
8812
8813   aopOp (left, ic, FALSE, FALSE);
8814   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8815
8816 #if VIEW_SIZE
8817   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8818             AOP_SIZE (left));
8819 #endif
8820
8821   /* test the LEFT size !!! */
8822
8823   /* I suppose that the left size >= result size */
8824   if (shCount == 0)
8825   {
8826       size = getDataSize (result);
8827       _startLazyDPSEvaluation();
8828       while (size--)
8829       {
8830         movLeft2Result (left, size, result, size, 0);
8831       }
8832       _endLazyDPSEvaluation();
8833   }
8834   else if (shCount >= (size * 8))
8835     {
8836       if (sign)
8837       {
8838         /* get sign in acc.7 */
8839         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8840       }
8841       addSign (result, LSB, sign);
8842     }
8843   else
8844     {
8845       switch (size)
8846         {
8847         case 1:
8848           genrshOne (result, left, shCount, sign);
8849           break;
8850
8851         case 2:
8852           genrshTwo (result, left, shCount, sign);
8853           break;
8854 #if 1
8855         case 4:
8856           genrshFour (result, left, shCount, sign);
8857           break;
8858 #endif    
8859         default:
8860           break;
8861         }
8862     }
8863   freeAsmop (left, NULL, ic, TRUE);
8864   freeAsmop (result, NULL, ic, TRUE);
8865   
8866   return TRUE;
8867 }
8868 #endif
8869
8870 /*-----------------------------------------------------------------*/
8871 /* genSignedRightShift - right shift of signed number              */
8872 /*-----------------------------------------------------------------*/
8873 static void
8874 genSignedRightShift (iCode * ic)
8875 {
8876   operand *right, *left, *result;
8877   int size, offset;
8878   char *l;
8879   symbol *tlbl, *tlbl1;
8880
8881   D (emitcode (";", "genSignedRightShift "););
8882
8883   /* we do it the hard way put the shift count in b
8884      and loop thru preserving the sign */
8885
8886   right = IC_RIGHT (ic);
8887   left = IC_LEFT (ic);
8888   result = IC_RESULT (ic);
8889
8890   aopOp (right, ic, FALSE, FALSE);
8891
8892 #ifdef BETTER_LITERAL_SHIFT
8893   if (AOP_TYPE (right) == AOP_LIT)
8894     {
8895       if (genRightShiftLiteral (left, right, result, ic, 1))
8896       {
8897         return;
8898       }
8899     }
8900 #endif
8901   /* shift count is unknown then we have to form
8902      a loop get the loop count in B : Note: we take
8903      only the lower order byte since shifting
8904      more that 32 bits make no sense anyway, ( the
8905      largest size of an object can be only 32 bits ) */
8906
8907   if (AOP_TYPE (right) == AOP_LIT)
8908   {
8909       /* Really should be handled by genRightShiftLiteral,
8910        * but since I'm too lazy to fix that today, at least we can make
8911        * some small improvement.
8912        */
8913        emitcode("mov", "b,#!constbyte",
8914                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8915   }
8916   else
8917   {
8918         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8919         emitcode ("inc", "b");
8920   }
8921   freeAsmop (right, NULL, ic, TRUE);
8922   aopOp (left, ic, FALSE, FALSE);
8923   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8924
8925   /* now move the left to the result if they are not the
8926      same */
8927   if (!sameRegs (AOP (left), AOP (result)) &&
8928       AOP_SIZE (result) > 1)
8929     {
8930
8931       size = AOP_SIZE (result);
8932       offset = 0;
8933       _startLazyDPSEvaluation ();
8934       while (size--)
8935         {
8936           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8937           if (*l == '@' && IS_AOP_PREG (result))
8938             {
8939
8940               emitcode ("mov", "a,%s", l);
8941               aopPut (AOP (result), "a", offset);
8942             }
8943           else
8944             aopPut (AOP (result), l, offset);
8945           offset++;
8946         }
8947       _endLazyDPSEvaluation ();
8948     }
8949
8950   /* mov the highest order bit to OVR */
8951   tlbl = newiTempLabel (NULL);
8952   tlbl1 = newiTempLabel (NULL);
8953
8954   size = AOP_SIZE (result);
8955   offset = size - 1;
8956   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8957   emitcode ("rlc", "a");
8958   emitcode ("mov", "ov,c");
8959   /* if it is only one byte then */
8960   if (size == 1)
8961     {
8962       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8963       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8964       emitcode ("", "!tlabeldef", tlbl->key + 100);
8965       emitcode ("mov", "c,ov");
8966       emitcode ("rrc", "a");
8967       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969       aopPut (AOP (result), "a", 0);
8970       goto release;
8971     }
8972
8973   reAdjustPreg (AOP (result));
8974   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8975   emitcode ("", "!tlabeldef", tlbl->key + 100);
8976   emitcode ("mov", "c,ov");
8977   _startLazyDPSEvaluation ();
8978   while (size--)
8979     {
8980       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8981       emitcode ("rrc", "a");
8982       aopPut (AOP (result), "a", offset--);
8983     }
8984   _endLazyDPSEvaluation ();
8985   reAdjustPreg (AOP (result));
8986   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8987   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8988
8989 release:
8990   freeAsmop (left, NULL, ic, TRUE);
8991   freeAsmop (result, NULL, ic, TRUE);
8992 }
8993
8994 /*-----------------------------------------------------------------*/
8995 /* genRightShift - generate code for right shifting                */
8996 /*-----------------------------------------------------------------*/
8997 static void
8998 genRightShift (iCode * ic)
8999 {
9000   operand *right, *left, *result;
9001   sym_link *letype;
9002   int size, offset;
9003   char *l;
9004   symbol *tlbl, *tlbl1;
9005
9006   D (emitcode (";", "genRightShift "););
9007
9008   /* if signed then we do it the hard way preserve the
9009      sign bit moving it inwards */
9010   letype = getSpec (operandType (IC_LEFT (ic)));
9011
9012   if (!SPEC_USIGN (letype))
9013     {
9014       genSignedRightShift (ic);
9015       return;
9016     }
9017
9018   /* signed & unsigned types are treated the same : i.e. the
9019      signed is NOT propagated inwards : quoting from the
9020      ANSI - standard : "for E1 >> E2, is equivalent to division
9021      by 2**E2 if unsigned or if it has a non-negative value,
9022      otherwise the result is implementation defined ", MY definition
9023      is that the sign does not get propagated */
9024
9025   right = IC_RIGHT (ic);
9026   left = IC_LEFT (ic);
9027   result = IC_RESULT (ic);
9028
9029   aopOp (right, ic, FALSE, FALSE);
9030
9031 #ifdef BETTER_LITERAL_SHIFT
9032   /* if the shift count is known then do it
9033      as efficiently as possible */
9034   if (AOP_TYPE (right) == AOP_LIT)
9035     {
9036       if (genRightShiftLiteral (left, right, result, ic, 0))
9037       {
9038         return;
9039       }
9040     }
9041 #endif
9042
9043   /* shift count is unknown then we have to form
9044      a loop get the loop count in B : Note: we take
9045      only the lower order byte since shifting
9046      more that 32 bits make no sense anyway, ( the
9047      largest size of an object can be only 32 bits ) */
9048   
9049   if (AOP_TYPE (right) == AOP_LIT)
9050   {
9051       /* Really should be handled by genRightShiftLiteral,
9052        * but since I'm too lazy to fix that today, at least we can make
9053        * some small improvement.
9054        */
9055        emitcode("mov", "b,#!constbyte",
9056                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9057   }
9058   else
9059   {
9060       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9061       emitcode ("inc", "b");
9062   }
9063   freeAsmop (right, NULL, ic, TRUE);
9064   aopOp (left, ic, FALSE, FALSE);
9065   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9066
9067   /* now move the left to the result if they are not the
9068      same */
9069   if (!sameRegs (AOP (left), AOP (result)) &&
9070       AOP_SIZE (result) > 1)
9071     {
9072
9073       size = AOP_SIZE (result);
9074       offset = 0;
9075       _startLazyDPSEvaluation ();
9076       while (size--)
9077         {
9078           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9079           if (*l == '@' && IS_AOP_PREG (result))
9080             {
9081
9082               emitcode ("mov", "a,%s", l);
9083               aopPut (AOP (result), "a", offset);
9084             }
9085           else
9086             aopPut (AOP (result), l, offset);
9087           offset++;
9088         }
9089       _endLazyDPSEvaluation ();
9090     }
9091
9092   tlbl = newiTempLabel (NULL);
9093   tlbl1 = newiTempLabel (NULL);
9094   size = AOP_SIZE (result);
9095   offset = size - 1;
9096
9097   /* if it is only one byte then */
9098   if (size == 1)
9099     {
9100       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9101       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9102       emitcode ("", "!tlabeldef", tlbl->key + 100);
9103       CLRC;
9104       emitcode ("rrc", "a");
9105       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9106       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9107       aopPut (AOP (result), "a", 0);
9108       goto release;
9109     }
9110
9111   reAdjustPreg (AOP (result));
9112   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9113   emitcode ("", "!tlabeldef", tlbl->key + 100);
9114   CLRC;
9115   _startLazyDPSEvaluation ();
9116   while (size--)
9117     {
9118       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9119       emitcode ("rrc", "a");
9120       aopPut (AOP (result), "a", offset--);
9121     }
9122   _endLazyDPSEvaluation ();
9123   reAdjustPreg (AOP (result));
9124
9125   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9126   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9127
9128 release:
9129   freeAsmop (left, NULL, ic, TRUE);
9130   freeAsmop (result, NULL, ic, TRUE);
9131 }
9132
9133
9134 /*-----------------------------------------------------------------*/
9135 /* emitPtrByteGet - emits code to get a byte into A through a      */
9136 /*                  pointer register (R0, R1, or DPTR). The        */
9137 /*                  original value of A can be preserved in B.     */
9138 /*-----------------------------------------------------------------*/
9139 static void
9140 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9141 {
9142   switch (p_type)
9143     {
9144     case IPOINTER:
9145     case POINTER:
9146       if (preserveAinB)
9147         emitcode ("mov", "b,a");
9148       emitcode ("mov", "a,@%s", rname);
9149       break;
9150
9151     case PPOINTER:
9152       if (preserveAinB)
9153         emitcode ("mov", "b,a");
9154       emitcode ("movx", "a,@%s", rname);
9155       break;
9156       
9157     case FPOINTER:
9158       if (preserveAinB)
9159         emitcode ("mov", "b,a");
9160       emitcode ("movx", "a,@dptr");
9161       break;
9162
9163     case CPOINTER:
9164       if (preserveAinB)
9165         emitcode ("mov", "b,a");
9166       emitcode ("clr", "a");
9167       emitcode ("movc", "a,@a+dptr");
9168       break;
9169
9170     case GPOINTER:
9171       if (preserveAinB)
9172         {
9173           emitcode ("push", "b");
9174           emitcode ("push", "acc");
9175         }
9176       emitcode ("lcall", "__gptrget");
9177       if (preserveAinB)
9178         emitcode ("pop", "b");
9179       break;
9180     }
9181 }
9182
9183 /*-----------------------------------------------------------------*/
9184 /* emitPtrByteSet - emits code to set a byte from src through a    */
9185 /*                  pointer register (R0, R1, or DPTR).            */
9186 /*-----------------------------------------------------------------*/
9187 static void
9188 emitPtrByteSet (char *rname, int p_type, char *src)
9189 {
9190   switch (p_type)
9191     {
9192     case IPOINTER:
9193     case POINTER:
9194       if (*src=='@')
9195         {
9196           MOVA (src);
9197           emitcode ("mov", "@%s,a", rname);
9198         }
9199       else
9200         emitcode ("mov", "@%s,%s", rname, src);
9201       break;
9202
9203     case PPOINTER:
9204       MOVA (src);
9205       emitcode ("movx", "@%s,a", rname);
9206       break;
9207       
9208     case FPOINTER:
9209       MOVA (src);
9210       emitcode ("movx", "@dptr,a");
9211       break;
9212
9213     case GPOINTER:
9214       MOVA (src);
9215       emitcode ("lcall", "__gptrput");
9216       break;
9217     }
9218 }
9219
9220 /*-----------------------------------------------------------------*/
9221 /* genUnpackBits - generates code for unpacking bits               */
9222 /*-----------------------------------------------------------------*/
9223 static void
9224 genUnpackBits (operand * result, char *rname, int ptype)
9225 {
9226   int offset = 0;       /* result byte offset */
9227   int rsize;            /* result size */
9228   int rlen = 0;         /* remaining bitfield length */
9229   sym_link *etype;      /* bitfield type information */
9230   int blen;             /* bitfield length */
9231   int bstr;             /* bitfield starting bit within byte */
9232
9233   D(emitcode (";     genUnpackBits",""));
9234
9235   etype = getSpec (operandType (result));
9236   rsize = getSize (operandType (result));
9237   blen = SPEC_BLEN (etype);
9238   bstr = SPEC_BSTR (etype);
9239
9240   /* If the bitfield length is less than a byte */
9241   if (blen < 8)
9242     {
9243       emitPtrByteGet (rname, ptype, FALSE);
9244       AccRsh (bstr);
9245       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9246       aopPut (AOP (result), "a", offset++);
9247       goto finish;
9248     }
9249
9250   /* Bit field did not fit in a byte. Copy all
9251      but the partial byte at the end.  */
9252   for (rlen=blen;rlen>=8;rlen-=8)
9253     {
9254       emitPtrByteGet (rname, ptype, FALSE);
9255       aopPut (AOP (result), "a", offset++);
9256       if (rlen>8)
9257         emitcode ("inc", "%s", rname);
9258     }
9259
9260   /* Handle the partial byte at the end */
9261   if (rlen)
9262     {
9263       emitPtrByteGet (rname, ptype, FALSE);
9264       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9265       aopPut (AOP (result), "a", offset++);
9266     }
9267
9268 finish:
9269   if (offset < rsize)
9270     {
9271       rsize -= offset;
9272       while (rsize--)
9273         aopPut (AOP (result), zero, offset++);
9274     }
9275 }
9276
9277
9278 /*-----------------------------------------------------------------*/
9279 /* genDataPointerGet - generates code when ptr offset is known     */
9280 /*-----------------------------------------------------------------*/
9281 static void
9282 genDataPointerGet (operand * left,
9283                    operand * result,
9284                    iCode * ic)
9285 {
9286   char *l;
9287   char buff[256];
9288   int size, offset = 0;
9289   aopOp (result, ic, TRUE, FALSE);
9290
9291   /* get the string representation of the name */
9292   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9293   size = AOP_SIZE (result);
9294   _startLazyDPSEvaluation ();
9295   while (size--)
9296     {
9297         if (offset)
9298         {
9299             SNPRINTF (buff, sizeof(buff), 
9300                       "(%s + %d)", l + 1, offset);
9301         }
9302         else
9303         {
9304             SNPRINTF (buff, sizeof(buff), 
9305                       "%s", l + 1);
9306         }
9307       aopPut (AOP (result), buff, offset++);
9308     }
9309   _endLazyDPSEvaluation ();
9310
9311   freeAsmop (left, NULL, ic, TRUE);
9312   freeAsmop (result, NULL, ic, TRUE);
9313 }
9314
9315 /*-----------------------------------------------------------------*/
9316 /* genNearPointerGet - emitcode for near pointer fetch             */
9317 /*-----------------------------------------------------------------*/
9318 static void
9319 genNearPointerGet (operand * left,
9320                    operand * result,
9321                    iCode * ic,
9322                    iCode *pi)
9323 {
9324   asmop *aop = NULL;
9325   regs *preg;
9326   char *rname;
9327   sym_link *rtype, *retype, *letype;
9328   sym_link *ltype = operandType (left);
9329   char buff[80];
9330
9331   rtype = operandType (result);
9332   retype = getSpec (rtype);
9333   letype = getSpec (ltype);
9334
9335   aopOp (left, ic, FALSE, FALSE);
9336
9337   /* if left is rematerialisable and
9338      result is not bit variable type and
9339      the left is pointer to data space i.e
9340      lower 128 bytes of space */
9341   if (AOP_TYPE (left) == AOP_IMMD &&
9342       !IS_BITVAR (retype) &&
9343       !IS_BITVAR (letype) &&
9344       DCL_TYPE (ltype) == POINTER)
9345     {
9346       genDataPointerGet (left, result, ic);
9347       return;
9348     }
9349
9350   /* if the value is already in a pointer register
9351      then don't need anything more */
9352   if (!AOP_INPREG (AOP (left)))
9353     {
9354       /* otherwise get a free pointer register */
9355       aop = newAsmop (0);
9356       preg = getFreePtr (ic, &aop, FALSE);
9357       emitcode ("mov", "%s,%s",
9358                 preg->name,
9359                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9360       rname = preg->name;
9361     }
9362   else
9363     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9364
9365   freeAsmop (left, NULL, ic, TRUE);
9366   aopOp (result, ic, FALSE, FALSE);
9367
9368   /* if bitfield then unpack the bits */
9369   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9370     genUnpackBits (result, rname, POINTER);
9371   else
9372     {
9373       /* we have can just get the values */
9374       int size = AOP_SIZE (result);
9375       int offset = 0;
9376
9377       while (size--)
9378         {
9379           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9380             {
9381
9382               emitcode ("mov", "a,@%s", rname);
9383               aopPut (AOP (result), "a", offset);
9384             }
9385           else
9386             {
9387               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9388               aopPut (AOP (result), buff, offset);
9389             }
9390           offset++;
9391           if (size || pi)
9392             {
9393                 emitcode ("inc", "%s", rname);
9394             }
9395         }
9396     }
9397
9398   /* now some housekeeping stuff */
9399   if (aop)
9400     {
9401       /* we had to allocate for this iCode */
9402       if (pi) { /* post increment present */
9403         aopPut(AOP ( left ),rname,0);
9404       }
9405       freeAsmop (NULL, aop, ic, TRUE);
9406     }
9407   else
9408     {
9409       /* we did not allocate which means left
9410          already in a pointer register, then
9411          if size > 0 && this could be used again
9412          we have to point it back to where it
9413          belongs */
9414       if (AOP_SIZE (result) > 1 &&
9415           !OP_SYMBOL (left)->remat &&
9416           (OP_SYMBOL (left)->liveTo > ic->seq ||
9417            ic->depth) &&
9418           !pi)
9419         {
9420           int size = AOP_SIZE (result) - 1;
9421           while (size--)
9422             emitcode ("dec", "%s", rname);
9423         }
9424     }
9425
9426   /* done */
9427   freeAsmop (result, NULL, ic, TRUE);
9428   if (pi) pi->generated = 1;
9429 }
9430
9431 /*-----------------------------------------------------------------*/
9432 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9433 /*-----------------------------------------------------------------*/
9434 static void
9435 genPagedPointerGet (operand * left,
9436                     operand * result,
9437                     iCode * ic,
9438                     iCode * pi)
9439 {
9440   asmop *aop = NULL;
9441   regs *preg;
9442   char *rname;
9443   sym_link *rtype, *retype, *letype;
9444
9445   rtype = operandType (result);
9446   retype = getSpec (rtype);
9447   letype = getSpec (operandType (left));
9448   aopOp (left, ic, FALSE, FALSE);
9449
9450   /* if the value is already in a pointer register
9451      then don't need anything more */
9452   if (!AOP_INPREG (AOP (left)))
9453     {
9454       /* otherwise get a free pointer register */
9455       aop = newAsmop (0);
9456       preg = getFreePtr (ic, &aop, FALSE);
9457       emitcode ("mov", "%s,%s",
9458                 preg->name,
9459                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9460       rname = preg->name;
9461     }
9462   else
9463     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9464
9465   freeAsmop (left, NULL, ic, TRUE);
9466   aopOp (result, ic, FALSE, FALSE);
9467
9468   /* if bitfield then unpack the bits */
9469   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9470     genUnpackBits (result, rname, PPOINTER);
9471   else
9472     {
9473       /* we have can just get the values */
9474       int size = AOP_SIZE (result);
9475       int offset = 0;
9476
9477       while (size--)
9478         {
9479
9480           emitcode ("movx", "a,@%s", rname);
9481           aopPut (AOP (result), "a", offset);
9482
9483           offset++;
9484
9485           if (size || pi)
9486             emitcode ("inc", "%s", rname);
9487         }
9488     }
9489
9490   /* now some housekeeping stuff */
9491   if (aop)
9492     {
9493       /* we had to allocate for this iCode */
9494       if (pi) aopPut ( AOP (left), rname, 0);
9495       freeAsmop (NULL, aop, ic, TRUE);
9496     }
9497   else
9498     {
9499       /* we did not allocate which means left
9500          already in a pointer register, then
9501          if size > 0 && this could be used again
9502          we have to point it back to where it
9503          belongs */
9504       if (AOP_SIZE (result) > 1 &&
9505           !OP_SYMBOL (left)->remat &&
9506           (OP_SYMBOL (left)->liveTo > ic->seq ||
9507            ic->depth) &&
9508           !pi)
9509         {
9510           int size = AOP_SIZE (result) - 1;
9511           while (size--)
9512             emitcode ("dec", "%s", rname);
9513         }
9514     }
9515
9516   /* done */
9517   freeAsmop (result, NULL, ic, TRUE);
9518   if (pi) pi->generated = 1;
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genFarPointerGet - gget value from far space                    */
9523 /*-----------------------------------------------------------------*/
9524 static void
9525 genFarPointerGet (operand * left,
9526                   operand * result, iCode * ic, iCode *pi)
9527 {
9528     int size, offset, dopi=1;
9529   sym_link *retype = getSpec (operandType (result));
9530   sym_link *letype = getSpec (operandType (left));
9531   D (emitcode (";", "genFarPointerGet"););
9532
9533   aopOp (left, ic, FALSE, FALSE);
9534
9535   /* if the operand is already in dptr
9536      then we do nothing else we move the value to dptr */
9537   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9538     {
9539       /* if this is remateriazable */
9540       if (AOP_TYPE (left) == AOP_IMMD)
9541         {
9542           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9543         }
9544       else
9545         {
9546           /* we need to get it byte by byte */
9547           _startLazyDPSEvaluation ();
9548           if (AOP_TYPE (left) != AOP_DPTR)
9549             {
9550               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9551               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9552               if (options.model == MODEL_FLAT24)
9553                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9554             }
9555           else
9556             {
9557               /* We need to generate a load to DPTR indirect through DPTR. */
9558               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9559               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9560               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9561               if (options.model == MODEL_FLAT24)
9562                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9563               emitcode ("pop", "dph");
9564               emitcode ("pop", "dpl");
9565               dopi =0;
9566             }
9567           _endLazyDPSEvaluation ();
9568         }
9569     }
9570   /* so dptr know contains the address */
9571   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9572
9573   /* if bit then unpack */
9574   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9575       if (AOP_INDPTRn(left)) {
9576           genSetDPTR(AOP(left)->aopu.dptr);
9577       }
9578       genUnpackBits (result, "dptr", FPOINTER);
9579       if (AOP_INDPTRn(left)) {
9580           genSetDPTR(0);
9581       }
9582   } else
9583     {
9584       size = AOP_SIZE (result);
9585       offset = 0;
9586
9587       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9588           while (size--) {
9589               genSetDPTR(AOP(left)->aopu.dptr);
9590               emitcode ("movx", "a,@dptr");
9591               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9592                   emitcode ("inc", "dptr");
9593               genSetDPTR (0);
9594               aopPut (AOP (result), "a", offset++);
9595           }
9596       } else {
9597           _startLazyDPSEvaluation ();
9598           while (size--) {
9599               if (AOP_INDPTRn(left)) {
9600                   genSetDPTR(AOP(left)->aopu.dptr);
9601               } else {
9602                   genSetDPTR (0);
9603               }
9604               _flushLazyDPS ();
9605               
9606               emitcode ("movx", "a,@dptr");
9607               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9608                   emitcode ("inc", "dptr");
9609               
9610               aopPut (AOP (result), "a", offset++);
9611           }
9612           _endLazyDPSEvaluation ();
9613       }
9614     }
9615   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9616       if (!AOP_INDPTRn(left)) {
9617           _startLazyDPSEvaluation ();
9618           aopPut ( AOP (left), "dpl", 0);
9619           aopPut ( AOP (left), "dph", 1);
9620           if (options.model == MODEL_FLAT24)
9621               aopPut ( AOP (left), "dpx", 2);
9622           _endLazyDPSEvaluation ();
9623       }
9624     pi->generated = 1;
9625   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9626              AOP_SIZE(result) > 1 &&
9627              IS_SYMOP(left) &&
9628              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9629       
9630       size = AOP_SIZE (result) - 1;
9631       if (AOP_INDPTRn(left)) {
9632           genSetDPTR(AOP(left)->aopu.dptr);
9633       }
9634       while (size--) emitcode ("lcall","__decdptr");
9635       if (AOP_INDPTRn(left)) {
9636           genSetDPTR(0);
9637       }
9638   }
9639
9640   freeAsmop (left, NULL, ic, TRUE);
9641   freeAsmop (result, NULL, ic, TRUE);
9642 }
9643
9644 /*-----------------------------------------------------------------*/
9645 /* genCodePointerGet - get value from code space                  */
9646 /*-----------------------------------------------------------------*/
9647 static void
9648 genCodePointerGet (operand * left,
9649                     operand * result, iCode * ic, iCode *pi)
9650 {
9651   int size, offset, dopi=1;
9652   sym_link *retype = getSpec (operandType (result));
9653
9654   aopOp (left, ic, FALSE, FALSE);
9655
9656   /* if the operand is already in dptr
9657      then we do nothing else we move the value to dptr */
9658   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9659     {
9660       /* if this is remateriazable */
9661       if (AOP_TYPE (left) == AOP_IMMD)
9662         {
9663           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9664         }
9665       else
9666         {                       /* we need to get it byte by byte */
9667           _startLazyDPSEvaluation ();
9668           if (AOP_TYPE (left) != AOP_DPTR)
9669             {
9670               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9671               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9672               if (options.model == MODEL_FLAT24)
9673                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9674             }
9675           else
9676             {
9677               /* We need to generate a load to DPTR indirect through DPTR. */
9678               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9679               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9680               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9681               if (options.model == MODEL_FLAT24)
9682                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9683               emitcode ("pop", "dph");
9684               emitcode ("pop", "dpl");
9685               dopi=0;
9686             }
9687           _endLazyDPSEvaluation ();
9688         }
9689     }
9690   /* so dptr know contains the address */
9691   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9692
9693   /* if bit then unpack */
9694   if (IS_BITVAR (retype)) {
9695       if (AOP_INDPTRn(left)) {
9696           genSetDPTR(AOP(left)->aopu.dptr);
9697       }
9698       genUnpackBits (result, "dptr", CPOINTER);
9699       if (AOP_INDPTRn(left)) {
9700           genSetDPTR(0);
9701       }
9702   } else
9703     {
9704       size = AOP_SIZE (result);
9705       offset = 0;
9706       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9707           while (size--) {
9708               genSetDPTR(AOP(left)->aopu.dptr);
9709               emitcode ("clr", "a");
9710               emitcode ("movc", "a,@a+dptr");
9711               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9712                   emitcode ("inc", "dptr");
9713               genSetDPTR (0);
9714               aopPut (AOP (result), "a", offset++);
9715           }
9716       } else {
9717           _startLazyDPSEvaluation ();
9718           while (size--)
9719               {
9720                   if (AOP_INDPTRn(left)) {
9721                       genSetDPTR(AOP(left)->aopu.dptr);
9722                   } else {
9723                       genSetDPTR (0);
9724                   }
9725                   _flushLazyDPS ();
9726                   
9727                   emitcode ("clr", "a");
9728                   emitcode ("movc", "a,@a+dptr");
9729                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9730                       emitcode ("inc", "dptr");
9731                   aopPut (AOP (result), "a", offset++);
9732               }
9733           _endLazyDPSEvaluation ();
9734       }
9735     }
9736   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9737       if (!AOP_INDPTRn(left)) {
9738           _startLazyDPSEvaluation ();
9739           
9740           aopPut ( AOP (left), "dpl", 0);
9741           aopPut ( AOP (left), "dph", 1);
9742           if (options.model == MODEL_FLAT24)
9743               aopPut ( AOP (left), "dpx", 2);
9744
9745           _endLazyDPSEvaluation ();
9746       }
9747       pi->generated = 1;
9748   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9749              AOP_SIZE(result) > 1 &&
9750              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9751       
9752       size = AOP_SIZE (result) - 1;
9753       if (AOP_INDPTRn(left)) {
9754           genSetDPTR(AOP(left)->aopu.dptr);
9755       }
9756       while (size--) emitcode ("lcall","__decdptr");
9757       if (AOP_INDPTRn(left)) {
9758           genSetDPTR(0);
9759       }
9760   }
9761   
9762   freeAsmop (left, NULL, ic, TRUE);
9763   freeAsmop (result, NULL, ic, TRUE);
9764 }
9765
9766 /*-----------------------------------------------------------------*/
9767 /* genGenPointerGet - gget value from generic pointer space        */
9768 /*-----------------------------------------------------------------*/
9769 static void
9770 genGenPointerGet (operand * left,
9771                   operand * result, iCode * ic, iCode * pi)
9772 {
9773   int size, offset;
9774   sym_link *retype = getSpec (operandType (result));
9775   sym_link *letype = getSpec (operandType (left));
9776
9777   D (emitcode (";", "genGenPointerGet "); );
9778
9779   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9780
9781   /* if the operand is already in dptr
9782      then we do nothing else we move the value to dptr */
9783   if (AOP_TYPE (left) != AOP_STR)
9784     {
9785       /* if this is remateriazable */
9786       if (AOP_TYPE (left) == AOP_IMMD)
9787         {
9788           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9789           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9790             {
9791                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9792             }
9793             else
9794             {
9795                 emitcode ("mov", "b,#%d", pointerCode (retype));
9796             }
9797         }
9798       else
9799         {                       /* we need to get it byte by byte */
9800             _startLazyDPSEvaluation ();
9801             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9802             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9803             if (options.model == MODEL_FLAT24) {
9804                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9805                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9806             } else {
9807                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9808             }
9809             _endLazyDPSEvaluation ();
9810         }
9811     }
9812
9813   /* so dptr-b now contains the address */
9814   _G.bInUse++;
9815   aopOp (result, ic, FALSE, TRUE);
9816   _G.bInUse--;
9817
9818   /* if bit then unpack */
9819   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9820   {
9821     genUnpackBits (result, "dptr", GPOINTER);
9822   }
9823   else
9824     {
9825         size = AOP_SIZE (result);
9826         offset = 0;
9827
9828         while (size--)
9829         {
9830             if (size)
9831             {
9832                 // Get two bytes at a time, results in _AP & A.
9833                 // dptr will be incremented ONCE by __gptrgetWord.
9834                 //
9835                 // Note: any change here must be coordinated
9836                 // with the implementation of __gptrgetWord
9837                 // in device/lib/_gptrget.c
9838                 emitcode ("lcall", "__gptrgetWord");
9839                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9840                 aopPut (AOP (result), "a", offset++);
9841                 size--;
9842             }
9843             else
9844             {
9845                 // Only one byte to get.
9846                 emitcode ("lcall", "__gptrget");
9847                 aopPut (AOP (result), "a", offset++);
9848             }
9849             
9850             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9851             {
9852                 emitcode ("inc", "dptr");
9853             }
9854         }
9855     }
9856
9857   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9858     _startLazyDPSEvaluation ();
9859       
9860     aopPut ( AOP (left), "dpl", 0);
9861     aopPut ( AOP (left), "dph", 1);
9862     if (options.model == MODEL_FLAT24) {
9863         aopPut ( AOP (left), "dpx", 2);
9864         aopPut ( AOP (left), "b", 3);   
9865     } else  aopPut ( AOP (left), "b", 2);       
9866     
9867     _endLazyDPSEvaluation ();
9868       
9869     pi->generated = 1;
9870   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9871              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9872       
9873       size = AOP_SIZE (result) - 1;
9874       while (size--) emitcode ("lcall","__decdptr");
9875   }
9876
9877   freeAsmop (left, NULL, ic, TRUE);
9878   freeAsmop (result, NULL, ic, TRUE);
9879 }
9880
9881 /*-----------------------------------------------------------------*/
9882 /* genPointerGet - generate code for pointer get                   */
9883 /*-----------------------------------------------------------------*/
9884 static void
9885 genPointerGet (iCode * ic, iCode *pi)
9886 {
9887   operand *left, *result;
9888   sym_link *type, *etype;
9889   int p_type;
9890
9891   D (emitcode (";", "genPointerGet ");
9892     );
9893
9894   left = IC_LEFT (ic);
9895   result = IC_RESULT (ic);
9896
9897   /* depending on the type of pointer we need to
9898      move it to the correct pointer register */
9899   type = operandType (left);
9900   etype = getSpec (type);
9901   /* if left is of type of pointer then it is simple */
9902   if (IS_PTR (type) && !IS_FUNC (type->next))
9903     p_type = DCL_TYPE (type);
9904   else
9905     {
9906       /* we have to go by the storage class */
9907       p_type = PTR_TYPE (SPEC_OCLS (etype));
9908     }
9909   /* special case when cast remat */
9910   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9911       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9912           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9913           type = operandType (left);
9914           p_type = DCL_TYPE (type);
9915   }
9916   /* now that we have the pointer type we assign
9917      the pointer values */
9918   switch (p_type)
9919     {
9920
9921     case POINTER:
9922     case IPOINTER:
9923       genNearPointerGet (left, result, ic, pi);
9924       break;
9925
9926     case PPOINTER:
9927       genPagedPointerGet (left, result, ic, pi);
9928       break;
9929
9930     case FPOINTER:
9931       genFarPointerGet (left, result, ic, pi);
9932       break;
9933
9934     case CPOINTER:
9935       genCodePointerGet (left, result, ic, pi);
9936       break;
9937
9938     case GPOINTER:
9939       genGenPointerGet (left, result, ic, pi);
9940       break;
9941     }
9942
9943 }
9944
9945 /*-----------------------------------------------------------------*/
9946 /* genPackBits - generates code for packed bit storage             */
9947 /*-----------------------------------------------------------------*/
9948 static void
9949 genPackBits (sym_link * etype,
9950              operand * right,
9951              char *rname, int p_type)
9952 {
9953   int offset = 0;       /* source byte offset */
9954   int rlen = 0;         /* remaining bitfield length */
9955   int blen;             /* bitfield length */
9956   int bstr;             /* bitfield starting bit within byte */
9957   int litval;           /* source literal value (if AOP_LIT) */
9958   unsigned char mask;   /* bitmask within current byte */
9959
9960   D(emitcode (";     genPackBits",""));
9961
9962   blen = SPEC_BLEN (etype);
9963   bstr = SPEC_BSTR (etype);
9964
9965   /* If the bitfield length is less than a byte */
9966   if (blen < 8)
9967     {
9968       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9969               (unsigned char) (0xFF >> (8 - bstr)));
9970
9971       if (AOP_TYPE (right) == AOP_LIT)
9972         {
9973           /* Case with a bitfield length <8 and literal source
9974           */
9975           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9976           litval <<= bstr;
9977           litval &= (~mask) & 0xff;
9978           emitPtrByteGet (rname, p_type, FALSE);
9979           if ((mask|litval)!=0xff)
9980             emitcode ("anl","a,#!constbyte", mask);
9981           if (litval)
9982             emitcode ("orl","a,#!constbyte", litval);
9983         }
9984       else
9985         {
9986           if ((blen==1) && (p_type!=GPOINTER))
9987             {
9988               /* Case with a bitfield length == 1 and no generic pointer
9989               */
9990               if (AOP_TYPE (right) == AOP_CRY)
9991                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9992               else
9993                 {
9994                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9995                   emitcode ("rrc","a");
9996                 }
9997               emitPtrByteGet (rname, p_type, FALSE);
9998               emitcode ("mov","acc.%d,c",bstr);
9999             }
10000           else
10001             {
10002               /* Case with a bitfield length < 8 and arbitrary source
10003               */
10004               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10005               /* shift and mask source value */
10006               AccLsh (bstr);
10007               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10008
10009               /* transfer A to B and get next byte */
10010               emitPtrByteGet (rname, p_type, TRUE);
10011
10012               emitcode ("anl", "a,#!constbyte", mask);
10013               emitcode ("orl", "a,b");
10014               if (p_type == GPOINTER)
10015                 emitcode ("pop", "b");
10016            }
10017         }
10018
10019       emitPtrByteSet (rname, p_type, "a");
10020       return;
10021     }
10022
10023   /* Bit length is greater than 7 bits. In this case, copy  */
10024   /* all except the partial byte at the end                 */
10025   for (rlen=blen;rlen>=8;rlen-=8)
10026     {
10027       emitPtrByteSet (rname, p_type, 
10028                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10029       if (rlen>8)
10030         emitcode ("inc", "%s", rname);
10031     }
10032
10033   /* If there was a partial byte at the end */
10034   if (rlen)
10035     {
10036       mask = (((unsigned char) -1 << rlen) & 0xff);
10037       
10038       if (AOP_TYPE (right) == AOP_LIT)
10039         {
10040           /* Case with partial byte and literal source
10041           */
10042           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10043           litval >>= (blen-rlen);
10044           litval &= (~mask) & 0xff;
10045           emitPtrByteGet (rname, p_type, FALSE);
10046           if ((mask|litval)!=0xff)
10047             emitcode ("anl","a,#!constbyte", mask);
10048           if (litval)
10049             emitcode ("orl","a,#!constbyte", litval);
10050         }
10051       else
10052         {
10053           /* Case with partial byte and arbitrary source
10054           */
10055           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10056           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10057
10058           /* transfer A to B and get next byte */
10059           emitPtrByteGet (rname, p_type, TRUE);
10060
10061           emitcode ("anl", "a,#!constbyte", mask);
10062           emitcode ("orl", "a,b");
10063           if (p_type == GPOINTER)
10064             emitcode ("pop", "b");
10065         }
10066       emitPtrByteSet (rname, p_type, "a");
10067     }
10068
10069 }
10070
10071
10072 /*-----------------------------------------------------------------*/
10073 /* genDataPointerSet - remat pointer to data space                 */
10074 /*-----------------------------------------------------------------*/
10075 static void
10076 genDataPointerSet (operand * right,
10077                    operand * result,
10078                    iCode * ic)
10079 {
10080   int size, offset = 0;
10081   char *l, buff[256];
10082
10083   aopOp (right, ic, FALSE, FALSE);
10084
10085   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10086   size = AOP_SIZE (right);
10087   while (size--)
10088     {
10089       if (offset)
10090         {
10091             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10092         }
10093       else
10094         {
10095             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10096         }
10097         
10098       emitcode ("mov", "%s,%s", buff,
10099                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10100     }
10101
10102   freeAsmop (right, NULL, ic, TRUE);
10103   freeAsmop (result, NULL, ic, TRUE);
10104 }
10105
10106 /*-----------------------------------------------------------------*/
10107 /* genNearPointerSet - emitcode for near pointer put                */
10108 /*-----------------------------------------------------------------*/
10109 static void
10110 genNearPointerSet (operand * right,
10111                    operand * result,
10112                    iCode * ic,
10113                    iCode * pi)
10114 {
10115   asmop *aop = NULL;
10116   char *rname, *l;
10117   sym_link *retype, *letype;
10118   sym_link *ptype = operandType (result);
10119
10120   retype = getSpec (operandType (right));
10121   letype = getSpec (ptype);
10122
10123   aopOp (result, ic, FALSE, FALSE);
10124
10125   /* if the result is rematerializable &
10126      in data space & not a bit variable */
10127   if (AOP_TYPE (result) == AOP_IMMD &&
10128       DCL_TYPE (ptype) == POINTER &&
10129       !IS_BITVAR (retype) &&
10130       !IS_BITVAR (letype))
10131     {
10132       genDataPointerSet (right, result, ic);
10133       return;
10134     }
10135
10136   /* if the value is already in a pointer register
10137      then don't need anything more */
10138   if (!AOP_INPREG (AOP (result)))
10139     {
10140       /* otherwise get a free pointer register */
10141       regs *preg;
10142         
10143       aop = newAsmop (0);
10144       preg = getFreePtr (ic, &aop, FALSE);
10145       emitcode ("mov", "%s,%s",
10146                 preg->name,
10147                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10148       rname = preg->name;
10149     }
10150   else
10151     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10152
10153   aopOp (right, ic, FALSE, FALSE);
10154
10155   /* if bitfield then unpack the bits */
10156   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10157     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10158   else
10159     {
10160       /* we have can just get the values */
10161       int size = AOP_SIZE (right);
10162       int offset = 0;
10163
10164       while (size--)
10165         {
10166           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10167           if (*l == '@')
10168             {
10169               MOVA (l);
10170               emitcode ("mov", "@%s,a", rname);
10171             }
10172           else
10173             emitcode ("mov", "@%s,%s", rname, l);
10174           if (size || pi)
10175             emitcode ("inc", "%s", rname);
10176           offset++;
10177         }
10178     }
10179
10180   /* now some housekeeping stuff */
10181   if (aop)
10182     {
10183       /* we had to allocate for this iCode */
10184       if (pi) aopPut (AOP (result),rname,0);
10185       freeAsmop (NULL, aop, ic, TRUE);
10186     }
10187   else
10188     {
10189       /* we did not allocate which means left
10190          already in a pointer register, then
10191          if size > 0 && this could be used again
10192          we have to point it back to where it
10193          belongs */
10194       if (AOP_SIZE (right) > 1 &&
10195           !OP_SYMBOL (result)->remat &&
10196           (OP_SYMBOL (result)->liveTo > ic->seq ||
10197            ic->depth) &&
10198           !pi)
10199         {
10200           int size = AOP_SIZE (right) - 1;
10201           while (size--)
10202             emitcode ("dec", "%s", rname);
10203         }
10204     }
10205
10206   /* done */
10207   if (pi) pi->generated = 1;
10208   freeAsmop (result, NULL, ic, TRUE);
10209   freeAsmop (right, NULL, ic, TRUE);
10210
10211
10212 }
10213
10214 /*-----------------------------------------------------------------*/
10215 /* genPagedPointerSet - emitcode for Paged pointer put             */
10216 /*-----------------------------------------------------------------*/
10217 static void
10218 genPagedPointerSet (operand * right,
10219                     operand * result,
10220                     iCode * ic,
10221                     iCode *pi)
10222 {
10223   asmop *aop = NULL;
10224   char *rname;
10225   sym_link *retype, *letype;
10226
10227   retype = getSpec (operandType (right));
10228   letype = getSpec (operandType (result));
10229
10230   aopOp (result, ic, FALSE, FALSE);
10231
10232   /* if the value is already in a pointer register
10233      then don't need anything more */
10234   if (!AOP_INPREG (AOP (result)))
10235     {
10236       /* otherwise get a free pointer register */
10237       regs *preg;
10238         
10239       aop = newAsmop (0);
10240       preg = getFreePtr (ic, &aop, FALSE);
10241       emitcode ("mov", "%s,%s",
10242                 preg->name,
10243                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10244       rname = preg->name;
10245     }
10246   else
10247     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10248
10249   aopOp (right, ic, FALSE, FALSE);
10250
10251   /* if bitfield then unpack the bits */
10252   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10253     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10254   else
10255     {
10256       /* we have can just get the values */
10257       int size = AOP_SIZE (right);
10258       int offset = 0;
10259
10260       while (size--)
10261         {
10262           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10263
10264           emitcode ("movx", "@%s,a", rname);
10265
10266           if (size || pi)
10267             emitcode ("inc", "%s", rname);
10268
10269           offset++;
10270         }
10271     }
10272
10273   /* now some housekeeping stuff */
10274   if (aop)
10275     {
10276       if (pi) aopPut (AOP (result),rname,0);
10277       /* we had to allocate for this iCode */
10278       freeAsmop (NULL, aop, ic, TRUE);
10279     }
10280   else
10281     {
10282       /* we did not allocate which means left
10283          already in a pointer register, then
10284          if size > 0 && this could be used again
10285          we have to point it back to where it
10286          belongs */
10287       if (AOP_SIZE (right) > 1 &&
10288           !OP_SYMBOL (result)->remat &&
10289           (OP_SYMBOL (result)->liveTo > ic->seq ||
10290            ic->depth) &&
10291           !pi)
10292         {
10293           int size = AOP_SIZE (right) - 1;
10294           while (size--)
10295             emitcode ("dec", "%s", rname);
10296         }
10297     }
10298
10299   /* done */
10300   if (pi) pi->generated = 1;
10301   freeAsmop (result, NULL, ic, TRUE);
10302   freeAsmop (right, NULL, ic, TRUE);
10303
10304
10305 }
10306
10307 /*-----------------------------------------------------------------*/
10308 /* genFarPointerSet - set value from far space                     */
10309 /*-----------------------------------------------------------------*/
10310 static void
10311 genFarPointerSet (operand * right,
10312                   operand * result, iCode * ic, iCode *pi)
10313 {
10314   int size, offset, dopi=1;
10315   sym_link *retype = getSpec (operandType (right));
10316   sym_link *letype = getSpec (operandType (result));
10317
10318   aopOp (result, ic, FALSE, FALSE);
10319
10320   /* if the operand is already in dptr
10321      then we do nothing else we move the value to dptr */
10322   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10323     {
10324       /* if this is remateriazable */
10325       if (AOP_TYPE (result) == AOP_IMMD)
10326         emitcode ("mov", "dptr,%s", 
10327                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10328       else
10329         {
10330           /* we need to get it byte by byte */
10331           _startLazyDPSEvaluation ();
10332           if (AOP_TYPE (result) != AOP_DPTR)
10333             {
10334               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10335               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10336               if (options.model == MODEL_FLAT24)
10337                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10338             }
10339           else
10340             {
10341               /* We need to generate a load to DPTR indirect through DPTR. */
10342               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10343                 
10344               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10345               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10346               if (options.model == MODEL_FLAT24)
10347                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10348               emitcode ("pop", "dph");
10349               emitcode ("pop", "dpl");
10350               dopi=0;
10351             }
10352           _endLazyDPSEvaluation ();
10353         }
10354     }
10355   /* so dptr know contains the address */
10356   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10357
10358   /* if bit then unpack */
10359   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10360       if (AOP_INDPTRn(result)) {
10361           genSetDPTR(AOP(result)->aopu.dptr);
10362       }
10363       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10364       if (AOP_INDPTRn(result)) {
10365           genSetDPTR(0);
10366       }
10367   } else {
10368       size = AOP_SIZE (right);
10369       offset = 0;
10370       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10371           while (size--) {
10372               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10373               
10374               genSetDPTR(AOP(result)->aopu.dptr);
10375               emitcode ("movx", "@dptr,a");
10376               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10377                   emitcode ("inc", "dptr");
10378               genSetDPTR (0);
10379           }
10380       } else {
10381           _startLazyDPSEvaluation ();
10382           while (size--) {
10383               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10384               
10385               if (AOP_INDPTRn(result)) {
10386                   genSetDPTR(AOP(result)->aopu.dptr);
10387               } else {
10388                   genSetDPTR (0);
10389               }
10390               _flushLazyDPS ();
10391               
10392               emitcode ("movx", "@dptr,a");
10393               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10394                   emitcode ("inc", "dptr");
10395           }
10396           _endLazyDPSEvaluation ();
10397       }
10398   }
10399   
10400   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10401       if (!AOP_INDPTRn(result)) {
10402           _startLazyDPSEvaluation ();
10403           
10404           aopPut (AOP(result),"dpl",0);
10405           aopPut (AOP(result),"dph",1);
10406           if (options.model == MODEL_FLAT24)
10407               aopPut (AOP(result),"dpx",2);
10408
10409           _endLazyDPSEvaluation ();
10410       }
10411       pi->generated=1;
10412   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10413              AOP_SIZE(right) > 1 &&
10414              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10415       
10416       size = AOP_SIZE (right) - 1;
10417       if (AOP_INDPTRn(result)) {
10418           genSetDPTR(AOP(result)->aopu.dptr);
10419       } 
10420       while (size--) emitcode ("lcall","__decdptr");
10421       if (AOP_INDPTRn(result)) {
10422           genSetDPTR(0);
10423       }
10424   }
10425   freeAsmop (result, NULL, ic, TRUE);
10426   freeAsmop (right, NULL, ic, TRUE);
10427 }
10428
10429 /*-----------------------------------------------------------------*/
10430 /* genGenPointerSet - set value from generic pointer space         */
10431 /*-----------------------------------------------------------------*/
10432 static void
10433 genGenPointerSet (operand * right,
10434                   operand * result, iCode * ic, iCode *pi)
10435 {
10436   int size, offset;
10437   sym_link *retype = getSpec (operandType (right));
10438   sym_link *letype = getSpec (operandType (result));
10439
10440   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10441
10442   /* if the operand is already in dptr
10443      then we do nothing else we move the value to dptr */
10444   if (AOP_TYPE (result) != AOP_STR)
10445     {
10446       _startLazyDPSEvaluation ();
10447       /* if this is remateriazable */
10448       if (AOP_TYPE (result) == AOP_IMMD)
10449         {
10450           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10451           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10452           {
10453               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10454           }
10455           else
10456           {
10457               emitcode ("mov", 
10458                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10459           }
10460         }
10461       else
10462         {                       /* we need to get it byte by byte */
10463           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10464           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10465           if (options.model == MODEL_FLAT24) {
10466             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10467             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10468           } else {
10469             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10470           }
10471         }
10472       _endLazyDPSEvaluation ();
10473     }
10474   /* so dptr + b now contains the address */
10475   _G.bInUse++;
10476   aopOp (right, ic, FALSE, TRUE);
10477   _G.bInUse--;
10478     
10479
10480   /* if bit then unpack */
10481   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10482     {
10483         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10484     }
10485   else
10486     {
10487         size = AOP_SIZE (right);
10488         offset = 0;
10489
10490         _startLazyDPSEvaluation ();
10491         while (size--)
10492         {
10493             if (size)
10494             {
10495                 // Set two bytes at a time, passed in _AP & A.
10496                 // dptr will be incremented ONCE by __gptrputWord.
10497                 //
10498                 // Note: any change here must be coordinated
10499                 // with the implementation of __gptrputWord
10500                 // in device/lib/_gptrput.c
10501                 emitcode("mov", "_ap, %s", 
10502                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10503                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10504                 
10505                 genSetDPTR (0);
10506                 _flushLazyDPS ();
10507                 emitcode ("lcall", "__gptrputWord");
10508                 size--;
10509             }
10510             else
10511             {
10512                 // Only one byte to put.
10513                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10514
10515                 genSetDPTR (0);
10516                 _flushLazyDPS ();               
10517                 emitcode ("lcall", "__gptrput");
10518             }
10519             
10520             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10521             {
10522                 emitcode ("inc", "dptr");
10523             }
10524         }
10525         _endLazyDPSEvaluation ();
10526     }
10527
10528   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10529       _startLazyDPSEvaluation ();
10530       
10531       aopPut (AOP(result),"dpl",0);
10532       aopPut (AOP(result),"dph",1);
10533       if (options.model == MODEL_FLAT24) {
10534           aopPut (AOP(result),"dpx",2);
10535           aopPut (AOP(result),"b",3);
10536       } else {
10537           aopPut (AOP(result),"b",2);
10538       }
10539       _endLazyDPSEvaluation ();
10540       
10541       pi->generated=1;
10542   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10543              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10544       
10545       size = AOP_SIZE (right) - 1;
10546       while (size--) emitcode ("lcall","__decdptr");
10547   }
10548   freeAsmop (result, NULL, ic, TRUE);
10549   freeAsmop (right, NULL, ic, TRUE);
10550 }
10551
10552 /*-----------------------------------------------------------------*/
10553 /* genPointerSet - stores the value into a pointer location        */
10554 /*-----------------------------------------------------------------*/
10555 static void
10556 genPointerSet (iCode * ic, iCode *pi)
10557 {
10558   operand *right, *result;
10559   sym_link *type, *etype;
10560   int p_type;
10561
10562   D (emitcode (";", "genPointerSet "););
10563
10564   right = IC_RIGHT (ic);
10565   result = IC_RESULT (ic);
10566
10567   /* depending on the type of pointer we need to
10568      move it to the correct pointer register */
10569   type = operandType (result);
10570   etype = getSpec (type);
10571   /* if left is of type of pointer then it is simple */
10572   if (IS_PTR (type) && !IS_FUNC (type->next))
10573     {
10574       p_type = DCL_TYPE (type);
10575     }
10576   else
10577     {
10578       /* we have to go by the storage class */
10579       p_type = PTR_TYPE (SPEC_OCLS (etype));
10580     }
10581   /* special case when cast remat */
10582   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10583       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10584           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10585           type = operandType (result);
10586           p_type = DCL_TYPE (type);
10587   }
10588
10589   /* now that we have the pointer type we assign
10590      the pointer values */
10591   switch (p_type)
10592     {
10593
10594     case POINTER:
10595     case IPOINTER:
10596       genNearPointerSet (right, result, ic, pi);
10597       break;
10598
10599     case PPOINTER:
10600       genPagedPointerSet (right, result, ic, pi);
10601       break;
10602
10603     case FPOINTER:
10604       genFarPointerSet (right, result, ic, pi);
10605       break;
10606
10607     case GPOINTER:
10608       genGenPointerSet (right, result, ic, pi);
10609       break;
10610
10611     default:
10612       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10613               "genPointerSet: illegal pointer type");
10614     }
10615
10616 }
10617
10618 /*-----------------------------------------------------------------*/
10619 /* genIfx - generate code for Ifx statement                        */
10620 /*-----------------------------------------------------------------*/
10621 static void
10622 genIfx (iCode * ic, iCode * popIc)
10623 {
10624   operand *cond = IC_COND (ic);
10625   int isbit = 0;
10626
10627   D (emitcode (";", "genIfx "););
10628
10629   aopOp (cond, ic, FALSE, FALSE);
10630
10631   /* get the value into acc */
10632   if (AOP_TYPE (cond) != AOP_CRY)
10633     {
10634         toBoolean (cond);
10635     }
10636   else
10637     {
10638         isbit = 1;
10639     }
10640     
10641   /* the result is now in the accumulator */
10642   freeAsmop (cond, NULL, ic, TRUE);
10643
10644   /* if there was something to be popped then do it */
10645   if (popIc)
10646     genIpop (popIc);
10647
10648   /* if the condition is  a bit variable */
10649   if (isbit && IS_ITEMP (cond) &&
10650       SPIL_LOC (cond))
10651     {
10652         genIfxJump (ic, SPIL_LOC (cond)->rname);
10653     }
10654   else if (isbit && !IS_ITEMP (cond))
10655     {
10656         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10657     }
10658   else
10659     {
10660         genIfxJump (ic, "a");
10661     }
10662
10663   ic->generated = 1;
10664 }
10665
10666 /*-----------------------------------------------------------------*/
10667 /* genAddrOf - generates code for address of                       */
10668 /*-----------------------------------------------------------------*/
10669 static void
10670 genAddrOf (iCode * ic)
10671 {
10672   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10673   int size, offset;
10674
10675   D (emitcode (";", "genAddrOf ");
10676     );
10677
10678   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10679
10680   /* if the operand is on the stack then we
10681      need to get the stack offset of this
10682      variable */
10683   if (sym->onStack) {
10684       
10685       /* if 10 bit stack */
10686       if (options.stack10bit) {
10687           char buff[10];
10688           int  offset;
10689           
10690           tsprintf(buff, sizeof(buff), 
10691                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10692           /* if it has an offset then we need to compute it */
10693 /*        emitcode ("subb", "a,#!constbyte", */
10694 /*                  -((sym->stack < 0) ? */
10695 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10696 /*                    ((short) sym->stack)) & 0xff); */
10697 /*        emitcode ("mov","b,a"); */
10698 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10699 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10700 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10701           if (sym->stack) {
10702               emitcode ("mov", "a,_bpx");
10703               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10704                                              ((char) (sym->stack - _G.nRegsSaved)) :
10705                                              ((char) sym->stack )) & 0xff);
10706               emitcode ("mov", "b,a");
10707               emitcode ("mov", "a,_bpx+1");
10708               
10709               offset = (((sym->stack < 0) ? 
10710                          ((short) (sym->stack - _G.nRegsSaved)) :
10711                          ((short) sym->stack )) >> 8) & 0xff;
10712           
10713               emitcode ("addc","a,#!constbyte", offset);
10714
10715               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10716               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10717               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10718           } else {
10719               /* we can just move _bp */
10720               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10721               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10722               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10723           }       
10724       } else {
10725           /* if it has an offset then we need to compute it */
10726           if (sym->stack) {
10727               emitcode ("mov", "a,_bp");
10728               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10729               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10730           } else {
10731               /* we can just move _bp */
10732               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10733           }
10734           /* fill the result with zero */
10735           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10736           
10737           
10738           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10739               fprintf (stderr,
10740                        "*** warning: pointer to stack var truncated.\n");
10741           }
10742
10743           offset = 1;
10744           while (size--) {
10745               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10746           }      
10747       }
10748       goto release;
10749   }
10750
10751   /* object not on stack then we need the name */
10752   size = AOP_SIZE (IC_RESULT (ic));
10753   offset = 0;
10754
10755   while (size--)
10756     {
10757       char s[SDCC_NAME_MAX];
10758       if (offset) {
10759           switch (offset) {
10760           case 1:
10761               tsprintf(s, sizeof(s), "#!his",sym->rname);
10762               break;
10763           case 2:
10764               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10765               break;
10766           case 3:
10767               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10768               break;
10769           default: /* should not need this (just in case) */
10770               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10771                        sym->rname,
10772                        offset * 8);
10773           }
10774       } 
10775       else
10776       {
10777           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10778       }
10779         
10780       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10781     }
10782
10783 release:
10784   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10785
10786 }
10787
10788 #if 0 // obsolete, and buggy for != xdata
10789 /*-----------------------------------------------------------------*/
10790 /* genArrayInit - generates code for address of                       */
10791 /*-----------------------------------------------------------------*/
10792 static void
10793 genArrayInit (iCode * ic)
10794 {
10795     literalList *iLoop;
10796     int         ix, count;
10797     int         elementSize = 0, eIndex;
10798     unsigned    val, lastVal;
10799     sym_link    *type;
10800     operand     *left=IC_LEFT(ic);
10801     
10802     D (emitcode (";", "genArrayInit "););
10803
10804     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10805     
10806     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10807     {
10808         // Load immediate value into DPTR.
10809         emitcode("mov", "dptr, %s",
10810              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10811     }
10812     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10813     {
10814 #if 0
10815       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10816               "Unexpected operand to genArrayInit.\n");
10817       exit(1);
10818 #else
10819       // a regression because of SDCCcse.c:1.52
10820       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10821       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10822       if (options.model == MODEL_FLAT24)
10823         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10824 #endif
10825     }
10826     
10827     type = operandType(IC_LEFT(ic));
10828     
10829     if (type && type->next)
10830     {
10831         elementSize = getSize(type->next);
10832     }
10833     else
10834     {
10835         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10836                                 "can't determine element size in genArrayInit.\n");
10837         exit(1);
10838     }
10839     
10840     iLoop = IC_ARRAYILIST(ic);
10841     lastVal = 0xffff;
10842     
10843     while (iLoop)
10844     {
10845         bool firstpass = TRUE;
10846         
10847         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10848                  iLoop->count, (int)iLoop->literalValue, elementSize);
10849         
10850         ix = iLoop->count;
10851         
10852         while (ix)
10853         {
10854             symbol *tlbl = NULL;
10855             
10856             count = ix > 256 ? 256 : ix;
10857             
10858             if (count > 1)
10859             {
10860                 tlbl = newiTempLabel (NULL);
10861                 if (firstpass || (count & 0xff))
10862                 {
10863                     emitcode("mov", "b, #!constbyte", count & 0xff);
10864                 }
10865                 
10866                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10867             }
10868             
10869             firstpass = FALSE;
10870                 
10871             for (eIndex = 0; eIndex < elementSize; eIndex++)
10872             {
10873                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10874                 if (val != lastVal)
10875                 {
10876                     emitcode("mov", "a, #!constbyte", val);
10877                     lastVal = val;
10878                 }
10879                 
10880                 emitcode("movx", "@dptr, a");
10881                 emitcode("inc", "dptr");
10882             }
10883             
10884             if (count > 1)
10885             {
10886                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10887             }
10888             
10889             ix -= count;
10890         }
10891         
10892         iLoop = iLoop->next;
10893     }
10894     
10895     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10896 }
10897 #endif
10898
10899 /*-----------------------------------------------------------------*/
10900 /* genFarFarAssign - assignment when both are in far space         */
10901 /*-----------------------------------------------------------------*/
10902 static void
10903 genFarFarAssign (operand * result, operand * right, iCode * ic)
10904 {
10905   int size = AOP_SIZE (right);
10906   int offset = 0;
10907   symbol *rSym = NULL;
10908
10909   if (size == 1)
10910   {
10911       /* quick & easy case. */
10912       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10913       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10914       freeAsmop (right, NULL, ic, FALSE);
10915       /* now assign DPTR to result */
10916       _G.accInUse++;
10917       aopOp(result, ic, FALSE, FALSE);
10918       _G.accInUse--;
10919       aopPut(AOP(result), "a", 0);
10920       freeAsmop(result, NULL, ic, FALSE);
10921       return;
10922   }
10923   
10924   /* See if we've got an underlying symbol to abuse. */
10925   if (IS_SYMOP(result) && OP_SYMBOL(result))
10926   {
10927       if (IS_TRUE_SYMOP(result))
10928       {
10929           rSym = OP_SYMBOL(result);
10930       }
10931       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10932       {
10933           rSym = OP_SYMBOL(result)->usl.spillLoc;
10934       }
10935   }
10936              
10937   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10938   {
10939       /* We can use the '390 auto-toggle feature to good effect here. */
10940       
10941       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10942       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10943       emitcode ("mov", "dptr,#%s", rSym->rname); 
10944       /* DP2 = result, DP1 = right, DP1 is current. */
10945       while (size)
10946       {
10947           emitcode("movx", "a,@dptr");
10948           emitcode("movx", "@dptr,a");
10949           if (--size)
10950           {
10951                emitcode("inc", "dptr");
10952                emitcode("inc", "dptr");
10953           }
10954       }
10955       emitcode("mov", "dps,#0");
10956       freeAsmop (right, NULL, ic, FALSE);
10957 #if 0
10958 some alternative code for processors without auto-toggle
10959 no time to test now, so later well put in...kpb
10960         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10961         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10962         emitcode ("mov", "dptr,#%s", rSym->rname); 
10963         /* DP2 = result, DP1 = right, DP1 is current. */
10964         while (size)
10965         {
10966           --size;
10967           emitcode("movx", "a,@dptr");
10968           if (size)
10969             emitcode("inc", "dptr");
10970           emitcode("inc", "dps");
10971           emitcode("movx", "@dptr,a");
10972           if (size)
10973             emitcode("inc", "dptr");
10974           emitcode("inc", "dps");
10975         }
10976         emitcode("mov", "dps,#0");
10977         freeAsmop (right, NULL, ic, FALSE);
10978 #endif
10979   }
10980   else
10981   {
10982       D (emitcode (";", "genFarFarAssign"););
10983       aopOp (result, ic, TRUE, TRUE);
10984
10985       _startLazyDPSEvaluation ();
10986       
10987       while (size--)
10988         {
10989           aopPut (AOP (result),
10990                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10991           offset++;
10992         }
10993       _endLazyDPSEvaluation ();
10994       freeAsmop (result, NULL, ic, FALSE);
10995       freeAsmop (right, NULL, ic, FALSE);
10996   }
10997 }
10998
10999 /*-----------------------------------------------------------------*/
11000 /* genAssign - generate code for assignment                        */
11001 /*-----------------------------------------------------------------*/
11002 static void
11003 genAssign (iCode * ic)
11004 {
11005   operand *result, *right;
11006   int size, offset;
11007   unsigned long lit = 0L;
11008
11009   D (emitcode (";", "genAssign ");
11010     );
11011
11012   result = IC_RESULT (ic);
11013   right = IC_RIGHT (ic);
11014
11015   /* if they are the same */
11016   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11017     return;
11018
11019   aopOp (right, ic, FALSE, FALSE);
11020
11021   emitcode (";", "genAssign: resultIsFar = %s",
11022             isOperandInFarSpace (result) ?
11023             "TRUE" : "FALSE");
11024
11025   /* special case both in far space */
11026   if ((AOP_TYPE (right) == AOP_DPTR ||
11027        AOP_TYPE (right) == AOP_DPTR2) &&
11028   /* IS_TRUE_SYMOP(result)       && */
11029       isOperandInFarSpace (result))
11030     {
11031       genFarFarAssign (result, right, ic);
11032       return;
11033     }
11034
11035   aopOp (result, ic, TRUE, FALSE);
11036
11037   /* if they are the same registers */
11038   if (sameRegs (AOP (right), AOP (result)))
11039     goto release;
11040
11041   /* if the result is a bit */
11042   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11043     {
11044       /* if the right size is a literal then
11045          we know what the value is */
11046       if (AOP_TYPE (right) == AOP_LIT)
11047         {
11048           if (((int) operandLitValue (right)))
11049             aopPut (AOP (result), one, 0);
11050           else
11051             aopPut (AOP (result), zero, 0);
11052           goto release;
11053         }
11054
11055       /* the right is also a bit variable */
11056       if (AOP_TYPE (right) == AOP_CRY)
11057         {
11058           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11059           aopPut (AOP (result), "c", 0);
11060           goto release;
11061         }
11062
11063       /* we need to or */
11064       toBoolean (right);
11065       aopPut (AOP (result), "a", 0);
11066       goto release;
11067     }
11068
11069   /* bit variables done */
11070   /* general case */
11071   size = AOP_SIZE (result);
11072   offset = 0;
11073   if (AOP_TYPE (right) == AOP_LIT)
11074     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11075
11076   if ((size > 1) &&
11077       (AOP_TYPE (result) != AOP_REG) &&
11078       (AOP_TYPE (right) == AOP_LIT) &&
11079       !IS_FLOAT (operandType (right)))
11080     {
11081       _startLazyDPSEvaluation ();
11082       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11083         {
11084           aopPut (AOP (result),
11085                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11086                   offset);
11087           offset++;
11088           size--;
11089         }
11090       /* And now fill the rest with zeros. */
11091       if (size)
11092         {
11093           emitcode ("clr", "a");
11094         }
11095       while (size--)
11096         {
11097           aopPut (AOP (result), "a", offset++);
11098         }
11099       _endLazyDPSEvaluation ();
11100     }
11101   else
11102     {
11103       _startLazyDPSEvaluation ();
11104       while (size--)
11105         {
11106           aopPut (AOP (result),
11107                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11108                   offset);
11109           offset++;
11110         }
11111       _endLazyDPSEvaluation ();
11112     }
11113
11114 release:
11115   freeAsmop (right, NULL, ic, FALSE);
11116   freeAsmop (result, NULL, ic, TRUE);
11117 }
11118
11119 /*-----------------------------------------------------------------*/
11120 /* genJumpTab - generates code for jump table                      */
11121 /*-----------------------------------------------------------------*/
11122 static void
11123 genJumpTab (iCode * ic)
11124 {
11125   symbol *jtab;
11126   char *l;
11127
11128   D (emitcode (";", "genJumpTab ");
11129     );
11130
11131   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11132   /* get the condition into accumulator */
11133   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11134   MOVA (l);
11135   /* multiply by four! */
11136   emitcode ("add", "a,acc");
11137   emitcode ("add", "a,acc");
11138   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11139
11140   jtab = newiTempLabel (NULL);
11141   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11142   emitcode ("jmp", "@a+dptr");
11143   emitcode ("", "!tlabeldef", jtab->key + 100);
11144   /* now generate the jump labels */
11145   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11146        jtab = setNextItem (IC_JTLABELS (ic)))
11147     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11148
11149 }
11150
11151 /*-----------------------------------------------------------------*/
11152 /* genCast - gen code for casting                                  */
11153 /*-----------------------------------------------------------------*/
11154 static void
11155 genCast (iCode * ic)
11156 {
11157   operand *result = IC_RESULT (ic);
11158   sym_link *ctype = operandType (IC_LEFT (ic));
11159   sym_link *rtype = operandType (IC_RIGHT (ic));
11160   operand *right = IC_RIGHT (ic);
11161   int size, offset;
11162
11163   D (emitcode (";", "genCast "););
11164
11165   /* if they are equivalent then do nothing */
11166   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11167     return;
11168
11169   aopOp (right, ic, FALSE, FALSE);
11170   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11171
11172   /* if the result is a bit */
11173   if (IS_BITVAR (OP_SYMBOL (result)->type)
11174       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11175     {
11176       /* if the right size is a literal then
11177          we know what the value is */
11178       if (AOP_TYPE (right) == AOP_LIT)
11179         {
11180           if (((int) operandLitValue (right)))
11181             aopPut (AOP (result), one, 0);
11182           else
11183             aopPut (AOP (result), zero, 0);
11184
11185           goto release;
11186         }
11187
11188       /* the right is also a bit variable */
11189       if (AOP_TYPE (right) == AOP_CRY)
11190         {
11191           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11192           aopPut (AOP (result), "c", 0);
11193           goto release;
11194         }
11195
11196       /* we need to or */
11197       toBoolean (right);
11198       aopPut (AOP (result), "a", 0);
11199       goto release;
11200     }
11201
11202   /* if they are the same size : or less */
11203   if (AOP_SIZE (result) <= AOP_SIZE (right))
11204     {
11205
11206       /* if they are in the same place */
11207       if (sameRegs (AOP (right), AOP (result)))
11208         goto release;
11209
11210       /* if they in different places then copy */
11211       size = AOP_SIZE (result);
11212       offset = 0;
11213       _startLazyDPSEvaluation ();
11214       while (size--)
11215         {
11216           aopPut (AOP (result),
11217                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11218                   offset);
11219           offset++;
11220         }
11221       _endLazyDPSEvaluation ();
11222       goto release;
11223     }
11224
11225
11226   /* if the result is of type pointer */
11227   if (IS_PTR (ctype))
11228     {
11229
11230       int p_type;
11231       sym_link *type = operandType (right);
11232
11233       /* pointer to generic pointer */
11234       if (IS_GENPTR (ctype))
11235         {
11236           if (IS_PTR (type))
11237             {
11238               p_type = DCL_TYPE (type);
11239             }
11240           else
11241             {
11242 #if OLD_CAST_BEHAVIOR
11243               /* KV: we are converting a non-pointer type to
11244                * a generic pointer. This (ifdef'd out) code
11245                * says that the resulting generic pointer
11246                * should have the same class as the storage
11247                * location of the non-pointer variable.
11248                *
11249                * For example, converting an int (which happens
11250                * to be stored in DATA space) to a pointer results
11251                * in a DATA generic pointer; if the original int
11252                * in XDATA space, so will be the resulting pointer.
11253                *
11254                * I don't like that behavior, and thus this change:
11255                * all such conversions will be forced to XDATA and
11256                * throw a warning. If you want some non-XDATA
11257                * type, or you want to suppress the warning, you
11258                * must go through an intermediate cast, like so:
11259                *
11260                * char _generic *gp = (char _xdata *)(intVar);
11261                */
11262               sym_link *etype = getSpec (type);
11263
11264               /* we have to go by the storage class */
11265               if (SPEC_OCLS (etype) != generic)
11266                 {
11267                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11268                 }
11269               else
11270 #endif
11271                 {
11272                   /* Converting unknown class (i.e. register variable)
11273                    * to generic pointer. This is not good, but
11274                    * we'll make a guess (and throw a warning).
11275                    */
11276                   p_type = FPOINTER;
11277                   werror (W_INT_TO_GEN_PTR_CAST);
11278                 }
11279             }
11280
11281           /* the first two bytes are known */
11282           size = GPTRSIZE - 1;
11283           offset = 0;
11284           _startLazyDPSEvaluation ();
11285           while (size--)
11286             {
11287               aopPut (AOP (result),
11288                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11289                       offset);
11290               offset++;
11291             }
11292           _endLazyDPSEvaluation ();
11293
11294           /* the last byte depending on type */
11295             {
11296                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11297                 char gpValStr[10];
11298             
11299                 if (gpVal == -1)
11300                 {
11301                     // pointerTypeToGPByte will have bitched.
11302                     exit(1);
11303                 }
11304             
11305                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11306                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11307             }
11308           goto release;
11309         }
11310
11311       /* just copy the pointers */
11312       size = AOP_SIZE (result);
11313       offset = 0;
11314       _startLazyDPSEvaluation ();
11315       while (size--)
11316         {
11317           aopPut (AOP (result),
11318                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11319                   offset);
11320           offset++;
11321         }
11322       _endLazyDPSEvaluation ();
11323       goto release;
11324     }
11325
11326   /* so we now know that the size of destination is greater
11327      than the size of the source */
11328   /* we move to result for the size of source */
11329   size = AOP_SIZE (right);
11330   offset = 0;
11331   _startLazyDPSEvaluation ();
11332   while (size--)
11333     {
11334       aopPut (AOP (result),
11335               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11336               offset);
11337       offset++;
11338     }
11339   _endLazyDPSEvaluation ();
11340
11341   /* now depending on the sign of the source && destination */
11342   size = AOP_SIZE (result) - AOP_SIZE (right);
11343   /* if unsigned or not an integral type */
11344   /* also, if the source is a bit, we don't need to sign extend, because
11345    * it can't possibly have set the sign bit.
11346    */
11347   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11348     {
11349       while (size--)
11350         {
11351           aopPut (AOP (result), zero, offset++);
11352         }
11353     }
11354   else
11355     {
11356       /* we need to extend the sign :{ */
11357       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11358                         FALSE, FALSE, NULL));
11359       emitcode ("rlc", "a");
11360       emitcode ("subb", "a,acc");
11361       while (size--)
11362         aopPut (AOP (result), "a", offset++);
11363     }
11364
11365   /* we are done hurray !!!! */
11366
11367 release:
11368   freeAsmop (right, NULL, ic, TRUE);
11369   freeAsmop (result, NULL, ic, TRUE);
11370
11371 }
11372
11373 /*-----------------------------------------------------------------*/
11374 /* genDjnz - generate decrement & jump if not zero instrucion      */
11375 /*-----------------------------------------------------------------*/
11376 static int
11377 genDjnz (iCode * ic, iCode * ifx)
11378 {
11379   symbol *lbl, *lbl1;
11380   if (!ifx)
11381     return 0;
11382
11383   /* if the if condition has a false label
11384      then we cannot save */
11385   if (IC_FALSE (ifx))
11386     return 0;
11387
11388   /* if the minus is not of the form
11389      a = a - 1 */
11390   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11391       !IS_OP_LITERAL (IC_RIGHT (ic)))
11392     return 0;
11393
11394   if (operandLitValue (IC_RIGHT (ic)) != 1)
11395     return 0;
11396
11397   /* if the size of this greater than one then no
11398      saving */
11399   if (getSize (operandType (IC_RESULT (ic))) > 1)
11400     return 0;
11401
11402   /* otherwise we can save BIG */
11403   D(emitcode(";", "genDjnz"););
11404
11405   lbl = newiTempLabel (NULL);
11406   lbl1 = newiTempLabel (NULL);
11407
11408   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11409
11410   if (AOP_NEEDSACC(IC_RESULT(ic)))
11411   {
11412       /* If the result is accessed indirectly via
11413        * the accumulator, we must explicitly write
11414        * it back after the decrement.
11415        */
11416       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11417       
11418       if (strcmp(rByte, "a"))
11419       {
11420            /* Something is hopelessly wrong */
11421            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11422                    __FILE__, __LINE__);
11423            /* We can just give up; the generated code will be inefficient,
11424             * but what the hey.
11425             */
11426            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11427            return 0;
11428       }
11429       emitcode ("dec", "%s", rByte);
11430       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11431       emitcode ("jnz", "!tlabel", lbl->key + 100);
11432   }
11433   else if (IS_AOP_PREG (IC_RESULT (ic)))
11434     {
11435       emitcode ("dec", "%s",
11436                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11437       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11438       emitcode ("jnz", "!tlabel", lbl->key + 100);
11439     }
11440   else
11441     {
11442       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11443                 lbl->key + 100);
11444     }
11445   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11446   emitcode ("", "!tlabeldef", lbl->key + 100);
11447   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11448   emitcode ("", "!tlabeldef", lbl1->key + 100);
11449
11450   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11451   ifx->generated = 1;
11452   return 1;
11453 }
11454
11455 /*-----------------------------------------------------------------*/
11456 /* genReceive - generate code for a receive iCode                  */
11457 /*-----------------------------------------------------------------*/
11458 static void
11459 genReceive (iCode * ic)
11460 {
11461     int size = getSize (operandType (IC_RESULT (ic)));
11462     int offset = 0;
11463     int rb1off ;
11464     
11465     D (emitcode (";", "genReceive "););
11466
11467     if (ic->argreg == 1) 
11468     {
11469         /* first parameter */
11470         if (AOP_IS_STR(IC_RESULT(ic)))
11471         {
11472             /* Nothing to do: it's already in the proper place. */
11473             return;
11474         }
11475         else
11476         {
11477             bool useDp2;
11478             
11479             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11480                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11481                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11482             
11483             _G.accInUse++;
11484             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11485             _G.accInUse--; 
11486             
11487             /* Sanity checking... */
11488             if (AOP_USESDPTR(IC_RESULT(ic)))
11489             {
11490                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11491                         "genReceive got unexpected DPTR.");
11492             }
11493             assignResultValue (IC_RESULT (ic));
11494         }
11495     } 
11496     else 
11497     { 
11498         /* second receive onwards */
11499         /* this gets a little tricky since unused recevies will be
11500          eliminated, we have saved the reg in the type field . and
11501          we use that to figure out which register to use */
11502         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11503         rb1off = ic->argreg;
11504         while (size--) 
11505         {
11506             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11507         }
11508     }
11509     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11510 }
11511
11512 /*-----------------------------------------------------------------*/
11513 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11514 /*-----------------------------------------------------------------*/
11515 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11516 {
11517     operand *from , *to , *count;
11518     symbol *lbl;
11519     bitVect *rsave;
11520     int i;
11521
11522     /* we know it has to be 3 parameters */
11523     assert (nparms == 3);
11524     
11525     rsave = newBitVect(16);
11526     /* save DPTR if it needs to be saved */
11527     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11528             if (bitVectBitValue(ic->rMask,i))
11529                     rsave = bitVectSetBit(rsave,i);
11530     }
11531     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11532                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11533     savermask(rsave);
11534     
11535     to = parms[0];
11536     from = parms[1];
11537     count = parms[2];
11538
11539     aopOp (from, ic->next, FALSE, FALSE);
11540
11541     /* get from into DPTR1 */
11542     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11543     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11544     if (options.model == MODEL_FLAT24) {
11545         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11546     }
11547
11548     freeAsmop (from, NULL, ic, FALSE);
11549     aopOp (to, ic, FALSE, FALSE);
11550     /* get "to" into DPTR */
11551     /* if the operand is already in dptr
11552        then we do nothing else we move the value to dptr */
11553     if (AOP_TYPE (to) != AOP_STR) {
11554         /* if already in DPTR then we need to push */
11555         if (AOP_TYPE(to) == AOP_DPTR) {
11556             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11557             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11558             if (options.model == MODEL_FLAT24)
11559                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11560             emitcode ("pop", "dph");
11561             emitcode ("pop", "dpl");        
11562         } else {
11563             _startLazyDPSEvaluation ();
11564             /* if this is remateriazable */
11565             if (AOP_TYPE (to) == AOP_IMMD) {
11566                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11567             } else {                    /* we need to get it byte by byte */
11568                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11569                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11570                 if (options.model == MODEL_FLAT24) {
11571                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11572                 }
11573             }
11574             _endLazyDPSEvaluation ();
11575         }
11576     }
11577     freeAsmop (to, NULL, ic, FALSE);
11578     _G.dptrInUse = _G.dptr1InUse = 1;
11579     aopOp (count, ic->next->next, FALSE,FALSE);
11580     lbl =newiTempLabel(NULL);
11581
11582     /* now for the actual copy */
11583     if (AOP_TYPE(count) == AOP_LIT && 
11584         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11585         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11586         if (fromc) {
11587             emitcode ("lcall","__bi_memcpyc2x_s");
11588         } else {
11589             emitcode ("lcall","__bi_memcpyx2x_s");
11590         }
11591         freeAsmop (count, NULL, ic, FALSE);
11592     } else {
11593         symbol *lbl1 = newiTempLabel(NULL);
11594         
11595         emitcode (";"," Auto increment but no djnz");
11596         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11597         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11598         freeAsmop (count, NULL, ic, FALSE);
11599         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11600         emitcode ("","!tlabeldef",lbl->key+100);
11601         if (fromc) {
11602             emitcode ("clr","a");
11603             emitcode ("movc", "a,@a+dptr");
11604         } else 
11605             emitcode ("movx", "a,@dptr");
11606         emitcode ("movx", "@dptr,a");
11607         emitcode ("inc", "dptr");
11608         emitcode ("inc", "dptr");
11609         emitcode ("mov","a,b");
11610         emitcode ("orl","a,_ap");
11611         emitcode ("jz","!tlabel",lbl1->key+100);
11612         emitcode ("mov","a,_ap");
11613         emitcode ("add","a,#!constbyte",0xFF);
11614         emitcode ("mov","_ap,a");
11615         emitcode ("mov","a,b");
11616         emitcode ("addc","a,#!constbyte",0xFF);
11617         emitcode ("mov","b,a");
11618         emitcode ("sjmp","!tlabel",lbl->key+100);
11619         emitcode ("","!tlabeldef",lbl1->key+100);
11620     }
11621     emitcode ("mov", "dps,#0"); 
11622     _G.dptrInUse = _G.dptr1InUse = 0;
11623     unsavermask(rsave);
11624
11625 }
11626
11627 /*-----------------------------------------------------------------*/
11628 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11629 /*-----------------------------------------------------------------*/
11630 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11631 {
11632     operand *from , *to , *count;
11633     symbol *lbl,*lbl2;
11634     bitVect *rsave;
11635     int i;
11636
11637     /* we know it has to be 3 parameters */
11638     assert (nparms == 3);
11639     
11640     rsave = newBitVect(16);
11641     /* save DPTR if it needs to be saved */
11642     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11643             if (bitVectBitValue(ic->rMask,i))
11644                     rsave = bitVectSetBit(rsave,i);
11645     }
11646     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11647                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11648     savermask(rsave);
11649     
11650     to = parms[0];
11651     from = parms[1];
11652     count = parms[2];
11653
11654     aopOp (from, ic->next, FALSE, FALSE);
11655
11656     /* get from into DPTR1 */
11657     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11658     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11659     if (options.model == MODEL_FLAT24) {
11660         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11661     }
11662
11663     freeAsmop (from, NULL, ic, FALSE);
11664     aopOp (to, ic, FALSE, FALSE);
11665     /* get "to" into DPTR */
11666     /* if the operand is already in dptr
11667        then we do nothing else we move the value to dptr */
11668     if (AOP_TYPE (to) != AOP_STR) {
11669         /* if already in DPTR then we need to push */
11670         if (AOP_TYPE(to) == AOP_DPTR) {
11671             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11672             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11673             if (options.model == MODEL_FLAT24)
11674                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11675             emitcode ("pop", "dph");
11676             emitcode ("pop", "dpl");        
11677         } else {
11678             _startLazyDPSEvaluation ();
11679             /* if this is remateriazable */
11680             if (AOP_TYPE (to) == AOP_IMMD) {
11681                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11682             } else {                    /* we need to get it byte by byte */
11683                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11684                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11685                 if (options.model == MODEL_FLAT24) {
11686                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11687                 }
11688             }
11689             _endLazyDPSEvaluation ();
11690         }
11691     }
11692     freeAsmop (to, NULL, ic, FALSE);
11693     _G.dptrInUse = _G.dptr1InUse = 1;
11694     aopOp (count, ic->next->next, FALSE,FALSE);
11695     lbl =newiTempLabel(NULL);
11696     lbl2 =newiTempLabel(NULL);
11697
11698     /* now for the actual compare */
11699     if (AOP_TYPE(count) == AOP_LIT && 
11700         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11701         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11702         if (fromc)
11703             emitcode("lcall","__bi_memcmpc2x_s");
11704         else
11705             emitcode("lcall","__bi_memcmpx2x_s");
11706         freeAsmop (count, NULL, ic, FALSE);
11707         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11708         aopPut(AOP(IC_RESULT(ic)),"a",0);
11709         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11710     } else {
11711         symbol *lbl1 = newiTempLabel(NULL);
11712
11713         emitcode("push","ar0");         
11714         emitcode (";"," Auto increment but no djnz");
11715         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11716         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11717         freeAsmop (count, NULL, ic, FALSE);
11718         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11719         emitcode ("","!tlabeldef",lbl->key+100);
11720         if (fromc) {
11721             emitcode ("clr","a");
11722             emitcode ("movc", "a,@a+dptr");
11723         } else 
11724             emitcode ("movx", "a,@dptr");
11725         emitcode ("mov","r0,a");
11726         emitcode ("movx", "a,@dptr");
11727         emitcode ("clr","c");
11728         emitcode ("subb","a,r0");
11729         emitcode ("jnz","!tlabel",lbl2->key+100);
11730         emitcode ("inc", "dptr");
11731         emitcode ("inc", "dptr");
11732         emitcode ("mov","a,b");
11733         emitcode ("orl","a,_ap");
11734         emitcode ("jz","!tlabel",lbl1->key+100);
11735         emitcode ("mov","a,_ap");
11736         emitcode ("add","a,#!constbyte",0xFF);
11737         emitcode ("mov","_ap,a");
11738         emitcode ("mov","a,b");
11739         emitcode ("addc","a,#!constbyte",0xFF);
11740         emitcode ("mov","b,a");
11741         emitcode ("sjmp","!tlabel",lbl->key+100);
11742         emitcode ("","!tlabeldef",lbl1->key+100);
11743         emitcode ("clr","a");
11744         emitcode ("","!tlabeldef",lbl2->key+100);
11745         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11746         aopPut(AOP(IC_RESULT(ic)),"a",0);
11747         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11748         emitcode("pop","ar0");
11749         emitcode ("mov", "dps,#0");      
11750     }
11751     _G.dptrInUse = _G.dptr1InUse = 0;
11752     unsavermask(rsave);
11753
11754 }
11755
11756 /*-----------------------------------------------------------------*/
11757 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11758 /* port, first parameter output area second parameter pointer to   */
11759 /* port third parameter count                                      */
11760 /*-----------------------------------------------------------------*/
11761 static void genInp( iCode *ic, int nparms, operand **parms)
11762 {
11763     operand *from , *to , *count;
11764     symbol *lbl;
11765     bitVect *rsave;
11766     int i;
11767
11768     /* we know it has to be 3 parameters */
11769     assert (nparms == 3);
11770     
11771     rsave = newBitVect(16);
11772     /* save DPTR if it needs to be saved */
11773     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11774             if (bitVectBitValue(ic->rMask,i))
11775                     rsave = bitVectSetBit(rsave,i);
11776     }
11777     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11778                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11779     savermask(rsave);
11780     
11781     to = parms[0];
11782     from = parms[1];
11783     count = parms[2];
11784
11785     aopOp (from, ic->next, FALSE, FALSE);
11786
11787     /* get from into DPTR1 */
11788     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11789     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11790     if (options.model == MODEL_FLAT24) {
11791         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11792     }
11793
11794     freeAsmop (from, NULL, ic, FALSE);
11795     aopOp (to, ic, FALSE, FALSE);
11796     /* get "to" into DPTR */
11797     /* if the operand is already in dptr
11798        then we do nothing else we move the value to dptr */
11799     if (AOP_TYPE (to) != AOP_STR) {
11800         /* if already in DPTR then we need to push */
11801         if (AOP_TYPE(to) == AOP_DPTR) {
11802             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11803             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11804             if (options.model == MODEL_FLAT24)
11805                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11806             emitcode ("pop", "dph");
11807             emitcode ("pop", "dpl");        
11808         } else {
11809             _startLazyDPSEvaluation ();
11810             /* if this is remateriazable */
11811             if (AOP_TYPE (to) == AOP_IMMD) {
11812                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11813             } else {                    /* we need to get it byte by byte */
11814                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11815                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11816                 if (options.model == MODEL_FLAT24) {
11817                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11818                 }
11819             }
11820             _endLazyDPSEvaluation ();
11821         }
11822     }
11823     freeAsmop (to, NULL, ic, FALSE);
11824
11825     _G.dptrInUse = _G.dptr1InUse = 1;
11826     aopOp (count, ic->next->next, FALSE,FALSE);
11827     lbl =newiTempLabel(NULL);
11828
11829     /* now for the actual copy */
11830     if (AOP_TYPE(count) == AOP_LIT && 
11831         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11832         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11833         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11834         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11835         freeAsmop (count, NULL, ic, FALSE);
11836         emitcode ("","!tlabeldef",lbl->key+100);
11837         emitcode ("movx", "a,@dptr");   /* read data from port */
11838         emitcode ("dec","dps");         /* switch to DPTR */
11839         emitcode ("movx", "@dptr,a");   /* save into location */
11840         emitcode ("inc", "dptr");       /* point to next area */
11841         emitcode ("inc","dps");         /* switch to DPTR2 */
11842         emitcode ("djnz","b,!tlabel",lbl->key+100);
11843     } else {
11844         symbol *lbl1 = newiTempLabel(NULL);
11845         
11846         emitcode (";"," Auto increment but no djnz");
11847         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11848         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11849         freeAsmop (count, NULL, ic, FALSE);
11850         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11851         emitcode ("","!tlabeldef",lbl->key+100);
11852         emitcode ("movx", "a,@dptr");
11853         emitcode ("dec","dps");         /* switch to DPTR */
11854         emitcode ("movx", "@dptr,a");
11855         emitcode ("inc", "dptr");
11856         emitcode ("inc","dps");         /* switch to DPTR2 */
11857 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11858 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11859         emitcode ("mov","a,b");
11860         emitcode ("orl","a,_ap");
11861         emitcode ("jz","!tlabel",lbl1->key+100);
11862         emitcode ("mov","a,_ap");
11863         emitcode ("add","a,#!constbyte",0xFF);
11864         emitcode ("mov","_ap,a");
11865         emitcode ("mov","a,b");
11866         emitcode ("addc","a,#!constbyte",0xFF);
11867         emitcode ("mov","b,a");
11868         emitcode ("sjmp","!tlabel",lbl->key+100);
11869         emitcode ("","!tlabeldef",lbl1->key+100);
11870     }
11871     emitcode ("mov", "dps,#0"); 
11872     _G.dptrInUse = _G.dptr1InUse = 0;
11873     unsavermask(rsave);
11874
11875 }
11876
11877 /*-----------------------------------------------------------------*/
11878 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11879 /* port, first parameter output area second parameter pointer to   */
11880 /* port third parameter count                                      */
11881 /*-----------------------------------------------------------------*/
11882 static void genOutp( iCode *ic, int nparms, operand **parms)
11883 {
11884     operand *from , *to , *count;
11885     symbol *lbl;
11886     bitVect *rsave;
11887     int i;
11888
11889     /* we know it has to be 3 parameters */
11890     assert (nparms == 3);
11891     
11892     rsave = newBitVect(16);
11893     /* save DPTR if it needs to be saved */
11894     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11895             if (bitVectBitValue(ic->rMask,i))
11896                     rsave = bitVectSetBit(rsave,i);
11897     }
11898     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11899                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11900     savermask(rsave);
11901     
11902     to = parms[0];
11903     from = parms[1];
11904     count = parms[2];
11905
11906     aopOp (from, ic->next, FALSE, FALSE);
11907
11908     /* get from into DPTR1 */
11909     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11910     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11911     if (options.model == MODEL_FLAT24) {
11912         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11913     }
11914
11915     freeAsmop (from, NULL, ic, FALSE);
11916     aopOp (to, ic, FALSE, FALSE);
11917     /* get "to" into DPTR */
11918     /* if the operand is already in dptr
11919        then we do nothing else we move the value to dptr */
11920     if (AOP_TYPE (to) != AOP_STR) {
11921         /* if already in DPTR then we need to push */
11922         if (AOP_TYPE(to) == AOP_DPTR) {
11923             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11924             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11925             if (options.model == MODEL_FLAT24)
11926                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11927             emitcode ("pop", "dph");
11928             emitcode ("pop", "dpl");        
11929         } else {
11930             _startLazyDPSEvaluation ();
11931             /* if this is remateriazable */
11932             if (AOP_TYPE (to) == AOP_IMMD) {
11933                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11934             } else {                    /* we need to get it byte by byte */
11935                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11936                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11937                 if (options.model == MODEL_FLAT24) {
11938                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11939                 }
11940             }
11941             _endLazyDPSEvaluation ();
11942         }
11943     }
11944     freeAsmop (to, NULL, ic, FALSE);
11945
11946     _G.dptrInUse = _G.dptr1InUse = 1;
11947     aopOp (count, ic->next->next, FALSE,FALSE);
11948     lbl =newiTempLabel(NULL);
11949
11950     /* now for the actual copy */
11951     if (AOP_TYPE(count) == AOP_LIT && 
11952         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11953         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11954         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11955         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11956         emitcode ("","!tlabeldef",lbl->key+100);
11957         emitcode ("movx", "a,@dptr");   /* read data from port */
11958         emitcode ("inc","dps");         /* switch to DPTR2 */
11959         emitcode ("movx", "@dptr,a");   /* save into location */
11960         emitcode ("inc", "dptr");       /* point to next area */
11961         emitcode ("dec","dps");         /* switch to DPTR */
11962         emitcode ("djnz","b,!tlabel",lbl->key+100);
11963         freeAsmop (count, NULL, ic, FALSE);
11964     } else {
11965         symbol *lbl1 = newiTempLabel(NULL);
11966         
11967         emitcode (";"," Auto increment but no djnz");
11968         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11969         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11970         freeAsmop (count, NULL, ic, FALSE);
11971         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11972         emitcode ("","!tlabeldef",lbl->key+100);
11973         emitcode ("movx", "a,@dptr");
11974         emitcode ("inc", "dptr");
11975         emitcode ("inc","dps");         /* switch to DPTR2 */
11976         emitcode ("movx", "@dptr,a");
11977         emitcode ("dec","dps");         /* switch to DPTR */
11978         emitcode ("mov","a,b");
11979         emitcode ("orl","a,_ap");
11980         emitcode ("jz","!tlabel",lbl1->key+100);
11981         emitcode ("mov","a,_ap");
11982         emitcode ("add","a,#!constbyte",0xFF);
11983         emitcode ("mov","_ap,a");
11984         emitcode ("mov","a,b");
11985         emitcode ("addc","a,#!constbyte",0xFF);
11986         emitcode ("mov","b,a");
11987         emitcode ("sjmp","!tlabel",lbl->key+100);
11988         emitcode ("","!tlabeldef",lbl1->key+100);
11989     }
11990     emitcode ("mov", "dps,#0"); 
11991     _G.dptrInUse = _G.dptr1InUse = 0;
11992     unsavermask(rsave);
11993
11994 }
11995
11996 /*-----------------------------------------------------------------*/
11997 /* genSwapW - swap lower & high order bytes                        */
11998 /*-----------------------------------------------------------------*/
11999 static void genSwapW(iCode *ic, int nparms, operand **parms)
12000 {
12001     operand *dest;
12002     operand *src;
12003     assert (nparms==1);
12004
12005     src = parms[0];
12006     dest=IC_RESULT(ic);
12007
12008     assert(getSize(operandType(src))==2);
12009
12010     aopOp (src, ic, FALSE, FALSE);
12011     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12012     _G.accInUse++;
12013     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12014     _G.accInUse--;
12015     freeAsmop (src, NULL, ic, FALSE);
12016     
12017     aopOp (dest,ic, FALSE, FALSE);
12018     aopPut(AOP(dest),"b",0);
12019     aopPut(AOP(dest),"a",1);
12020     freeAsmop (dest, NULL, ic, FALSE);    
12021 }
12022
12023 /*-----------------------------------------------------------------*/
12024 /* genMemsetX - gencode for memSetX data                           */
12025 /*-----------------------------------------------------------------*/
12026 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12027 {
12028     operand *to , *val , *count;
12029     symbol *lbl;
12030     char *l;
12031     int i;
12032     bitVect *rsave;
12033
12034     /* we know it has to be 3 parameters */
12035     assert (nparms == 3);
12036     
12037     to = parms[0];
12038     val = parms[1];
12039     count = parms[2];
12040         
12041     /* save DPTR if it needs to be saved */
12042     rsave = newBitVect(16);
12043     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12044             if (bitVectBitValue(ic->rMask,i))
12045                     rsave = bitVectSetBit(rsave,i);
12046     }
12047     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12048                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12049     savermask(rsave);
12050
12051     aopOp (to, ic, FALSE, FALSE);
12052     /* get "to" into DPTR */
12053     /* if the operand is already in dptr
12054        then we do nothing else we move the value to dptr */
12055     if (AOP_TYPE (to) != AOP_STR) {
12056         /* if already in DPTR then we need to push */
12057         if (AOP_TYPE(to) == AOP_DPTR) {
12058             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12059             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12060             if (options.model == MODEL_FLAT24)
12061                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12062             emitcode ("pop", "dph");
12063             emitcode ("pop", "dpl");        
12064         } else {
12065             _startLazyDPSEvaluation ();
12066             /* if this is remateriazable */
12067             if (AOP_TYPE (to) == AOP_IMMD) {
12068                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12069             } else {                    /* we need to get it byte by byte */
12070                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12071                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12072                 if (options.model == MODEL_FLAT24) {
12073                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12074                 }
12075             }
12076             _endLazyDPSEvaluation ();
12077         }
12078     }
12079     freeAsmop (to, NULL, ic, FALSE);
12080
12081     aopOp (val, ic->next->next, FALSE,FALSE);
12082     aopOp (count, ic->next->next, FALSE,FALSE);    
12083     lbl =newiTempLabel(NULL);
12084     /* now for the actual copy */
12085     if (AOP_TYPE(count) == AOP_LIT && 
12086         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12087         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12088         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12089         MOVA(l);
12090         emitcode ("","!tlabeldef",lbl->key+100);
12091         emitcode ("movx", "@dptr,a");
12092         emitcode ("inc", "dptr");
12093         emitcode ("djnz","b,!tlabel",lbl->key+100);
12094     } else {
12095         symbol *lbl1 = newiTempLabel(NULL);
12096         
12097         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12098         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12099         emitcode ("","!tlabeldef",lbl->key+100);
12100         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12101         emitcode ("movx", "@dptr,a");
12102         emitcode ("inc", "dptr");
12103         emitcode ("mov","a,b");
12104         emitcode ("orl","a,_ap");
12105         emitcode ("jz","!tlabel",lbl1->key+100);
12106         emitcode ("mov","a,_ap");
12107         emitcode ("add","a,#!constbyte",0xFF);
12108         emitcode ("mov","_ap,a");
12109         emitcode ("mov","a,b");
12110         emitcode ("addc","a,#!constbyte",0xFF);
12111         emitcode ("mov","b,a");
12112         emitcode ("sjmp","!tlabel",lbl->key+100);
12113         emitcode ("","!tlabeldef",lbl1->key+100);
12114     }
12115     freeAsmop (count, NULL, ic, FALSE);
12116     unsavermask(rsave);
12117 }
12118
12119 /*-----------------------------------------------------------------*/
12120 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12121 /*-----------------------------------------------------------------*/
12122 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12123 {
12124         bitVect *rsave ;
12125         operand *pnum, *result;
12126         int i;
12127     
12128         assert (nparms==1);
12129         /* save registers that need to be saved */
12130         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12131                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12132     
12133         pnum = parms[0]; 
12134         aopOp (pnum, ic, FALSE, FALSE);
12135         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12136         freeAsmop (pnum, NULL, ic, FALSE);
12137         emitcode ("lcall","NatLib_LoadPrimitive");
12138         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12139         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12140             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12141                 for (i = (size-1) ; i >= 0 ; i-- ) {
12142                         emitcode ("push","a%s",javaRet[i]);
12143                 }
12144                 for (i=0; i < size ; i++ ) {
12145                         emitcode ("pop","a%s",
12146                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12147                 }
12148         } else {
12149                 for (i = 0 ; i < size ; i++ ) {
12150                         aopPut(AOP(result),javaRet[i],i);
12151                 }
12152         }    
12153         freeAsmop (result, NULL, ic, FALSE);
12154         unsavermask(rsave);
12155 }
12156
12157 /*-----------------------------------------------------------------*/
12158 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12159 /*-----------------------------------------------------------------*/
12160 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12161 {
12162         bitVect *rsave ;
12163         operand *pnum, *result;
12164         int size = 3;
12165         int i;
12166     
12167         assert (nparms==1);
12168         /* save registers that need to be saved */
12169         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12170                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12171     
12172         pnum = parms[0]; 
12173         aopOp (pnum, ic, FALSE, FALSE);
12174         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12175         freeAsmop (pnum, NULL, ic, FALSE);
12176         emitcode ("lcall","NatLib_LoadPointer");
12177         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12178         if (AOP_TYPE(result)!=AOP_STR) {
12179                 for (i = 0 ; i < size ; i++ ) {
12180                         aopPut(AOP(result),fReturn[i],i);
12181                 }
12182         }    
12183         freeAsmop (result, NULL, ic, FALSE);
12184         unsavermask(rsave);
12185 }
12186
12187 /*-----------------------------------------------------------------*/
12188 /* genNatLibInstallStateBlock -                                    */
12189 /*-----------------------------------------------------------------*/
12190 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12191                                        operand **parms, const char *name)
12192 {
12193         bitVect *rsave ;
12194         operand *psb, *handle;
12195         assert (nparms==2);
12196
12197         /* save registers that need to be saved */
12198         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12199                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12200         psb = parms[0];
12201         handle = parms[1];
12202
12203         /* put pointer to state block into DPTR1 */
12204         aopOp (psb, ic, FALSE, FALSE);
12205         if (AOP_TYPE (psb) == AOP_IMMD) {
12206                 emitcode ("mov","dps,#1");
12207                 emitcode ("mov", "dptr,%s",
12208                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12209                 emitcode ("mov","dps,#0");
12210         } else {
12211                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12212                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12213                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12214         }
12215         freeAsmop (psb, NULL, ic, FALSE);
12216
12217         /* put libraryID into DPTR */
12218         emitcode ("mov","dptr,#LibraryID");
12219
12220         /* put handle into r3:r2 */
12221         aopOp (handle, ic, FALSE, FALSE);
12222         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12223                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12224                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12225                 emitcode ("pop","ar3");
12226                 emitcode ("pop","ar2");
12227         } else {        
12228                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12229                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12230         }
12231         freeAsmop (psb, NULL, ic, FALSE);
12232
12233         /* make the call */
12234         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12235
12236         /* put return value into place*/
12237         _G.accInUse++;
12238         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12239         _G.accInUse--;
12240         aopPut(AOP(IC_RESULT(ic)),"a",0);
12241         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12242         unsavermask(rsave);
12243 }
12244
12245 /*-----------------------------------------------------------------*/
12246 /* genNatLibRemoveStateBlock -                                     */
12247 /*-----------------------------------------------------------------*/
12248 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12249 {
12250         bitVect *rsave ;
12251
12252         assert(nparms==0);
12253
12254         /* save registers that need to be saved */
12255         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12256                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12257
12258         /* put libraryID into DPTR */
12259         emitcode ("mov","dptr,#LibraryID");
12260         /* make the call */
12261         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12262         unsavermask(rsave);
12263 }
12264
12265 /*-----------------------------------------------------------------*/
12266 /* genNatLibGetStateBlock -                                        */
12267 /*-----------------------------------------------------------------*/
12268 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12269                                    operand **parms,const char *name)
12270 {
12271         bitVect *rsave ;
12272         symbol *lbl = newiTempLabel(NULL);
12273         
12274         assert(nparms==0);
12275         /* save registers that need to be saved */
12276         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12277                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12278
12279         /* put libraryID into DPTR */
12280         emitcode ("mov","dptr,#LibraryID");
12281         /* make the call */
12282         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12283         emitcode ("jnz","!tlabel",lbl->key+100);
12284
12285         /* put return value into place */
12286         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12287         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12288                 emitcode ("push","ar3");
12289                 emitcode ("push","ar2");
12290                 emitcode ("pop","%s",
12291                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12292                 emitcode ("pop","%s",
12293                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12294         } else {
12295                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12296                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12297         }
12298         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12299         emitcode ("","!tlabeldef",lbl->key+100);
12300         unsavermask(rsave);
12301 }
12302
12303 /*-----------------------------------------------------------------*/
12304 /* genMMMalloc -                                                   */
12305 /*-----------------------------------------------------------------*/
12306 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12307                          int size, const char *name)
12308 {
12309         bitVect *rsave ;
12310         operand *bsize;
12311         symbol *rsym;
12312         symbol *lbl = newiTempLabel(NULL);
12313
12314         assert (nparms == 1);
12315         /* save registers that need to be saved */
12316         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12317                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12318         
12319         bsize=parms[0];
12320         aopOp (bsize,ic,FALSE,FALSE);
12321
12322         /* put the size in R4-R2 */
12323         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12324                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12325                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12326                 if (size==3) {
12327                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12328                         emitcode("pop","ar4");
12329                 }
12330                 emitcode("pop","ar3");
12331                 emitcode("pop","ar2");          
12332         } else {
12333                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12334                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12335                 if (size==3) {
12336                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12337                 }
12338         }
12339         freeAsmop (bsize, NULL, ic, FALSE);
12340
12341         /* make the call */
12342         emitcode ("lcall","MM_%s",name);
12343         emitcode ("jz","!tlabel",lbl->key+100);
12344         emitcode ("mov","r2,#!constbyte",0xff);
12345         emitcode ("mov","r3,#!constbyte",0xff);
12346         emitcode ("","!tlabeldef",lbl->key+100);
12347         /* we don't care about the pointer : we just save the handle */
12348         rsym = OP_SYMBOL(IC_RESULT(ic));
12349         if (rsym->liveFrom != rsym->liveTo) {
12350                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12351                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12352                         emitcode ("push","ar3");
12353                         emitcode ("push","ar2");
12354                         emitcode ("pop","%s",
12355                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12356                         emitcode ("pop","%s",
12357                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12358                 } else {
12359                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12360                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12361                 }
12362                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12363         }
12364         unsavermask(rsave);
12365 }
12366
12367 /*-----------------------------------------------------------------*/
12368 /* genMMDeref -                                                    */
12369 /*-----------------------------------------------------------------*/
12370 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12371 {
12372         bitVect *rsave ;
12373         operand *handle;
12374
12375         assert (nparms == 1);
12376         /* save registers that need to be saved */
12377         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12378                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12379         
12380         handle=parms[0];
12381         aopOp (handle,ic,FALSE,FALSE);
12382
12383         /* put the size in R4-R2 */
12384         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12385                 emitcode("push","%s",
12386                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12387                 emitcode("push","%s",
12388                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12389                 emitcode("pop","ar3");
12390                 emitcode("pop","ar2");          
12391         } else {
12392                 emitcode ("mov","r2,%s",
12393                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12394                 emitcode ("mov","r3,%s",
12395                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12396         }
12397         freeAsmop (handle, NULL, ic, FALSE);
12398
12399         /* make the call */
12400         emitcode ("lcall","MM_Deref");
12401         
12402         {
12403                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12404                 if (rsym->liveFrom != rsym->liveTo) {                   
12405                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12406                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12407                             _startLazyDPSEvaluation ();
12408                             
12409                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12410                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12411                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12412
12413                             _endLazyDPSEvaluation ();
12414                             
12415                         }
12416                 }
12417         }
12418         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12419         unsavermask(rsave);
12420 }
12421
12422 /*-----------------------------------------------------------------*/
12423 /* genMMUnrestrictedPersist -                                      */
12424 /*-----------------------------------------------------------------*/
12425 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12426 {
12427         bitVect *rsave ;
12428         operand *handle;
12429
12430         assert (nparms == 1);
12431         /* save registers that need to be saved */
12432         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12433                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12434         
12435         handle=parms[0];
12436         aopOp (handle,ic,FALSE,FALSE);
12437
12438         /* put the size in R3-R2 */
12439         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12440                 emitcode("push","%s",
12441                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12442                 emitcode("push","%s",
12443                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12444                 emitcode("pop","ar3");
12445                 emitcode("pop","ar2");          
12446         } else {
12447                 emitcode ("mov","r2,%s",
12448                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12449                 emitcode ("mov","r3,%s",
12450                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12451         }
12452         freeAsmop (handle, NULL, ic, FALSE);
12453
12454         /* make the call */
12455         emitcode ("lcall","MM_UnrestrictedPersist");
12456
12457         {
12458                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12459                 if (rsym->liveFrom != rsym->liveTo) {   
12460                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12461                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12462                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12463                 }
12464         }
12465         unsavermask(rsave);
12466 }
12467
12468 /*-----------------------------------------------------------------*/
12469 /* genSystemExecJavaProcess -                                      */
12470 /*-----------------------------------------------------------------*/
12471 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12472 {
12473         bitVect *rsave ;
12474         operand *handle, *pp;
12475
12476         assert (nparms==2);
12477         /* save registers that need to be saved */
12478         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12479                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12480         
12481         pp = parms[0];
12482         handle = parms[1];
12483         
12484         /* put the handle in R3-R2 */
12485         aopOp (handle,ic,FALSE,FALSE);
12486         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12487                 emitcode("push","%s",
12488                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12489                 emitcode("push","%s",
12490                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12491                 emitcode("pop","ar3");
12492                 emitcode("pop","ar2");          
12493         } else {
12494                 emitcode ("mov","r2,%s",
12495                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12496                 emitcode ("mov","r3,%s",
12497                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12498         }
12499         freeAsmop (handle, NULL, ic, FALSE);
12500         
12501         /* put pointer in DPTR */
12502         aopOp (pp,ic,FALSE,FALSE);
12503         if (AOP_TYPE(pp) == AOP_IMMD) {
12504                 emitcode ("mov", "dptr,%s",
12505                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12506         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12507                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12508                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12509                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12510         }
12511         freeAsmop (handle, NULL, ic, FALSE);
12512
12513         /* make the call */
12514         emitcode ("lcall","System_ExecJavaProcess");
12515         
12516         /* put result in place */
12517         {
12518                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12519                 if (rsym->liveFrom != rsym->liveTo) {   
12520                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12521                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12522                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12523                 }
12524         }
12525         
12526         unsavermask(rsave);
12527 }
12528
12529 /*-----------------------------------------------------------------*/
12530 /* genSystemRTCRegisters -                                         */
12531 /*-----------------------------------------------------------------*/
12532 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12533                                   char *name)
12534 {
12535         bitVect *rsave ;
12536         operand *pp;
12537
12538         assert (nparms==1);
12539         /* save registers that need to be saved */
12540         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12541                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12542         
12543         pp=parms[0];
12544         /* put pointer in DPTR */
12545         aopOp (pp,ic,FALSE,FALSE);
12546         if (AOP_TYPE (pp) == AOP_IMMD) {
12547                 emitcode ("mov","dps,#1");
12548                 emitcode ("mov", "dptr,%s", 
12549                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12550                 emitcode ("mov","dps,#0");
12551         } else {
12552                 emitcode ("mov","dpl1,%s",
12553                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12554                 emitcode ("mov","dph1,%s",
12555                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12556                 emitcode ("mov","dpx1,%s",
12557                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12558         }
12559         freeAsmop (pp, NULL, ic, FALSE);
12560
12561         /* make the call */
12562         emitcode ("lcall","System_%sRTCRegisters",name);
12563
12564         unsavermask(rsave);
12565 }
12566
12567 /*-----------------------------------------------------------------*/
12568 /* genSystemThreadSleep -                                          */
12569 /*-----------------------------------------------------------------*/
12570 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12571 {
12572         bitVect *rsave ;
12573         operand *to, *s;
12574
12575         assert (nparms==1);
12576         /* save registers that need to be saved */
12577         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12578                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12579
12580         to = parms[0];
12581         aopOp(to,ic,FALSE,FALSE);
12582         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12583             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12584                 emitcode ("push","%s",
12585                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12586                 emitcode ("push","%s",
12587                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12588                 emitcode ("push","%s",
12589                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12590                 emitcode ("push","%s",
12591                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12592                 emitcode ("pop","ar3");
12593                 emitcode ("pop","ar2");
12594                 emitcode ("pop","ar1");
12595                 emitcode ("pop","ar0");
12596         } else {
12597                 emitcode ("mov","r0,%s",
12598                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12599                 emitcode ("mov","r1,%s",
12600                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12601                 emitcode ("mov","r2,%s",
12602                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12603                 emitcode ("mov","r3,%s",
12604                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12605         }
12606         freeAsmop (to, NULL, ic, FALSE);
12607
12608         /* suspend in acc */
12609         s = parms[1];
12610         aopOp(s,ic,FALSE,FALSE);
12611         emitcode ("mov","a,%s",
12612                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12613         freeAsmop (s, NULL, ic, FALSE);
12614
12615         /* make the call */
12616         emitcode ("lcall","System_%s",name);
12617
12618         unsavermask(rsave);
12619 }
12620
12621 /*-----------------------------------------------------------------*/
12622 /* genSystemThreadResume -                                         */
12623 /*-----------------------------------------------------------------*/
12624 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12625 {
12626         bitVect *rsave ;
12627         operand *tid,*pid;
12628
12629         assert (nparms==2);
12630         /* save registers that need to be saved */
12631         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12632                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12633         
12634         tid = parms[0];
12635         pid = parms[1];
12636         
12637         /* PID in R0 */
12638         aopOp(pid,ic,FALSE,FALSE);
12639         emitcode ("mov","r0,%s",
12640                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12641         freeAsmop (pid, NULL, ic, FALSE);
12642         
12643         /* tid into ACC */
12644         aopOp(tid,ic,FALSE,FALSE);
12645         emitcode ("mov","a,%s",
12646                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12647         freeAsmop (tid, NULL, ic, FALSE);
12648         
12649         emitcode ("lcall","System_ThreadResume");
12650
12651         /* put result into place */
12652         {
12653                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12654                 if (rsym->liveFrom != rsym->liveTo) {   
12655                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12656                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12657                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12658                 }
12659         }
12660         unsavermask(rsave);
12661 }
12662
12663 /*-----------------------------------------------------------------*/
12664 /* genSystemProcessResume -                                        */
12665 /*-----------------------------------------------------------------*/
12666 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12667 {
12668         bitVect *rsave ;
12669         operand *pid;
12670
12671         assert (nparms==1);
12672         /* save registers that need to be saved */
12673         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12674                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12675         
12676         pid = parms[0];
12677         
12678         /* pid into ACC */
12679         aopOp(pid,ic,FALSE,FALSE);
12680         emitcode ("mov","a,%s",
12681                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12682         freeAsmop (pid, NULL, ic, FALSE);
12683         
12684         emitcode ("lcall","System_ProcessResume");
12685
12686         unsavermask(rsave);
12687 }
12688
12689 /*-----------------------------------------------------------------*/
12690 /* genSystem -                                                     */
12691 /*-----------------------------------------------------------------*/
12692 static void genSystem (iCode *ic,int nparms,char *name)
12693 {
12694         assert(nparms == 0);
12695
12696         emitcode ("lcall","System_%s",name);
12697 }
12698
12699 /*-----------------------------------------------------------------*/
12700 /* genSystemPoll -                                                  */
12701 /*-----------------------------------------------------------------*/
12702 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12703 {
12704         bitVect *rsave ;
12705         operand *fp;
12706
12707         assert (nparms==1);
12708         /* save registers that need to be saved */
12709         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12710                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12711
12712         fp = parms[0];
12713         aopOp (fp,ic,FALSE,FALSE);
12714         if (AOP_TYPE (fp) == AOP_IMMD) {
12715                 emitcode ("mov", "dptr,%s", 
12716                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12717         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12718                 emitcode ("mov","dpl,%s",
12719                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12720                 emitcode ("mov","dph,%s",
12721                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12722                 emitcode ("mov","dpx,%s",
12723                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12724         }
12725         freeAsmop (fp, NULL, ic, FALSE);
12726
12727         emitcode ("lcall","System_%sPoll",name);
12728
12729         /* put result into place */
12730         {
12731                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12732                 if (rsym->liveFrom != rsym->liveTo) {   
12733                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12734                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12735                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12736                 }
12737         }
12738         unsavermask(rsave);
12739 }
12740
12741 /*-----------------------------------------------------------------*/
12742 /* genSystemGetCurrentID -                                         */
12743 /*-----------------------------------------------------------------*/
12744 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12745 {
12746         assert (nparms==0);
12747
12748         emitcode ("lcall","System_GetCurrent%sId",name);
12749         /* put result into place */
12750         {
12751                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12752                 if (rsym->liveFrom != rsym->liveTo) {   
12753                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12754                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12755                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12756                 }
12757         }
12758 }
12759
12760 /*-----------------------------------------------------------------*/
12761 /* genDummyRead - generate code for dummy read of volatiles        */
12762 /*-----------------------------------------------------------------*/
12763 static void
12764 genDummyRead (iCode * ic)
12765 {
12766   operand *op;
12767   int size, offset;
12768
12769   D(emitcode(";     genDummyRead",""));
12770
12771   op = IC_RIGHT (ic);
12772   if (op && IS_SYMOP (op))
12773     {
12774       aopOp (op, ic, FALSE, FALSE);
12775
12776       /* if the result is a bit */
12777       if (AOP_TYPE (op) == AOP_CRY)
12778         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12779       else
12780         {
12781           /* bit variables done */
12782           /* general case */
12783           size = AOP_SIZE (op);
12784           offset = 0;
12785           while (size--)
12786           {
12787             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12788             offset++;
12789           }
12790         }
12791
12792       freeAsmop (op, NULL, ic, TRUE);
12793     }
12794
12795   op = IC_LEFT (ic);
12796   if (op && IS_SYMOP (op))
12797     {
12798       aopOp (op, ic, FALSE, FALSE);
12799
12800       /* if the result is a bit */
12801       if (AOP_TYPE (op) == AOP_CRY)
12802         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
12803       else
12804         {
12805           /* bit variables done */
12806           /* general case */
12807           size = AOP_SIZE (op);
12808           offset = 0;
12809           while (size--)
12810           {
12811             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
12812             offset++;
12813           }
12814         }
12815
12816       freeAsmop (op, NULL, ic, TRUE);
12817     }
12818     
12819 }
12820
12821 /*-----------------------------------------------------------------*/
12822 /* genCritical - generate code for start of a critical sequence    */
12823 /*-----------------------------------------------------------------*/
12824 static void
12825 genCritical (iCode *ic)
12826 {
12827   symbol *tlbl = newiTempLabel (NULL);
12828
12829   D(emitcode(";     genCritical",""));
12830   
12831   if (IC_RESULT (ic))
12832     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12833
12834   emitcode ("setb", "c");
12835   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12836   emitcode ("clr", "c");
12837   emitcode ("", "%05d$:", (tlbl->key + 100));
12838
12839   if (IC_RESULT (ic))
12840     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12841   else
12842     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12843
12844   if (IC_RESULT (ic))
12845     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12846 }
12847
12848 /*-----------------------------------------------------------------*/
12849 /* genEndCritical - generate code for end of a critical sequence   */
12850 /*-----------------------------------------------------------------*/
12851 static void
12852 genEndCritical (iCode *ic)
12853 {
12854   D(emitcode(";     genEndCritical",""));
12855   
12856   if (IC_RIGHT (ic))
12857     {
12858       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12859       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12860         {
12861           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12862           emitcode ("mov", "ea,c");
12863         }
12864       else
12865         {
12866           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12867           emitcode ("rrc", "a");
12868           emitcode ("mov", "ea,c");
12869         }
12870       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12871     }
12872   else
12873     {
12874       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12875       emitcode ("mov", "ea,c");
12876     }
12877 }
12878
12879
12880
12881 /*-----------------------------------------------------------------*/
12882 /* genBuiltIn - calls the appropriate function to  generating code */
12883 /* for a built in function                                         */
12884 /*-----------------------------------------------------------------*/
12885 static void genBuiltIn (iCode *ic)
12886 {
12887         operand *bi_parms[MAX_BUILTIN_ARGS];
12888         int nbi_parms;
12889         iCode *bi_iCode;
12890         symbol *bif;
12891
12892         /* get all the arguments for a built in function */
12893         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12894
12895         /* which function is it */
12896         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12897         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12898                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12899         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12900                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12901         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12902                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12903         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12904                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12905         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12906                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12907         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12908                 genInp(bi_iCode,nbi_parms,bi_parms);
12909         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12910                 genOutp(bi_iCode,nbi_parms,bi_parms);
12911         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12912                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12913                 /* JavaNative builtIns */               
12914         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12915                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12916         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12917                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12918         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12919                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12920         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12921                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12922         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12923                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12924         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12925                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12926         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12927                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12928         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12929                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12930         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12931                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12932         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12933                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12934         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12935                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12936         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12937                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12938         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12939                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12940         } else if (strcmp(bif->name,"MM_Free")==0) {
12941                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12942         } else if (strcmp(bif->name,"MM_Deref")==0) {
12943                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12944         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12945                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12946         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12947                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12948         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12949                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12950         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12951                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12952         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12953                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12954         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12955                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12956         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12957                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12958         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12959                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12960         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12961                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12962         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12963                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12964         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12965                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12966         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12967                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12968         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12969                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12970         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12971                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12972         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12973                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12974         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12975                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12976         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12977                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12978         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12979                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12980         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12981                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12982         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12983                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12984         } else {
12985                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12986                 return ;
12987         }
12988         return ;    
12989 }
12990
12991 /*-----------------------------------------------------------------*/
12992 /* gen390Code - generate code for Dallas 390 based controllers     */
12993 /*-----------------------------------------------------------------*/
12994 void
12995 gen390Code (iCode * lic)
12996 {
12997   iCode *ic;
12998   int cln = 0;
12999
13000   lineHead = lineCurr = NULL;
13001   dptrn[1][0] = "dpl1";
13002   dptrn[1][1] = "dph1";
13003   dptrn[1][2] = "dpx1";
13004   
13005   if (options.model == MODEL_FLAT24) {
13006     fReturnSizeDS390 = 5;
13007     fReturn = fReturn24;
13008   } else {
13009     fReturnSizeDS390 = 4;
13010     fReturn = fReturn16;
13011     options.stack10bit=0;
13012   }
13013 #if 1
13014   /* print the allocation information */
13015   if (allocInfo && currFunc)
13016     printAllocInfo (currFunc, codeOutFile);
13017 #endif
13018   /* if debug information required */
13019   if (options.debug && currFunc)
13020     {
13021       debugFile->writeFunction(currFunc);
13022       _G.debugLine = 1;
13023       if (IS_STATIC (currFunc->etype))
13024         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
13025       else
13026         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
13027       _G.debugLine = 0;
13028     }
13029   /* stack pointer name */
13030   if (options.useXstack)
13031     spname = "_spx";
13032   else
13033     spname = "sp";
13034
13035
13036   for (ic = lic; ic; ic = ic->next)
13037     {
13038
13039       if (ic->lineno && cln != ic->lineno)
13040         {
13041           if (options.debug)
13042             {
13043               _G.debugLine = 1;
13044               emitcode ("", "C$%s$%d$%d$%d ==.",
13045                         FileBaseName (ic->filename), ic->lineno,
13046                         ic->level, ic->block);
13047               _G.debugLine = 0;
13048             }
13049           if (!options.noCcodeInAsm) {
13050             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
13051                       printCLine(ic->filename, ic->lineno));
13052           }
13053           cln = ic->lineno;
13054         }
13055       if (options.iCodeInAsm) {
13056         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13057       }
13058       /* if the result is marked as
13059          spilt and rematerializable or code for
13060          this has already been generated then
13061          do nothing */
13062       if (resultRemat (ic) || ic->generated)
13063         continue;
13064
13065       /* depending on the operation */
13066       switch (ic->op)
13067         {
13068         case '!':
13069           genNot (ic);
13070           break;
13071
13072         case '~':
13073           genCpl (ic);
13074           break;
13075
13076         case UNARYMINUS:
13077           genUminus (ic);
13078           break;
13079
13080         case IPUSH:
13081           genIpush (ic);
13082           break;
13083
13084         case IPOP:
13085           /* IPOP happens only when trying to restore a
13086              spilt live range, if there is an ifx statement
13087              following this pop then the if statement might
13088              be using some of the registers being popped which
13089              would destory the contents of the register so
13090              we need to check for this condition and handle it */
13091           if (ic->next &&
13092               ic->next->op == IFX &&
13093               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13094             genIfx (ic->next, ic);
13095           else
13096             genIpop (ic);
13097           break;
13098
13099         case CALL:
13100           genCall (ic);
13101           break;
13102
13103         case PCALL:
13104           genPcall (ic);
13105           break;
13106
13107         case FUNCTION:
13108           genFunction (ic);
13109           break;
13110
13111         case ENDFUNCTION:
13112           genEndFunction (ic);
13113           break;
13114
13115         case RETURN:
13116           genRet (ic);
13117           break;
13118
13119         case LABEL:
13120           genLabel (ic);
13121           break;
13122
13123         case GOTO:
13124           genGoto (ic);
13125           break;
13126
13127         case '+':
13128           genPlus (ic);
13129           break;
13130
13131         case '-':
13132           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13133             genMinus (ic);
13134           break;
13135
13136         case '*':
13137           genMult (ic);
13138           break;
13139
13140         case '/':
13141           genDiv (ic);
13142           break;
13143
13144         case '%':
13145           genMod (ic);
13146           break;
13147
13148         case '>':
13149           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13150           break;
13151
13152         case '<':
13153           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13154           break;
13155
13156         case LE_OP:
13157         case GE_OP:
13158         case NE_OP:
13159
13160           /* note these two are xlated by algebraic equivalence
13161              during parsing SDCC.y */
13162           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13163                   "got '>=' or '<=' shouldn't have come here");
13164           break;
13165
13166         case EQ_OP:
13167           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13168           break;
13169
13170         case AND_OP:
13171           genAndOp (ic);
13172           break;
13173
13174         case OR_OP:
13175           genOrOp (ic);
13176           break;
13177
13178         case '^':
13179           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13180           break;
13181
13182         case '|':
13183           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13184           break;
13185
13186         case BITWISEAND:
13187           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13188           break;
13189
13190         case INLINEASM:
13191           genInline (ic);
13192           break;
13193
13194         case RRC:
13195           genRRC (ic);
13196           break;
13197
13198         case RLC:
13199           genRLC (ic);
13200           break;
13201
13202         case GETHBIT:
13203           genGetHbit (ic);
13204           break;
13205
13206         case LEFT_OP:
13207           genLeftShift (ic);
13208           break;
13209
13210         case RIGHT_OP:
13211           genRightShift (ic);
13212           break;
13213
13214         case GET_VALUE_AT_ADDRESS:
13215           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13216           break;
13217
13218         case '=':
13219           if (POINTER_SET (ic))
13220             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13221           else
13222             genAssign (ic);
13223           break;
13224
13225         case IFX:
13226           genIfx (ic, NULL);
13227           break;
13228
13229         case ADDRESS_OF:
13230           genAddrOf (ic);
13231           break;
13232
13233         case JUMPTABLE:
13234           genJumpTab (ic);
13235           break;
13236
13237         case CAST:
13238           genCast (ic);
13239           break;
13240
13241         case RECEIVE:
13242           genReceive (ic);
13243           break;
13244
13245         case SEND:
13246           if (ic->builtinSEND) genBuiltIn(ic);
13247           else addSet (&_G.sendSet, ic);
13248           break;
13249
13250         case DUMMY_READ_VOLATILE:
13251           genDummyRead (ic);
13252           break;
13253
13254         case CRITICAL:
13255           genCritical (ic);
13256           break;
13257
13258         case ENDCRITICAL:
13259           genEndCritical (ic);
13260           break;
13261         
13262         case SWAP:
13263           genSwap (ic);
13264           break;
13265           
13266 #if 0 // obsolete, and buggy for != xdata
13267         case ARRAYINIT:
13268             genArrayInit(ic);
13269             break;
13270 #endif
13271             
13272         default:
13273           ic = ic;
13274         }
13275     }
13276
13277
13278   /* now we are ready to call the
13279      peep hole optimizer */
13280   if (!options.nopeep)
13281     peepHole (&lineHead);
13282
13283   /* now do the actual printing */
13284   printLine (lineHead, codeOutFile);
13285   return;
13286 }