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