* src/configure.in: check for endianess (even while cross-compiling)
[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 /* aopForSym - for a true symbol                                   */
443 /*-----------------------------------------------------------------*/
444 static asmop *
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
446 {
447   asmop *aop;
448   memmap *space = SPEC_OCLS (sym->etype);
449
450   /* if already has one */
451   if (sym->aop)
452     return sym->aop;
453
454   /* assign depending on the storage class */
455   /* if it is on the stack or indirectly addressable */
456   /* space we need to assign either r0 or r1 to it   */
457   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
458     {
459       sym->aop = aop = newAsmop (0);
460       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461       aop->size = getSize (sym->type);
462
463       /* now assign the address of the variable to
464          the pointer register */
465       if (aop->type != AOP_STK)
466         {
467
468           if (sym->onStack)
469             {
470               if (_G.accInUse)
471                 emitcode ("push", "acc");
472
473               if (_G.bInUse)
474                 emitcode ("push", "b");
475
476               emitcode ("mov", "a,_bp");
477               emitcode ("add", "a,#!constbyte",
478                         ((sym->stack < 0) ?
479                          ((char) (sym->stack - _G.nRegsSaved)) :
480                          ((char) sym->stack)) & 0xff);
481               emitcode ("mov", "%s,a",
482                         aop->aopu.aop_ptr->name);
483
484               if (_G.bInUse)
485                 emitcode ("pop", "b");
486
487               if (_G.accInUse)
488                 emitcode ("pop", "acc");
489             }
490           else
491             emitcode ("mov", "%s,#%s",
492                       aop->aopu.aop_ptr->name,
493                       sym->rname);
494           aop->paged = space->paged;
495         }
496       else
497         aop->aopu.aop_stk = sym->stack;
498       return aop;
499     }
500
501   if (sym->onStack && options.stack10bit)
502     {
503         short stack_val = -((sym->stack < 0) ?
504                             ((short) (sym->stack - _G.nRegsSaved)) :
505                             ((short) sym->stack)) ;
506         if (useDP2 && _G.dptr1InUse) {
507             emitcode ("push","dpl1");
508             emitcode ("push","dph1");
509             emitcode ("push","dpx1");
510         } else if (_G.dptrInUse ) {
511             emitcode ("push","dpl");
512             emitcode ("push","dph");
513             emitcode ("push","dpx");
514         }
515       /* It's on the 10 bit stack, which is located in
516        * far data space.
517        */           
518         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
519             if (useDP2) {
520                 if (options.model == MODEL_FLAT24)
521                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
522                 TR_DPTR("#2");
523                 emitcode ("mov", "dph1,_bpx+1");
524                 emitcode ("mov", "dpl1,_bpx");
525                 emitcode ("mov","dps,#1");
526             } else {
527                 if (options.model == MODEL_FLAT24)
528                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
529                 emitcode ("mov", "dph,_bpx+1");
530                 emitcode ("mov", "dpl,_bpx");
531             }
532             stack_val = -stack_val;
533             while (stack_val--) {
534                 emitcode ("inc","dptr");
535             }
536             if (useDP2) {
537                 emitcode("mov","dps,#0");
538             }
539         }  else {
540             if (_G.accInUse)
541                 emitcode ("push", "acc");
542             
543             if (_G.bInUse)
544                 emitcode ("push", "b");
545         
546             emitcode ("mov", "a,_bpx");
547             emitcode ("clr","c");
548             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
549             emitcode ("mov","b,a");
550             emitcode ("mov","a,_bpx+1");
551             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
552             if (useDP2) {
553                 if (options.model == MODEL_FLAT24)
554                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
555                 TR_DPTR("#2");
556                 emitcode ("mov", "dph1,a");
557                 emitcode ("mov", "dpl1,b");
558             } else {
559                 if (options.model == MODEL_FLAT24)
560                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
561                 emitcode ("mov", "dph,a");
562                 emitcode ("mov", "dpl,b");
563             }
564             
565             if (_G.bInUse)
566                 emitcode ("pop", "b");
567             
568             if (_G.accInUse)
569                 emitcode ("pop", "acc");
570         }
571         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
572         aop->size = getSize (sym->type);
573         return aop;
574     }
575
576   /* if in bit space */
577   if (IN_BITSPACE (space))
578     {
579       sym->aop = aop = newAsmop (AOP_CRY);
580       aop->aopu.aop_dir = sym->rname;
581       aop->size = getSize (sym->type);
582       return aop;
583     }
584   /* if it is in direct space */
585   if (IN_DIRSPACE (space))
586     {
587       sym->aop = aop = newAsmop (AOP_DIR);
588       aop->aopu.aop_dir = sym->rname;
589       aop->size = getSize (sym->type);
590       return aop;
591     }
592
593   /* special case for a function */
594   if (IS_FUNC (sym->type))
595     {
596       sym->aop = aop = newAsmop (AOP_IMMD);
597       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
598       aop->size = FPTRSIZE;
599       return aop;
600     }
601   
602   /* only remaining is far space */
603   /* in which case DPTR gets the address */
604   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605   if (useDP2)
606     {
607       genSetDPTR (1);
608       _flushLazyDPS ();
609       emitcode ("mov", "dptr,#%s", sym->rname);
610       genSetDPTR (0);
611     }
612   else
613     {
614       emitcode ("mov", "dptr,#%s", sym->rname);
615     }
616   aop->size = getSize (sym->type);
617
618   /* if it is in code space */
619   if (IN_CODESPACE (space))
620     aop->code = 1;
621
622   return aop;
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* aopForRemat - rematerialzes an object                           */
627 /*-----------------------------------------------------------------*/
628 static asmop *
629 aopForRemat (symbol * sym)
630 {
631   iCode *ic = sym->rematiCode;
632   asmop *aop = newAsmop (AOP_IMMD);
633   int ptr_type =0;
634   int val = 0;
635
636   for (;;)
637     {
638       if (ic->op == '+')
639         val += (int) operandLitValue (IC_RIGHT (ic));
640       else if (ic->op == '-')
641         val -= (int) operandLitValue (IC_RIGHT (ic));
642       else if (IS_CAST_ICODE(ic)) {
643               sym_link *from_type = operandType(IC_RIGHT(ic));
644               aop->aopu.aop_immd.from_cast_remat = 1;
645               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
646               ptr_type = DCL_TYPE(from_type);
647               if (ptr_type == IPOINTER) {
648                 // bug #481053
649                 ptr_type = POINTER;
650               }
651               continue ;
652       } else break;
653       
654       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
655     }
656
657   if (val)
658   {
659       SNPRINTF (buffer, sizeof(buffer),
660                 "(%s %c 0x%04x)",
661                 OP_SYMBOL (IC_LEFT (ic))->rname,
662                 val >= 0 ? '+' : '-',
663                 abs (val) & 0xffff);
664   }
665   else 
666   {
667       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
668       {
669           SNPRINTF(buffer, sizeof(buffer), 
670                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
671       }
672       else
673       {
674           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
675       }
676   }
677
678   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
679   /* set immd2 field if required */
680   if (aop->aopu.aop_immd.from_cast_remat) 
681   {
682       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
683       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
684   }
685
686   return aop;
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopHasRegs - returns true if aop has regs between from-to       */
691 /*-----------------------------------------------------------------*/
692 static int aopHasRegs(asmop *aop, int from, int to)
693 {
694     int size =0;
695
696     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
697
698     for (; size < aop->size ; size++) {
699         int reg;
700         for (reg = from ; reg <= to ; reg++)
701             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
702     }
703     return 0;
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* regsInCommon - two operands have some registers in common       */
708 /*-----------------------------------------------------------------*/
709 static bool
710 regsInCommon (operand * op1, operand * op2)
711 {
712   symbol *sym1, *sym2;
713   int i;
714
715   /* if they have registers in common */
716   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
717     return FALSE;
718
719   sym1 = OP_SYMBOL (op1);
720   sym2 = OP_SYMBOL (op2);
721
722   if (sym1->nRegs == 0 || sym2->nRegs == 0)
723     return FALSE;
724
725   for (i = 0; i < sym1->nRegs; i++)
726     {
727       int j;
728       if (!sym1->regs[i])
729         continue;
730
731       for (j = 0; j < sym2->nRegs; j++)
732         {
733           if (!sym2->regs[j])
734             continue;
735
736           if (sym2->regs[j] == sym1->regs[i])
737             return TRUE;
738         }
739     }
740
741   return FALSE;
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* operandsEqu - equivalent                                        */
746 /*-----------------------------------------------------------------*/
747 static bool
748 operandsEqu (operand * op1, operand * op2)
749 {
750   symbol *sym1, *sym2;
751
752   /* if they not symbols */
753   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
754     return FALSE;
755
756   sym1 = OP_SYMBOL (op1);
757   sym2 = OP_SYMBOL (op2);
758
759   /* if both are itemps & one is spilt
760      and the other is not then false */
761   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
762       sym1->isspilt != sym2->isspilt)
763     return FALSE;
764
765   /* if they are the same */
766   if (sym1 == sym2)
767     return TRUE;
768
769   if (strcmp (sym1->rname, sym2->rname) == 0)
770     return TRUE;
771
772
773   /* if left is a tmp & right is not */
774   if (IS_ITEMP (op1) &&
775       !IS_ITEMP (op2) &&
776       sym1->isspilt &&
777       (sym1->usl.spillLoc == sym2))
778     return TRUE;
779
780   if (IS_ITEMP (op2) &&
781       !IS_ITEMP (op1) &&
782       sym2->isspilt &&
783       sym1->level > 0 &&
784       (sym2->usl.spillLoc == sym1))
785     return TRUE;
786
787   return FALSE;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* sameRegs - two asmops have the same registers                   */
792 /*-----------------------------------------------------------------*/
793 static bool
794 sameRegs (asmop * aop1, asmop * aop2)
795 {
796   int i;
797
798   if (aop1 == aop2)
799     {
800       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
801         {
802           return FALSE;
803         }
804       return TRUE;
805     }
806
807   if (aop1->type != AOP_REG ||
808       aop2->type != AOP_REG)
809     return FALSE;
810
811   if (aop1->size != aop2->size)
812     return FALSE;
813
814   for (i = 0; i < aop1->size; i++)
815     if (aop1->aopu.aop_reg[i] !=
816         aop2->aopu.aop_reg[i])
817       return FALSE;
818
819   return TRUE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* aopOp - allocates an asmop for an operand  :                    */
824 /*-----------------------------------------------------------------*/
825 static void
826 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
827 {
828   asmop *aop;
829   symbol *sym;
830   int i;
831
832   if (!op)
833     return;
834
835   /* if this a literal */
836   if (IS_OP_LITERAL (op))
837     {
838       op->aop = aop = newAsmop (AOP_LIT);
839       aop->aopu.aop_lit = op->operand.valOperand;
840       aop->size = getSize (operandType (op));
841       return;
842     }
843
844   /* if already has a asmop then continue */
845   if (op->aop)
846     return;
847
848   /* if the underlying symbol has a aop */
849   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
850     {
851       op->aop = OP_SYMBOL (op)->aop;
852       return;
853     }
854
855   /* if this is a true symbol */
856   if (IS_TRUE_SYMOP (op))
857     {
858       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
859       return;
860     }
861
862   /* this is a temporary : this has
863      only four choices :
864      a) register
865      b) spillocation
866      c) rematerialize
867      d) conditional
868      e) can be a return use only */
869
870   sym = OP_SYMBOL (op);
871
872
873   /* if the type is a conditional */
874   if (sym->regType == REG_CND)
875     {
876       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
877       aop->size = 0;
878       return;
879     }
880
881   /* if it is spilt then two situations
882      a) is rematerialize
883      b) has a spill location */
884   if (sym->isspilt || sym->nRegs == 0)
885     {
886
887       /* rematerialize it NOW */
888       if (sym->remat)
889         {
890           sym->aop = op->aop = aop =
891             aopForRemat (sym);
892           aop->size = getSize (sym->type);
893           return;
894         }
895
896       if (sym->accuse)
897         {
898           int i;
899           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
900           aop->size = getSize (sym->type);
901           for (i = 0; i < 2; i++)
902             aop->aopu.aop_str[i] = accUse[i];
903           return;
904         }
905
906       if (sym->ruonly)
907         {
908           int i;
909
910           if (useDP2)
911             {
912               /* a AOP_STR uses DPTR, but DPTR is already in use;
913                * we're just hosed.
914                */
915                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
916             }
917
918           aop = op->aop = sym->aop = newAsmop (AOP_STR);
919           aop->size = getSize (sym->type);
920           for (i = 0; i < (int) fReturnSizeDS390; i++)
921             aop->aopu.aop_str[i] = fReturn[i];
922           return;
923         }
924       
925       if (sym->dptr) { /* has been allocated to a DPTRn */
926           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
927           aop->size = getSize (sym->type);
928           aop->aopu.dptr = sym->dptr;
929           return ;
930       }
931       /* else spill location  */
932       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
933           /* force a new aop if sizes differ */
934           sym->usl.spillLoc->aop = NULL;
935       }
936       sym->aop = op->aop = aop =
937         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
938       aop->size = getSize (sym->type);
939       return;
940     }
941
942   /* must be in a register */
943   sym->aop = op->aop = aop = newAsmop (AOP_REG);
944   aop->size = sym->nRegs;
945   for (i = 0; i < sym->nRegs; i++)
946     aop->aopu.aop_reg[i] = sym->regs[i];
947 }
948
949 /*-----------------------------------------------------------------*/
950 /* freeAsmop - free up the asmop given to an operand               */
951 /*----------------------------------------------------------------*/
952 static void
953 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
954 {
955   asmop *aop;
956
957   if (!op)
958     aop = aaop;
959   else
960     aop = op->aop;
961
962   if (!aop)
963     return;
964
965   if (aop->freed)
966     goto dealloc;
967
968   aop->freed = 1;
969
970   /* depending on the asmop type only three cases need work AOP_RO
971      , AOP_R1 && AOP_STK */
972   switch (aop->type)
973     {
974     case AOP_R0:
975       if (_G.r0Pushed)
976         {
977           if (pop)
978             {
979               emitcode ("pop", "ar0");
980               _G.r0Pushed--;
981             }
982         }
983       bitVectUnSetBit (ic->rUsed, R0_IDX);
984       break;
985
986     case AOP_R1:
987       if (_G.r1Pushed)
988         {
989           if (pop)
990             {
991               emitcode ("pop", "ar1");
992               _G.r1Pushed--;
993             }
994         }
995       bitVectUnSetBit (ic->rUsed, R1_IDX);
996       break;
997
998     case AOP_STK:
999       {
1000         int sz = aop->size;
1001         int stk = aop->aopu.aop_stk + aop->size;
1002         bitVectUnSetBit (ic->rUsed, R0_IDX);
1003         bitVectUnSetBit (ic->rUsed, R1_IDX);
1004
1005         getFreePtr (ic, &aop, FALSE);
1006
1007         if (options.stack10bit)
1008           {
1009             /* I'm not sure what to do here yet... */
1010             /* #STUB */
1011             fprintf (stderr,
1012                      "*** Warning: probably generating bad code for "
1013                      "10 bit stack mode.\n");
1014           }
1015
1016         if (stk)
1017           {
1018             emitcode ("mov", "a,_bp");
1019             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1020             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1021           }
1022         else
1023           {
1024             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1025           }
1026
1027         while (sz--)
1028           {
1029             emitcode ("pop", "acc");
1030             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1031             if (!sz)
1032               break;
1033             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1034           }
1035         op->aop = aop;
1036         freeAsmop (op, NULL, ic, TRUE);
1037         if (_G.r0Pushed)
1038           {
1039             emitcode ("pop", "ar0");
1040             _G.r0Pushed--;
1041           }
1042
1043         if (_G.r1Pushed)
1044           {
1045             emitcode ("pop", "ar1");
1046             _G.r1Pushed--;
1047           }
1048       }
1049     case AOP_DPTR2:
1050         if (_G.dptr1InUse) {
1051             emitcode ("pop","dpx1");
1052             emitcode ("pop","dph1");
1053             emitcode ("pop","dpl1");
1054         }
1055         break;
1056     case AOP_DPTR:
1057         if (_G.dptrInUse) {
1058             emitcode ("pop","dpx");
1059             emitcode ("pop","dph");
1060             emitcode ("pop","dpl");
1061         }
1062         break;
1063     }
1064 dealloc:
1065   /* all other cases just dealloc */
1066   if (op)
1067     {
1068       op->aop = NULL;
1069       if (IS_SYMOP (op))
1070         {
1071           OP_SYMBOL (op)->aop = NULL;
1072           /* if the symbol has a spill */
1073           if (SPIL_LOC (op))
1074             SPIL_LOC (op)->aop = NULL;
1075         }
1076     }
1077 }
1078
1079 #define DEFAULT_ACC_WARNING 0
1080 static int saveAccWarn = DEFAULT_ACC_WARNING;
1081
1082 /*-------------------------------------------------------------------*/
1083 /* aopGet - for fetching value of the aop                            */
1084 /*                                                                   */
1085 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1086 /* in the accumulator. Set it to the name of a free register         */
1087 /* if acc must be preserved; the register will be used to preserve   */
1088 /* acc temporarily and to return the result byte.                    */
1089 /*-------------------------------------------------------------------*/
1090
1091 static char *
1092 aopGet (asmop *aop,
1093         int   offset,
1094         bool  bit16,
1095         bool  dname,
1096         char  *saveAcc)
1097 {
1098   /* offset is greater than
1099      size then zero */
1100   if (offset > (aop->size - 1) &&
1101       aop->type != AOP_LIT)
1102     return zero;
1103
1104   /* depending on type */
1105   switch (aop->type)
1106     {
1107
1108     case AOP_R0:
1109     case AOP_R1:
1110       /* if we need to increment it */
1111       while (offset > aop->coff)
1112         {
1113           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1114           aop->coff++;
1115         }
1116
1117       while (offset < aop->coff)
1118         {
1119           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1120           aop->coff--;
1121         }
1122
1123       aop->coff = offset;
1124       if (aop->paged)
1125         {
1126           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1127           return (dname ? "acc" : "a");
1128         }
1129       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1130       return Safe_strdup(buffer);       
1131
1132     case AOP_DPTRn:
1133         assert(offset <= 3);
1134         return dptrn[aop->aopu.dptr][offset];
1135
1136     case AOP_DPTR:
1137     case AOP_DPTR2:
1138
1139       if (aop->type == AOP_DPTR2)
1140         {
1141           genSetDPTR (1);
1142         }
1143         
1144       if (saveAcc)
1145         {
1146             TR_AP("#1");
1147 //          if (aop->type != AOP_DPTR2)
1148 //          {
1149 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1150 //              emitcode(";", "spanky: saveAcc for DPTR");
1151 //          }
1152             
1153             emitcode ("xch", "a, %s", saveAcc);
1154         }
1155
1156       _flushLazyDPS ();
1157
1158       while (offset > aop->coff)
1159         {
1160           emitcode ("inc", "dptr");
1161           aop->coff++;
1162         }
1163
1164       while (offset < aop->coff)
1165         {
1166           emitcode ("lcall", "__decdptr");
1167           aop->coff--;
1168         }
1169
1170       aop->coff = offset;
1171       if (aop->code)
1172         {
1173           emitcode ("clr", "a");
1174           emitcode ("movc", "a,@a+dptr");
1175         }
1176       else
1177         {
1178           emitcode ("movx", "a,@dptr");
1179         }
1180
1181       if (aop->type == AOP_DPTR2)
1182         {
1183           genSetDPTR (0);
1184         }
1185         
1186         if (saveAcc)
1187         {
1188        TR_AP("#2");
1189               emitcode ("xch", "a, %s", saveAcc);
1190 //            if (strcmp(saveAcc, "_ap"))
1191 //            {
1192 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1193 //            }
1194                   
1195               return saveAcc;
1196         }
1197       return (dname ? "acc" : "a");
1198
1199     case AOP_IMMD:
1200       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1201       {
1202           SNPRINTF(buffer, sizeof(buffer), 
1203                    "%s",aop->aopu.aop_immd.aop_immd2);
1204       } 
1205       else if (bit16)
1206       {
1207          SNPRINTF(buffer, sizeof(buffer), 
1208                   "#%s", aop->aopu.aop_immd.aop_immd1);
1209       }
1210       else if (offset) 
1211       {
1212           switch (offset) {
1213           case 1:
1214               tsprintf(buffer, sizeof(buffer),
1215                        "#!his",aop->aopu.aop_immd.aop_immd1);
1216               break;
1217           case 2:
1218               tsprintf(buffer, sizeof(buffer), 
1219                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1220               break;
1221           case 3:
1222               tsprintf(buffer, sizeof(buffer),
1223                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1224               break;
1225           default: /* should not need this (just in case) */
1226               SNPRINTF (buffer, sizeof(buffer), 
1227                         "#(%s >> %d)",
1228                        aop->aopu.aop_immd.aop_immd1,
1229                        offset * 8);
1230           }
1231       }
1232       else
1233       {
1234         SNPRINTF (buffer, sizeof(buffer), 
1235                   "#%s", aop->aopu.aop_immd.aop_immd1);
1236       }
1237       return Safe_strdup(buffer);       
1238
1239     case AOP_DIR:
1240       if (offset)
1241       {
1242         SNPRINTF (buffer, sizeof(buffer),
1243                   "(%s + %d)",
1244                  aop->aopu.aop_dir,
1245                  offset);
1246       }
1247       else
1248       {
1249         SNPRINTF(buffer, sizeof(buffer), 
1250                  "%s", aop->aopu.aop_dir);
1251       }
1252
1253       return Safe_strdup(buffer);
1254
1255     case AOP_REG:
1256       if (dname)
1257         return aop->aopu.aop_reg[offset]->dname;
1258       else
1259         return aop->aopu.aop_reg[offset]->name;
1260
1261     case AOP_CRY:
1262       emitcode ("clr", "a");
1263       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1264       emitcode ("rlc", "a");
1265       return (dname ? "acc" : "a");
1266
1267     case AOP_ACC:
1268       if (!offset && dname)
1269         return "acc";
1270       return aop->aopu.aop_str[offset];
1271
1272     case AOP_LIT:
1273       return aopLiteral (aop->aopu.aop_lit, offset);
1274
1275     case AOP_STR:
1276       aop->coff = offset;
1277       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1278           dname)
1279         return "acc";
1280
1281       return aop->aopu.aop_str[offset];
1282
1283     }
1284
1285   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286           "aopget got unsupported aop->type");
1287   exit (1);
1288     
1289   return NULL;  // not reached, but makes compiler happy.
1290 }
1291 /*-----------------------------------------------------------------*/
1292 /* aopPut - puts a string for a aop                                */
1293 /*-----------------------------------------------------------------*/
1294 static void
1295 aopPut (asmop * aop, char *s, int offset)
1296 {
1297   if (aop->size && offset > (aop->size - 1))
1298     {
1299       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1300               "aopPut got offset > aop->size");
1301       exit (1);
1302     }
1303
1304   /* will assign value to value */
1305   /* depending on where it is ofcourse */
1306   switch (aop->type)
1307     {
1308     case AOP_DIR:
1309         if (offset)
1310         {
1311             SNPRINTF (buffer, sizeof(buffer),
1312                       "(%s + %d)",
1313                       aop->aopu.aop_dir, offset);
1314         }
1315         else
1316         {
1317             SNPRINTF (buffer, sizeof(buffer), 
1318                      "%s", aop->aopu.aop_dir);
1319         }
1320         
1321
1322         if (strcmp (buffer, s))
1323         {
1324             emitcode ("mov", "%s,%s", buffer, s);
1325         }
1326       break;
1327
1328     case AOP_REG:
1329       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1330           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1331         {
1332           if (*s == '@' ||
1333               strcmp (s, "r0") == 0 ||
1334               strcmp (s, "r1") == 0 ||
1335               strcmp (s, "r2") == 0 ||
1336               strcmp (s, "r3") == 0 ||
1337               strcmp (s, "r4") == 0 ||
1338               strcmp (s, "r5") == 0 ||
1339               strcmp (s, "r6") == 0 ||
1340               strcmp (s, "r7") == 0)
1341             {
1342                 emitcode ("mov", "%s,%s",
1343                           aop->aopu.aop_reg[offset]->dname, s);
1344             }
1345             else
1346             {
1347                 emitcode ("mov", "%s,%s",
1348                           aop->aopu.aop_reg[offset]->name, s);
1349             }
1350         }
1351       break;
1352
1353     case AOP_DPTRn:
1354         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1355         break;
1356
1357     case AOP_DPTR:
1358     case AOP_DPTR2:
1359
1360       if (aop->type == AOP_DPTR2)
1361         {
1362           genSetDPTR (1);
1363         }
1364       _flushLazyDPS ();
1365
1366       if (aop->code)
1367         {
1368           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1369                   "aopPut writting to code space");
1370           exit (1);
1371         }
1372
1373       while (offset > aop->coff)
1374         {
1375           aop->coff++;
1376           emitcode ("inc", "dptr");
1377         }
1378
1379       while (offset < aop->coff)
1380         {
1381           aop->coff--;
1382           emitcode ("lcall", "__decdptr");
1383         }
1384
1385       aop->coff = offset;
1386
1387       /* if not in accumulater */
1388       MOVA (s);
1389
1390       emitcode ("movx", "@dptr,a");
1391
1392       if (aop->type == AOP_DPTR2)
1393         {
1394           genSetDPTR (0);
1395         }
1396       break;
1397
1398     case AOP_R0:
1399     case AOP_R1:
1400       while (offset > aop->coff)
1401         {
1402           aop->coff++;
1403           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1404         }
1405       while (offset < aop->coff)
1406         {
1407           aop->coff--;
1408           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1409         }
1410       aop->coff = offset;
1411
1412       if (aop->paged)
1413         {
1414           MOVA (s);
1415           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1416
1417         }
1418       else if (*s == '@')
1419         {
1420           MOVA (s);
1421           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1422         }
1423       else if (strcmp (s, "r0") == 0 ||
1424                strcmp (s, "r1") == 0 ||
1425                strcmp (s, "r2") == 0 ||
1426                strcmp (s, "r3") == 0 ||
1427                strcmp (s, "r4") == 0 ||
1428                strcmp (s, "r5") == 0 ||
1429                strcmp (s, "r6") == 0 ||
1430                strcmp (s, "r7") == 0)
1431         {
1432           char buff[10];
1433           SNPRINTF(buff, sizeof(buff), 
1434                    "a%s", s);
1435           emitcode ("mov", "@%s,%s",
1436                     aop->aopu.aop_ptr->name, buff);
1437         }
1438         else
1439         {
1440             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1441         }
1442       break;
1443
1444     case AOP_STK:
1445       if (strcmp (s, "a") == 0)
1446         emitcode ("push", "acc");
1447       else
1448         if (*s=='@') {
1449           MOVA(s);
1450           emitcode ("push", "acc");
1451         } else {
1452           emitcode ("push", s);
1453         }
1454
1455       break;
1456
1457     case AOP_CRY:
1458       /* if bit variable */
1459       if (!aop->aopu.aop_dir)
1460         {
1461           emitcode ("clr", "a");
1462           emitcode ("rlc", "a");
1463         }
1464       else
1465         {
1466           if (s == zero)
1467             emitcode ("clr", "%s", aop->aopu.aop_dir);
1468           else if (s == one)
1469             emitcode ("setb", "%s", aop->aopu.aop_dir);
1470           else if (!strcmp (s, "c"))
1471             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1472           else
1473             {
1474               if (strcmp (s, "a"))
1475                 {
1476                   MOVA (s);
1477                 }
1478               {
1479                 /* set C, if a >= 1 */
1480                 emitcode ("add", "a,#!constbyte",0xff);
1481                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1482               }
1483             }
1484         }
1485       break;
1486
1487     case AOP_STR:
1488       aop->coff = offset;
1489       if (strcmp (aop->aopu.aop_str[offset], s))
1490         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1491       break;
1492
1493     case AOP_ACC:
1494       aop->coff = offset;
1495       if (!offset && (strcmp (s, "acc") == 0))
1496         break;
1497
1498       if (strcmp (aop->aopu.aop_str[offset], s))
1499         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1500       break;
1501
1502     default:
1503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1504               "aopPut got unsupported aop->type");
1505       exit (1);
1506     }
1507
1508 }
1509
1510
1511 /*--------------------------------------------------------------------*/
1512 /* reAdjustPreg - points a register back to where it should (coff==0) */
1513 /*--------------------------------------------------------------------*/
1514 static void
1515 reAdjustPreg (asmop * aop)
1516 {
1517   if ((aop->coff==0) || (aop->size <= 1)) {
1518     return;
1519   }
1520
1521   switch (aop->type)
1522     {
1523     case AOP_R0:
1524     case AOP_R1:
1525       while (aop->coff--)
1526         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1527       break;
1528     case AOP_DPTR:
1529     case AOP_DPTR2:
1530       if (aop->type == AOP_DPTR2)
1531         {
1532           genSetDPTR (1);
1533           _flushLazyDPS ();
1534         }
1535       while (aop->coff--)
1536         {
1537           emitcode ("lcall", "__decdptr");
1538         }
1539
1540       if (aop->type == AOP_DPTR2)
1541         {
1542           genSetDPTR (0);
1543         }
1544       break;
1545
1546     }
1547   aop->coff=0;
1548 }
1549
1550 #define AOP(op) op->aop
1551 #define AOP_TYPE(op) AOP(op)->type
1552 #define AOP_SIZE(op) AOP(op)->size
1553 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1554                        AOP_TYPE(x) == AOP_R0))
1555
1556 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1557                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1558                          AOP(x)->paged))
1559
1560 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1561                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1562                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1563 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1564 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1565 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1566
1567 // The following two macros can be used even if the aop has not yet been aopOp'd.
1568 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1569 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1570
1571 /* Workaround for DS80C390 bug: div ab may return bogus results
1572  * if A is accessed in instruction immediately before the div.
1573  *
1574  * Will be fixed in B4 rev of processor, Dallas claims.
1575  */
1576
1577 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1578     if (!AOP_NEEDSACC(RIGHT))         \
1579     {               \
1580       /* We can load A first, then B, since     \
1581        * B (the RIGHT operand) won't clobber A,   \
1582        * thus avoiding touching A right before the div. \
1583        */             \
1584       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1585       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1586       MOVA(L);            \
1587       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1588       MOVB(L); \
1589     }               \
1590     else              \
1591     {               \
1592       /* Just stuff in a nop after loading A. */    \
1593       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1594       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1595       MOVA(L);            \
1596       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1597     }
1598
1599 /*-----------------------------------------------------------------*/
1600 /* genNotFloat - generates not for float operations              */
1601 /*-----------------------------------------------------------------*/
1602 static void
1603 genNotFloat (operand * op, operand * res)
1604 {
1605   int size, offset;
1606   symbol *tlbl;
1607
1608   D (emitcode (";", "genNotFloat "););
1609
1610   /* we will put 127 in the first byte of
1611      the result */
1612   aopPut (AOP (res), "#127", 0);
1613   size = AOP_SIZE (op) - 1;
1614   offset = 1;
1615
1616   _startLazyDPSEvaluation ();
1617   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1618
1619   while (size--)
1620     {
1621       emitcode ("orl", "a,%s",
1622                 aopGet (op->aop,
1623                         offset++, FALSE, FALSE,
1624                         DP2_RESULT_REG));
1625     }
1626   _endLazyDPSEvaluation ();
1627
1628   tlbl = newiTempLabel (NULL);
1629   aopPut (res->aop, one, 1);
1630   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1631   aopPut (res->aop, zero, 1);
1632   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1633
1634   size = res->aop->size - 2;
1635   offset = 2;
1636   /* put zeros in the rest */
1637   while (size--)
1638     aopPut (res->aop, zero, offset++);
1639 }
1640
1641 /*-----------------------------------------------------------------*/
1642 /* opIsGptr: returns non-zero if the passed operand is       */
1643 /* a generic pointer type.             */
1644 /*-----------------------------------------------------------------*/
1645 static int
1646 opIsGptr (operand * op)
1647 {
1648   sym_link *type = operandType (op);
1649
1650   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1651     {
1652       return 1;
1653     }
1654   return 0;
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* getDataSize - get the operand data size                         */
1659 /*-----------------------------------------------------------------*/
1660 static int
1661 getDataSize (operand * op)
1662 {
1663   int size;
1664   size = AOP_SIZE (op);
1665   if (size == GPTRSIZE)
1666     {
1667       sym_link *type = operandType (op);
1668       if (IS_GENPTR (type))
1669         {
1670           /* generic pointer; arithmetic operations
1671            * should ignore the high byte (pointer type).
1672            */
1673           size--;
1674         }
1675     }
1676   return size;
1677 }
1678
1679 /*-----------------------------------------------------------------*/
1680 /* outAcc - output Acc                                             */
1681 /*-----------------------------------------------------------------*/
1682 static void
1683 outAcc (operand * result)
1684 {
1685   int size, offset;
1686   size = getDataSize (result);
1687   if (size)
1688     {
1689       aopPut (AOP (result), "a", 0);
1690       size--;
1691       offset = 1;
1692       /* unsigned or positive */
1693       while (size--)
1694         {
1695           aopPut (AOP (result), zero, offset++);
1696         }
1697     }
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* outBitC - output a bit C                                        */
1702 /*-----------------------------------------------------------------*/
1703 static void
1704 outBitC (operand * result)
1705 {
1706   /* if the result is bit */
1707   if (AOP_TYPE (result) == AOP_CRY)
1708     {
1709       aopPut (AOP (result), "c", 0);
1710     }
1711   else
1712     {
1713       emitcode ("clr", "a");
1714       emitcode ("rlc", "a");
1715       outAcc (result);
1716     }
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* toBoolean - emit code for orl a,operator(sizeop)                */
1721 /*-----------------------------------------------------------------*/
1722 static void
1723 toBoolean (operand * oper)
1724 {
1725   int   size = AOP_SIZE (oper) - 1;
1726   int   offset = 1;
1727   bool usedB = FALSE;
1728
1729   /* The generic part of a generic pointer should
1730    * not participate in it's truth value.
1731    *
1732    * i.e. 0x10000000 is zero.
1733    */
1734   if (opIsGptr (oper))
1735     {
1736       D (emitcode (";", "toBoolean: generic ptr special case."););
1737       size--;
1738     }
1739
1740   _startLazyDPSEvaluation ();
1741   if (AOP_NEEDSACC (oper) && size)
1742     {
1743       usedB = TRUE;
1744       if (_G.bInUse)
1745       {
1746           emitcode ("push", "b");
1747       }
1748       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1749     }
1750   else
1751     {
1752       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1753     }
1754     
1755   while (size--)
1756     {
1757       if (usedB)
1758         {
1759           emitcode ("orl", "b,%s",
1760                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1761         }
1762       else
1763         {
1764           emitcode ("orl", "a,%s",
1765                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1766         }
1767     }
1768   _endLazyDPSEvaluation ();
1769
1770   if (usedB)
1771     {
1772       emitcode ("mov", "a,b");
1773       if (_G.bInUse)
1774       {
1775           emitcode ("pop", "b");
1776       }
1777         
1778     }
1779 }
1780
1781
1782 /*-----------------------------------------------------------------*/
1783 /* genNot - generate code for ! operation                          */
1784 /*-----------------------------------------------------------------*/
1785 static void
1786 genNot (iCode * ic)
1787 {
1788   symbol *tlbl;
1789   sym_link *optype = operandType (IC_LEFT (ic));
1790
1791   D (emitcode (";", "genNot "););
1792
1793   /* assign asmOps to operand & result */
1794   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1795   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1796
1797   /* if in bit space then a special case */
1798   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1799     {
1800       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1801       emitcode ("cpl", "c");
1802       outBitC (IC_RESULT (ic));
1803       goto release;
1804     }
1805
1806   /* if type float then do float */
1807   if (IS_FLOAT (optype))
1808     {
1809       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1810       goto release;
1811     }
1812
1813   toBoolean (IC_LEFT (ic));
1814
1815   tlbl = newiTempLabel (NULL);
1816   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1817   emitcode ("", "!tlabeldef", tlbl->key + 100);
1818   outBitC (IC_RESULT (ic));
1819
1820 release:
1821   /* release the aops */
1822   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1824 }
1825
1826
1827 /*-----------------------------------------------------------------*/
1828 /* genCpl - generate code for complement                           */
1829 /*-----------------------------------------------------------------*/
1830 static void
1831 genCpl (iCode * ic)
1832 {
1833   int offset = 0;
1834   int size;
1835   symbol *tlbl;
1836
1837   D (emitcode (";", "genCpl "););
1838
1839
1840   /* assign asmOps to operand & result */
1841   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1842   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1843
1844   /* special case if in bit space */
1845   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1846     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1847       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1848       emitcode ("cpl", "c");
1849       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1850       goto release;
1851     }
1852     tlbl=newiTempLabel(NULL);
1853     emitcode ("cjne", "%s,#0x01,%05d$", 
1854               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1855     emitcode ("", "%05d$:", tlbl->key+100);
1856     outBitC (IC_RESULT(ic));
1857     goto release;
1858   }
1859
1860   size = AOP_SIZE (IC_RESULT (ic));
1861   _startLazyDPSEvaluation ();
1862   while (size--)
1863     {
1864       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1865       emitcode ("cpl", "a");
1866       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1867     }
1868   _endLazyDPSEvaluation ();
1869
1870
1871 release:
1872   /* release the aops */
1873   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1874   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genUminusFloat - unary minus for floating points                */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genUminusFloat (operand * op, operand * result)
1882 {
1883   int size, offset = 0;
1884     
1885   D(emitcode (";", "genUminusFloat"););
1886   
1887   /* for this we just copy and then flip the bit */
1888     
1889   _startLazyDPSEvaluation ();
1890   size = AOP_SIZE (op) - 1;
1891
1892   while (size--)
1893   {
1894       aopPut (AOP (result),
1895               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1896               offset);
1897       offset++;
1898     }
1899   
1900   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1901
1902   emitcode ("cpl", "acc.7");
1903   aopPut (AOP (result), "a", offset);    
1904   _endLazyDPSEvaluation ();
1905 }
1906
1907 /*-----------------------------------------------------------------*/
1908 /* genUminus - unary minus code generation                         */
1909 /*-----------------------------------------------------------------*/
1910 static void
1911 genUminus (iCode * ic)
1912 {
1913   int offset, size;
1914   sym_link *optype;
1915
1916   D (emitcode (";", "genUminus "););
1917
1918   /* assign asmops */
1919   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1920   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1921
1922   /* if both in bit space then special
1923      case */
1924   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1925       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1926     {
1927
1928       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929       emitcode ("cpl", "c");
1930       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1931       goto release;
1932     }
1933
1934   optype = operandType (IC_LEFT (ic));
1935
1936   /* if float then do float stuff */
1937   if (IS_FLOAT (optype))
1938     {
1939       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1940       goto release;
1941     }
1942
1943   /* otherwise subtract from zero */
1944   size = AOP_SIZE (IC_LEFT (ic));
1945   offset = 0;
1946   _startLazyDPSEvaluation ();
1947   while (size--)
1948     {
1949       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1950       if (!strcmp (l, "a"))
1951         {
1952           if (offset == 0)
1953             SETC;
1954           emitcode ("cpl", "a");
1955           emitcode ("addc", "a,#0");
1956         }
1957       else
1958         {
1959           if (offset == 0)
1960             CLRC;
1961           emitcode ("clr", "a");
1962           emitcode ("subb", "a,%s", l);
1963         }
1964       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1965     }
1966   _endLazyDPSEvaluation ();
1967
1968   /* if any remaining bytes in the result */
1969   /* we just need to propagate the sign   */
1970   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1971     {
1972       emitcode ("rlc", "a");
1973       emitcode ("subb", "a,acc");
1974       while (size--)
1975         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977
1978 release:
1979   /* release the aops */
1980   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1981   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1982 }
1983
1984 /*-----------------------------------------------------------------*/
1985 /* savermask - saves registers in the mask                         */
1986 /*-----------------------------------------------------------------*/
1987 static void savermask(bitVect *rs_mask)
1988 {
1989     int i;
1990     if (options.useXstack) {
1991         if (bitVectBitValue (rs_mask, R0_IDX))
1992             emitcode ("mov", "b,r0");
1993         emitcode ("mov", "r0,%s", spname);
1994         for (i = 0; i < ds390_nRegs; i++) {
1995             if (bitVectBitValue (rs_mask, i)) {
1996                 if (i == R0_IDX)
1997                     emitcode ("mov", "a,b");
1998                 else
1999                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2000                 emitcode ("movx", "@r0,a");
2001                 emitcode ("inc", "r0");
2002             }
2003         }
2004         emitcode ("mov", "%s,r0", spname);
2005         if (bitVectBitValue (rs_mask, R0_IDX))
2006             emitcode ("mov", "r0,b");
2007     } else {
2008         for (i = 0; i < ds390_nRegs; i++) {
2009             if (bitVectBitValue (rs_mask, i))
2010                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2011         }
2012     }
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* saveRegisters - will look for a call and save the registers     */
2017 /*-----------------------------------------------------------------*/
2018 static void
2019 saveRegisters (iCode * lic)
2020 {
2021   iCode *ic;
2022   bitVect *rsave;
2023
2024   /* look for call */
2025   for (ic = lic; ic; ic = ic->next)
2026     if (ic->op == CALL || ic->op == PCALL)
2027       break;
2028
2029   if (!ic)
2030     {
2031       fprintf (stderr, "found parameter push with no function call\n");
2032       return;
2033     }
2034
2035   /* if the registers have been saved already then
2036      do nothing */
2037   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2038
2039   /* special case if DPTR alive across a function call then must save it 
2040      even though callee saves */
2041   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2042       int i;
2043       rsave = newBitVect(ic->rMask->size);
2044       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2045           if (bitVectBitValue(ic->rMask,i))
2046               rsave = bitVectSetBit(rsave,i);
2047       }
2048       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2049   } else {
2050     /* safe the registers in use at this time but skip the
2051        ones for the result */
2052     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2053                            ds390_rUmaskForOp (IC_RESULT(ic)));
2054   }
2055   ic->regsSaved = 1;
2056   savermask(rsave);
2057 }
2058
2059 /*-----------------------------------------------------------------*/
2060 /* usavermask - restore registers with mask                        */
2061 /*-----------------------------------------------------------------*/
2062 static void unsavermask(bitVect *rs_mask)
2063 {
2064     int i;
2065     if (options.useXstack) {
2066         emitcode ("mov", "r0,%s", spname);
2067         for (i = ds390_nRegs; i >= 0; i--) {
2068             if (bitVectBitValue (rs_mask, i)) {
2069                 emitcode ("dec", "r0");
2070                 emitcode ("movx", "a,@r0");
2071                 if (i == R0_IDX)
2072                     emitcode ("mov", "b,a");
2073                 else
2074                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2075             }       
2076         }
2077         emitcode ("mov", "%s,r0", spname);
2078         if (bitVectBitValue (rs_mask, R0_IDX))
2079             emitcode ("mov", "r0,b");
2080     } else {
2081         for (i = ds390_nRegs; i >= 0; i--) {
2082             if (bitVectBitValue (rs_mask, i))
2083                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2084         }
2085     }
2086 }
2087
2088 /*-----------------------------------------------------------------*/
2089 /* unsaveRegisters - pop the pushed registers                      */
2090 /*-----------------------------------------------------------------*/
2091 static void
2092 unsaveRegisters (iCode * ic)
2093 {
2094   bitVect *rsave;
2095
2096   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2097       int i;
2098       rsave = newBitVect(ic->rMask->size);
2099       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2100           if (bitVectBitValue(ic->rMask,i))
2101               rsave = bitVectSetBit(rsave,i);
2102       }
2103       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2104   } else {
2105     /* restore the registers in use at this time but skip the
2106        ones for the result */
2107     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2108                            ds390_rUmaskForOp (IC_RESULT(ic)));
2109   }
2110   unsavermask(rsave);
2111 }
2112
2113
2114 /*-----------------------------------------------------------------*/
2115 /* pushSide -                */
2116 /*-----------------------------------------------------------------*/
2117 static void
2118 pushSide (operand * oper, int size)
2119 {
2120   int offset = 0;
2121   _startLazyDPSEvaluation ();
2122   while (size--)
2123     {
2124       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2125       if (AOP_TYPE (oper) != AOP_REG &&
2126           AOP_TYPE (oper) != AOP_DIR &&
2127           strcmp (l, "a"))
2128         {
2129           emitcode ("mov", "a,%s", l);
2130           emitcode ("push", "acc");
2131         }
2132       else
2133         emitcode ("push", "%s", l);
2134     }
2135   _endLazyDPSEvaluation ();
2136 }
2137
2138 /*-----------------------------------------------------------------*/
2139 /* assignResultValue -               */
2140 /*-----------------------------------------------------------------*/
2141 static void
2142 assignResultValue (operand * oper)
2143 {
2144   int offset = 0;
2145   int size = AOP_SIZE (oper);
2146   bool pushedAcc = FALSE;
2147
2148   if (size == fReturnSizeDS390)
2149   {
2150       /* I don't think this case can ever happen... */
2151       /* ACC is the last part of this. If writing the result
2152        * uses AC, we must preserve it.
2153        */
2154       if (AOP_NEEDSACC(oper))
2155       {
2156           emitcode(";", "assignResultValue special case for ACC.");
2157           emitcode("push", "acc");
2158           pushedAcc = TRUE;
2159           size--;
2160       }
2161   }
2162     
2163     
2164   _startLazyDPSEvaluation ();
2165   while (size--)
2166     {
2167       aopPut (AOP (oper), fReturn[offset], offset);
2168       offset++;
2169     }
2170   _endLazyDPSEvaluation ();
2171     
2172   if (pushedAcc)
2173     {
2174         emitcode("pop", "acc");
2175         aopPut(AOP(oper), "a", offset);
2176     }
2177 }
2178
2179
2180 /*-----------------------------------------------------------------*/
2181 /* genXpush - pushes onto the external stack                       */
2182 /*-----------------------------------------------------------------*/
2183 static void
2184 genXpush (iCode * ic)
2185 {
2186   asmop *aop = newAsmop (0);
2187   regs *r;
2188   int size, offset = 0;
2189
2190   D (emitcode (";", "genXpush ");
2191     );
2192
2193   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2194   r = getFreePtr (ic, &aop, FALSE);
2195
2196
2197   emitcode ("mov", "%s,_spx", r->name);
2198
2199   size = AOP_SIZE (IC_LEFT (ic));
2200   _startLazyDPSEvaluation ();
2201   while (size--)
2202     {
2203
2204       MOVA (aopGet (AOP (IC_LEFT (ic)),
2205                         offset++, FALSE, FALSE, NULL));
2206       emitcode ("movx", "@%s,a", r->name);
2207       emitcode ("inc", "%s", r->name);
2208
2209     }
2210   _endLazyDPSEvaluation ();
2211
2212
2213   emitcode ("mov", "_spx,%s", r->name);
2214
2215   freeAsmop (NULL, aop, ic, TRUE);
2216   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2217 }
2218
2219 /*-----------------------------------------------------------------*/
2220 /* genIpush - generate code for pushing this gets a little complex  */
2221 /*-----------------------------------------------------------------*/
2222 static void
2223 genIpush (iCode * ic)
2224 {
2225   int size, offset = 0;
2226   char *l;
2227
2228   D (emitcode (";", "genIpush ");
2229     );
2230
2231   /* if this is not a parm push : ie. it is spill push
2232      and spill push is always done on the local stack */
2233   if (!ic->parmPush)
2234     {
2235
2236       /* and the item is spilt then do nothing */
2237       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2238         return;
2239
2240       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241       size = AOP_SIZE (IC_LEFT (ic));
2242       /* push it on the stack */
2243       _startLazyDPSEvaluation ();
2244       while (size--)
2245         {
2246           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2247           if (*l == '#')
2248             {
2249               MOVA (l);
2250               l = "acc";
2251             }
2252           emitcode ("push", "%s", l);
2253         }
2254       _endLazyDPSEvaluation ();
2255       return;
2256     }
2257
2258   /* this is a paramter push: in this case we call
2259      the routine to find the call and save those
2260      registers that need to be saved */
2261   saveRegisters (ic);
2262
2263   /* if use external stack then call the external
2264      stack pushing routine */
2265   if (options.useXstack)
2266     {
2267       genXpush (ic);
2268       return;
2269     }
2270
2271   /* then do the push */
2272   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2273
2274   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2275   size = AOP_SIZE (IC_LEFT (ic));
2276
2277   _startLazyDPSEvaluation ();
2278   while (size--)
2279     {
2280       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2281       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2282           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2283           strcmp (l, "acc"))
2284         {
2285           emitcode ("mov", "a,%s", l);
2286           emitcode ("push", "acc");
2287         }
2288       else
2289         {
2290             emitcode ("push", "%s", l);
2291         }
2292     }
2293   _endLazyDPSEvaluation ();
2294
2295   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2296 }
2297
2298 /*-----------------------------------------------------------------*/
2299 /* genIpop - recover the registers: can happen only for spilling   */
2300 /*-----------------------------------------------------------------*/
2301 static void
2302 genIpop (iCode * ic)
2303 {
2304   int size, offset;
2305
2306   D (emitcode (";", "genIpop ");
2307     );
2308
2309
2310   /* if the temp was not pushed then */
2311   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2312     return;
2313
2314   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2315   size = AOP_SIZE (IC_LEFT (ic));
2316   offset = (size - 1);
2317   _startLazyDPSEvaluation ();
2318   while (size--)
2319     {
2320       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2321                                      FALSE, TRUE, NULL));
2322     }
2323   _endLazyDPSEvaluation ();
2324
2325   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2326 }
2327
2328 /*-----------------------------------------------------------------*/
2329 /* unsaveRBank - restores the resgister bank from stack            */
2330 /*-----------------------------------------------------------------*/
2331 static void
2332 unsaveRBank (int bank, iCode * ic, bool popPsw)
2333 {
2334   int i;
2335   asmop *aop = NULL;
2336   regs *r = NULL;
2337
2338   if (options.useXstack)
2339   {
2340       if (!ic)
2341       {
2342           /* Assume r0 is available for use. */
2343           r = ds390_regWithIdx (R0_IDX);;          
2344       } 
2345       else
2346       {
2347           aop = newAsmop (0);
2348           r = getFreePtr (ic, &aop, FALSE);
2349       }
2350       emitcode ("mov", "%s,_spx", r->name);      
2351   }
2352   
2353   if (popPsw)
2354     {
2355       if (options.useXstack)
2356       {
2357           emitcode ("movx", "a,@%s", r->name);
2358           emitcode ("mov", "psw,a");
2359           emitcode ("dec", "%s", r->name);
2360         }
2361       else
2362       {
2363         emitcode ("pop", "psw");
2364       }
2365     }
2366
2367   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2368     {
2369       if (options.useXstack)
2370         {
2371           emitcode ("movx", "a,@%s", r->name);
2372           emitcode ("mov", "(%s+%d),a",
2373                     regs390[i].base, 8 * bank + regs390[i].offset);
2374           emitcode ("dec", "%s", r->name);
2375
2376         }
2377       else
2378         emitcode ("pop", "(%s+%d)",
2379                   regs390[i].base, 8 * bank + regs390[i].offset);
2380     }
2381
2382   if (options.useXstack)
2383     {
2384       emitcode ("mov", "_spx,%s", r->name);
2385     }
2386     
2387   if (aop)
2388   {
2389       freeAsmop (NULL, aop, ic, TRUE);  
2390   }    
2391 }
2392
2393 /*-----------------------------------------------------------------*/
2394 /* saveRBank - saves an entire register bank on the stack          */
2395 /*-----------------------------------------------------------------*/
2396 static void
2397 saveRBank (int bank, iCode * ic, bool pushPsw)
2398 {
2399   int i;
2400   asmop *aop = NULL;
2401   regs *r = NULL;
2402
2403   if (options.useXstack)
2404     {
2405         if (!ic)
2406         {
2407           /* Assume r0 is available for use. */
2408                   r = ds390_regWithIdx (R0_IDX);;
2409         }
2410         else
2411         {
2412           aop = newAsmop (0);
2413           r = getFreePtr (ic, &aop, FALSE);
2414         }
2415         emitcode ("mov", "%s,_spx", r->name);    
2416     }
2417
2418   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2419     {
2420       if (options.useXstack)
2421         {
2422           emitcode ("inc", "%s", r->name);
2423           emitcode ("mov", "a,(%s+%d)",
2424                     regs390[i].base, 8 * bank + regs390[i].offset);
2425           emitcode ("movx", "@%s,a", r->name);
2426         }
2427       else
2428         emitcode ("push", "(%s+%d)",
2429                   regs390[i].base, 8 * bank + regs390[i].offset);
2430     }
2431
2432   if (pushPsw)
2433     {
2434       if (options.useXstack)
2435         {
2436           emitcode ("mov", "a,psw");
2437           emitcode ("movx", "@%s,a", r->name);
2438           emitcode ("inc", "%s", r->name);
2439           emitcode ("mov", "_spx,%s", r->name);
2440         }
2441       else
2442       {
2443         emitcode ("push", "psw");
2444       }
2445
2446       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2447     }
2448   
2449   if (aop)
2450   {
2451        freeAsmop (NULL, aop, ic, TRUE);
2452   }    
2453     
2454   if (ic)
2455   {  
2456       ic->bankSaved = 1;
2457   }
2458 }
2459
2460 /*-----------------------------------------------------------------*/
2461 /* genSend - gen code for SEND                                     */
2462 /*-----------------------------------------------------------------*/
2463 static void genSend(set *sendSet)
2464 {
2465     iCode *sic;
2466     int sendCount = 0 ;
2467     static int rb1_count = 0;
2468
2469     for (sic = setFirstItem (sendSet); sic;
2470          sic = setNextItem (sendSet)) {     
2471         int size, offset = 0;
2472         
2473         size=getSize(operandType(IC_LEFT(sic)));
2474         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2475         if (sendCount == 0) { /* first parameter */
2476             // we know that dpl(hxb) is the result, so
2477             rb1_count = 0 ;
2478             _startLazyDPSEvaluation ();
2479             if (size>1) {
2480                 aopOp (IC_LEFT (sic), sic, FALSE, 
2481                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2482             } else {
2483                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2484             }
2485             while (size--) {
2486                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2487                                   FALSE, FALSE, NULL);
2488                 if (strcmp (l, fReturn[offset])) {
2489                     emitcode ("mov", "%s,%s",
2490                               fReturn[offset],
2491                               l);
2492                 }
2493                 offset++;
2494             }
2495             _endLazyDPSEvaluation ();
2496             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2497             rb1_count =0;
2498         } else { /* if more parameter in registers */
2499             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2500             while (size--) {
2501                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2502                                                                 FALSE, FALSE, NULL));
2503             }
2504             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2505         }
2506         sendCount++;
2507     }
2508 }
2509
2510 /*-----------------------------------------------------------------*/
2511 /* genCall - generates a call statement                            */
2512 /*-----------------------------------------------------------------*/
2513 static void
2514 genCall (iCode * ic)
2515 {
2516   sym_link *dtype;
2517   bool restoreBank = FALSE;
2518   bool swapBanks = FALSE;
2519
2520   D (emitcode (";", "genCall "););
2521
2522   /* if we are calling a not _naked function that is not using
2523      the same register bank then we need to save the
2524      destination registers on the stack */
2525   dtype = operandType (IC_LEFT (ic));
2526   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2527       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2528       IFFUNC_ISISR (currFunc->type))
2529   {
2530       if (!ic->bankSaved) 
2531       {
2532            /* This is unexpected; the bank should have been saved in
2533             * genFunction.
2534             */
2535            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2536            restoreBank = TRUE;
2537       }
2538       swapBanks = TRUE;
2539   }
2540   
2541     /* if caller saves & we have not saved then */
2542     if (!ic->regsSaved)
2543       saveRegisters (ic);
2544   
2545   /* if send set is not empty the assign */
2546   /* We've saved all the registers we care about;
2547   * therefore, we may clobber any register not used
2548   * in the calling convention (i.e. anything not in
2549   * fReturn.
2550   */
2551   if (_G.sendSet)
2552     {
2553         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2554             genSend(reverseSet(_G.sendSet));
2555         } else {
2556             genSend(_G.sendSet);
2557         }
2558       _G.sendSet = NULL;
2559     }  
2560     
2561   if (swapBanks)
2562   {
2563         emitcode ("mov", "psw,#!constbyte", 
2564            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2565   }
2566
2567   /* make the call */
2568   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2569                             OP_SYMBOL (IC_LEFT (ic))->rname :
2570                             OP_SYMBOL (IC_LEFT (ic))->name));
2571
2572   if (swapBanks)
2573   {
2574        emitcode ("mov", "psw,#!constbyte", 
2575           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2576   }
2577
2578   /* if we need assign a result value */
2579   if ((IS_ITEMP (IC_RESULT (ic)) &&
2580        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2581         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2582         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2583       IS_TRUE_SYMOP (IC_RESULT (ic)))
2584     {
2585       if (isOperandInFarSpace (IC_RESULT (ic))
2586           && getSize (operandType (IC_RESULT (ic))) <= 2)
2587         {
2588           int size = getSize (operandType (IC_RESULT (ic)));
2589
2590           /* Special case for 1 or 2 byte return in far space. */
2591           MOVA (fReturn[0]);
2592           if (size > 1)
2593             {
2594               emitcode ("mov", "b,%s", fReturn[1]);
2595             }
2596
2597           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2598           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2599
2600           if (size > 1)
2601             {
2602               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2603             }
2604           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2605         }
2606       else
2607         {
2608           _G.accInUse++;
2609           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2610           _G.accInUse--;
2611
2612           assignResultValue (IC_RESULT (ic));
2613
2614           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2615         }
2616     }
2617
2618   /* adjust the stack for parameters if
2619      required */
2620   if (ic->parmBytes) {
2621       int i;
2622       if (options.stack10bit) {
2623           if (ic->parmBytes <= 10) {
2624               emitcode(";","stack adjustment for parms");
2625               for (i=0; i < ic->parmBytes ; i++) {
2626                   emitcode("pop","acc");
2627               }
2628           } else {            
2629               PROTECT_SP;
2630               emitcode ("clr","c");
2631               emitcode ("mov","a,sp");
2632               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2633               emitcode ("mov","sp,a");
2634               emitcode ("mov","a,esp");
2635               emitcode ("anl","a,#3");
2636               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2637               emitcode ("mov","esp,a");   
2638               UNPROTECT_SP;
2639           }
2640       } else {
2641           if (ic->parmBytes > 3) {
2642               emitcode ("mov", "a,%s", spname);
2643               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2644               emitcode ("mov", "%s,a", spname);
2645           } else
2646               for (i = 0; i < ic->parmBytes; i++)
2647                   emitcode ("dec", "%s", spname);
2648       }
2649   }
2650
2651   /* if we hade saved some registers then unsave them */
2652   if (ic->regsSaved)
2653     unsaveRegisters (ic);
2654
2655   /* if register bank was saved then pop them */
2656   if (restoreBank)
2657     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2658 }
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genPcall - generates a call by pointer statement                */
2662 /*-----------------------------------------------------------------*/
2663 static void
2664 genPcall (iCode * ic)
2665 {
2666   sym_link *dtype;
2667   symbol *rlbl = newiTempLabel (NULL);
2668   bool restoreBank=FALSE;
2669
2670   D (emitcode (";", "genPcall ");
2671     );
2672
2673
2674   /* if caller saves & we have not saved then */
2675   if (!ic->regsSaved)
2676     saveRegisters (ic);
2677
2678   /* if we are calling a function that is not using
2679      the same register bank then we need to save the
2680      destination registers on the stack */
2681   dtype = operandType (IC_LEFT (ic));
2682   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2683       IFFUNC_ISISR (currFunc->type) &&
2684       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2685     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2686     restoreBank=TRUE;
2687   }
2688
2689   /* push the return address on to the stack */
2690   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2691   emitcode ("push", "acc");
2692   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2693   emitcode ("push", "acc");
2694
2695   if (options.model == MODEL_FLAT24)
2696     {
2697       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2698       emitcode ("push", "acc");
2699     }
2700
2701   /* now push the calling address */
2702   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2703
2704   pushSide (IC_LEFT (ic), FPTRSIZE);
2705
2706   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2707
2708   /* if send set is not empty the assign */
2709   if (_G.sendSet)
2710     {
2711         genSend(reverseSet(_G.sendSet));
2712         _G.sendSet = NULL;
2713     }
2714
2715   emitcode ("ret", "");
2716   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2717
2718
2719   /* if we need assign a result value */
2720   if ((IS_ITEMP (IC_RESULT (ic)) &&
2721        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2722         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2723       IS_TRUE_SYMOP (IC_RESULT (ic)))
2724     {
2725
2726       _G.accInUse++;
2727       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2728       _G.accInUse--;
2729
2730       assignResultValue (IC_RESULT (ic));
2731
2732       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2733     }
2734
2735   /* adjust the stack for parameters if
2736      required */
2737   if (ic->parmBytes)
2738     {
2739       int i;
2740       if (options.stack10bit) {
2741           if (ic->parmBytes <= 10) {
2742               emitcode(";","stack adjustment for parms");
2743               for (i=0; i < ic->parmBytes ; i++) {
2744                   emitcode("pop","acc");
2745               }
2746           } else {            
2747               PROTECT_SP;
2748               emitcode ("clr","c");
2749               emitcode ("mov","a,sp");
2750               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2751               emitcode ("mov","sp,a");
2752               emitcode ("mov","a,esp");
2753               emitcode ("anl","a,#3");
2754               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2755               emitcode ("mov","esp,a");   
2756               UNPROTECT_SP;
2757           }
2758       } else {
2759           if (ic->parmBytes > 3) {
2760               emitcode ("mov", "a,%s", spname);
2761               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2762               emitcode ("mov", "%s,a", spname);
2763           }
2764           else
2765               for (i = 0; i < ic->parmBytes; i++)
2766                   emitcode ("dec", "%s", spname);
2767           
2768       }
2769     }
2770   /* if register bank was saved then unsave them */
2771   if (restoreBank)
2772     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2773   
2774   /* if we hade saved some registers then
2775      unsave them */
2776   if (ic->regsSaved)
2777     unsaveRegisters (ic);
2778
2779 }
2780
2781 /*-----------------------------------------------------------------*/
2782 /* resultRemat - result  is rematerializable                       */
2783 /*-----------------------------------------------------------------*/
2784 static int
2785 resultRemat (iCode * ic)
2786 {
2787   if (SKIP_IC (ic) || ic->op == IFX)
2788     return 0;
2789
2790   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2791     {
2792       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2793       if (sym->remat && !POINTER_SET (ic))
2794         return 1;
2795     }
2796
2797   return 0;
2798 }
2799
2800 #if defined(__BORLANDC__) || defined(_MSC_VER)
2801 #define STRCASECMP stricmp
2802 #else
2803 #define STRCASECMP strcasecmp
2804 #endif
2805
2806 /*-----------------------------------------------------------------*/
2807 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2808 /*-----------------------------------------------------------------*/
2809 static bool
2810 inExcludeList (char *s)
2811 {
2812   int i = 0;
2813
2814   if (options.excludeRegs[i] &&
2815       STRCASECMP (options.excludeRegs[i], "none") == 0)
2816     return FALSE;
2817
2818   for (i = 0; options.excludeRegs[i]; i++)
2819     {
2820       if (options.excludeRegs[i] &&
2821           STRCASECMP (s, options.excludeRegs[i]) == 0)
2822         return TRUE;
2823     }
2824   return FALSE;
2825 }
2826
2827 /*-----------------------------------------------------------------*/
2828 /* genFunction - generated code for function entry                 */
2829 /*-----------------------------------------------------------------*/
2830 static void
2831 genFunction (iCode * ic)
2832 {
2833   symbol *sym;
2834   sym_link *ftype;
2835   bool   switchedPSW = FALSE;
2836
2837   D (emitcode (";", "genFunction "););
2838
2839   _G.nRegsSaved = 0;
2840   /* create the function header */
2841   emitcode (";", "-----------------------------------------");
2842   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2843   emitcode (";", "-----------------------------------------");
2844
2845   emitcode ("", "%s:", sym->rname);
2846   ftype = operandType (IC_LEFT (ic));
2847
2848   if (IFFUNC_ISNAKED(ftype))
2849   {
2850       emitcode(";", "naked function: no prologue.");
2851       return;
2852   }
2853   
2854   if (options.stack_probe) 
2855       emitcode ("lcall","__stack_probe");
2856   /* if critical function then turn interrupts off */
2857   if (IFFUNC_ISCRITICAL (ftype))
2858     emitcode ("clr", "ea");
2859
2860   /* here we need to generate the equates for the
2861      register bank if required */
2862   if (FUNC_REGBANK (ftype) != rbank)
2863     {
2864       int i;
2865
2866       rbank = FUNC_REGBANK (ftype);
2867       for (i = 0; i < ds390_nRegs; i++)
2868         {
2869           if (regs390[i].print) {
2870               if (strcmp (regs390[i].base, "0") == 0)
2871                   emitcode ("", "%s !equ !constbyte",
2872                             regs390[i].dname,
2873                             8 * rbank + regs390[i].offset);
2874               else
2875                   emitcode ("", "%s !equ %s + !constbyte",
2876                             regs390[i].dname,
2877                             regs390[i].base,
2878                             8 * rbank + regs390[i].offset);
2879           }
2880         }
2881     }
2882
2883   /* if this is an interrupt service routine then
2884      save acc, b, dpl, dph  */
2885   if (IFFUNC_ISISR (sym->type))
2886       { /* is ISR */
2887       if (!inExcludeList ("acc"))
2888         emitcode ("push", "acc");
2889       if (!inExcludeList ("b"))
2890         emitcode ("push", "b");
2891       if (!inExcludeList ("dpl"))
2892         emitcode ("push", "dpl");
2893       if (!inExcludeList ("dph"))
2894         emitcode ("push", "dph");
2895       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2896         {
2897           emitcode ("push", "dpx");
2898           /* Make sure we're using standard DPTR */
2899           emitcode ("push", "dps");
2900           emitcode ("mov", "dps,#0");
2901           if (options.stack10bit)
2902             {
2903               /* This ISR could conceivably use DPTR2. Better save it. */
2904               emitcode ("push", "dpl1");
2905               emitcode ("push", "dph1");
2906               emitcode ("push", "dpx1");
2907               emitcode ("push",  DP2_RESULT_REG);
2908             }
2909         }
2910       /* if this isr has no bank i.e. is going to
2911          run with bank 0 , then we need to save more
2912          registers :-) */
2913       if (!FUNC_REGBANK (sym->type))
2914         {
2915             int i;
2916
2917           /* if this function does not call any other
2918              function then we can be economical and
2919              save only those registers that are used */
2920           if (!IFFUNC_HASFCALL(sym->type))
2921             {
2922
2923               /* if any registers used */
2924               if (sym->regsUsed)
2925                 {
2926                   /* save the registers used */
2927                   for (i = 0; i < sym->regsUsed->size; i++)
2928                     {
2929                       if (bitVectBitValue (sym->regsUsed, i) ||
2930                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2931                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2932                     }
2933                 }
2934
2935             }
2936           else
2937             {
2938               /* this function has  a function call cannot
2939                  determines register usage so we will have to push the
2940                  entire bank */
2941               saveRBank (0, ic, FALSE);
2942               if (options.parms_in_bank1) {
2943                   for (i=0; i < 8 ; i++ ) {
2944                       emitcode ("push","%s",rb1regs[i]);
2945                   }
2946               }
2947             }
2948         }
2949         else
2950         {
2951             /* This ISR uses a non-zero bank.
2952              *
2953              * We assume that the bank is available for our
2954              * exclusive use.
2955              *
2956              * However, if this ISR calls a function which uses some
2957              * other bank, we must save that bank entirely.
2958              */
2959             unsigned long banksToSave = 0;
2960             
2961             if (IFFUNC_HASFCALL(sym->type))
2962             {
2963
2964 #define MAX_REGISTER_BANKS 4
2965
2966                 iCode *i;
2967                 int ix;
2968
2969                 for (i = ic; i; i = i->next)
2970                 {
2971                     if (i->op == ENDFUNCTION)
2972                     {
2973                         /* we got to the end OK. */
2974                         break;
2975                     }
2976                     
2977                     if (i->op == CALL)
2978                     {
2979                         sym_link *dtype;
2980                         
2981                         dtype = operandType (IC_LEFT(i));
2982                         if (dtype 
2983                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2984                         {
2985                              /* Mark this bank for saving. */
2986                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2987                              {
2988                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2989                              }
2990                              else
2991                              {
2992                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2993                              }
2994                              
2995                              /* And note that we don't need to do it in 
2996                               * genCall.
2997                               */
2998                              i->bankSaved = 1;
2999                         }
3000                     }
3001                     if (i->op == PCALL)
3002                     {
3003                         /* This is a mess; we have no idea what
3004                          * register bank the called function might
3005                          * use.
3006                          *
3007                          * The only thing I can think of to do is
3008                          * throw a warning and hope.
3009                          */
3010                         werror(W_FUNCPTR_IN_USING_ISR);   
3011                     }
3012                 }
3013
3014                 if (banksToSave && options.useXstack)
3015                 {
3016                     /* Since we aren't passing it an ic, 
3017                      * saveRBank will assume r0 is available to abuse.
3018                      *
3019                      * So switch to our (trashable) bank now, so
3020                      * the caller's R0 isn't trashed.
3021                      */
3022                     emitcode ("push", "psw");
3023                     emitcode ("mov", "psw,#!constbyte", 
3024                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3025                     switchedPSW = TRUE;
3026                 }
3027                 
3028                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3029                 {
3030                      if (banksToSave & (1 << ix))
3031                      {
3032                          saveRBank(ix, NULL, FALSE);
3033                      }
3034                 }
3035             }
3036             // jwk: this needs a closer look
3037             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3038         }
3039     }
3040   else
3041     {
3042       /* if callee-save to be used for this function
3043          then save the registers being used in this function */
3044       if (IFFUNC_CALLEESAVES(sym->type))
3045         {
3046           int i;
3047
3048           /* if any registers used */
3049           if (sym->regsUsed)
3050             {
3051               /* save the registers used */
3052               for (i = 0; i < sym->regsUsed->size; i++)
3053                 {
3054                   if (bitVectBitValue (sym->regsUsed, i) ||
3055                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3056                     {
3057                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3058                       _G.nRegsSaved++;
3059                     }
3060                 }
3061             }
3062         }
3063     }
3064
3065   /* set the register bank to the desired value */
3066   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3067    && !switchedPSW)
3068     {
3069       emitcode ("push", "psw");
3070       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3071     }
3072
3073   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3074        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3075       if (options.stack10bit) {
3076           emitcode ("push","_bpx");
3077           emitcode ("push","_bpx+1");
3078           emitcode ("mov","_bpx,%s",spname);
3079           emitcode ("mov","_bpx+1,esp");
3080           emitcode ("anl","_bpx+1,#3");
3081       } else {
3082           if (options.useXstack) {
3083               emitcode ("mov", "r0,%s", spname);
3084               emitcode ("mov", "a,_bp");
3085               emitcode ("movx", "@r0,a");
3086               emitcode ("inc", "%s", spname);
3087           } else {
3088               /* set up the stack */
3089               emitcode ("push", "_bp"); /* save the callers stack  */
3090           }
3091           emitcode ("mov", "_bp,%s", spname);
3092       }
3093   }
3094
3095   /* adjust the stack for the function */
3096   if (sym->stack) {
3097       int i = sym->stack;
3098       if (options.stack10bit) {
3099           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3100           assert (sym->recvSize <= 4);
3101           if (sym->stack <= 8) {
3102               while (i--) emitcode ("push","acc");
3103           } else {
3104               PROTECT_SP;
3105               emitcode ("mov","a,sp");
3106               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3107               emitcode ("mov","sp,a");
3108               emitcode ("mov","a,esp");
3109               emitcode ("anl","a,#3");
3110               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3111               emitcode ("mov","esp,a");
3112               UNPROTECT_SP;
3113           }
3114       } else {
3115           if (i > 256)
3116               werror (W_STACK_OVERFLOW, sym->name);
3117           
3118           if (i > 3 && sym->recvSize < 4) {
3119               
3120               emitcode ("mov", "a,sp");
3121               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3122               emitcode ("mov", "sp,a");
3123               
3124           } else
3125               while (i--)
3126                   emitcode ("inc", "sp");
3127       }
3128   }
3129
3130   if (sym->xstack)
3131     {
3132
3133       emitcode ("mov", "a,_spx");
3134       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3135       emitcode ("mov", "_spx,a");
3136     }
3137
3138 }
3139
3140 /*-----------------------------------------------------------------*/
3141 /* genEndFunction - generates epilogue for functions               */
3142 /*-----------------------------------------------------------------*/
3143 static void
3144 genEndFunction (iCode * ic)
3145 {
3146   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3147
3148   D (emitcode (";", "genEndFunction "););
3149
3150   if (IFFUNC_ISNAKED(sym->type))
3151   {
3152       emitcode(";", "naked function: no epilogue.");
3153       return;
3154   }
3155
3156   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3157        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3158
3159       if (options.stack10bit) {
3160           PROTECT_SP;     
3161           emitcode ("mov", "sp,_bpx", spname);
3162           emitcode ("mov", "esp,_bpx+1", spname);
3163           UNPROTECT_SP;
3164       } else {
3165           emitcode ("mov", "%s,_bp", spname);
3166       }
3167   }
3168
3169   /* if use external stack but some variables were
3170      added to the local stack then decrement the
3171      local stack */
3172   if (options.useXstack && sym->stack) {
3173       emitcode ("mov", "a,sp");
3174       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3175       emitcode ("mov", "sp,a");
3176   }
3177
3178
3179   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3180        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3181
3182       if (options.useXstack) {
3183           emitcode ("mov", "r0,%s", spname);
3184           emitcode ("movx", "a,@r0");
3185           emitcode ("mov", "_bp,a");
3186           emitcode ("dec", "%s", spname);
3187       } else {
3188           if (options.stack10bit) {
3189               emitcode ("pop", "_bpx+1");
3190               emitcode ("pop", "_bpx");
3191           } else {
3192               emitcode ("pop", "_bp");
3193           }
3194       }
3195   }
3196
3197   /* restore the register bank  */
3198   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3199   {
3200     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3201      || !options.useXstack)
3202     {
3203         /* Special case of ISR using non-zero bank with useXstack
3204          * is handled below.
3205          */
3206         emitcode ("pop", "psw");
3207     }
3208   } 
3209
3210   if (IFFUNC_ISISR (sym->type))
3211       { /* is ISR */  
3212
3213       /* now we need to restore the registers */
3214       /* if this isr has no bank i.e. is going to
3215          run with bank 0 , then we need to save more
3216          registers :-) */
3217       if (!FUNC_REGBANK (sym->type))
3218         {
3219             int i;
3220           /* if this function does not call any other
3221              function then we can be economical and
3222              save only those registers that are used */
3223           if (!IFFUNC_HASFCALL(sym->type))
3224             {
3225
3226               /* if any registers used */
3227               if (sym->regsUsed)
3228                 {
3229                   /* save the registers used */
3230                   for (i = sym->regsUsed->size; i >= 0; i--)
3231                     {
3232                       if (bitVectBitValue (sym->regsUsed, i) ||
3233                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3234                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3235                     }
3236                 }
3237
3238             }
3239           else
3240             {
3241               /* this function has  a function call cannot
3242                  determines register usage so we will have to pop the
3243                  entire bank */
3244               if (options.parms_in_bank1) {
3245                   for (i = 7 ; i >= 0 ; i-- ) {
3246                       emitcode ("pop","%s",rb1regs[i]);
3247                   }
3248               }
3249               unsaveRBank (0, ic, FALSE);
3250             }
3251         }
3252         else
3253         {
3254             /* This ISR uses a non-zero bank.
3255              *
3256              * Restore any register banks saved by genFunction
3257              * in reverse order.
3258              */
3259           // jwk: this needs a closer look
3260             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3261             int ix;
3262           
3263             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3264             {
3265                 if (savedBanks & (1 << ix))
3266                 {
3267                     unsaveRBank(ix, NULL, FALSE);
3268                 }
3269             }
3270             
3271             if (options.useXstack)
3272             {
3273                 /* Restore bank AFTER calling unsaveRBank,
3274                  * since it can trash r0.
3275                  */
3276                 emitcode ("pop", "psw");
3277             }
3278         }
3279
3280       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3281         {
3282           if (options.stack10bit)
3283             {
3284               emitcode ("pop", DP2_RESULT_REG);
3285               emitcode ("pop", "dpx1");
3286               emitcode ("pop", "dph1");
3287               emitcode ("pop", "dpl1");
3288             }
3289           emitcode ("pop", "dps");
3290           emitcode ("pop", "dpx");
3291         }
3292       if (!inExcludeList ("dph"))
3293         emitcode ("pop", "dph");
3294       if (!inExcludeList ("dpl"))
3295         emitcode ("pop", "dpl");
3296       if (!inExcludeList ("b"))
3297         emitcode ("pop", "b");
3298       if (!inExcludeList ("acc"))
3299         emitcode ("pop", "acc");
3300
3301       if (IFFUNC_ISCRITICAL (sym->type))
3302         emitcode ("setb", "ea");
3303
3304       /* if debug then send end of function */
3305       if (options.debug && currFunc) {
3306           _G.debugLine = 1;
3307           emitcode ("", "C$%s$%d$%d$%d ==.",
3308                     FileBaseName (ic->filename), currFunc->lastLine,
3309                     ic->level, ic->block);
3310           if (IS_STATIC (currFunc->etype))
3311             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3312           else
3313             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3314           _G.debugLine = 0;
3315         }
3316
3317       emitcode ("reti", "");
3318     }
3319   else
3320     {
3321       if (IFFUNC_ISCRITICAL (sym->type))
3322         emitcode ("setb", "ea");
3323
3324       if (IFFUNC_CALLEESAVES(sym->type))
3325         {
3326           int i;
3327
3328           /* if any registers used */
3329           if (sym->regsUsed)
3330             {
3331               /* save the registers used */
3332               for (i = sym->regsUsed->size; i >= 0; i--)
3333                 {
3334                   if (bitVectBitValue (sym->regsUsed, i) ||
3335                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3336                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3337                 }
3338             }
3339
3340         }
3341
3342       /* if debug then send end of function */
3343       if (options.debug && currFunc)
3344         {
3345           _G.debugLine = 1;
3346           emitcode ("", "C$%s$%d$%d$%d ==.",
3347                     FileBaseName (ic->filename), currFunc->lastLine,
3348                     ic->level, ic->block);
3349           if (IS_STATIC (currFunc->etype))
3350             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3351           else
3352             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3353           _G.debugLine = 0;
3354         }
3355
3356       emitcode ("ret", "");
3357     }
3358
3359 }
3360
3361 /*-----------------------------------------------------------------*/
3362 /* genJavaNativeRet - generate code for return JavaNative          */
3363 /*-----------------------------------------------------------------*/
3364 static void genJavaNativeRet(iCode *ic)
3365 {
3366     int i, size;
3367
3368     aopOp (IC_LEFT (ic), ic, FALSE, 
3369            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3370     size = AOP_SIZE (IC_LEFT (ic));
3371
3372     assert (size <= 4);
3373
3374     /* it is assigned to GPR0-R3 then push them */
3375     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3376         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3377         for (i = 0 ; i < size ; i++ ) {
3378             emitcode ("push","%s",
3379                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3380         }
3381         for (i = (size-1) ; i >= 0 ; i--) {
3382             emitcode ("pop","a%s",javaRet[i]);
3383         }
3384     } else {
3385         for (i = 0 ; i < size ; i++) 
3386             emitcode ("mov","%s,%s",javaRet[i],
3387                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3388     }
3389     for (i = size ; i < 4 ; i++ )
3390             emitcode ("mov","%s,#0",javaRet[i]);
3391     return;
3392 }
3393
3394 /*-----------------------------------------------------------------*/
3395 /* genRet - generate code for return statement                     */
3396 /*-----------------------------------------------------------------*/
3397 static void
3398 genRet (iCode * ic)
3399 {
3400   int size, offset = 0, pushed = 0;
3401
3402   D (emitcode (";", "genRet "););
3403
3404   /* if we have no return value then
3405      just generate the "ret" */
3406   if (!IC_LEFT (ic))
3407     goto jumpret;
3408
3409   /* if this is a JavaNative function then return 
3410      value in different register */
3411   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3412       genJavaNativeRet(ic);
3413       goto jumpret;
3414   }
3415   /* we have something to return then
3416      move the return value into place */
3417   aopOp (IC_LEFT (ic), ic, FALSE, 
3418          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3419   size = AOP_SIZE (IC_LEFT (ic));
3420
3421   _startLazyDPSEvaluation ();
3422   while (size--)
3423     {
3424       char *l;
3425       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3426         {
3427           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3428                       FALSE, TRUE, NULL);
3429           emitcode ("push", "%s", l);
3430           pushed++;
3431         }
3432       else
3433         {
3434           /* Since A is the last element of fReturn,
3435            * is is OK to clobber it in the aopGet.
3436            */
3437           l = aopGet (AOP (IC_LEFT (ic)), offset,
3438                       FALSE, FALSE, NULL);
3439           if (strcmp (fReturn[offset], l))
3440             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3441         }
3442     }
3443   _endLazyDPSEvaluation ();
3444
3445   if (pushed)
3446     {
3447       while (pushed)
3448         {
3449           pushed--;
3450           if (strcmp (fReturn[pushed], "a"))
3451             emitcode ("pop", fReturn[pushed]);
3452           else
3453             emitcode ("pop", "acc");
3454         }
3455     }
3456   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3457
3458 jumpret:
3459   /* generate a jump to the return label
3460      if the next is not the return statement */
3461   if (!(ic->next && ic->next->op == LABEL &&
3462         IC_LABEL (ic->next) == returnLabel))
3463
3464     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3465
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genLabel - generates a label                                    */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 genLabel (iCode * ic)
3473 {
3474   /* special case never generate */
3475   if (IC_LABEL (ic) == entryLabel)
3476     return;
3477
3478   D (emitcode (";", "genLabel ");
3479     );
3480
3481   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3482 }
3483
3484 /*-----------------------------------------------------------------*/
3485 /* genGoto - generates a ljmp                                      */
3486 /*-----------------------------------------------------------------*/
3487 static void
3488 genGoto (iCode * ic)
3489 {
3490   D (emitcode (";", "genGoto ");
3491     );
3492   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3493 }
3494
3495 /*-----------------------------------------------------------------*/
3496 /* findLabelBackwards: walks back through the iCode chain looking  */
3497 /* for the given label. Returns number of iCode instructions     */
3498 /* between that label and given ic.          */
3499 /* Returns zero if label not found.          */
3500 /*-----------------------------------------------------------------*/
3501 static int
3502 findLabelBackwards (iCode * ic, int key)
3503 {
3504   int count = 0;
3505
3506   while (ic->prev)
3507     {
3508       ic = ic->prev;
3509       count++;
3510
3511       /* If we have any pushes or pops, we cannot predict the distance.
3512          I don't like this at all, this should be dealt with in the 
3513          back-end */
3514       if (ic->op == IPUSH || ic->op == IPOP) {
3515         return 0;
3516       }
3517
3518       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3519         {
3520           /* printf("findLabelBackwards = %d\n", count); */
3521           return count;
3522         }
3523     }
3524
3525   return 0;
3526 }
3527
3528 /*-----------------------------------------------------------------*/
3529 /* genPlusIncr :- does addition with increment if possible         */
3530 /*-----------------------------------------------------------------*/
3531 static bool
3532 genPlusIncr (iCode * ic)
3533 {
3534   unsigned int icount;
3535   unsigned int size = getDataSize (IC_RESULT (ic));
3536
3537   /* will try to generate an increment */
3538   /* if the right side is not a literal
3539      we cannot */
3540   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3541     return FALSE;
3542
3543   /* if the literal value of the right hand side
3544      is greater than 4 then it is not worth it */
3545   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3546     return FALSE;
3547
3548   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3549       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3550       while (icount--) {
3551           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3552       }
3553       return TRUE;
3554   }
3555   /* if increment 16 bits in register */
3556   if (
3557        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3558        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3559        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3560        (size > 1) &&
3561        (icount == 1))
3562     {
3563       symbol  *tlbl;
3564       int     emitTlbl;
3565       int     labelRange;
3566       char    *l;
3567
3568       /* If the next instruction is a goto and the goto target
3569        * is <= 5 instructions previous to this, we can generate
3570        * jumps straight to that target.
3571        */
3572       if (ic->next && ic->next->op == GOTO
3573           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3574           && labelRange <= 5)
3575         {
3576           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3577           tlbl = IC_LABEL (ic->next);
3578           emitTlbl = 0;
3579         }
3580       else
3581         {
3582           tlbl = newiTempLabel (NULL);
3583           emitTlbl = 1;
3584         }
3585         
3586       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3587       emitcode ("inc", "%s", l);
3588       
3589       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3590           IS_AOP_PREG (IC_RESULT (ic)))
3591       {   
3592         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3593       }
3594       else
3595       {
3596           emitcode ("clr", "a");
3597           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3598       }
3599
3600       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3601       emitcode ("inc", "%s", l);
3602       if (size > 2)
3603         {
3604             if (!strcmp(l, "acc"))
3605             {
3606                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3607             }
3608             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3609                      IS_AOP_PREG (IC_RESULT (ic)))
3610             {
3611                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3612             }
3613             else
3614             {
3615                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3616             }
3617
3618             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3619             emitcode ("inc", "%s", l);
3620         }
3621       if (size > 3)
3622         {
3623             if (!strcmp(l, "acc"))
3624             {
3625                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3626             }
3627             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3628                      IS_AOP_PREG (IC_RESULT (ic)))
3629             {
3630                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3631             }
3632             else
3633             {
3634                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3635             }
3636
3637             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3638             emitcode ("inc", "%s", l);  }
3639
3640       if (emitTlbl)
3641         {
3642           emitcode ("", "!tlabeldef", tlbl->key + 100);
3643         }
3644       return TRUE;
3645     }
3646
3647   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3648       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3649       options.model == MODEL_FLAT24 ) {
3650
3651       switch (size) {
3652       case 3:
3653           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3654       case 2:
3655           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3656       case 1:
3657           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3658           break;
3659       }
3660       while (icount--) emitcode ("inc","dptr");      
3661       return TRUE;
3662   }
3663
3664   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3665       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3666       icount <= 5 ) {
3667       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3668       while (icount--) emitcode ("inc","dptr");
3669       emitcode ("mov","dps,#0");
3670       return TRUE;
3671   }
3672
3673   /* if the sizes are greater than 1 then we cannot */
3674   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3675       AOP_SIZE (IC_LEFT (ic)) > 1)
3676     return FALSE;
3677
3678   /* we can if the aops of the left & result match or
3679      if they are in registers and the registers are the
3680      same */
3681   if (
3682        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3683        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3684        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3685     {
3686
3687       if (icount > 3)
3688         {
3689           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3690           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3691           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3692         }
3693       else
3694         {
3695
3696           _startLazyDPSEvaluation ();
3697           while (icount--)
3698             {
3699               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3700             }
3701           _endLazyDPSEvaluation ();
3702         }
3703
3704       return TRUE;
3705     }
3706
3707   return FALSE;
3708 }
3709
3710 /*-----------------------------------------------------------------*/
3711 /* outBitAcc - output a bit in acc                                 */
3712 /*-----------------------------------------------------------------*/
3713 static void
3714 outBitAcc (operand * result)
3715 {
3716   symbol *tlbl = newiTempLabel (NULL);
3717   /* if the result is a bit */
3718   if (AOP_TYPE (result) == AOP_CRY)
3719     {
3720       aopPut (AOP (result), "a", 0);
3721     }
3722   else
3723     {
3724       emitcode ("jz", "!tlabel", tlbl->key + 100);
3725       emitcode ("mov", "a,%s", one);
3726       emitcode ("", "!tlabeldef", tlbl->key + 100);
3727       outAcc (result);
3728     }
3729 }
3730
3731 /*-----------------------------------------------------------------*/
3732 /* genPlusBits - generates code for addition of two bits           */
3733 /*-----------------------------------------------------------------*/
3734 static void
3735 genPlusBits (iCode * ic)
3736 {
3737   D (emitcode (";", "genPlusBits "););
3738     
3739   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3740     {
3741       symbol *lbl = newiTempLabel (NULL);
3742       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3743       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3744       emitcode ("cpl", "c");
3745       emitcode ("", "!tlabeldef", (lbl->key + 100));
3746       outBitC (IC_RESULT (ic));
3747     }
3748   else
3749     {
3750       emitcode ("clr", "a");
3751       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3752       emitcode ("rlc", "a");
3753       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3754       emitcode ("addc", "a,#0");
3755       outAcc (IC_RESULT (ic));
3756     }
3757 }
3758
3759 static void
3760 adjustArithmeticResult (iCode * ic)
3761 {
3762   if (opIsGptr (IC_RESULT (ic)) &&
3763       opIsGptr (IC_LEFT (ic)) &&
3764       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3765     {
3766       aopPut (AOP (IC_RESULT (ic)),
3767               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3768               GPTRSIZE - 1);
3769     }
3770
3771   if (opIsGptr (IC_RESULT (ic)) &&
3772       opIsGptr (IC_RIGHT (ic)) &&
3773       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3774     {
3775       aopPut (AOP (IC_RESULT (ic)),
3776             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3777               GPTRSIZE - 1);
3778     }
3779
3780   if (opIsGptr (IC_RESULT (ic)) &&
3781       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3782       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3783       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3784       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3785     {
3786       char buff[5];
3787       SNPRINTF (buff, sizeof(buff), 
3788                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3789       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3790     }
3791 }
3792
3793 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3794 // generates the result if possible. If result is generated, returns TRUE; otherwise
3795 // returns false and caller must deal with fact that result isn't aopOp'd.
3796 bool aopOp3(iCode * ic)
3797 {
3798     bool dp1InUse, dp2InUse;
3799     bool useDp2;
3800     
3801     // First, generate the right opcode. DPTR may be used if neither left nor result are
3802     // of type AOP_STR.
3803     
3804 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3805 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3806 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3807 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3808 //      );
3809 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3810 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3811 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3812 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3813 //      );      
3814
3815     
3816     // Right uses DPTR unless left or result is an AOP_STR.
3817     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3818     
3819     // if the right used DPTR, left MUST use DPTR2.
3820     // if the right used DPTR2, left MUST use DPTR.
3821     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3822     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3823     // enabling us to assign DPTR to result.
3824      
3825     if (AOP_USESDPTR(IC_RIGHT(ic)))
3826     {
3827         useDp2 = TRUE;
3828     }
3829     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3830     {
3831         useDp2 = FALSE;
3832     }
3833     else
3834     {
3835         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3836         {
3837             useDp2 = TRUE;
3838         }
3839         else
3840         {
3841             useDp2 = FALSE;
3842         }
3843     }
3844
3845     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3846     
3847     // We've op'd the left & right. So, if left or right are the same operand as result, 
3848     // we know aopOp will succeed, and we can just do it & bail.
3849     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3850         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3851     {
3852 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3853         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3854         return TRUE;
3855     }
3856     
3857     // Note which dptrs are currently in use.
3858     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3859     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3860     
3861     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3862     // generate it.
3863     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3864     {
3865         return FALSE;
3866     }
3867     
3868     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3869     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3870     {
3871         return FALSE;
3872     }
3873     
3874     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3875     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3876     {
3877         return FALSE;
3878     }
3879
3880     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3881
3882     // Some sanity checking...
3883     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3884     {
3885         fprintf(stderr,
3886                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3887                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3888         emitcode(";", ">>> unexpected DPTR here.");
3889     }
3890     
3891     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3892     {
3893         fprintf(stderr,
3894                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3895                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3896         emitcode(";", ">>> unexpected DPTR2 here.");
3897     }    
3898     
3899     return TRUE;
3900 }
3901
3902 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3903 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3904 // will be set TRUE. The caller must then handle the case specially, noting
3905 // that the IC_RESULT operand is not aopOp'd.
3906 // 
3907 #define AOP_OP_3_NOFATAL(ic, rc) \
3908             do { rc = !aopOp3(ic); } while (0)
3909
3910 // aopOp the left & right operands of an ic.
3911 #define AOP_OP_2(ic) \
3912     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3913     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3914
3915 // convienience macro.
3916 #define AOP_SET_LOCALS(ic) \
3917     left = IC_LEFT(ic); \
3918     right = IC_RIGHT(ic); \
3919     result = IC_RESULT(ic);
3920
3921
3922 // Given an integer value of pushedSize bytes on the stack,
3923 // adjust it to be resultSize bytes, either by discarding
3924 // the most significant bytes or by zero-padding.
3925 //
3926 // On exit from this macro, pushedSize will have been adjusted to
3927 // equal resultSize, and ACC may be trashed.
3928 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3929       /* If the pushed data is bigger than the result,          \
3930        * simply discard unused bytes. Icky, but works.          \
3931        */                                                       \
3932       while (pushedSize > resultSize)                           \
3933       {                                                         \
3934           D (emitcode (";", "discarding unused result byte."););\
3935           emitcode ("pop", "acc");                              \
3936           pushedSize--;                                         \
3937       }                                                         \
3938       if (pushedSize < resultSize)                              \
3939       {                                                         \
3940           emitcode ("clr", "a");                                \
3941           /* Conversly, we haven't pushed enough here.          \
3942            * just zero-pad, and all is well.                    \
3943            */                                                   \
3944           while (pushedSize < resultSize)                       \
3945           {                                                     \
3946               emitcode("push", "acc");                          \
3947               pushedSize++;                                     \
3948           }                                                     \
3949       }                                                         \
3950       assert(pushedSize == resultSize);
3951
3952 /*-----------------------------------------------------------------*/
3953 /* genPlus - generates code for addition                           */
3954 /*-----------------------------------------------------------------*/
3955 static void
3956 genPlus (iCode * ic)
3957 {
3958   int size, offset = 0;
3959   bool pushResult;
3960   int rSize;
3961
3962   D (emitcode (";", "genPlus "););
3963
3964   /* special cases :- */
3965   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3966       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3967       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3968       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3969       if (size <= 9) {
3970           while (size--) emitcode ("inc","dptr");
3971       } else {
3972           emitcode ("mov","a,dpl");
3973           emitcode ("add","a,#!constbyte",size & 0xff);
3974           emitcode ("mov","dpl,a");
3975           emitcode ("mov","a,dph");
3976           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3977           emitcode ("mov","dph,a");
3978           emitcode ("mov","a,dpx");
3979           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3980           emitcode ("mov","dpx,a");
3981       }
3982       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3983       return ;
3984   }
3985   if ( IS_SYMOP(IC_LEFT(ic)) && 
3986        OP_SYMBOL(IC_LEFT(ic))->remat &&
3987        isOperandInFarSpace(IC_RIGHT(ic))) {
3988       operand *op = IC_RIGHT(ic);
3989       IC_RIGHT(ic) = IC_LEFT(ic);
3990       IC_LEFT(ic) = op;
3991   }
3992                 
3993   AOP_OP_3_NOFATAL (ic, pushResult);
3994     
3995   if (pushResult)
3996     {
3997       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3998     }
3999
4000   if (!pushResult)
4001     {
4002       /* if literal, literal on the right or
4003          if left requires ACC or right is already
4004          in ACC */
4005       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4006        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4007           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4008         {
4009           operand *t = IC_RIGHT (ic);
4010           IC_RIGHT (ic) = IC_LEFT (ic);
4011           IC_LEFT (ic) = t;
4012           emitcode (";", "Swapped plus args.");
4013         }
4014
4015       /* if both left & right are in bit
4016          space */
4017       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4018           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4019         {
4020           genPlusBits (ic);
4021           goto release;
4022         }
4023
4024       /* if left in bit space & right literal */
4025       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4026           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4027         {
4028           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4029           /* if result in bit space */
4030           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4031             {
4032               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4033                 emitcode ("cpl", "c");
4034               outBitC (IC_RESULT (ic));
4035             }
4036           else
4037             {
4038               size = getDataSize (IC_RESULT (ic));
4039               _startLazyDPSEvaluation ();
4040               while (size--)
4041                 {
4042                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4043                   emitcode ("addc", "a,#0");
4044                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4045                 }
4046               _endLazyDPSEvaluation ();
4047             }
4048           goto release;
4049         }
4050
4051       /* if I can do an increment instead
4052          of add then GOOD for ME */
4053       if (genPlusIncr (ic) == TRUE)
4054         {
4055           emitcode (";", "did genPlusIncr");
4056           goto release;
4057         }
4058
4059     }
4060   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4061
4062   _startLazyDPSEvaluation ();
4063   while (size--)
4064     {
4065       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4066         {
4067           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4068           if (offset == 0)
4069             emitcode ("add", "a,%s",
4070                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4071           else
4072             emitcode ("addc", "a,%s",
4073                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4074         }
4075       else
4076         {
4077           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4078           {
4079               /* right is going to use ACC or we would have taken the
4080                * above branch.
4081                */
4082               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4083        TR_AP("#3");
4084               D(emitcode(";", "+ AOP_ACC special case."););
4085               emitcode("xch", "a, %s", DP2_RESULT_REG);
4086           }
4087           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4088           if (offset == 0)
4089           {
4090             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4091             {
4092          TR_AP("#4");
4093                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4094             }
4095             else
4096             {
4097                 emitcode ("add", "a,%s",
4098                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4099                                   DP2_RESULT_REG));
4100             }
4101           }
4102           else
4103           {
4104             emitcode ("addc", "a,%s",
4105                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4106                           DP2_RESULT_REG));
4107           }
4108         }
4109       if (!pushResult)
4110         {
4111           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4112         }
4113       else
4114         {
4115           emitcode ("push", "acc");
4116         }
4117       offset++;
4118     }
4119   _endLazyDPSEvaluation ();
4120
4121   if (pushResult)
4122     {
4123       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4124
4125       size = getDataSize (IC_LEFT (ic));
4126       rSize = getDataSize (IC_RESULT (ic));
4127
4128       ADJUST_PUSHED_RESULT(size, rSize);
4129
4130       _startLazyDPSEvaluation ();
4131       while (size--)
4132         {
4133           emitcode ("pop", "acc");
4134           aopPut (AOP (IC_RESULT (ic)), "a", size);
4135         }
4136       _endLazyDPSEvaluation ();
4137     }
4138
4139   adjustArithmeticResult (ic);
4140
4141 release:
4142   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4143   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* genMinusDec :- does subtraction with deccrement if possible     */
4149 /*-----------------------------------------------------------------*/
4150 static bool
4151 genMinusDec (iCode * ic)
4152 {
4153   unsigned int icount;
4154   unsigned int size = getDataSize (IC_RESULT (ic));
4155
4156   /* will try to generate an increment */
4157   /* if the right side is not a literal
4158      we cannot */
4159   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4160     return FALSE;
4161
4162   /* if the literal value of the right hand side
4163      is greater than 4 then it is not worth it */
4164   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4165     return FALSE;
4166
4167   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4168       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4169       while (icount--) {
4170           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4171       }
4172       return TRUE;
4173   }
4174   /* if decrement 16 bits in register */
4175   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4176       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4177       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4178       (size > 1) &&
4179       (icount == 1))
4180     {
4181       symbol *tlbl;
4182       int    emitTlbl;
4183       int    labelRange;
4184       char   *l;
4185
4186       /* If the next instruction is a goto and the goto target
4187          * is <= 5 instructions previous to this, we can generate
4188          * jumps straight to that target.
4189        */
4190       if (ic->next && ic->next->op == GOTO
4191           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4192           && labelRange <= 5)
4193         {
4194           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4195           tlbl = IC_LABEL (ic->next);
4196           emitTlbl = 0;
4197         }
4198       else
4199         {
4200           tlbl = newiTempLabel (NULL);
4201           emitTlbl = 1;
4202         }
4203
4204       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4205       emitcode ("dec", "%s", l);
4206  
4207       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4209           IS_AOP_PREG (IC_RESULT (ic)))
4210       {     
4211           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4212       }
4213       else
4214       {
4215           emitcode ("mov", "a,#!constbyte",0xff);
4216           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4217       }
4218       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4219       emitcode ("dec", "%s", l);
4220       if (size > 2)
4221         {
4222             if (!strcmp(l, "acc"))
4223             {
4224                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4225             }
4226             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4227                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4228                      IS_AOP_PREG (IC_RESULT (ic)))
4229             {       
4230                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4231             }
4232             else
4233             {
4234                 emitcode ("mov", "a,#!constbyte",0xff);
4235                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4236             }
4237             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4238             emitcode ("dec", "%s", l);
4239         }
4240       if (size > 3)
4241         {
4242             if (!strcmp(l, "acc"))
4243             {
4244                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4245             }
4246             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4247                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4248                      IS_AOP_PREG (IC_RESULT (ic)))
4249             {       
4250                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4251             }
4252             else
4253             {
4254                 emitcode ("mov", "a,#!constbyte",0xff);
4255                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4256             }       
4257             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4258             emitcode ("dec", "%s", l);
4259         }
4260       if (emitTlbl)
4261         {
4262           emitcode ("", "!tlabeldef", tlbl->key + 100);
4263         }
4264       return TRUE;
4265     }
4266
4267   /* if the sizes are greater than 1 then we cannot */
4268   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4269       AOP_SIZE (IC_LEFT (ic)) > 1)
4270     return FALSE;
4271
4272   /* we can if the aops of the left & result match or
4273      if they are in registers and the registers are the
4274      same */
4275   if (
4276        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4277        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4278        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4279     {
4280
4281       _startLazyDPSEvaluation ();
4282       while (icount--)
4283         {
4284           emitcode ("dec", "%s",
4285                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4286         }
4287       _endLazyDPSEvaluation ();
4288
4289       return TRUE;
4290     }
4291
4292   return FALSE;
4293 }
4294
4295 /*-----------------------------------------------------------------*/
4296 /* addSign - complete with sign                                    */
4297 /*-----------------------------------------------------------------*/
4298 static void
4299 addSign (operand * result, int offset, int sign)
4300 {
4301   int size = (getDataSize (result) - offset);
4302   if (size > 0)
4303     {
4304       _startLazyDPSEvaluation();
4305       if (sign)
4306         {
4307           emitcode ("rlc", "a");
4308           emitcode ("subb", "a,acc");
4309           while (size--)
4310           {
4311             aopPut (AOP (result), "a", offset++);
4312           }
4313         }
4314       else
4315       {
4316         while (size--)
4317         {
4318           aopPut (AOP (result), zero, offset++);
4319         }
4320       }
4321       _endLazyDPSEvaluation();
4322     }
4323 }
4324
4325 /*-----------------------------------------------------------------*/
4326 /* genMinusBits - generates code for subtraction  of two bits      */
4327 /*-----------------------------------------------------------------*/
4328 static void
4329 genMinusBits (iCode * ic)
4330 {
4331   symbol *lbl = newiTempLabel (NULL);
4332
4333   D (emitcode (";", "genMinusBits "););
4334
4335   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4336     {
4337       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4338       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4339       emitcode ("cpl", "c");
4340       emitcode ("", "!tlabeldef", (lbl->key + 100));
4341       outBitC (IC_RESULT (ic));
4342     }
4343   else
4344     {
4345       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4346       emitcode ("subb", "a,acc");
4347       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4348       emitcode ("inc", "a");
4349       emitcode ("", "!tlabeldef", (lbl->key + 100));
4350       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4351       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4352     }
4353 }
4354
4355 /*-----------------------------------------------------------------*/
4356 /* genMinus - generates code for subtraction                       */
4357 /*-----------------------------------------------------------------*/
4358 static void
4359 genMinus (iCode * ic)
4360 {
4361     int size, offset = 0;
4362     int rSize;
4363     long lit = 0L;
4364     bool pushResult;
4365
4366     D (emitcode (";", "genMinus "););
4367
4368     AOP_OP_3_NOFATAL(ic, pushResult);   
4369
4370     if (!pushResult)
4371     {
4372       /* special cases :- */
4373       /* if both left & right are in bit space */
4374       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4375           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4376         {
4377           genMinusBits (ic);
4378           goto release;
4379         }
4380
4381       /* if I can do an decrement instead
4382          of subtract then GOOD for ME */
4383       if (genMinusDec (ic) == TRUE)
4384         goto release;
4385
4386     }
4387
4388   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4389
4390   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4391     {
4392       CLRC;
4393     }
4394   else
4395     {
4396       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4397       lit = -lit;
4398     }
4399
4400
4401   /* if literal, add a,#-lit, else normal subb */
4402   _startLazyDPSEvaluation ();
4403   while (size--) {
4404       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4405           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4406               emitcode ("mov","b,%s",
4407                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4408               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4409               emitcode ("subb","a,b");
4410           } else {
4411               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4412               emitcode ("subb", "a,%s",
4413                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4414                                 DP2_RESULT_REG));
4415           }
4416       } else {
4417           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4418           /* first add without previous c */
4419           if (!offset) {
4420               if (!size && lit==-1) {
4421                   emitcode ("dec", "a");
4422               } else {
4423                   emitcode ("add", "a,#!constbyte",
4424                             (unsigned int) (lit & 0x0FFL));
4425               }
4426           } else {
4427               emitcode ("addc", "a,#!constbyte",
4428                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4429           }
4430       }
4431       
4432       if (pushResult) {
4433           emitcode ("push", "acc");
4434       } else {
4435           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4436       }
4437       offset++;
4438   }
4439   _endLazyDPSEvaluation ();
4440   
4441   if (pushResult)
4442     {
4443       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4444
4445       size = getDataSize (IC_LEFT (ic));
4446       rSize = getDataSize (IC_RESULT (ic));
4447
4448       ADJUST_PUSHED_RESULT(size, rSize);
4449
4450       _startLazyDPSEvaluation ();
4451       while (size--)
4452         {
4453           emitcode ("pop", "acc");
4454           aopPut (AOP (IC_RESULT (ic)), "a", size);
4455         }
4456       _endLazyDPSEvaluation ();
4457     }
4458
4459   adjustArithmeticResult (ic);
4460
4461 release:
4462   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4463   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4464   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4465 }
4466
4467
4468 /*-----------------------------------------------------------------*/
4469 /* genMultbits :- multiplication of bits                           */
4470 /*-----------------------------------------------------------------*/
4471 static void
4472 genMultbits (operand * left,
4473              operand * right,
4474              operand * result,
4475              iCode   * ic)
4476 {
4477   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4478   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4479   aopOp(result, ic, TRUE, FALSE);
4480   outBitC (result);
4481 }
4482
4483
4484 /*-----------------------------------------------------------------*/
4485 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4486 /*-----------------------------------------------------------------*/
4487 static void
4488 genMultOneByte (operand * left,
4489                 operand * right,
4490                 operand * result,
4491                 iCode   * ic)
4492 {
4493   sym_link *opetype = operandType (result);
4494   symbol *lbl;
4495
4496
4497   /* (if two literals: the value is computed before) */
4498   /* if one literal, literal on the right */
4499   if (AOP_TYPE (left) == AOP_LIT)
4500     {
4501       operand *t = right;
4502       right = left;
4503       left = t;
4504       emitcode (";", "swapped left and right");
4505     }
4506
4507   if (SPEC_USIGN(opetype)
4508       // ignore the sign of left and right, what else can we do?
4509       || (SPEC_USIGN(operandType(left)) && 
4510           SPEC_USIGN(operandType(right)))) {
4511     // just an unsigned 8*8=8/16 multiply
4512     //emitcode (";","unsigned");
4513     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4514     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4515     emitcode ("mul", "ab");
4516    
4517     _G.accInUse++; _G.bInUse++;
4518     aopOp(result, ic, TRUE, FALSE);
4519       
4520       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4521       {
4522           // this should never happen
4523           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4524                    AOP_SIZE(result), __FILE__, lineno);
4525           exit (1);
4526       }      
4527       
4528     aopPut (AOP (result), "a", 0);
4529     _G.accInUse--; _G.bInUse--;
4530     if (AOP_SIZE(result)==2) 
4531     {
4532       aopPut (AOP (result), "b", 1);
4533     }
4534     return;
4535   }
4536
4537   // we have to do a signed multiply
4538
4539   emitcode (";", "signed");
4540   emitcode ("clr", "F0"); // reset sign flag
4541   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4542
4543   lbl=newiTempLabel(NULL);
4544   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4545   // left side is negative, 8-bit two's complement, this fails for -128
4546   emitcode ("setb", "F0"); // set sign flag
4547   emitcode ("cpl", "a");
4548   emitcode ("inc", "a");
4549
4550   emitcode ("", "!tlabeldef", lbl->key+100);
4551
4552   /* if literal */
4553   if (AOP_TYPE(right)==AOP_LIT) {
4554     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4555     /* AND literal negative */
4556     if ((int) val < 0) {
4557       emitcode ("cpl", "F0"); // complement sign flag
4558       emitcode ("mov", "b,#!constbyte", -val);
4559     } else {
4560       emitcode ("mov", "b,#!constbyte", val);
4561     }
4562   } else {
4563     lbl=newiTempLabel(NULL);
4564     emitcode ("mov", "b,a");
4565     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4566     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4567     // right side is negative, 8-bit two's complement
4568     emitcode ("cpl", "F0"); // complement sign flag
4569     emitcode ("cpl", "a");
4570     emitcode ("inc", "a");
4571     emitcode ("", "!tlabeldef", lbl->key+100);
4572   }
4573   emitcode ("mul", "ab");
4574     
4575   _G.accInUse++;_G.bInUse++;
4576   aopOp(result, ic, TRUE, FALSE);
4577     
4578   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4579   {
4580     // this should never happen
4581       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4582                AOP_SIZE(result), __FILE__, lineno);
4583       exit (1);
4584   }    
4585     
4586   lbl=newiTempLabel(NULL);
4587   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4588   // only ONE op was negative, we have to do a 8/16-bit two's complement
4589   emitcode ("cpl", "a"); // lsb
4590   if (AOP_SIZE(result)==1) {
4591     emitcode ("inc", "a");
4592   } else {
4593     emitcode ("add", "a,#1");
4594     emitcode ("xch", "a,b");
4595     emitcode ("cpl", "a"); // msb
4596     emitcode ("addc", "a,#0");
4597     emitcode ("xch", "a,b");
4598   }
4599
4600   emitcode ("", "!tlabeldef", lbl->key+100);
4601   aopPut (AOP (result), "a", 0);
4602   _G.accInUse--;_G.bInUse--;
4603   if (AOP_SIZE(result)==2) {
4604     aopPut (AOP (result), "b", 1);
4605   }
4606 }
4607
4608 /*-----------------------------------------------------------------*/
4609 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4610 /*-----------------------------------------------------------------*/
4611 static void genMultTwoByte (operand *left, operand *right, 
4612                             operand *result, iCode *ic)
4613 {
4614         sym_link *retype = getSpec(operandType(right));
4615         sym_link *letype = getSpec(operandType(left));
4616         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4617         symbol *lbl;
4618
4619         if (AOP_TYPE (left) == AOP_LIT) {
4620                 operand *t = right;
4621                 right = left;
4622                 left = t;
4623         }
4624         /* save EA bit in F1 */
4625         lbl = newiTempLabel(NULL);
4626         emitcode ("setb","F1");
4627         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628         emitcode ("clr","F1");
4629         emitcode("","!tlabeldef",lbl->key+100);
4630
4631         /* load up MB with right */
4632         if (!umult) {
4633                 emitcode("clr","F0");
4634                 if (AOP_TYPE(right) == AOP_LIT) {
4635                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4636                         if (val < 0) {
4637                                 emitcode("setb","F0");
4638                                 val = -val;
4639                         }
4640                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4641                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4642                 } else {
4643                         lbl = newiTempLabel(NULL);
4644                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4645                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4646                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4647                         emitcode ("xch", "a,b");
4648                         emitcode ("cpl","a");
4649                         emitcode ("add", "a,#1");
4650                         emitcode ("xch", "a,b");
4651                         emitcode ("cpl", "a"); // msb
4652                         emitcode ("addc", "a,#0");
4653                         emitcode ("setb","F0");
4654                         emitcode ("","!tlabeldef",lbl->key+100);
4655                         emitcode ("mov","mb,b");
4656                         emitcode ("mov","mb,a");
4657                 }
4658         } else {
4659                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4660                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4661         }
4662         /* load up MA with left */
4663         if (!umult) {
4664                 lbl = newiTempLabel(NULL);
4665                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4666                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4667                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4668                 emitcode ("xch", "a,b");
4669                 emitcode ("cpl","a");
4670                 emitcode ("add", "a,#1");
4671                 emitcode ("xch", "a,b");
4672                 emitcode ("cpl", "a"); // msb
4673                 emitcode ("addc","a,#0");
4674                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4675                 emitcode ("setb","F0");
4676                 emitcode ("","!tlabeldef",lbl->key+100);
4677                 emitcode ("mov","ma,b");
4678                 emitcode ("mov","ma,a");
4679         } else {
4680                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4681                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4682         }
4683         /* wait for multiplication to finish */
4684         lbl = newiTempLabel(NULL);
4685         emitcode("","!tlabeldef", lbl->key+100);
4686         emitcode("mov","a,mcnt1");
4687         emitcode("anl","a,#!constbyte",0x80);
4688         emitcode("jnz","!tlabel",lbl->key+100);
4689         
4690         freeAsmop (left, NULL, ic, TRUE);
4691         freeAsmop (right, NULL, ic,TRUE);
4692         aopOp(result, ic, TRUE, FALSE);
4693
4694         /* if unsigned then simple */   
4695         if (umult) {
4696                 emitcode ("mov","a,ma");
4697                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4698                 emitcode ("mov","a,ma");
4699                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4700                 aopPut(AOP(result),"ma",1);
4701                 aopPut(AOP(result),"ma",0);
4702         } else {
4703                 emitcode("push","ma");
4704                 emitcode("push","ma");
4705                 emitcode("push","ma");
4706                 MOVA("ma");
4707                 /* negate result if needed */
4708                 lbl = newiTempLabel(NULL);      
4709                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4710                 emitcode("cpl","a");
4711                 emitcode("add","a,#1");
4712                 emitcode("","!tlabeldef", lbl->key+100);
4713                 if (AOP_TYPE(result) == AOP_ACC)
4714                 {
4715                     D(emitcode(";", "ACC special case."););
4716                     /* We know result is the only live aop, and 
4717                      * it's obviously not a DPTR2, so AP is available.
4718                      */
4719                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4720                 }
4721                 else
4722                 {
4723                     aopPut(AOP(result),"a",0);
4724                 }
4725             
4726                 emitcode("pop","acc");
4727                 lbl = newiTempLabel(NULL);      
4728                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4729                 emitcode("cpl","a");
4730                 emitcode("addc","a,#0");
4731                 emitcode("","!tlabeldef", lbl->key+100);
4732                 aopPut(AOP(result),"a",1);
4733                 emitcode("pop","acc");
4734                 if (AOP_SIZE(result) >= 3) {
4735                         lbl = newiTempLabel(NULL);      
4736                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4737                         emitcode("cpl","a");
4738                         emitcode("addc","a,#0");                        
4739                         emitcode("","!tlabeldef", lbl->key+100);
4740                         aopPut(AOP(result),"a",2);
4741                 }
4742                 emitcode("pop","acc");
4743                 if (AOP_SIZE(result) >= 4) {
4744                         lbl = newiTempLabel(NULL);      
4745                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4746                         emitcode("cpl","a");
4747                         emitcode("addc","a,#0");                        
4748                         emitcode("","!tlabeldef", lbl->key+100);
4749                         aopPut(AOP(result),"a",3);
4750                 }
4751                 if (AOP_TYPE(result) == AOP_ACC)
4752                 {
4753                     /* We stashed the result away above. */
4754                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4755                 }           
4756                 
4757         }
4758         freeAsmop (result, NULL, ic, TRUE);
4759
4760         /* restore EA bit in F1 */
4761         lbl = newiTempLabel(NULL);
4762         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4763         emitcode ("setb","EA");
4764         emitcode("","!tlabeldef",lbl->key+100);
4765         return ;
4766 }
4767
4768 /*-----------------------------------------------------------------*/
4769 /* genMult - generates code for multiplication                     */
4770 /*-----------------------------------------------------------------*/
4771 static void
4772 genMult (iCode * ic)
4773 {
4774   operand *left = IC_LEFT (ic);
4775   operand *right = IC_RIGHT (ic);
4776   operand *result = IC_RESULT (ic);
4777
4778   D (emitcode (";", "genMult "););
4779
4780   /* assign the amsops */
4781   AOP_OP_2 (ic);
4782
4783   /* special cases first */
4784   /* both are bits */
4785   if (AOP_TYPE (left) == AOP_CRY &&
4786       AOP_TYPE (right) == AOP_CRY)
4787     {
4788       genMultbits (left, right, result, ic);
4789       goto release;
4790     }
4791
4792   /* if both are of size == 1 */
4793   if (AOP_SIZE (left) == 1 &&
4794       AOP_SIZE (right) == 1)
4795     {
4796       genMultOneByte (left, right, result, ic);
4797       goto release;
4798     }
4799
4800   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4801           /* use the ds390 ARITHMETIC accel UNIT */
4802           genMultTwoByte (left, right, result, ic);
4803           return ;
4804   }
4805   /* should have been converted to function call */
4806   assert (0);
4807
4808 release:
4809   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4810   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4811   freeAsmop (result, NULL, ic, TRUE);
4812 }
4813
4814 /*-----------------------------------------------------------------*/
4815 /* genDivbits :- division of bits                                  */
4816 /*-----------------------------------------------------------------*/
4817 static void
4818 genDivbits (operand * left,
4819             operand * right,
4820             operand * result,
4821             iCode   * ic)
4822 {
4823
4824   char *l;
4825
4826   /* the result must be bit */
4827   LOAD_AB_FOR_DIV (left, right, l);
4828   emitcode ("div", "ab");
4829   emitcode ("rrc", "a");
4830   aopOp(result, ic, TRUE, FALSE);
4831     
4832   aopPut (AOP (result), "c", 0);
4833 }
4834
4835 /*-----------------------------------------------------------------*/
4836 /* genDivOneByte : 8 bit division                                  */
4837 /*-----------------------------------------------------------------*/
4838 static void
4839 genDivOneByte (operand * left,
4840                operand * right,
4841                operand * result,
4842                iCode   * ic)
4843 {
4844   sym_link *opetype = operandType (result);
4845   char *l;
4846   symbol *lbl;
4847   int size, offset;
4848
4849   offset = 1;
4850   /* signed or unsigned */
4851   if (SPEC_USIGN (opetype))
4852     {
4853         /* unsigned is easy */
4854         LOAD_AB_FOR_DIV (left, right, l);
4855         emitcode ("div", "ab");
4856
4857         _G.accInUse++;
4858         aopOp(result, ic, TRUE, FALSE);
4859         aopPut (AOP (result), "a", 0);
4860         _G.accInUse--;
4861
4862         size = AOP_SIZE (result) - 1;
4863         
4864         while (size--)
4865         {
4866             aopPut (AOP (result), zero, offset++);
4867         }
4868       return;
4869     }
4870
4871   /* signed is a little bit more difficult */
4872
4873   /* save the signs of the operands */
4874   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4875   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4876   emitcode ("push", "acc");     /* save it on the stack */
4877
4878   /* now sign adjust for both left & right */
4879   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4880   lbl = newiTempLabel (NULL);
4881   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4882   emitcode ("cpl", "a");
4883   emitcode ("inc", "a");
4884   emitcode ("", "!tlabeldef", (lbl->key + 100));
4885   emitcode ("mov", "b,a");
4886
4887   /* sign adjust left side */
4888   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4889
4890   lbl = newiTempLabel (NULL);
4891   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4892   emitcode ("cpl", "a");
4893   emitcode ("inc", "a");
4894   emitcode ("", "!tlabeldef", (lbl->key + 100));
4895
4896   /* now the division */
4897   emitcode ("nop", "; workaround for DS80C390 div bug.");
4898   emitcode ("div", "ab");
4899   /* we are interested in the lower order
4900      only */
4901   emitcode ("mov", "b,a");
4902   lbl = newiTempLabel (NULL);
4903   emitcode ("pop", "acc");
4904   /* if there was an over flow we don't
4905      adjust the sign of the result */
4906   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4907   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4908   CLRC;
4909   emitcode ("clr", "a");
4910   emitcode ("subb", "a,b");
4911   emitcode ("mov", "b,a");
4912   emitcode ("", "!tlabeldef", (lbl->key + 100));
4913
4914   /* now we are done */
4915   _G.accInUse++;     _G.bInUse++;
4916     aopOp(result, ic, TRUE, FALSE);
4917     
4918     aopPut (AOP (result), "b", 0);
4919     
4920     size = AOP_SIZE (result) - 1;
4921     
4922     if (size > 0)
4923     {
4924       emitcode ("mov", "c,b.7");
4925       emitcode ("subb", "a,acc");
4926     }
4927     while (size--)
4928     {
4929         aopPut (AOP (result), "a", offset++);
4930     }
4931     _G.accInUse--;     _G.bInUse--;
4932
4933 }
4934
4935 /*-----------------------------------------------------------------*/
4936 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4937 /*-----------------------------------------------------------------*/
4938 static void genDivTwoByte (operand *left, operand *right, 
4939                             operand *result, iCode *ic)
4940 {
4941         sym_link *retype = getSpec(operandType(right));
4942         sym_link *letype = getSpec(operandType(left));
4943         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4944         symbol *lbl;
4945
4946         /* save EA bit in F1 */
4947         lbl = newiTempLabel(NULL);
4948         emitcode ("setb","F1");
4949         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4950         emitcode ("clr","F1");
4951         emitcode("","!tlabeldef",lbl->key+100);
4952
4953         /* load up MA with left */
4954         if (!umult) {
4955                 emitcode("clr","F0");
4956                 lbl = newiTempLabel(NULL);
4957                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4958                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4959                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4960                 emitcode ("xch", "a,b");
4961                 emitcode ("cpl","a");
4962                 emitcode ("add", "a,#1");
4963                 emitcode ("xch", "a,b");
4964                 emitcode ("cpl", "a"); // msb
4965                 emitcode ("addc","a,#0");
4966                 emitcode ("setb","F0");
4967                 emitcode ("","!tlabeldef",lbl->key+100);
4968                 emitcode ("mov","ma,b");
4969                 emitcode ("mov","ma,a");
4970         } else {
4971                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4972                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4973         }
4974
4975         /* load up MB with right */
4976         if (!umult) {
4977                 if (AOP_TYPE(right) == AOP_LIT) {
4978                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4979                         if (val < 0) {
4980                                 lbl = newiTempLabel(NULL);
4981                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4982                                 emitcode("setb","F0");
4983                                 emitcode ("","!tlabeldef",lbl->key+100);
4984                                 val = -val;
4985                         } 
4986                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4987                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4988                 } else {
4989                         lbl = newiTempLabel(NULL);
4990                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4991                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4992                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4993                         emitcode ("xch", "a,b");
4994                         emitcode ("cpl","a");
4995                         emitcode ("add", "a,#1");
4996                         emitcode ("xch", "a,b");
4997                         emitcode ("cpl", "a"); // msb
4998                         emitcode ("addc", "a,#0");
4999                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5000                         emitcode ("setb","F0");
5001                         emitcode ("","!tlabeldef",lbl->key+100);
5002                         emitcode ("mov","mb,b");
5003                         emitcode ("mov","mb,a");
5004                 }
5005         } else {
5006                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5007                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5008         }
5009
5010         /* wait for multiplication to finish */
5011         lbl = newiTempLabel(NULL);
5012         emitcode("","!tlabeldef", lbl->key+100);
5013         emitcode("mov","a,mcnt1");
5014         emitcode("anl","a,#!constbyte",0x80);
5015         emitcode("jnz","!tlabel",lbl->key+100);
5016         
5017         freeAsmop (left, NULL, ic, TRUE);
5018         freeAsmop (right, NULL, ic,TRUE);
5019         aopOp(result, ic, TRUE, FALSE);
5020
5021         /* if unsigned then simple */   
5022         if (umult) {
5023                 aopPut(AOP(result),"ma",1);
5024                 aopPut(AOP(result),"ma",0);
5025         } else {
5026                 emitcode("push","ma");
5027                 MOVA("ma");
5028                 /* negate result if needed */
5029                 lbl = newiTempLabel(NULL);      
5030                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5031                 emitcode("cpl","a");
5032                 emitcode("add","a,#1");
5033                 emitcode("","!tlabeldef", lbl->key+100);
5034                 aopPut(AOP(result),"a",0);
5035                 emitcode("pop","acc");
5036                 lbl = newiTempLabel(NULL);      
5037                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5038                 emitcode("cpl","a");
5039                 emitcode("addc","a,#0");
5040                 emitcode("","!tlabeldef", lbl->key+100);
5041                 aopPut(AOP(result),"a",1);
5042         }
5043         freeAsmop (result, NULL, ic, TRUE);
5044         /* restore EA bit in F1 */
5045         lbl = newiTempLabel(NULL);
5046         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5047         emitcode ("setb","EA");
5048         emitcode("","!tlabeldef",lbl->key+100);
5049         return ;
5050 }
5051
5052 /*-----------------------------------------------------------------*/
5053 /* genDiv - generates code for division                            */
5054 /*-----------------------------------------------------------------*/
5055 static void
5056 genDiv (iCode * ic)
5057 {
5058   operand *left = IC_LEFT (ic);
5059   operand *right = IC_RIGHT (ic);
5060   operand *result = IC_RESULT (ic);
5061
5062   D (emitcode (";", "genDiv "););
5063
5064   /* assign the amsops */
5065   AOP_OP_2 (ic);
5066
5067   /* special cases first */
5068   /* both are bits */
5069   if (AOP_TYPE (left) == AOP_CRY &&
5070       AOP_TYPE (right) == AOP_CRY)
5071     {
5072       genDivbits (left, right, result, ic);
5073       goto release;
5074     }
5075
5076   /* if both are of size == 1 */
5077   if (AOP_SIZE (left) == 1 &&
5078       AOP_SIZE (right) == 1)
5079     {
5080       genDivOneByte (left, right, result, ic);
5081       goto release;
5082     }
5083
5084   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5085           /* use the ds390 ARITHMETIC accel UNIT */
5086           genDivTwoByte (left, right, result, ic);
5087           return ;
5088   }
5089   /* should have been converted to function call */
5090   assert (0);
5091 release:
5092   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094   freeAsmop (result, NULL, ic, TRUE);
5095 }
5096
5097 /*-----------------------------------------------------------------*/
5098 /* genModbits :- modulus of bits                                   */
5099 /*-----------------------------------------------------------------*/
5100 static void
5101 genModbits (operand * left,
5102             operand * right,
5103             operand * result,
5104             iCode   * ic)
5105 {
5106
5107   char *l;
5108
5109   /* the result must be bit */
5110   LOAD_AB_FOR_DIV (left, right, l);
5111   emitcode ("div", "ab");
5112   emitcode ("mov", "a,b");
5113   emitcode ("rrc", "a");
5114   aopOp(result, ic, TRUE, FALSE);
5115   aopPut (AOP (result), "c", 0);
5116 }
5117
5118 /*-----------------------------------------------------------------*/
5119 /* genModOneByte : 8 bit modulus                                   */
5120 /*-----------------------------------------------------------------*/
5121 static void
5122 genModOneByte (operand * left,
5123                operand * right,
5124                operand * result,
5125                iCode   * ic)
5126 {
5127   sym_link *opetype = operandType (result);
5128   char *l;
5129   symbol *lbl;
5130
5131   /* signed or unsigned */
5132   if (SPEC_USIGN (opetype))
5133     {
5134       /* unsigned is easy */
5135       LOAD_AB_FOR_DIV (left, right, l);
5136       emitcode ("div", "ab");
5137       aopOp(result, ic, TRUE, FALSE);   
5138       aopPut (AOP (result), "b", 0);
5139       return;
5140     }
5141
5142   /* signed is a little bit more difficult */
5143
5144   /* save the signs of the operands */
5145   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5146
5147   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5148   emitcode ("push", "acc");     /* save it on the stack */
5149
5150   /* now sign adjust for both left & right */
5151   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5152
5153   lbl = newiTempLabel (NULL);
5154   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5155   emitcode ("cpl", "a");
5156   emitcode ("inc", "a");
5157   emitcode ("", "!tlabeldef", (lbl->key + 100));
5158   emitcode ("mov", "b,a");
5159
5160   /* sign adjust left side */
5161   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5162
5163   lbl = newiTempLabel (NULL);
5164   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5165   emitcode ("cpl", "a");
5166   emitcode ("inc", "a");
5167   emitcode ("", "!tlabeldef", (lbl->key + 100));
5168
5169   /* now the multiplication */
5170   emitcode ("nop", "; workaround for DS80C390 div bug.");
5171   emitcode ("div", "ab");
5172   /* we are interested in the lower order
5173      only */
5174   lbl = newiTempLabel (NULL);
5175   emitcode ("pop", "acc");
5176   /* if there was an over flow we don't
5177      adjust the sign of the result */
5178   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5179   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5180   CLRC;
5181   emitcode ("clr", "a");
5182   emitcode ("subb", "a,b");
5183   emitcode ("mov", "b,a");
5184   emitcode ("", "!tlabeldef", (lbl->key + 100));
5185   
5186   _G.bInUse++;
5187   /* now we are done */
5188   aopOp(result, ic, TRUE, FALSE);    
5189   aopPut (AOP (result), "b", 0);
5190   _G.bInUse--;
5191
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5196 /*-----------------------------------------------------------------*/
5197 static void genModTwoByte (operand *left, operand *right, 
5198                             operand *result, iCode *ic)
5199 {
5200         sym_link *retype = getSpec(operandType(right));
5201         sym_link *letype = getSpec(operandType(left));
5202         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5203         symbol *lbl;
5204
5205         /* load up MA with left */
5206         /* save EA bit in F1 */
5207         lbl = newiTempLabel(NULL);
5208         emitcode ("setb","F1");
5209         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5210         emitcode ("clr","F1");
5211         emitcode("","!tlabeldef",lbl->key+100);
5212
5213         if (!umult) {
5214                 lbl = newiTempLabel(NULL);
5215                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5216                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5217                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5218                 emitcode ("xch", "a,b");
5219                 emitcode ("cpl","a");
5220                 emitcode ("add", "a,#1");
5221                 emitcode ("xch", "a,b");
5222                 emitcode ("cpl", "a"); // msb
5223                 emitcode ("addc","a,#0");
5224                 emitcode ("","!tlabeldef",lbl->key+100);
5225                 emitcode ("mov","ma,b");
5226                 emitcode ("mov","ma,a");
5227         } else {
5228                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5229                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5230         }
5231
5232         /* load up MB with right */
5233         if (!umult) {
5234                 if (AOP_TYPE(right) == AOP_LIT) {
5235                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5236                         if (val < 0) {
5237                                 val = -val;
5238                         } 
5239                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5240                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5241                 } else {
5242                         lbl = newiTempLabel(NULL);
5243                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5244                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5245                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5246                         emitcode ("xch", "a,b");
5247                         emitcode ("cpl","a");
5248                         emitcode ("add", "a,#1");
5249                         emitcode ("xch", "a,b");
5250                         emitcode ("cpl", "a"); // msb
5251                         emitcode ("addc", "a,#0");
5252                         emitcode ("","!tlabeldef",lbl->key+100);
5253                         emitcode ("mov","mb,b");
5254                         emitcode ("mov","mb,a");
5255                 }
5256         } else {
5257                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5258                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5259         }
5260
5261         /* wait for multiplication to finish */
5262         lbl = newiTempLabel(NULL);
5263         emitcode("","!tlabeldef", lbl->key+100);
5264         emitcode("mov","a,mcnt1");
5265         emitcode("anl","a,#!constbyte",0x80);
5266         emitcode("jnz","!tlabel",lbl->key+100);
5267         
5268         freeAsmop (left, NULL, ic, TRUE);
5269         freeAsmop (right, NULL, ic,TRUE);
5270         aopOp(result, ic, TRUE, FALSE);
5271
5272         aopPut(AOP(result),"mb",1);
5273         aopPut(AOP(result),"mb",0);
5274         freeAsmop (result, NULL, ic, TRUE);
5275
5276         /* restore EA bit in F1 */
5277         lbl = newiTempLabel(NULL);
5278         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5279         emitcode ("setb","EA");
5280         emitcode("","!tlabeldef",lbl->key+100);
5281         return ;
5282 }
5283
5284 /*-----------------------------------------------------------------*/
5285 /* genMod - generates code for division                            */
5286 /*-----------------------------------------------------------------*/
5287 static void
5288 genMod (iCode * ic)
5289 {
5290   operand *left = IC_LEFT (ic);
5291   operand *right = IC_RIGHT (ic);
5292   operand *result = IC_RESULT (ic);
5293
5294   D (emitcode (";", "genMod "); );
5295
5296   /* assign the amsops */
5297   AOP_OP_2 (ic);
5298
5299   /* special cases first */
5300   /* both are bits */
5301   if (AOP_TYPE (left) == AOP_CRY &&
5302       AOP_TYPE (right) == AOP_CRY)
5303     {
5304       genModbits (left, right, result, ic);
5305       goto release;
5306     }
5307
5308   /* if both are of size == 1 */
5309   if (AOP_SIZE (left) == 1 &&
5310       AOP_SIZE (right) == 1)
5311     {
5312       genModOneByte (left, right, result, ic);
5313       goto release;
5314     }
5315
5316   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5317           /* use the ds390 ARITHMETIC accel UNIT */
5318           genModTwoByte (left, right, result, ic);
5319           return ;
5320   }
5321
5322   /* should have been converted to function call */
5323   assert (0);
5324
5325 release:
5326   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5327   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5328   freeAsmop (result, NULL, ic, TRUE);
5329 }
5330
5331 /*-----------------------------------------------------------------*/
5332 /* genIfxJump :- will create a jump depending on the ifx           */
5333 /*-----------------------------------------------------------------*/
5334 static void
5335 genIfxJump (iCode * ic, char *jval)
5336 {
5337   symbol *jlbl;
5338   symbol *tlbl = newiTempLabel (NULL);
5339   char *inst;
5340
5341   D (emitcode (";", "genIfxJump"););
5342
5343   /* if true label then we jump if condition
5344      supplied is true */
5345   if (IC_TRUE (ic))
5346     {
5347       jlbl = IC_TRUE (ic);
5348       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5349                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5350     }
5351   else
5352     {
5353       /* false label is present */
5354       jlbl = IC_FALSE (ic);
5355       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5356                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5357     }
5358   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5359     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5360   else
5361     emitcode (inst, "!tlabel", tlbl->key + 100);
5362   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5363   emitcode ("", "!tlabeldef", tlbl->key + 100);
5364
5365   /* mark the icode as generated */
5366   ic->generated = 1;
5367 }
5368
5369 /*-----------------------------------------------------------------*/
5370 /* genCmp :- greater or less than comparison                       */
5371 /*-----------------------------------------------------------------*/
5372 static void
5373 genCmp (operand * left, operand * right,
5374         iCode * ic, iCode * ifx, int sign)
5375 {
5376   int size, offset = 0;
5377   unsigned long lit = 0L;
5378   operand *result;
5379
5380   D (emitcode (";", "genCmp"););
5381
5382   result = IC_RESULT (ic);
5383
5384   /* if left & right are bit variables */
5385   if (AOP_TYPE (left) == AOP_CRY &&
5386       AOP_TYPE (right) == AOP_CRY)
5387     {
5388       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5389       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5390     }
5391   else
5392     {
5393       /* subtract right from left if at the
5394          end the carry flag is set then we know that
5395          left is greater than right */
5396       size = max (AOP_SIZE (left), AOP_SIZE (right));
5397
5398       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5399       if ((size == 1) && !sign 
5400           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5401         {
5402           symbol *lbl = newiTempLabel (NULL);
5403           emitcode ("cjne", "%s,%s,!tlabel",
5404                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5405                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5406                     lbl->key + 100);
5407           emitcode ("", "!tlabeldef", lbl->key + 100);
5408         }
5409       else
5410         {
5411           if (AOP_TYPE (right) == AOP_LIT)
5412             {
5413               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5414               /* optimize if(x < 0) or if(x >= 0) */
5415               if (lit == 0L)
5416                 {
5417                   if (!sign)
5418                     {
5419                       CLRC;
5420                     }
5421                   else
5422                     {
5423                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5424
5425                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5426                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5427
5428                       aopOp (result, ic, FALSE, FALSE);
5429
5430                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5431                         {
5432                           freeAsmop (result, NULL, ic, TRUE);
5433                           genIfxJump (ifx, "acc.7");
5434                           return;
5435                         }
5436                       else
5437                         {
5438                           emitcode ("rlc", "a");
5439                         }
5440                       goto release_freedLR;
5441                     }
5442                   goto release;
5443                 }
5444             }
5445           CLRC;
5446           while (size--)
5447             {
5448               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5449               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5450               // emitcode (";", "genCmp #2");
5451               if (sign && (size == 0))
5452                 {
5453                   // emitcode (";", "genCmp #3");
5454                   emitcode ("xrl", "a,#!constbyte",0x80);
5455                   if (AOP_TYPE (right) == AOP_LIT)
5456                     {
5457                       unsigned long lit = (unsigned long)
5458                       floatFromVal (AOP (right)->aopu.aop_lit);
5459                       // emitcode (";", "genCmp #3.1");
5460                       emitcode ("subb", "a,#!constbyte",
5461                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5462                     }
5463                   else
5464                     {
5465                       // emitcode (";", "genCmp #3.2");
5466                       saveAccWarn = 0;  
5467                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5468                       saveAccWarn = DEFAULT_ACC_WARNING;
5469                       emitcode ("xrl", "b,#!constbyte",0x80);
5470                       emitcode ("subb", "a,b");
5471                     }
5472                 }
5473               else
5474                 {
5475                   const char *s;
5476
5477                   // emitcode (";", "genCmp #4");
5478                   saveAccWarn = 0;
5479                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5480                   saveAccWarn = DEFAULT_ACC_WARNING;
5481
5482                   emitcode ("subb", "a,%s", s);
5483                 }
5484             }
5485         }
5486     }
5487
5488 release:
5489 /* Don't need the left & right operands any more; do need the result. */
5490   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5491   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5492
5493   aopOp (result, ic, FALSE, FALSE);
5494
5495 release_freedLR:
5496
5497   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5498     {
5499       outBitC (result);
5500     }
5501   else
5502     {
5503       /* if the result is used in the next
5504          ifx conditional branch then generate
5505          code a little differently */
5506       if (ifx)
5507         {
5508           genIfxJump (ifx, "c");
5509         }
5510       else
5511         {
5512           outBitC (result);
5513         }
5514       /* leave the result in acc */
5515     }
5516   freeAsmop (result, NULL, ic, TRUE);
5517 }
5518
5519 /*-----------------------------------------------------------------*/
5520 /* genCmpGt :- greater than comparison                             */
5521 /*-----------------------------------------------------------------*/
5522 static void
5523 genCmpGt (iCode * ic, iCode * ifx)
5524 {
5525   operand *left, *right;
5526   sym_link *letype, *retype;
5527   int sign;
5528
5529   D (emitcode (";", "genCmpGt ");
5530     );
5531
5532   left = IC_LEFT (ic);
5533   right = IC_RIGHT (ic);
5534
5535   letype = getSpec (operandType (left));
5536   retype = getSpec (operandType (right));
5537   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5538
5539   /* assign the left & right amsops */
5540   AOP_OP_2 (ic);
5541
5542   genCmp (right, left, ic, ifx, sign);
5543 }
5544
5545 /*-----------------------------------------------------------------*/
5546 /* genCmpLt - less than comparisons                                */
5547 /*-----------------------------------------------------------------*/
5548 static void
5549 genCmpLt (iCode * ic, iCode * ifx)
5550 {
5551   operand *left, *right;
5552   sym_link *letype, *retype;
5553   int sign;
5554
5555   D (emitcode (";", "genCmpLt "););
5556
5557   left = IC_LEFT (ic);
5558   right = IC_RIGHT (ic);
5559
5560   letype = getSpec (operandType (left));
5561   retype = getSpec (operandType (right));
5562   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5563
5564   /* assign the left & right amsops */
5565   AOP_OP_2 (ic);
5566
5567   genCmp (left, right, ic, ifx, sign);
5568 }
5569
5570 /*-----------------------------------------------------------------*/
5571 /* gencjneshort - compare and jump if not equal                    */
5572 /*-----------------------------------------------------------------*/
5573 static void
5574 gencjneshort (operand * left, operand * right, symbol * lbl)
5575 {
5576   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5577   int offset = 0;
5578   unsigned long lit = 0L;
5579
5580   D (emitcode (";", "gencjneshort");
5581     );
5582
5583   /* if the left side is a literal or
5584      if the right is in a pointer register and left
5585      is not */
5586   if ((AOP_TYPE (left) == AOP_LIT) ||
5587       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5588     {
5589       operand *t = right;
5590       right = left;
5591       left = t;
5592     }
5593
5594   if (AOP_TYPE (right) == AOP_LIT)
5595     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5596
5597   if (opIsGptr (left) || opIsGptr (right))
5598     {
5599       /* We are comparing a generic pointer to something.
5600        * Exclude the generic type byte from the comparison.
5601        */
5602       size--;
5603       D (emitcode (";", "cjneshort: generic ptr special case."););
5604     }
5605
5606
5607   /* if the right side is a literal then anything goes */
5608   if (AOP_TYPE (right) == AOP_LIT &&
5609       AOP_TYPE (left) != AOP_DIR)
5610     {
5611       while (size--)
5612         {
5613           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5614           emitcode ("cjne", "a,%s,!tlabel",
5615                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5616                     lbl->key + 100);
5617           offset++;
5618         }
5619     }
5620
5621   /* if the right side is in a register or in direct space or
5622      if the left is a pointer register & right is not */
5623   else if (AOP_TYPE (right) == AOP_REG ||
5624            AOP_TYPE (right) == AOP_DIR ||
5625            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5626            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5627     {
5628       while (size--)
5629         {
5630           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5631           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5632               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5633             emitcode ("jnz", "!tlabel", lbl->key + 100);
5634           else
5635             emitcode ("cjne", "a,%s,!tlabel",
5636                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5637                       lbl->key + 100);
5638           offset++;
5639         }
5640     }
5641   else
5642     {
5643       /* right is a pointer reg need both a & b */
5644       while (size--)
5645         {
5646           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5647           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5648           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5649           offset++;
5650         }
5651     }
5652 }
5653
5654 /*-----------------------------------------------------------------*/
5655 /* gencjne - compare and jump if not equal                         */
5656 /*-----------------------------------------------------------------*/
5657 static void
5658 gencjne (operand * left, operand * right, symbol * lbl)
5659 {
5660   symbol *tlbl = newiTempLabel (NULL);
5661
5662   D (emitcode (";", "gencjne");
5663     );
5664
5665   gencjneshort (left, right, lbl);
5666
5667   emitcode ("mov", "a,%s", one);
5668   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5669   emitcode ("", "!tlabeldef", lbl->key + 100);
5670   emitcode ("clr", "a");
5671   emitcode ("", "!tlabeldef", tlbl->key + 100);
5672 }
5673
5674 /*-----------------------------------------------------------------*/
5675 /* genCmpEq - generates code for equal to                          */
5676 /*-----------------------------------------------------------------*/
5677 static void
5678 genCmpEq (iCode * ic, iCode * ifx)
5679 {
5680   operand *left, *right, *result;
5681
5682   D (emitcode (";", "genCmpEq ");
5683     );
5684
5685   AOP_OP_2 (ic);
5686   AOP_SET_LOCALS (ic);
5687
5688   /* if literal, literal on the right or
5689      if the right is in a pointer register and left
5690      is not */
5691   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5692       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5693     {
5694       operand *t = IC_RIGHT (ic);
5695       IC_RIGHT (ic) = IC_LEFT (ic);
5696       IC_LEFT (ic) = t;
5697     }
5698
5699   if (ifx &&                    /* !AOP_SIZE(result) */
5700       OP_SYMBOL (result) &&
5701       OP_SYMBOL (result)->regType == REG_CND)
5702     {
5703       symbol *tlbl;
5704       /* if they are both bit variables */
5705       if (AOP_TYPE (left) == AOP_CRY &&
5706           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5707         {
5708           if (AOP_TYPE (right) == AOP_LIT)
5709             {
5710               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5711               if (lit == 0L)
5712                 {
5713                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5714                   emitcode ("cpl", "c");
5715                 }
5716               else if (lit == 1L)
5717                 {
5718                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5719                 }
5720               else
5721                 {
5722                   emitcode ("clr", "c");
5723                 }
5724               /* AOP_TYPE(right) == AOP_CRY */
5725             }
5726           else
5727             {
5728               symbol *lbl = newiTempLabel (NULL);
5729               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5730               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5731               emitcode ("cpl", "c");
5732               emitcode ("", "!tlabeldef", (lbl->key + 100));
5733             }
5734           /* if true label then we jump if condition
5735              supplied is true */
5736           tlbl = newiTempLabel (NULL);
5737           if (IC_TRUE (ifx))
5738             {
5739               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5740               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5741             }
5742           else
5743             {
5744               emitcode ("jc", "!tlabel", tlbl->key + 100);
5745               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5746             }
5747           emitcode ("", "!tlabeldef", tlbl->key + 100);
5748         }
5749       else
5750         {
5751           tlbl = newiTempLabel (NULL);
5752           gencjneshort (left, right, tlbl);
5753           if (IC_TRUE (ifx))
5754             {
5755               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5756               emitcode ("", "!tlabeldef", tlbl->key + 100);
5757             }
5758           else
5759             {
5760               symbol *lbl = newiTempLabel (NULL);
5761               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5762               emitcode ("", "!tlabeldef", tlbl->key + 100);
5763               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5764               emitcode ("", "!tlabeldef", lbl->key + 100);
5765             }
5766         }
5767       /* mark the icode as generated */
5768       ifx->generated = 1;
5769
5770       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5771       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5772       return;
5773     }
5774
5775   /* if they are both bit variables */
5776   if (AOP_TYPE (left) == AOP_CRY &&
5777       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5778     {
5779       if (AOP_TYPE (right) == AOP_LIT)
5780         {
5781           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5782           if (lit == 0L)
5783             {
5784               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5785               emitcode ("cpl", "c");
5786             }
5787           else if (lit == 1L)
5788             {
5789               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5790             }
5791           else
5792             {
5793               emitcode ("clr", "c");
5794             }
5795           /* AOP_TYPE(right) == AOP_CRY */
5796         }
5797       else
5798         {
5799           symbol *lbl = newiTempLabel (NULL);
5800           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5802           emitcode ("cpl", "c");
5803           emitcode ("", "!tlabeldef", (lbl->key + 100));
5804         }
5805
5806       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5808
5809       aopOp (result, ic, TRUE, FALSE);
5810
5811       /* c = 1 if egal */
5812       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5813         {
5814           outBitC (result);
5815           goto release;
5816         }
5817       if (ifx)
5818         {
5819           genIfxJump (ifx, "c");
5820           goto release;
5821         }
5822       /* if the result is used in an arithmetic operation
5823          then put the result in place */
5824       outBitC (result);
5825     }
5826   else
5827     {
5828       gencjne (left, right, newiTempLabel (NULL));
5829
5830       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5831       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5832
5833       aopOp (result, ic, TRUE, FALSE);
5834
5835       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5836         {
5837           aopPut (AOP (result), "a", 0);
5838           goto release;
5839         }
5840       if (ifx)
5841         {
5842           genIfxJump (ifx, "a");
5843           goto release;
5844         }
5845       /* if the result is used in an arithmetic operation
5846          then put the result in place */
5847       if (AOP_TYPE (result) != AOP_CRY)
5848         outAcc (result);
5849       /* leave the result in acc */
5850     }
5851
5852 release:
5853   freeAsmop (result, NULL, ic, TRUE);
5854 }
5855
5856 /*-----------------------------------------------------------------*/
5857 /* ifxForOp - returns the icode containing the ifx for operand     */
5858 /*-----------------------------------------------------------------*/
5859 static iCode *
5860 ifxForOp (operand * op, iCode * ic)
5861 {
5862   /* if true symbol then needs to be assigned */
5863   if (IS_TRUE_SYMOP (op))
5864     return NULL;
5865
5866   /* if this has register type condition and
5867      the next instruction is ifx with the same operand
5868      and live to of the operand is upto the ifx only then */
5869   if (ic->next &&
5870       ic->next->op == IFX &&
5871       IC_COND (ic->next)->key == op->key &&
5872       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5873     return ic->next;
5874
5875   return NULL;
5876 }
5877 /*-----------------------------------------------------------------*/
5878 /* hasInc - operand is incremented before any other use            */
5879 /*-----------------------------------------------------------------*/
5880 static iCode *
5881 hasInc (operand *op, iCode *ic, int osize)
5882 {
5883   sym_link *type = operandType(op);
5884   sym_link *retype = getSpec (type);
5885   iCode *lic = ic->next;
5886   int isize ;
5887   
5888   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5889   if (!IS_SYMOP(op)) return NULL;
5890
5891   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5892   if (IS_AGGREGATE(type->next)) return NULL;
5893   if (osize != (isize = getSize(type->next))) return NULL;
5894
5895   while (lic) {
5896       /* if operand of the form op = op + <sizeof *op> */
5897       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5898           isOperandEqual(IC_RESULT(lic),op) && 
5899           isOperandLiteral(IC_RIGHT(lic)) &&
5900           operandLitValue(IC_RIGHT(lic)) == isize) {
5901           return lic;
5902       }
5903       /* if the operand used or deffed */
5904       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5905           return NULL;
5906       }
5907       /* if GOTO or IFX */
5908       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5909       lic = lic->next;
5910   }
5911   return NULL;
5912 }
5913
5914 /*-----------------------------------------------------------------*/
5915 /* genAndOp - for && operation                                     */
5916 /*-----------------------------------------------------------------*/
5917 static void
5918 genAndOp (iCode * ic)
5919 {
5920   operand *left, *right, *result;
5921   symbol *tlbl;
5922
5923   D (emitcode (";", "genAndOp "););
5924
5925   /* note here that && operations that are in an
5926      if statement are taken away by backPatchLabels
5927      only those used in arthmetic operations remain */
5928   AOP_OP_2 (ic);
5929   AOP_SET_LOCALS (ic);
5930
5931   /* if both are bit variables */
5932   if (AOP_TYPE (left) == AOP_CRY &&
5933       AOP_TYPE (right) == AOP_CRY)
5934     {
5935       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5936       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5937       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939   
5940       aopOp (result,ic,FALSE, FALSE);
5941       outBitC (result);
5942     }
5943   else
5944     {
5945       tlbl = newiTempLabel (NULL);
5946       toBoolean (left);
5947       emitcode ("jz", "!tlabel", tlbl->key + 100);
5948       toBoolean (right);
5949       emitcode ("", "!tlabeldef", tlbl->key + 100);
5950       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952   
5953       aopOp (result,ic,FALSE, FALSE);
5954       outBitAcc (result);
5955     }
5956     freeAsmop (result, NULL, ic, TRUE);
5957 }
5958
5959
5960 /*-----------------------------------------------------------------*/
5961 /* genOrOp - for || operation                                      */
5962 /*-----------------------------------------------------------------*/
5963 static void
5964 genOrOp (iCode * ic)
5965 {
5966   operand *left, *right, *result;
5967   symbol *tlbl;
5968
5969   D (emitcode (";", "genOrOp "););
5970
5971   /* note here that || operations that are in an
5972      if statement are taken away by backPatchLabels
5973      only those used in arthmetic operations remain */
5974   AOP_OP_2 (ic);
5975   AOP_SET_LOCALS (ic);
5976
5977   /* if both are bit variables */
5978   if (AOP_TYPE (left) == AOP_CRY &&
5979       AOP_TYPE (right) == AOP_CRY)
5980     {
5981       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5982       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5983       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985   
5986       aopOp (result,ic,FALSE, FALSE);
5987       
5988       outBitC (result);
5989     }
5990   else
5991     {
5992       tlbl = newiTempLabel (NULL);
5993       toBoolean (left);
5994       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5995       toBoolean (right);
5996       emitcode ("", "!tlabeldef", tlbl->key + 100);
5997       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5998       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999   
6000       aopOp (result,ic,FALSE, FALSE);
6001       
6002       outBitAcc (result);
6003     }
6004
6005   freeAsmop (result, NULL, ic, TRUE);
6006 }
6007
6008 /*-----------------------------------------------------------------*/
6009 /* isLiteralBit - test if lit == 2^n                               */
6010 /*-----------------------------------------------------------------*/
6011 static int
6012 isLiteralBit (unsigned long lit)
6013 {
6014   unsigned long pw[32] =
6015   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6016    0x100L, 0x200L, 0x400L, 0x800L,
6017    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6018    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6019    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6020    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6021    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6022   int idx;
6023
6024   for (idx = 0; idx < 32; idx++)
6025     if (lit == pw[idx])
6026       return idx + 1;
6027   return 0;
6028 }
6029
6030 /*-----------------------------------------------------------------*/
6031 /* continueIfTrue -                                                */
6032 /*-----------------------------------------------------------------*/
6033 static void
6034 continueIfTrue (iCode * ic)
6035 {
6036   if (IC_TRUE (ic))
6037     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6038   ic->generated = 1;
6039 }
6040
6041 /*-----------------------------------------------------------------*/
6042 /* jmpIfTrue -                                                     */
6043 /*-----------------------------------------------------------------*/
6044 static void
6045 jumpIfTrue (iCode * ic)
6046 {
6047   if (!IC_TRUE (ic))
6048     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6049   ic->generated = 1;
6050 }
6051
6052 /*-----------------------------------------------------------------*/
6053 /* jmpTrueOrFalse -                                                */
6054 /*-----------------------------------------------------------------*/
6055 static void
6056 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6057 {
6058   // ugly but optimized by peephole
6059   if (IC_TRUE (ic))
6060     {
6061       symbol *nlbl = newiTempLabel (NULL);
6062       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6063       emitcode ("", "!tlabeldef", tlbl->key + 100);
6064       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6065       emitcode ("", "!tlabeldef", nlbl->key + 100);
6066     }
6067   else
6068     {
6069       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6070       emitcode ("", "!tlabeldef", tlbl->key + 100);
6071     }
6072   ic->generated = 1;
6073 }
6074
6075 // Generate code to perform a bit-wise logic operation
6076 // on two operands in far space (assumed to already have been 
6077 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6078 // in far space. This requires pushing the result on the stack
6079 // then popping it into the result.
6080 static void
6081 genFarFarLogicOp(iCode *ic, char *logicOp)
6082 {
6083       int size, resultSize, compSize;
6084       int offset = 0;
6085       
6086       TR_AP("#5");
6087       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6088       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6089                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6090       
6091       _startLazyDPSEvaluation();
6092       for (size = compSize; (size--); offset++)
6093       {
6094           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6095           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6096           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6097           
6098           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6099           emitcode ("push", "acc");
6100       }
6101       _endLazyDPSEvaluation();
6102      
6103       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6104       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6105       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6106      
6107       resultSize = AOP_SIZE(IC_RESULT(ic));
6108
6109       ADJUST_PUSHED_RESULT(compSize, resultSize);
6110
6111       _startLazyDPSEvaluation();
6112       while (compSize--)
6113       {
6114           emitcode ("pop", "acc");
6115           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6116       }
6117       _endLazyDPSEvaluation();
6118       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6119 }
6120
6121
6122 /*-----------------------------------------------------------------*/
6123 /* genAnd  - code for and                                          */
6124 /*-----------------------------------------------------------------*/
6125 static void
6126 genAnd (iCode * ic, iCode * ifx)
6127 {
6128   operand *left, *right, *result;
6129   int size, offset = 0;
6130   unsigned long lit = 0L;
6131   int bytelit;
6132   char buff[10];
6133   bool pushResult;
6134
6135   D (emitcode (";", "genAnd "););
6136
6137   AOP_OP_3_NOFATAL (ic, pushResult);
6138   AOP_SET_LOCALS (ic);
6139
6140   if (pushResult)
6141   {
6142       genFarFarLogicOp(ic, "anl");
6143       return;
6144   }  
6145
6146 #ifdef DEBUG_TYPE
6147   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6148             AOP_TYPE (result),
6149             AOP_TYPE (left), AOP_TYPE (right));
6150   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6151             AOP_SIZE (result),
6152             AOP_SIZE (left), AOP_SIZE (right));
6153 #endif
6154
6155   /* if left is a literal & right is not then exchange them */
6156   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6157 #ifdef LOGIC_OPS_BROKEN      
6158     ||  AOP_NEEDSACC (left)
6159 #endif
6160     )
6161     {
6162       operand *tmp = right;
6163       right = left;
6164       left = tmp;
6165     }
6166
6167   /* if result = right then exchange them */
6168   if (sameRegs (AOP (result), AOP (right)))
6169     {
6170       operand *tmp = right;
6171       right = left;
6172       left = tmp;
6173     }
6174
6175   /* if right is bit then exchange them */
6176   if (AOP_TYPE (right) == AOP_CRY &&
6177       AOP_TYPE (left) != AOP_CRY)
6178     {
6179       operand *tmp = right;
6180       right = left;
6181       left = tmp;
6182     }
6183   if (AOP_TYPE (right) == AOP_LIT)
6184     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6185
6186   size = AOP_SIZE (result);
6187
6188   // if(bit & yy)
6189   // result = bit & yy;
6190   if (AOP_TYPE (left) == AOP_CRY)
6191     {
6192       // c = bit & literal;
6193       if (AOP_TYPE (right) == AOP_LIT)
6194         {
6195           if (lit & 1)
6196             {
6197               if (size && sameRegs (AOP (result), AOP (left)))
6198                 // no change
6199                 goto release;
6200               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6201             }
6202           else
6203             {
6204               // bit(result) = 0;
6205               if (size && (AOP_TYPE (result) == AOP_CRY))
6206                 {
6207                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6208                   goto release;
6209                 }
6210               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6211                 {
6212                   jumpIfTrue (ifx);
6213                   goto release;
6214                 }
6215               emitcode ("clr", "c");
6216             }
6217         }
6218       else
6219         {
6220           if (AOP_TYPE (right) == AOP_CRY)
6221             {
6222               // c = bit & bit;
6223               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6224               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6225             }
6226           else
6227             {
6228               // c = bit & val;
6229               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6230               // c = lsb
6231               emitcode ("rrc", "a");
6232               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6233             }
6234         }
6235       // bit = c
6236       // val = c
6237       if (size)
6238         outBitC (result);
6239       // if(bit & ...)
6240       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6241         genIfxJump (ifx, "c");
6242       goto release;
6243     }
6244
6245   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6246   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6247   if ((AOP_TYPE (right) == AOP_LIT) &&
6248       (AOP_TYPE (result) == AOP_CRY) &&
6249       (AOP_TYPE (left) != AOP_CRY))
6250     {
6251       int posbit = isLiteralBit (lit);
6252       /* left &  2^n */
6253       if (posbit)
6254         {
6255           posbit--;
6256           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6257           // bit = left & 2^n
6258           if (size)
6259             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6260           // if(left &  2^n)
6261           else
6262             {
6263               if (ifx)
6264                 {
6265                   SNPRINTF (buff, sizeof(buff), 
6266                             "acc.%d", posbit & 0x07);
6267                   genIfxJump (ifx, buff);
6268                 }
6269               else 
6270                   {
6271                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6272                   }
6273               goto release;
6274             }
6275         }
6276       else
6277         {
6278           symbol *tlbl = newiTempLabel (NULL);
6279           int sizel = AOP_SIZE (left);
6280           if (size)
6281             emitcode ("setb", "c");
6282           while (sizel--)
6283             {
6284               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6285                 {
6286                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6287                   // byte ==  2^n ?
6288                   if ((posbit = isLiteralBit (bytelit)) != 0)
6289                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6290                   else
6291                     {
6292                       if (bytelit != 0x0FFL)
6293                         emitcode ("anl", "a,%s",
6294                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6295                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6296                     }
6297                 }
6298               offset++;
6299             }
6300           // bit = left & literal
6301           if (size)
6302             {
6303               emitcode ("clr", "c");
6304               emitcode ("", "!tlabeldef", tlbl->key + 100);
6305             }
6306           // if(left & literal)
6307           else
6308             {
6309               if (ifx)
6310                 jmpTrueOrFalse (ifx, tlbl);
6311               goto release;
6312             }
6313         }
6314       outBitC (result);
6315       goto release;
6316     }
6317
6318   /* if left is same as result */
6319   if (sameRegs (AOP (result), AOP (left)))
6320     {
6321       for (; size--; offset++)
6322         {
6323           if (AOP_TYPE (right) == AOP_LIT)
6324             {
6325               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6326                 continue;
6327               else if (bytelit == 0)
6328                 aopPut (AOP (result), zero, offset);
6329               else if (IS_AOP_PREG (result))
6330                 {
6331                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6332                   emitcode ("anl", "a,%s",
6333                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6334                   aopPut (AOP (result), "a", offset);
6335                 }
6336               else
6337                 emitcode ("anl", "%s,%s",
6338                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6339                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6340             }
6341           else
6342             {
6343               if (AOP_TYPE (left) == AOP_ACC)
6344                 emitcode ("anl", "a,%s",
6345                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6346               else
6347                 {
6348                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6349                   if (IS_AOP_PREG (result))
6350                     {
6351                       emitcode ("anl", "a,%s",
6352                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6353                       aopPut (AOP (result), "a", offset);
6354                     }
6355                   else
6356                     emitcode ("anl", "%s,a",
6357                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6358                 }
6359             }
6360         }
6361     }
6362   else
6363     {
6364       // left & result in different registers
6365       if (AOP_TYPE (result) == AOP_CRY)
6366         {
6367           // result = bit
6368           // if(size), result in bit
6369           // if(!size && ifx), conditional oper: if(left & right)
6370           symbol *tlbl = newiTempLabel (NULL);
6371           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6372           if (size)
6373             emitcode ("setb", "c");
6374           while (sizer--)
6375             {
6376               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6377                 emitcode ("anl", "a,%s",
6378                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6379               } else {
6380                 if (AOP_TYPE(left)==AOP_ACC) {
6381                   emitcode("mov", "b,a");
6382                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6383                   emitcode("anl", "a,b");
6384                 }else {
6385                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6386                   emitcode ("anl", "a,%s",
6387                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6388                 }
6389               }
6390               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6391               offset++;
6392             }
6393           if (size)
6394             {
6395               CLRC;
6396               emitcode ("", "!tlabeldef", tlbl->key + 100);
6397               outBitC (result);
6398             }
6399           else if (ifx)
6400             jmpTrueOrFalse (ifx, tlbl);
6401         }
6402       else
6403         {
6404           for (; (size--); offset++)
6405             {
6406               // normal case
6407               // result = left & right
6408               if (AOP_TYPE (right) == AOP_LIT)
6409                 {
6410                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6411                     {
6412                       aopPut (AOP (result),
6413                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6414                               offset);
6415                       continue;
6416                     }
6417                   else if (bytelit == 0)
6418                     {
6419                       aopPut (AOP (result), zero, offset);
6420                       continue;
6421                     }
6422                   D (emitcode (";", "better literal AND."););
6423                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6424                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6425                                                     FALSE, FALSE, DP2_RESULT_REG));
6426
6427                 }
6428               else
6429                 {
6430                   // faster than result <- left, anl result,right
6431                   // and better if result is SFR
6432                   if (AOP_TYPE (left) == AOP_ACC)
6433                     {
6434                       emitcode ("anl", "a,%s", 
6435                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6436                     }
6437                   else
6438                     {
6439                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6440                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6441                       {
6442                           emitcode("mov", "b,a");
6443                           rOp = "b";
6444                       }
6445                         
6446                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6447                       emitcode ("anl", "a,%s", rOp);
6448                     }                   
6449                 }
6450               aopPut (AOP (result), "a", offset);
6451             }
6452         }
6453     }
6454
6455 release:
6456   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6457   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6458   freeAsmop (result, NULL, ic, TRUE);
6459 }
6460
6461
6462 /*-----------------------------------------------------------------*/
6463 /* genOr  - code for or                                            */
6464 /*-----------------------------------------------------------------*/
6465 static void
6466 genOr (iCode * ic, iCode * ifx)
6467 {
6468   operand *left, *right, *result;
6469   int size, offset = 0;
6470   unsigned long lit = 0L;
6471   bool     pushResult;
6472
6473   D (emitcode (";", "genOr "););
6474
6475   AOP_OP_3_NOFATAL (ic, pushResult);
6476   AOP_SET_LOCALS (ic);
6477
6478   if (pushResult)
6479   {
6480       genFarFarLogicOp(ic, "orl");
6481       return;
6482   }
6483
6484
6485 #ifdef DEBUG_TYPE
6486   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6487             AOP_TYPE (result),
6488             AOP_TYPE (left), AOP_TYPE (right));
6489   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6490             AOP_SIZE (result),
6491             AOP_SIZE (left), AOP_SIZE (right));
6492 #endif
6493
6494   /* if left is a literal & right is not then exchange them */
6495   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6496 #ifdef LOGIC_OPS_BROKEN
6497    || AOP_NEEDSACC (left) // I think this is a net loss now.
6498 #endif      
6499       )
6500     {
6501       operand *tmp = right;
6502       right = left;
6503       left = tmp;
6504     }
6505
6506   /* if result = right then exchange them */
6507   if (sameRegs (AOP (result), AOP (right)))
6508     {
6509       operand *tmp = right;
6510       right = left;
6511       left = tmp;
6512     }
6513
6514   /* if right is bit then exchange them */
6515   if (AOP_TYPE (right) == AOP_CRY &&
6516       AOP_TYPE (left) != AOP_CRY)
6517     {
6518       operand *tmp = right;
6519       right = left;
6520       left = tmp;
6521     }
6522   if (AOP_TYPE (right) == AOP_LIT)
6523     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6524
6525   size = AOP_SIZE (result);
6526
6527   // if(bit | yy)
6528   // xx = bit | yy;
6529   if (AOP_TYPE (left) == AOP_CRY)
6530     {
6531       if (AOP_TYPE (right) == AOP_LIT)
6532         {
6533           // c = bit & literal;
6534           if (lit)
6535             {
6536               // lit != 0 => result = 1
6537               if (AOP_TYPE (result) == AOP_CRY)
6538                 {
6539                   if (size)
6540                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6541                   else if (ifx)
6542                     continueIfTrue (ifx);
6543                   goto release;
6544                 }
6545               emitcode ("setb", "c");
6546             }
6547           else
6548             {
6549               // lit == 0 => result = left
6550               if (size && sameRegs (AOP (result), AOP (left)))
6551                 goto release;
6552               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6553             }
6554         }
6555       else
6556         {
6557           if (AOP_TYPE (right) == AOP_CRY)
6558             {
6559               // c = bit | bit;
6560               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6561               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6562             }
6563           else
6564             {
6565               // c = bit | val;
6566               symbol *tlbl = newiTempLabel (NULL);
6567               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6568                 emitcode ("setb", "c");
6569               emitcode ("jb", "%s,!tlabel",
6570                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6571               toBoolean (right);
6572               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6573               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6574                 {
6575                   jmpTrueOrFalse (ifx, tlbl);
6576                   goto release;
6577                 }
6578               else
6579                 {
6580                   CLRC;
6581                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6582                 }
6583             }
6584         }
6585       // bit = c
6586       // val = c
6587       if (size)
6588         outBitC (result);
6589       // if(bit | ...)
6590       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6591            genIfxJump (ifx, "c");
6592       goto release;
6593     }
6594
6595   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6596   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6597   if ((AOP_TYPE (right) == AOP_LIT) &&
6598       (AOP_TYPE (result) == AOP_CRY) &&
6599       (AOP_TYPE (left) != AOP_CRY))
6600     {
6601       if (lit)
6602         {
6603           // result = 1
6604           if (size)
6605             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6606           else
6607             continueIfTrue (ifx);
6608           goto release;
6609         }
6610       else
6611         {
6612           // lit = 0, result = boolean(left)
6613           if (size)
6614             emitcode ("setb", "c");
6615           toBoolean (right);
6616           if (size)
6617             {
6618               symbol *tlbl = newiTempLabel (NULL);
6619               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6620               CLRC;
6621               emitcode ("", "!tlabeldef", tlbl->key + 100);
6622             }
6623           else
6624             {
6625               genIfxJump (ifx, "a");
6626               goto release;
6627             }
6628         }
6629       outBitC (result);
6630       goto release;
6631     }
6632
6633   /* if left is same as result */
6634   if (sameRegs (AOP (result), AOP (left)))
6635     {
6636       for (; size--; offset++)
6637         {
6638           if (AOP_TYPE (right) == AOP_LIT)
6639             {
6640               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6641                 {
6642                   continue;
6643                 }
6644               else
6645                 {
6646                   if (IS_AOP_PREG (left))
6647                     {
6648                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6649                       emitcode ("orl", "a,%s",
6650                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6651                       aopPut (AOP (result), "a", offset);
6652                     }
6653                   else
6654                     {
6655                       emitcode ("orl", "%s,%s",
6656                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6657                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6658                     }
6659                 }
6660             }
6661           else
6662             {
6663               if (AOP_TYPE (left) == AOP_ACC)
6664                 {
6665                   emitcode ("orl", "a,%s",
6666                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6667                 }
6668               else
6669                 {
6670                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6671                   if (IS_AOP_PREG (left))
6672                     {
6673                       emitcode ("orl", "a,%s", 
6674                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6675                       aopPut (AOP (result), "a", offset);
6676                     }
6677                   else
6678                     {
6679                       emitcode ("orl", "%s,a",
6680                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6681                     }
6682                 }
6683             }
6684         }
6685     }
6686   else
6687     {
6688       // left & result in different registers
6689       if (AOP_TYPE (result) == AOP_CRY)
6690         {
6691           // result = bit
6692           // if(size), result in bit
6693           // if(!size && ifx), conditional oper: if(left | right)
6694           symbol *tlbl = newiTempLabel (NULL);
6695           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6696           if (size)
6697             emitcode ("setb", "c");
6698           while (sizer--)
6699             {
6700               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6701                 emitcode ("orl", "a,%s",
6702                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6703               } else {
6704                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6705                 emitcode ("orl", "a,%s",
6706                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6707               }
6708               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6709               offset++;
6710             }
6711           if (size)
6712             {
6713               CLRC;
6714               emitcode ("", "!tlabeldef", tlbl->key + 100);
6715               outBitC (result);
6716             }
6717           else if (ifx)
6718             jmpTrueOrFalse (ifx, tlbl);
6719         }
6720       else
6721         {
6722             _startLazyDPSEvaluation();
6723           for (; (size--); offset++)
6724             {
6725               // normal case
6726               // result = left & right
6727               if (AOP_TYPE (right) == AOP_LIT)
6728                 {
6729                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6730                     {
6731                       aopPut (AOP (result),
6732                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6733                               offset);
6734                       continue;
6735                     }
6736                   D (emitcode (";", "better literal OR."););
6737                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6738                   emitcode ("orl", "a, %s",
6739                             aopGet (AOP (right), offset,
6740                                     FALSE, FALSE, DP2_RESULT_REG));
6741
6742                 }
6743               else
6744                 {
6745                   // faster than result <- left, anl result,right
6746                   // and better if result is SFR
6747                   if (AOP_TYPE (left) == AOP_ACC)
6748                     {
6749                       emitcode ("orl", "a,%s",
6750                                 aopGet (AOP (right), offset,
6751                                         FALSE, FALSE, DP2_RESULT_REG));
6752                     }
6753                   else
6754                     {
6755                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6756                         
6757                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6758                       {
6759                           emitcode("mov", "b,a");
6760                           rOp = "b";
6761                       }
6762                         
6763                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6764                       emitcode ("orl", "a,%s", rOp);
6765                     }
6766                 }
6767               aopPut (AOP (result), "a", offset);
6768             }
6769             _endLazyDPSEvaluation();
6770         }
6771     }
6772
6773 release:
6774   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6775   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6776   freeAsmop (result, NULL, ic, TRUE);
6777 }
6778
6779 /*-----------------------------------------------------------------*/
6780 /* genXor - code for xclusive or                                   */
6781 /*-----------------------------------------------------------------*/
6782 static void
6783 genXor (iCode * ic, iCode * ifx)
6784 {
6785   operand *left, *right, *result;
6786   int size, offset = 0;
6787   unsigned long lit = 0L;
6788   bool pushResult;
6789
6790   D (emitcode (";", "genXor "););
6791
6792   AOP_OP_3_NOFATAL (ic, pushResult);
6793   AOP_SET_LOCALS (ic);
6794
6795   if (pushResult)
6796   {
6797       genFarFarLogicOp(ic, "xrl");
6798       return;
6799   }  
6800
6801 #ifdef DEBUG_TYPE
6802   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6803             AOP_TYPE (result),
6804             AOP_TYPE (left), AOP_TYPE (right));
6805   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6806             AOP_SIZE (result),
6807             AOP_SIZE (left), AOP_SIZE (right));
6808 #endif
6809
6810   /* if left is a literal & right is not ||
6811      if left needs acc & right does not */
6812   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6813 #ifdef LOGIC_OPS_BROKEN      
6814       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6815 #endif
6816      )
6817     {
6818       operand *tmp = right;
6819       right = left;
6820       left = tmp;
6821     }
6822
6823   /* if result = right then exchange them */
6824   if (sameRegs (AOP (result), AOP (right)))
6825     {
6826       operand *tmp = right;
6827       right = left;
6828       left = tmp;
6829     }
6830
6831   /* if right is bit then exchange them */
6832   if (AOP_TYPE (right) == AOP_CRY &&
6833       AOP_TYPE (left) != AOP_CRY)
6834     {
6835       operand *tmp = right;
6836       right = left;
6837       left = tmp;
6838     }
6839   if (AOP_TYPE (right) == AOP_LIT)
6840     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6841
6842   size = AOP_SIZE (result);
6843
6844   // if(bit ^ yy)
6845   // xx = bit ^ yy;
6846   if (AOP_TYPE (left) == AOP_CRY)
6847     {
6848       if (AOP_TYPE (right) == AOP_LIT)
6849         {
6850           // c = bit & literal;
6851           if (lit >> 1)
6852             {
6853               // lit>>1  != 0 => result = 1
6854               if (AOP_TYPE (result) == AOP_CRY)
6855                 {
6856                   if (size)
6857                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6858                   else if (ifx)
6859                     continueIfTrue (ifx);
6860                   goto release;
6861                 }
6862               emitcode ("setb", "c");
6863             }
6864           else
6865             {
6866               // lit == (0 or 1)
6867               if (lit == 0)
6868                 {
6869                   // lit == 0, result = left
6870                   if (size && sameRegs (AOP (result), AOP (left)))
6871                     goto release;
6872                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6873                 }
6874               else
6875                 {
6876                   // lit == 1, result = not(left)
6877                   if (size && sameRegs (AOP (result), AOP (left)))
6878                     {
6879                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6880                       goto release;
6881                     }
6882                   else
6883                     {
6884                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6885                       emitcode ("cpl", "c");
6886                     }
6887                 }
6888             }
6889
6890         }
6891       else
6892         {
6893           // right != literal
6894           symbol *tlbl = newiTempLabel (NULL);
6895           if (AOP_TYPE (right) == AOP_CRY)
6896             {
6897               // c = bit ^ bit;
6898               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6899             }
6900           else
6901             {
6902               int sizer = AOP_SIZE (right);
6903               // c = bit ^ val
6904               // if val>>1 != 0, result = 1
6905               emitcode ("setb", "c");
6906               while (sizer)
6907                 {
6908                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6909                   if (sizer == 1)
6910                     // test the msb of the lsb
6911                     emitcode ("anl", "a,#!constbyte",0xfe);
6912                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6913                   sizer--;
6914                 }
6915               // val = (0,1)
6916               emitcode ("rrc", "a");
6917             }
6918           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6919           emitcode ("cpl", "c");
6920           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6921         }
6922       // bit = c
6923       // val = c
6924       if (size)
6925         outBitC (result);
6926       // if(bit | ...)
6927       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6928         genIfxJump (ifx, "c");
6929       goto release;
6930     }
6931
6932   if (sameRegs (AOP (result), AOP (left)))
6933     {
6934       /* if left is same as result */
6935       for (; size--; offset++)
6936         {
6937           if (AOP_TYPE (right) == AOP_LIT)
6938             {
6939               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6940                 continue;
6941               else if (IS_AOP_PREG (left))
6942                 {
6943                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6944                   emitcode ("xrl", "a,%s",
6945                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6946                   aopPut (AOP (result), "a", offset);
6947                 }
6948               else
6949                 emitcode ("xrl", "%s,%s",
6950                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6951                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6952             }
6953           else
6954             {
6955               if (AOP_TYPE (left) == AOP_ACC)
6956                 emitcode ("xrl", "a,%s",
6957                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6958               else
6959                 {
6960                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6961                   if (IS_AOP_PREG (left))
6962                     {
6963                       emitcode ("xrl", "a,%s",
6964                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6965                       aopPut (AOP (result), "a", offset);
6966                     }
6967                   else
6968                     emitcode ("xrl", "%s,a",
6969                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6970                 }
6971             }
6972         }
6973     }
6974   else
6975     {
6976       // left & result in different registers
6977       if (AOP_TYPE (result) == AOP_CRY)
6978         {
6979           // result = bit
6980           // if(size), result in bit
6981           // if(!size && ifx), conditional oper: if(left ^ right)
6982           symbol *tlbl = newiTempLabel (NULL);
6983           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6984                   
6985           if (size)
6986             emitcode ("setb", "c");
6987           while (sizer--)
6988             {
6989               if ((AOP_TYPE (right) == AOP_LIT) &&
6990                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6991                 {
6992                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6993                 }
6994               else
6995                 {
6996                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6997                     emitcode ("xrl", "a,%s",
6998                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6999                   } else {
7000                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7001                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7002                       {
7003                           emitcode("mov", "b,a");
7004                           rOp = "b";
7005                       }
7006                         
7007                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7008                       emitcode ("xrl", "a,%s", rOp);                  
7009                   }
7010                 }
7011               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7012               offset++;
7013             }
7014           if (size)
7015             {
7016               CLRC;
7017               emitcode ("", "!tlabeldef", tlbl->key + 100);
7018               outBitC (result);
7019             }
7020           else if (ifx)
7021             jmpTrueOrFalse (ifx, tlbl);
7022         }
7023       else
7024         {
7025         for (; (size--); offset++)
7026           {
7027             // normal case
7028             // result = left & right
7029             if (AOP_TYPE (right) == AOP_LIT)
7030               {
7031                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7032                   {
7033                     aopPut (AOP (result),
7034                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7035                             offset);
7036                     continue;
7037                   }
7038                 D (emitcode (";", "better literal XOR."););
7039                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7040                 emitcode ("xrl", "a, %s",
7041                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7042               }
7043             else
7044               {
7045                 // faster than result <- left, anl result,right
7046                 // and better if result is SFR
7047                 if (AOP_TYPE (left) == AOP_ACC)
7048                   {
7049                     emitcode ("xrl", "a,%s",
7050                               aopGet (AOP (right), offset,
7051                                       FALSE, FALSE, DP2_RESULT_REG));
7052                   }
7053                 else
7054                   {
7055                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7056                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7057                       {
7058                           emitcode("mov", "b,a");
7059                           rOp = "b";
7060                       }
7061                         
7062                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7063                       emitcode ("xrl", "a,%s", rOp);
7064                   }
7065               }
7066             aopPut (AOP (result), "a", offset);
7067           }
7068         }
7069         
7070     }
7071
7072 release:
7073   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7074   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7075   freeAsmop (result, NULL, ic, TRUE);
7076 }
7077
7078 /*-----------------------------------------------------------------*/
7079 /* genInline - write the inline code out                           */
7080 /*-----------------------------------------------------------------*/
7081 static void
7082 genInline (iCode * ic)
7083 {
7084   char *buffer, *bp, *bp1;
7085
7086   D (emitcode (";", "genInline "); );
7087
7088   _G.inLine += (!options.asmpeep);
7089
7090   buffer = Safe_strdup(IC_INLINE(ic));
7091   bp = buffer;
7092   bp1 = buffer;
7093
7094   /* emit each line as a code */
7095   while (*bp)
7096     {
7097       if (*bp == '\n')
7098         {
7099           *bp++ = '\0';
7100           emitcode (bp1, "");
7101           bp1 = bp;
7102         }
7103       else
7104         {
7105           if (*bp == ':')
7106             {
7107               bp++;
7108               *bp = '\0';
7109               bp++;
7110               emitcode (bp1, "");
7111               bp1 = bp;
7112             }
7113           else
7114             bp++;
7115         }
7116     }
7117   if (bp1 != bp)
7118     emitcode (bp1, "");
7119   /*     emitcode("",buffer); */
7120   _G.inLine -= (!options.asmpeep);
7121 }
7122
7123 /*-----------------------------------------------------------------*/
7124 /* genRRC - rotate right with carry                                */
7125 /*-----------------------------------------------------------------*/
7126 static void
7127 genRRC (iCode * ic)
7128 {
7129   operand *left, *result;
7130   int     size, offset;
7131
7132   D (emitcode (";", "genRRC "););
7133
7134   /* rotate right with carry */
7135   left = IC_LEFT (ic);
7136   result = IC_RESULT (ic);
7137   aopOp (left, ic, FALSE, FALSE);
7138   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7139
7140   /* move it to the result */
7141   size = AOP_SIZE (result);
7142   offset = size - 1;
7143   CLRC;
7144
7145   _startLazyDPSEvaluation ();
7146   while (size--)
7147     {
7148       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7149       emitcode ("rrc", "a");
7150       if (AOP_SIZE (result) > 1)
7151         aopPut (AOP (result), "a", offset--);
7152     }
7153   _endLazyDPSEvaluation ();
7154
7155   /* now we need to put the carry into the
7156      highest order byte of the result */
7157   if (AOP_SIZE (result) > 1)
7158     {
7159       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7160     }
7161   emitcode ("mov", "acc.7,c");
7162   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7163   freeAsmop (left, NULL, ic, TRUE);
7164   freeAsmop (result, NULL, ic, TRUE);
7165 }
7166
7167 /*-----------------------------------------------------------------*/
7168 /* genRLC - generate code for rotate left with carry               */
7169 /*-----------------------------------------------------------------*/
7170 static void
7171 genRLC (iCode * ic)
7172 {
7173   operand *left, *result;
7174   int size, offset;
7175   char *l;
7176
7177   D (emitcode (";", "genRLC "););
7178
7179   /* rotate right with carry */
7180   left = IC_LEFT (ic);
7181   result = IC_RESULT (ic);
7182   aopOp (left, ic, FALSE, FALSE);
7183   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7184
7185   /* move it to the result */
7186   size = AOP_SIZE (result);
7187   offset = 0;
7188   if (size--)
7189     {
7190       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7191       MOVA (l);
7192       emitcode ("add", "a,acc");
7193       if (AOP_SIZE (result) > 1)
7194         {
7195           aopPut (AOP (result), "a", offset++);
7196         }
7197
7198       _startLazyDPSEvaluation ();
7199       while (size--)
7200         {
7201           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7202           MOVA (l);
7203           emitcode ("rlc", "a");
7204           if (AOP_SIZE (result) > 1)
7205             aopPut (AOP (result), "a", offset++);
7206         }
7207       _endLazyDPSEvaluation ();
7208     }
7209   /* now we need to put the carry into the
7210      highest order byte of the result */
7211   if (AOP_SIZE (result) > 1)
7212     {
7213       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7214       MOVA (l);
7215     }
7216   emitcode ("mov", "acc.0,c");
7217   aopPut (AOP (result), "a", 0);
7218   freeAsmop (left, NULL, ic, TRUE);
7219   freeAsmop (result, NULL, ic, TRUE);
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* genGetHbit - generates code get highest order bit               */
7224 /*-----------------------------------------------------------------*/
7225 static void
7226 genGetHbit (iCode * ic)
7227 {
7228   operand *left, *result;
7229   left = IC_LEFT (ic);
7230   result = IC_RESULT (ic);
7231   aopOp (left, ic, FALSE, FALSE);
7232   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7233
7234   D (emitcode (";", "genGetHbit "););
7235
7236   /* get the highest order byte into a */
7237   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7238   if (AOP_TYPE (result) == AOP_CRY)
7239     {
7240       emitcode ("rlc", "a");
7241       outBitC (result);
7242     }
7243   else
7244     {
7245       emitcode ("rl", "a");
7246       emitcode ("anl", "a,#1");
7247       outAcc (result);
7248     }
7249
7250
7251   freeAsmop (left, NULL, ic, TRUE);
7252   freeAsmop (result, NULL, ic, TRUE);
7253 }
7254
7255 /*-----------------------------------------------------------------*/
7256 /* AccRol - rotate left accumulator by known count                 */
7257 /*-----------------------------------------------------------------*/
7258 static void
7259 AccRol (int shCount)
7260 {
7261   shCount &= 0x0007;            // shCount : 0..7
7262
7263   switch (shCount)
7264     {
7265     case 0:
7266       break;
7267     case 1:
7268       emitcode ("rl", "a");
7269       break;
7270     case 2:
7271       emitcode ("rl", "a");
7272       emitcode ("rl", "a");
7273       break;
7274     case 3:
7275       emitcode ("swap", "a");
7276       emitcode ("rr", "a");
7277       break;
7278     case 4:
7279       emitcode ("swap", "a");
7280       break;
7281     case 5:
7282       emitcode ("swap", "a");
7283       emitcode ("rl", "a");
7284       break;
7285     case 6:
7286       emitcode ("rr", "a");
7287       emitcode ("rr", "a");
7288       break;
7289     case 7:
7290       emitcode ("rr", "a");
7291       break;
7292     }
7293 }
7294
7295 /*-----------------------------------------------------------------*/
7296 /* AccLsh - left shift accumulator by known count                  */
7297 /*-----------------------------------------------------------------*/
7298 static void
7299 AccLsh (int shCount)
7300 {
7301   if (shCount != 0)
7302     {
7303       if (shCount == 1)
7304         emitcode ("add", "a,acc");
7305       else if (shCount == 2)
7306         {
7307           emitcode ("add", "a,acc");
7308           emitcode ("add", "a,acc");
7309         }
7310       else
7311         {
7312           /* rotate left accumulator */
7313           AccRol (shCount);
7314           /* and kill the lower order bits */
7315           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7316         }
7317     }
7318 }
7319
7320 /*-----------------------------------------------------------------*/
7321 /* AccRsh - right shift accumulator by known count                 */
7322 /*-----------------------------------------------------------------*/
7323 static void
7324 AccRsh (int shCount)
7325 {
7326   if (shCount != 0)
7327     {
7328       if (shCount == 1)
7329         {
7330           CLRC;
7331           emitcode ("rrc", "a");
7332         }
7333       else
7334         {
7335           /* rotate right accumulator */
7336           AccRol (8 - shCount);
7337           /* and kill the higher order bits */
7338           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7339         }
7340     }
7341 }
7342
7343 #ifdef BETTER_LITERAL_SHIFT
7344 /*-----------------------------------------------------------------*/
7345 /* AccSRsh - signed right shift accumulator by known count                 */
7346 /*-----------------------------------------------------------------*/
7347 static void
7348 AccSRsh (int shCount)
7349 {
7350   symbol *tlbl;
7351   if (shCount != 0)
7352     {
7353       if (shCount == 1)
7354         {
7355           emitcode ("mov", "c,acc.7");
7356           emitcode ("rrc", "a");
7357         }
7358       else if (shCount == 2)
7359         {
7360           emitcode ("mov", "c,acc.7");
7361           emitcode ("rrc", "a");
7362           emitcode ("mov", "c,acc.7");
7363           emitcode ("rrc", "a");
7364         }
7365       else
7366         {
7367           tlbl = newiTempLabel (NULL);
7368           /* rotate right accumulator */
7369           AccRol (8 - shCount);
7370           /* and kill the higher order bits */
7371           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7372           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7373           emitcode ("orl", "a,#!constbyte",
7374                     (unsigned char) ~SRMask[shCount]);
7375           emitcode ("", "!tlabeldef", tlbl->key + 100);
7376         }
7377     }
7378 }
7379 #endif
7380
7381 #ifdef BETTER_LITERAL_SHIFT
7382 /*-----------------------------------------------------------------*/
7383 /* shiftR1Left2Result - shift right one byte from left to result   */
7384 /*-----------------------------------------------------------------*/
7385 static void
7386 shiftR1Left2Result (operand * left, int offl,
7387                     operand * result, int offr,
7388                     int shCount, int sign)
7389 {
7390   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7391   /* shift right accumulator */
7392   if (sign)
7393     AccSRsh (shCount);
7394   else
7395     AccRsh (shCount);
7396   aopPut (AOP (result), "a", offr);
7397 }
7398 #endif
7399
7400 #ifdef BETTER_LITERAL_SHIFT
7401 /*-----------------------------------------------------------------*/
7402 /* shiftL1Left2Result - shift left one byte from left to result    */
7403 /*-----------------------------------------------------------------*/
7404 static void
7405 shiftL1Left2Result (operand * left, int offl,
7406                     operand * result, int offr, int shCount)
7407 {
7408   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7409   /* shift left accumulator */
7410   AccLsh (shCount);
7411   aopPut (AOP (result), "a", offr);
7412 }
7413 #endif
7414
7415 #ifdef BETTER_LITERAL_SHIFT
7416 /*-----------------------------------------------------------------*/
7417 /* movLeft2Result - move byte from left to result                  */
7418 /*-----------------------------------------------------------------*/
7419 static void
7420 movLeft2Result (operand * left, int offl,
7421                 operand * result, int offr, int sign)
7422 {
7423   char *l;
7424   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7425   {
7426       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7427
7428       if (*l == '@' && (IS_AOP_PREG (result)))
7429       {
7430           emitcode ("mov", "a,%s", l);
7431           aopPut (AOP (result), "a", offr);
7432       }
7433       else
7434       {
7435           if (!sign)
7436           {
7437             aopPut (AOP (result), l, offr);
7438           }
7439           else
7440             {
7441               /* MSB sign in acc.7 ! */
7442               if (getDataSize (left) == offl + 1)
7443                 {
7444                   emitcode ("mov", "a,%s", l);
7445                   aopPut (AOP (result), "a", offr);
7446                 }
7447             }
7448       }
7449   }
7450 }
7451 #endif
7452
7453 #ifdef BETTER_LITERAL_SHIFT
7454 /*-----------------------------------------------------------------*/
7455 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7456 /*-----------------------------------------------------------------*/
7457 static void
7458 AccAXRrl1 (char *x)
7459 {
7460   emitcode ("rrc", "a");
7461   emitcode ("xch", "a,%s", x);
7462   emitcode ("rrc", "a");
7463   emitcode ("xch", "a,%s", x);
7464 }
7465 #endif
7466
7467 #ifdef BETTER_LITERAL_SHIFT
7468 //REMOVE ME!!!
7469 /*-----------------------------------------------------------------*/
7470 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7471 /*-----------------------------------------------------------------*/
7472 static void
7473 AccAXLrl1 (char *x)
7474 {
7475   emitcode ("xch", "a,%s", x);
7476   emitcode ("rlc", "a");
7477   emitcode ("xch", "a,%s", x);
7478   emitcode ("rlc", "a");
7479 }
7480 #endif
7481
7482 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7485 /*-----------------------------------------------------------------*/
7486 static void
7487 AccAXLsh1 (char *x)
7488 {
7489   emitcode ("xch", "a,%s", x);
7490   emitcode ("add", "a,acc");
7491   emitcode ("xch", "a,%s", x);
7492   emitcode ("rlc", "a");
7493 }
7494 #endif
7495
7496 #ifdef BETTER_LITERAL_SHIFT
7497 /*-----------------------------------------------------------------*/
7498 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7499 /*-----------------------------------------------------------------*/
7500 static void
7501 AccAXLsh (char *x, int shCount)
7502 {
7503   switch (shCount)
7504     {
7505     case 0:
7506       break;
7507     case 1:
7508       AccAXLsh1 (x);
7509       break;
7510     case 2:
7511       AccAXLsh1 (x);
7512       AccAXLsh1 (x);
7513       break;
7514     case 3:
7515     case 4:
7516     case 5:                     // AAAAABBB:CCCCCDDD
7517
7518       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7519
7520       emitcode ("anl", "a,#!constbyte",
7521                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7522
7523       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7524
7525       AccRol (shCount);         // DDDCCCCC:BBB00000
7526
7527       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7528
7529       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7530
7531       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7532
7533       emitcode ("anl", "a,#!constbyte",
7534                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7535
7536       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7537
7538       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7539
7540       break;
7541     case 6:                     // AAAAAABB:CCCCCCDD
7542       emitcode ("anl", "a,#!constbyte",
7543                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7544       emitcode ("mov", "c,acc.0");      // c = B
7545       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7546 #if 0
7547       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7548       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7549 #else
7550       emitcode("rrc","a"); 
7551       emitcode("xch","a,%s", x); 
7552       emitcode("rrc","a"); 
7553       emitcode("mov","c,acc.0"); //<< get correct bit 
7554       emitcode("xch","a,%s", x); 
7555
7556       emitcode("rrc","a"); 
7557       emitcode("xch","a,%s", x); 
7558       emitcode("rrc","a"); 
7559       emitcode("xch","a,%s", x); 
7560 #endif
7561       break;
7562     case 7:                     // a:x <<= 7
7563
7564       emitcode ("anl", "a,#!constbyte",
7565                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7566
7567       emitcode ("mov", "c,acc.0");      // c = B
7568
7569       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7570
7571       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7572
7573       break;
7574     default:
7575       break;
7576     }
7577 }
7578 #endif
7579
7580 #ifdef BETTER_LITERAL_SHIFT
7581 //REMOVE ME!!!
7582 /*-----------------------------------------------------------------*/
7583 /* AccAXRsh - right shift a:x known count (0..7)                   */
7584 /*-----------------------------------------------------------------*/
7585 static void
7586 AccAXRsh (char *x, int shCount)
7587 {
7588   switch (shCount)
7589     {
7590     case 0:
7591       break;
7592     case 1:
7593       CLRC;
7594       AccAXRrl1 (x);            // 0->a:x
7595
7596       break;
7597     case 2:
7598       CLRC;
7599       AccAXRrl1 (x);            // 0->a:x
7600
7601       CLRC;
7602       AccAXRrl1 (x);            // 0->a:x
7603
7604       break;
7605     case 3:
7606     case 4:
7607     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7608
7609       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7610
7611       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7612
7613       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7614
7615       emitcode ("anl", "a,#!constbyte",
7616                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7617
7618       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7619
7620       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7621
7622       emitcode ("anl", "a,#!constbyte",
7623                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7624
7625       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7626
7627       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7628
7629       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7630
7631       break;
7632     case 6:                     // AABBBBBB:CCDDDDDD
7633
7634       emitcode ("mov", "c,acc.7");
7635       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7636
7637       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7638
7639       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7640
7641       emitcode ("anl", "a,#!constbyte",
7642                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7643
7644       break;
7645     case 7:                     // ABBBBBBB:CDDDDDDD
7646
7647       emitcode ("mov", "c,acc.7");      // c = A
7648
7649       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7650
7651       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7652
7653       emitcode ("anl", "a,#!constbyte",
7654                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7655
7656       break;
7657     default:
7658       break;
7659     }
7660 }
7661 #endif
7662
7663 #ifdef BETTER_LITERAL_SHIFT
7664 /*-----------------------------------------------------------------*/
7665 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7666 /*-----------------------------------------------------------------*/
7667 static void
7668 AccAXRshS (char *x, int shCount)
7669 {
7670   symbol *tlbl;
7671   switch (shCount)
7672     {
7673     case 0:
7674       break;
7675     case 1:
7676       emitcode ("mov", "c,acc.7");
7677       AccAXRrl1 (x);            // s->a:x
7678
7679       break;
7680     case 2:
7681       emitcode ("mov", "c,acc.7");
7682       AccAXRrl1 (x);            // s->a:x
7683
7684       emitcode ("mov", "c,acc.7");
7685       AccAXRrl1 (x);            // s->a:x
7686
7687       break;
7688     case 3:
7689     case 4:
7690     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7691
7692       tlbl = newiTempLabel (NULL);
7693       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7694
7695       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7696
7697       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7698
7699       emitcode ("anl", "a,#!constbyte",
7700                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7701
7702       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7703
7704       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7705
7706       emitcode ("anl", "a,#!constbyte",
7707                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7708
7709       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7710
7711       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7712
7713       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7714
7715       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7716       emitcode ("orl", "a,#!constbyte",
7717                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7718
7719       emitcode ("", "!tlabeldef", tlbl->key + 100);
7720       break;                    // SSSSAAAA:BBBCCCCC
7721
7722     case 6:                     // AABBBBBB:CCDDDDDD
7723
7724       tlbl = newiTempLabel (NULL);
7725       emitcode ("mov", "c,acc.7");
7726       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7727
7728       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7729
7730       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7731
7732       emitcode ("anl", "a,#!constbyte",
7733                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7734
7735       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7736       emitcode ("orl", "a,#!constbyte",
7737                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7738
7739       emitcode ("", "!tlabeldef", tlbl->key + 100);
7740       break;
7741     case 7:                     // ABBBBBBB:CDDDDDDD
7742
7743       tlbl = newiTempLabel (NULL);
7744       emitcode ("mov", "c,acc.7");      // c = A
7745
7746       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7747
7748       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7749
7750       emitcode ("anl", "a,#!constbyte",
7751                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7752
7753       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7754       emitcode ("orl", "a,#!constbyte",
7755                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7756
7757       emitcode ("", "!tlabeldef", tlbl->key + 100);
7758       break;
7759     default:
7760       break;
7761     }
7762 }
7763 #endif
7764
7765 #ifdef BETTER_LITERAL_SHIFT
7766 static void
7767 _loadLeftIntoAx(char    **lsb, 
7768                 operand *left, 
7769                 operand *result,
7770                 int     offl,
7771                 int     offr)
7772 {
7773   // Get the initial value from left into a pair of registers.
7774   // MSB must be in A, LSB can be any register.
7775   //
7776   // If the result is held in registers, it is an optimization
7777   // if the LSB can be held in the register which will hold the,
7778   // result LSB since this saves us from having to copy it into
7779   // the result following AccAXLsh.
7780   //
7781   // If the result is addressed indirectly, this is not a gain.
7782   if (AOP_NEEDSACC(result))
7783   {
7784        char *leftByte;
7785        
7786        _startLazyDPSEvaluation();
7787       if (AOP_TYPE(left) == AOP_DPTR2)
7788        {
7789            // Get MSB in A.
7790            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7791            // get LSB in DP2_RESULT_REG.
7792            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7793            assert(!strcmp(leftByte, DP2_RESULT_REG));
7794        }
7795        else
7796        {
7797            // get LSB into DP2_RESULT_REG
7798            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7799            if (strcmp(leftByte, DP2_RESULT_REG))
7800            {
7801                TR_AP("#7");
7802                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7803            }
7804            // And MSB in A.
7805            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7806            assert(strcmp(leftByte, DP2_RESULT_REG));
7807            MOVA(leftByte);
7808        }
7809        _endLazyDPSEvaluation();
7810        *lsb = DP2_RESULT_REG;
7811   }
7812   else
7813   {
7814       if (sameRegs (AOP (result), AOP (left)) &&
7815         ((offl + MSB16) == offr))
7816       {
7817           /* don't crash result[offr] */
7818           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7819           emitcode ("xch", "a,%s", 
7820                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7821       }
7822       else
7823       {
7824           movLeft2Result (left, offl, result, offr, 0);
7825           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7826       }
7827       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7828       assert(strcmp(*lsb,"a"));      
7829   }
7830 }
7831
7832 static void
7833 _storeAxResults(char    *lsb,
7834                 operand *result,
7835                 int     offr)
7836 {
7837   _startLazyDPSEvaluation();
7838   if (AOP_NEEDSACC(result))
7839   {
7840       /* We have to explicitly update the result LSB.
7841        */
7842       emitcode("xch","a,%s", lsb);
7843       aopPut(AOP(result), "a", offr);
7844       emitcode("mov","a,%s", lsb);
7845   }
7846   if (getDataSize (result) > 1)
7847   {
7848       aopPut (AOP (result), "a", offr + MSB16);
7849   }
7850   _endLazyDPSEvaluation();
7851 }
7852
7853 /*-----------------------------------------------------------------*/
7854 /* shiftL2Left2Result - shift left two bytes from left to result   */
7855 /*-----------------------------------------------------------------*/
7856 static void
7857 shiftL2Left2Result (operand * left, int offl,
7858                     operand * result, int offr, int shCount)
7859 {
7860   char *lsb;
7861
7862   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7863   
7864   AccAXLsh (lsb, shCount);
7865   
7866   _storeAxResults(lsb, result, offr);
7867 }
7868 #endif
7869
7870 #ifdef BETTER_LITERAL_SHIFT
7871 /*-----------------------------------------------------------------*/
7872 /* shiftR2Left2Result - shift right two bytes from left to result  */
7873 /*-----------------------------------------------------------------*/
7874 static void
7875 shiftR2Left2Result (operand * left, int offl,
7876                     operand * result, int offr,
7877                     int shCount, int sign)
7878 {
7879   char *lsb;
7880   
7881   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7882   
7883   /* a:x >> shCount (x = lsb(result)) */
7884   if (sign)
7885   {
7886      AccAXRshS(lsb, shCount);
7887   }
7888   else
7889   {
7890     AccAXRsh(lsb, shCount);
7891   }
7892   
7893   _storeAxResults(lsb, result, offr);
7894 }
7895 #endif
7896
7897 #if 0
7898 //REMOVE ME!!!
7899 /*-----------------------------------------------------------------*/
7900 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7901 /*-----------------------------------------------------------------*/
7902 static void
7903 shiftLLeftOrResult (operand * left, int offl,
7904                     operand * result, int offr, int shCount)
7905 {
7906   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7907   /* shift left accumulator */
7908   AccLsh (shCount);
7909   /* or with result */
7910   emitcode ("orl", "a,%s",
7911             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7912   /* back to result */
7913   aopPut (AOP (result), "a", offr);
7914 }
7915 #endif
7916
7917 #if 0
7918 //REMOVE ME!!!
7919 /*-----------------------------------------------------------------*/
7920 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7921 /*-----------------------------------------------------------------*/
7922 static void
7923 shiftRLeftOrResult (operand * left, int offl,
7924                     operand * result, int offr, int shCount)
7925 {
7926   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7927   /* shift right accumulator */
7928   AccRsh (shCount);
7929   /* or with result */
7930   emitcode ("orl", "a,%s",
7931             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7932   /* back to result */
7933   aopPut (AOP (result), "a", offr);
7934 }
7935 #endif
7936
7937 #ifdef BETTER_LITERAL_SHIFT
7938 /*-----------------------------------------------------------------*/
7939 /* genlshOne - left shift a one byte quantity by known count       */
7940 /*-----------------------------------------------------------------*/
7941 static void
7942 genlshOne (operand * result, operand * left, int shCount)
7943 {
7944   D (emitcode (";", "genlshOne "););
7945   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7946 }
7947 #endif
7948
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* genlshTwo - left shift two bytes by known amount != 0           */
7952 /*-----------------------------------------------------------------*/
7953 static void
7954 genlshTwo (operand * result, operand * left, int shCount)
7955 {
7956   int size;
7957
7958   D (emitcode (";", "genlshTwo "););
7959
7960   size = getDataSize (result);
7961
7962   /* if shCount >= 8 */
7963   if (shCount >= 8)
7964   {
7965       shCount -= 8;
7966
7967       _startLazyDPSEvaluation();
7968
7969       if (size > 1)
7970         {
7971           if (shCount)
7972           {
7973             _endLazyDPSEvaluation();
7974             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7975             aopPut (AOP (result), zero, LSB);       
7976           }
7977           else
7978           {
7979             movLeft2Result (left, LSB, result, MSB16, 0);
7980             aopPut (AOP (result), zero, LSB);
7981             _endLazyDPSEvaluation();
7982           }
7983         }
7984         else
7985         {
7986           aopPut (AOP (result), zero, LSB);
7987           _endLazyDPSEvaluation();
7988         }
7989   }
7990
7991   /*  1 <= shCount <= 7 */
7992   else
7993     {
7994       if (size == 1)
7995       {
7996         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7997       }
7998       else
7999       {
8000         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8001       }
8002     }
8003 }
8004 #endif
8005
8006 #if 0
8007 //REMOVE ME!!!
8008 /*-----------------------------------------------------------------*/
8009 /* shiftLLong - shift left one long from left to result            */
8010 /* offl = LSB or MSB16                                             */
8011 /*-----------------------------------------------------------------*/
8012 static void
8013 shiftLLong (operand * left, operand * result, int offr)
8014 {
8015   char *l;
8016   int size = AOP_SIZE (result);
8017
8018   if (size >= LSB + offr)
8019     {
8020       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8021       MOVA (l);
8022       emitcode ("add", "a,acc");
8023       if (sameRegs (AOP (left), AOP (result)) &&
8024           size >= MSB16 + offr && offr != LSB)
8025         emitcode ("xch", "a,%s",
8026                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8027       else
8028         aopPut (AOP (result), "a", LSB + offr);
8029     }
8030
8031   if (size >= MSB16 + offr)
8032     {
8033       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8034         {
8035           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8036         }
8037       emitcode ("rlc", "a");
8038       if (sameRegs (AOP (left), AOP (result)) &&
8039           size >= MSB24 + offr && offr != LSB)
8040         emitcode ("xch", "a,%s",
8041                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8042       else
8043         aopPut (AOP (result), "a", MSB16 + offr);
8044     }
8045
8046   if (size >= MSB24 + offr)
8047     {
8048       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8049         {
8050           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8051         }
8052       emitcode ("rlc", "a");
8053       if (sameRegs (AOP (left), AOP (result)) &&
8054           size >= MSB32 + offr && offr != LSB)
8055         emitcode ("xch", "a,%s",
8056                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8057       else
8058         aopPut (AOP (result), "a", MSB24 + offr);
8059     }
8060
8061   if (size > MSB32 + offr)
8062     {
8063       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8064         {
8065           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8066         }
8067       emitcode ("rlc", "a");
8068       aopPut (AOP (result), "a", MSB32 + offr);
8069     }
8070   if (offr != LSB)
8071     aopPut (AOP (result), zero, LSB);
8072 }
8073 #endif
8074
8075 #if 0
8076 //REMOVE ME!!!
8077 /*-----------------------------------------------------------------*/
8078 /* genlshFour - shift four byte by a known amount != 0             */
8079 /*-----------------------------------------------------------------*/
8080 static void
8081 genlshFour (operand * result, operand * left, int shCount)
8082 {
8083   int size;
8084
8085   D (emitcode (";", "genlshFour ");
8086     );
8087
8088   size = AOP_SIZE (result);
8089
8090   /* if shifting more that 3 bytes */
8091   if (shCount >= 24)
8092     {
8093       shCount -= 24;
8094       if (shCount)
8095         /* lowest order of left goes to the highest
8096            order of the destination */
8097         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8098       else
8099         movLeft2Result (left, LSB, result, MSB32, 0);
8100       aopPut (AOP (result), zero, LSB);
8101       aopPut (AOP (result), zero, MSB16);
8102       aopPut (AOP (result), zero, MSB24);
8103       return;
8104     }
8105
8106   /* more than two bytes */
8107   else if (shCount >= 16)
8108     {
8109       /* lower order two bytes goes to higher order two bytes */
8110       shCount -= 16;
8111       /* if some more remaining */
8112       if (shCount)
8113         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8114       else
8115         {
8116           movLeft2Result (left, MSB16, result, MSB32, 0);
8117           movLeft2Result (left, LSB, result, MSB24, 0);
8118         }
8119       aopPut (AOP (result), zero, MSB16);
8120       aopPut (AOP (result), zero, LSB);
8121       return;
8122     }
8123
8124   /* if more than 1 byte */
8125   else if (shCount >= 8)
8126     {
8127       /* lower order three bytes goes to higher order  three bytes */
8128       shCount -= 8;
8129       if (size == 2)
8130         {
8131           if (shCount)
8132             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8133           else
8134             movLeft2Result (left, LSB, result, MSB16, 0);
8135         }
8136       else
8137         {                       /* size = 4 */
8138           if (shCount == 0)
8139             {
8140               movLeft2Result (left, MSB24, result, MSB32, 0);
8141               movLeft2Result (left, MSB16, result, MSB24, 0);
8142               movLeft2Result (left, LSB, result, MSB16, 0);
8143               aopPut (AOP (result), zero, LSB);
8144             }
8145           else if (shCount == 1)
8146             shiftLLong (left, result, MSB16);
8147           else
8148             {
8149               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8150               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8151               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8152               aopPut (AOP (result), zero, LSB);
8153             }
8154         }
8155     }
8156
8157   /* 1 <= shCount <= 7 */
8158   else if (shCount <= 2)
8159     {
8160       shiftLLong (left, result, LSB);
8161       if (shCount == 2)
8162         shiftLLong (result, result, LSB);
8163     }
8164   /* 3 <= shCount <= 7, optimize */
8165   else
8166     {
8167       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8168       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8169       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8170     }
8171 }
8172 #endif
8173
8174 #ifdef BETTER_LITERAL_SHIFT
8175 /*-----------------------------------------------------------------*/
8176 /* genLeftShiftLiteral - left shifting by known count              */
8177 /*-----------------------------------------------------------------*/
8178 static bool
8179 genLeftShiftLiteral (operand * left,
8180                      operand * right,
8181                      operand * result,
8182                      iCode * ic)
8183 {
8184   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8185   int size;
8186
8187   size = getSize (operandType (result));
8188
8189   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8190
8191   /* We only handle certain easy cases so far. */
8192   if ((shCount != 0)
8193    && (shCount < (size * 8))
8194    && (size != 1)
8195    && (size != 2))
8196   {
8197       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8198       return FALSE;
8199   }
8200
8201   freeAsmop (right, NULL, ic, TRUE);
8202
8203   aopOp(left, ic, FALSE, FALSE);
8204   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8205
8206 #if 0 // debug spew
8207   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8208   {
8209         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8210         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8211         {
8212            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8213         }
8214   }
8215   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8216   {
8217         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8218         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8219         {
8220            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8221         }       
8222   }  
8223 #endif
8224   
8225 #if VIEW_SIZE
8226   emitcode ("; shift left ", "result %d, left %d", size,
8227             AOP_SIZE (left));
8228 #endif
8229
8230   /* I suppose that the left size >= result size */
8231   if (shCount == 0)
8232   {
8233         _startLazyDPSEvaluation();
8234         while (size--)
8235         {
8236           movLeft2Result (left, size, result, size, 0);
8237         }
8238         _endLazyDPSEvaluation();
8239   }
8240   else if (shCount >= (size * 8))
8241   {
8242     _startLazyDPSEvaluation();
8243     while (size--)
8244     {
8245       aopPut (AOP (result), zero, size);
8246     }
8247     _endLazyDPSEvaluation();
8248   }
8249   else
8250   {
8251       switch (size)
8252         {
8253         case 1:
8254           genlshOne (result, left, shCount);
8255           break;
8256
8257         case 2:
8258           genlshTwo (result, left, shCount);
8259           break;
8260 #if 0
8261         case 4:
8262           genlshFour (result, left, shCount);
8263           break;
8264 #endif
8265         default:
8266           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8267           break;
8268         }
8269     }
8270   freeAsmop (left, NULL, ic, TRUE);
8271   freeAsmop (result, NULL, ic, TRUE);
8272   return TRUE;
8273 }
8274 #endif
8275
8276 /*-----------------------------------------------------------------*/
8277 /* genLeftShift - generates code for left shifting                 */
8278 /*-----------------------------------------------------------------*/
8279 static void
8280 genLeftShift (iCode * ic)
8281 {
8282   operand *left, *right, *result;
8283   int size, offset;
8284   char *l;
8285   symbol *tlbl, *tlbl1;
8286
8287   D (emitcode (";", "genLeftShift "););
8288
8289   right = IC_RIGHT (ic);
8290   left = IC_LEFT (ic);
8291   result = IC_RESULT (ic);
8292
8293   aopOp (right, ic, FALSE, FALSE);
8294
8295
8296 #ifdef BETTER_LITERAL_SHIFT
8297   /* if the shift count is known then do it
8298      as efficiently as possible */
8299   if (AOP_TYPE (right) == AOP_LIT)
8300     {
8301       if (genLeftShiftLiteral (left, right, result, ic))
8302       {
8303         return;
8304       }
8305     }
8306 #endif
8307
8308   /* shift count is unknown then we have to form
8309      a loop get the loop count in B : Note: we take
8310      only the lower order byte since shifting
8311      more that 32 bits make no sense anyway, ( the
8312      largest size of an object can be only 32 bits ) */
8313
8314   if (AOP_TYPE (right) == AOP_LIT)
8315   {
8316       /* Really should be handled by genLeftShiftLiteral,
8317        * but since I'm too lazy to fix that today, at least we can make
8318        * some small improvement.
8319        */
8320        emitcode("mov", "b,#!constbyte",
8321                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8322   }
8323   else
8324   {
8325       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8326       emitcode ("inc", "b");
8327   }
8328   freeAsmop (right, NULL, ic, TRUE);
8329   aopOp (left, ic, FALSE, FALSE);
8330   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8331
8332   /* now move the left to the result if they are not the
8333      same */
8334   if (!sameRegs (AOP (left), AOP (result)) &&
8335       AOP_SIZE (result) > 1)
8336     {
8337
8338       size = AOP_SIZE (result);
8339       offset = 0;
8340       _startLazyDPSEvaluation ();
8341       while (size--)
8342         {
8343           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8344           if (*l == '@' && (IS_AOP_PREG (result)))
8345             {
8346
8347               emitcode ("mov", "a,%s", l);
8348               aopPut (AOP (result), "a", offset);
8349             }
8350           else
8351             aopPut (AOP (result), l, offset);
8352           offset++;
8353         }
8354       _endLazyDPSEvaluation ();
8355     }
8356
8357   tlbl = newiTempLabel (NULL);
8358   size = AOP_SIZE (result);
8359   offset = 0;
8360   tlbl1 = newiTempLabel (NULL);
8361
8362   /* if it is only one byte then */
8363   if (size == 1)
8364     {
8365       symbol *tlbl1 = newiTempLabel (NULL);
8366
8367       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8368       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8369       emitcode ("", "!tlabeldef", tlbl->key + 100);
8370       emitcode ("add", "a,acc");
8371       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8372       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8373       aopPut (AOP (result), "a", 0);
8374       goto release;
8375     }
8376
8377   reAdjustPreg (AOP (result));
8378
8379   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8380   emitcode ("", "!tlabeldef", tlbl->key + 100);
8381   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8382   emitcode ("add", "a,acc");
8383   aopPut (AOP (result), "a", offset++);
8384   _startLazyDPSEvaluation ();
8385   while (--size)
8386     {
8387       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8388       emitcode ("rlc", "a");
8389       aopPut (AOP (result), "a", offset++);
8390     }
8391   _endLazyDPSEvaluation ();
8392   reAdjustPreg (AOP (result));
8393
8394   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8395   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8396 release:
8397   freeAsmop (left, NULL, ic, TRUE);
8398   freeAsmop (result, NULL, ic, TRUE);
8399 }
8400
8401 #ifdef BETTER_LITERAL_SHIFT
8402 /*-----------------------------------------------------------------*/
8403 /* genrshOne - right shift a one byte quantity by known count      */
8404 /*-----------------------------------------------------------------*/
8405 static void
8406 genrshOne (operand * result, operand * left,
8407            int shCount, int sign)
8408 {
8409   D (emitcode (";", "genrshOne"););
8410   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8411 }
8412 #endif
8413
8414 #ifdef BETTER_LITERAL_SHIFT
8415 /*-----------------------------------------------------------------*/
8416 /* genrshTwo - right shift two bytes by known amount != 0          */
8417 /*-----------------------------------------------------------------*/
8418 static void
8419 genrshTwo (operand * result, operand * left,
8420            int shCount, int sign)
8421 {
8422   D (emitcode (";", "genrshTwo"););
8423
8424   /* if shCount >= 8 */
8425   if (shCount >= 8)
8426     {
8427       shCount -= 8;
8428       _startLazyDPSEvaluation();
8429       if (shCount)
8430       {
8431         shiftR1Left2Result (left, MSB16, result, LSB,
8432                             shCount, sign);
8433       }                     
8434       else
8435       {
8436         movLeft2Result (left, MSB16, result, LSB, sign);
8437       }
8438       addSign (result, MSB16, sign);
8439       _endLazyDPSEvaluation();
8440     }
8441
8442   /*  1 <= shCount <= 7 */
8443   else
8444   {
8445     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8446   }
8447 }
8448 #endif
8449
8450 #if 0
8451 //REMOVE ME!!!
8452 /*-----------------------------------------------------------------*/
8453 /* shiftRLong - shift right one long from left to result           */
8454 /* offl = LSB or MSB16                                             */
8455 /*-----------------------------------------------------------------*/
8456 static void
8457 shiftRLong (operand * left, int offl,
8458             operand * result, int sign)
8459 {
8460   int isSameRegs=sameRegs(AOP(left),AOP(result));
8461
8462   if (isSameRegs && offl>1) {
8463     // we are in big trouble, but this shouldn't happen
8464     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8465   }
8466
8467   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8468   
8469   if (offl==MSB16) {
8470     // shift is > 8
8471     if (sign) {
8472       emitcode ("rlc", "a");
8473       emitcode ("subb", "a,acc");
8474       emitcode ("xch", "a,%s",
8475                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8476     } else {
8477       aopPut (AOP(result), zero, MSB32);
8478     }
8479   }
8480
8481   if (!sign) {
8482     emitcode ("clr", "c");
8483   } else {
8484     emitcode ("mov", "c,acc.7");
8485   }
8486
8487   emitcode ("rrc", "a");
8488
8489   if (isSameRegs && offl==MSB16) {
8490     emitcode ("xch",
8491               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8492   } else {
8493     aopPut (AOP (result), "a", MSB32);
8494     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8495   }
8496
8497   emitcode ("rrc", "a");
8498   if (isSameRegs && offl==1) {
8499     emitcode ("xch", "a,%s",
8500               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8501   } else {
8502     aopPut (AOP (result), "a", MSB24);
8503     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8504   }
8505   emitcode ("rrc", "a");
8506   aopPut (AOP (result), "a", MSB16 - offl);
8507
8508   if (offl == LSB)
8509     {
8510       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8511       emitcode ("rrc", "a");
8512       aopPut (AOP (result), "a", LSB);
8513     }
8514 }
8515 #endif
8516
8517 #if 0
8518 //REMOVE ME!!!
8519 /*-----------------------------------------------------------------*/
8520 /* genrshFour - shift four byte by a known amount != 0             */
8521 /*-----------------------------------------------------------------*/
8522 static void
8523 genrshFour (operand * result, operand * left,
8524             int shCount, int sign)
8525 {
8526   D (emitcode (";", "genrshFour");
8527     );
8528
8529   /* if shifting more that 3 bytes */
8530   if (shCount >= 24)
8531     {
8532       shCount -= 24;
8533       if (shCount)
8534         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8535       else
8536         movLeft2Result (left, MSB32, result, LSB, sign);
8537       addSign (result, MSB16, sign);
8538     }
8539   else if (shCount >= 16)
8540     {
8541       shCount -= 16;
8542       if (shCount)
8543         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8544       else
8545         {
8546           movLeft2Result (left, MSB24, result, LSB, 0);
8547           movLeft2Result (left, MSB32, result, MSB16, sign);
8548         }
8549       addSign (result, MSB24, sign);
8550     }
8551   else if (shCount >= 8)
8552     {
8553       shCount -= 8;
8554       if (shCount == 1)
8555         shiftRLong (left, MSB16, result, sign);
8556       else if (shCount == 0)
8557         {
8558           movLeft2Result (left, MSB16, result, LSB, 0);
8559           movLeft2Result (left, MSB24, result, MSB16, 0);
8560           movLeft2Result (left, MSB32, result, MSB24, sign);
8561           addSign (result, MSB32, sign);
8562         }
8563       else
8564         {
8565           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8566           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8567           /* the last shift is signed */
8568           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8569           addSign (result, MSB32, sign);
8570         }
8571     }
8572   else
8573     {                           /* 1 <= shCount <= 7 */
8574       if (shCount <= 2)
8575         {
8576           shiftRLong (left, LSB, result, sign);
8577           if (shCount == 2)
8578             shiftRLong (result, LSB, result, sign);
8579         }
8580       else
8581         {
8582           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8583           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8584           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8585         }
8586     }
8587 }
8588 #endif
8589
8590 #ifdef BETTER_LITERAL_SHIFT
8591 /*-----------------------------------------------------------------*/
8592 /* genRightShiftLiteral - right shifting by known count            */
8593 /*-----------------------------------------------------------------*/
8594 static bool
8595 genRightShiftLiteral (operand * left,
8596                       operand * right,
8597                       operand * result,
8598                       iCode * ic,
8599                       int sign)
8600 {
8601   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8602   int size;
8603
8604   size = getSize (operandType (result));
8605
8606   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8607
8608   /* We only handle certain easy cases so far. */
8609   if ((shCount != 0)
8610    && (shCount < (size * 8))
8611    && (size != 1)
8612    && (size != 2))
8613   {
8614       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8615       return FALSE;
8616   }
8617
8618   freeAsmop (right, NULL, ic, TRUE);
8619
8620   aopOp (left, ic, FALSE, FALSE);
8621   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8622
8623 #if VIEW_SIZE
8624   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8625             AOP_SIZE (left));
8626 #endif
8627
8628   /* test the LEFT size !!! */
8629
8630   /* I suppose that the left size >= result size */
8631   if (shCount == 0)
8632   {
8633       size = getDataSize (result);
8634       _startLazyDPSEvaluation();
8635       while (size--)
8636       {
8637         movLeft2Result (left, size, result, size, 0);
8638       }
8639       _endLazyDPSEvaluation();
8640   }
8641   else if (shCount >= (size * 8))
8642     {
8643       if (sign)
8644       {
8645         /* get sign in acc.7 */
8646         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8647       }
8648       addSign (result, LSB, sign);
8649     }
8650   else
8651     {
8652       switch (size)
8653         {
8654         case 1:
8655           genrshOne (result, left, shCount, sign);
8656           break;
8657
8658         case 2:
8659           genrshTwo (result, left, shCount, sign);
8660           break;
8661 #if 0
8662         case 4:
8663           genrshFour (result, left, shCount, sign);
8664           break;
8665 #endif    
8666         default:
8667           break;
8668         }
8669     }
8670   freeAsmop (left, NULL, ic, TRUE);
8671   freeAsmop (result, NULL, ic, TRUE);
8672   
8673   return TRUE;
8674 }
8675 #endif
8676
8677 /*-----------------------------------------------------------------*/
8678 /* genSignedRightShift - right shift of signed number              */
8679 /*-----------------------------------------------------------------*/
8680 static void
8681 genSignedRightShift (iCode * ic)
8682 {
8683   operand *right, *left, *result;
8684   int size, offset;
8685   char *l;
8686   symbol *tlbl, *tlbl1;
8687
8688   D (emitcode (";", "genSignedRightShift "););
8689
8690   /* we do it the hard way put the shift count in b
8691      and loop thru preserving the sign */
8692
8693   right = IC_RIGHT (ic);
8694   left = IC_LEFT (ic);
8695   result = IC_RESULT (ic);
8696
8697   aopOp (right, ic, FALSE, FALSE);
8698
8699 #ifdef BETTER_LITERAL_SHIFT
8700   if (AOP_TYPE (right) == AOP_LIT)
8701     {
8702       if (genRightShiftLiteral (left, right, result, ic, 1))
8703       {
8704         return;
8705       }
8706     }
8707 #endif
8708   /* shift count is unknown then we have to form
8709      a loop get the loop count in B : Note: we take
8710      only the lower order byte since shifting
8711      more that 32 bits make no sense anyway, ( the
8712      largest size of an object can be only 32 bits ) */
8713
8714   if (AOP_TYPE (right) == AOP_LIT)
8715   {
8716       /* Really should be handled by genRightShiftLiteral,
8717        * but since I'm too lazy to fix that today, at least we can make
8718        * some small improvement.
8719        */
8720        emitcode("mov", "b,#!constbyte",
8721                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8722   }
8723   else
8724   {
8725         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8726         emitcode ("inc", "b");
8727   }
8728   freeAsmop (right, NULL, ic, TRUE);
8729   aopOp (left, ic, FALSE, FALSE);
8730   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8731
8732   /* now move the left to the result if they are not the
8733      same */
8734   if (!sameRegs (AOP (left), AOP (result)) &&
8735       AOP_SIZE (result) > 1)
8736     {
8737
8738       size = AOP_SIZE (result);
8739       offset = 0;
8740       _startLazyDPSEvaluation ();
8741       while (size--)
8742         {
8743           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8744           if (*l == '@' && IS_AOP_PREG (result))
8745             {
8746
8747               emitcode ("mov", "a,%s", l);
8748               aopPut (AOP (result), "a", offset);
8749             }
8750           else
8751             aopPut (AOP (result), l, offset);
8752           offset++;
8753         }
8754       _endLazyDPSEvaluation ();
8755     }
8756
8757   /* mov the highest order bit to OVR */
8758   tlbl = newiTempLabel (NULL);
8759   tlbl1 = newiTempLabel (NULL);
8760
8761   size = AOP_SIZE (result);
8762   offset = size - 1;
8763   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8764   emitcode ("rlc", "a");
8765   emitcode ("mov", "ov,c");
8766   /* if it is only one byte then */
8767   if (size == 1)
8768     {
8769       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8770       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8771       emitcode ("", "!tlabeldef", tlbl->key + 100);
8772       emitcode ("mov", "c,ov");
8773       emitcode ("rrc", "a");
8774       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8775       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8776       aopPut (AOP (result), "a", 0);
8777       goto release;
8778     }
8779
8780   reAdjustPreg (AOP (result));
8781   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8782   emitcode ("", "!tlabeldef", tlbl->key + 100);
8783   emitcode ("mov", "c,ov");
8784   _startLazyDPSEvaluation ();
8785   while (size--)
8786     {
8787       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8788       emitcode ("rrc", "a");
8789       aopPut (AOP (result), "a", offset--);
8790     }
8791   _endLazyDPSEvaluation ();
8792   reAdjustPreg (AOP (result));
8793   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8794   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8795
8796 release:
8797   freeAsmop (left, NULL, ic, TRUE);
8798   freeAsmop (result, NULL, ic, TRUE);
8799 }
8800
8801 /*-----------------------------------------------------------------*/
8802 /* genRightShift - generate code for right shifting                */
8803 /*-----------------------------------------------------------------*/
8804 static void
8805 genRightShift (iCode * ic)
8806 {
8807   operand *right, *left, *result;
8808   sym_link *retype;
8809   int size, offset;
8810   char *l;
8811   symbol *tlbl, *tlbl1;
8812
8813   D (emitcode (";", "genRightShift "););
8814
8815   /* if signed then we do it the hard way preserve the
8816      sign bit moving it inwards */
8817   retype = getSpec (operandType (IC_RESULT (ic)));
8818
8819   if (!SPEC_USIGN (retype))
8820     {
8821       genSignedRightShift (ic);
8822       return;
8823     }
8824
8825   /* signed & unsigned types are treated the same : i.e. the
8826      signed is NOT propagated inwards : quoting from the
8827      ANSI - standard : "for E1 >> E2, is equivalent to division
8828      by 2**E2 if unsigned or if it has a non-negative value,
8829      otherwise the result is implementation defined ", MY definition
8830      is that the sign does not get propagated */
8831
8832   right = IC_RIGHT (ic);
8833   left = IC_LEFT (ic);
8834   result = IC_RESULT (ic);
8835
8836   aopOp (right, ic, FALSE, FALSE);
8837
8838 #ifdef BETTER_LITERAL_SHIFT
8839   /* if the shift count is known then do it
8840      as efficiently as possible */
8841   if (AOP_TYPE (right) == AOP_LIT)
8842     {
8843       if (genRightShiftLiteral (left, right, result, ic, 0))
8844       {
8845         return;
8846       }
8847     }
8848 #endif
8849
8850   /* shift count is unknown then we have to form
8851      a loop get the loop count in B : Note: we take
8852      only the lower order byte since shifting
8853      more that 32 bits make no sense anyway, ( the
8854      largest size of an object can be only 32 bits ) */
8855   
8856   if (AOP_TYPE (right) == AOP_LIT)
8857   {
8858       /* Really should be handled by genRightShiftLiteral,
8859        * but since I'm too lazy to fix that today, at least we can make
8860        * some small improvement.
8861        */
8862        emitcode("mov", "b,#!constbyte",
8863                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8864   }
8865   else
8866   {
8867       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8868       emitcode ("inc", "b");
8869   }
8870   freeAsmop (right, NULL, ic, TRUE);
8871   aopOp (left, ic, FALSE, FALSE);
8872   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8873
8874   /* now move the left to the result if they are not the
8875      same */
8876   if (!sameRegs (AOP (left), AOP (result)) &&
8877       AOP_SIZE (result) > 1)
8878     {
8879
8880       size = AOP_SIZE (result);
8881       offset = 0;
8882       _startLazyDPSEvaluation ();
8883       while (size--)
8884         {
8885           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8886           if (*l == '@' && IS_AOP_PREG (result))
8887             {
8888
8889               emitcode ("mov", "a,%s", l);
8890               aopPut (AOP (result), "a", offset);
8891             }
8892           else
8893             aopPut (AOP (result), l, offset);
8894           offset++;
8895         }
8896       _endLazyDPSEvaluation ();
8897     }
8898
8899   tlbl = newiTempLabel (NULL);
8900   tlbl1 = newiTempLabel (NULL);
8901   size = AOP_SIZE (result);
8902   offset = size - 1;
8903
8904   /* if it is only one byte then */
8905   if (size == 1)
8906     {
8907       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8908       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8909       emitcode ("", "!tlabeldef", tlbl->key + 100);
8910       CLRC;
8911       emitcode ("rrc", "a");
8912       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8913       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8914       aopPut (AOP (result), "a", 0);
8915       goto release;
8916     }
8917
8918   reAdjustPreg (AOP (result));
8919   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8920   emitcode ("", "!tlabeldef", tlbl->key + 100);
8921   CLRC;
8922   _startLazyDPSEvaluation ();
8923   while (size--)
8924     {
8925       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8926       emitcode ("rrc", "a");
8927       aopPut (AOP (result), "a", offset--);
8928     }
8929   _endLazyDPSEvaluation ();
8930   reAdjustPreg (AOP (result));
8931
8932   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8933   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8934
8935 release:
8936   freeAsmop (left, NULL, ic, TRUE);
8937   freeAsmop (result, NULL, ic, TRUE);
8938 }
8939
8940 /*-----------------------------------------------------------------*/
8941 /* genUnpackBits - generates code for unpacking bits               */
8942 /*-----------------------------------------------------------------*/
8943 static void
8944 genUnpackBits (operand * result, char *rname, int ptype)
8945 {
8946   int shCnt;
8947   int rlen;
8948   sym_link *etype;
8949   int offset = 0;
8950
8951   D (emitcode (";", "genUnpackBits "););
8952
8953   etype = getSpec (operandType (result));
8954
8955   /* read the first byte  */
8956   switch (ptype)
8957     {
8958
8959     case POINTER:
8960     case IPOINTER:
8961       emitcode ("mov", "a,@%s", rname);
8962       break;
8963
8964     case PPOINTER:
8965       emitcode ("movx", "a,@%s", rname);
8966       break;
8967
8968     case FPOINTER:
8969       emitcode ("movx", "a,@dptr");
8970       break;
8971
8972     case CPOINTER:
8973       emitcode ("clr", "a");
8974       emitcode ("movc", "a,@a+dptr");
8975       break;
8976
8977     case GPOINTER:
8978       emitcode ("lcall", "__gptrget");
8979       break;
8980     }
8981
8982   /* if we have bitdisplacement then it fits   */
8983   /* into this byte completely or if length is */
8984   /* less than a byte                          */
8985   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8986     {
8987
8988       /* shift right acc */
8989       AccRsh (shCnt);
8990
8991       emitcode ("anl", "a,#!constbyte",
8992                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8993       aopPut (AOP (result), "a", offset);
8994       return;
8995     }
8996
8997   /* bit field did not fit in a byte  */
8998   rlen = SPEC_BLEN (etype) - 8;
8999   aopPut (AOP (result), "a", offset++);
9000
9001   while (1)
9002     {
9003
9004       switch (ptype)
9005         {
9006         case POINTER:
9007         case IPOINTER:
9008           emitcode ("inc", "%s", rname);
9009           emitcode ("mov", "a,@%s", rname);
9010           break;
9011
9012         case PPOINTER:
9013           emitcode ("inc", "%s", rname);
9014           emitcode ("movx", "a,@%s", rname);
9015           break;
9016
9017         case FPOINTER:
9018           emitcode ("inc", "dptr");
9019           emitcode ("movx", "a,@dptr");
9020           break;
9021
9022         case CPOINTER:
9023           emitcode ("clr", "a");
9024           emitcode ("inc", "dptr");
9025           emitcode ("movc", "a,@a+dptr");
9026           break;
9027
9028         case GPOINTER:
9029           emitcode ("inc", "dptr");
9030           emitcode ("lcall", "__gptrget");
9031           break;
9032         }
9033
9034       rlen -= 8;
9035       /* if we are done */
9036       if (rlen < 8)
9037         break;
9038
9039       aopPut (AOP (result), "a", offset++);
9040
9041     }
9042
9043   if (rlen)
9044     {
9045       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9046       aopPut (AOP (result), "a", offset);
9047     }
9048
9049   return;
9050 }
9051
9052
9053 /*-----------------------------------------------------------------*/
9054 /* genDataPointerGet - generates code when ptr offset is known     */
9055 /*-----------------------------------------------------------------*/
9056 static void
9057 genDataPointerGet (operand * left,
9058                    operand * result,
9059                    iCode * ic)
9060 {
9061   char *l;
9062   char buff[256];
9063   int size, offset = 0;
9064   aopOp (result, ic, TRUE, FALSE);
9065
9066   /* get the string representation of the name */
9067   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9068   size = AOP_SIZE (result);
9069   _startLazyDPSEvaluation ();
9070   while (size--)
9071     {
9072         if (offset)
9073         {
9074             SNPRINTF (buff, sizeof(buff), 
9075                       "(%s + %d)", l + 1, offset);
9076         }
9077         else
9078         {
9079             SNPRINTF (buff, sizeof(buff), 
9080                       "%s", l + 1);
9081         }
9082       aopPut (AOP (result), buff, offset++);
9083     }
9084   _endLazyDPSEvaluation ();
9085
9086   freeAsmop (left, NULL, ic, TRUE);
9087   freeAsmop (result, NULL, ic, TRUE);
9088 }
9089
9090 /*-----------------------------------------------------------------*/
9091 /* genNearPointerGet - emitcode for near pointer fetch             */
9092 /*-----------------------------------------------------------------*/
9093 static void
9094 genNearPointerGet (operand * left,
9095                    operand * result,
9096                    iCode * ic,
9097                    iCode *pi)
9098 {
9099   asmop *aop = NULL;
9100   regs *preg;
9101   char *rname;
9102   sym_link *rtype, *retype, *letype;
9103   sym_link *ltype = operandType (left);
9104   char buff[80];
9105
9106   rtype = operandType (result);
9107   retype = getSpec (rtype);
9108   letype = getSpec (ltype);
9109
9110   aopOp (left, ic, FALSE, FALSE);
9111
9112   /* if left is rematerialisable and
9113      result is not bit variable type and
9114      the left is pointer to data space i.e
9115      lower 128 bytes of space */
9116   if (AOP_TYPE (left) == AOP_IMMD &&
9117       !IS_BITVAR (retype) &&
9118       !IS_BITVAR (letype) &&
9119       DCL_TYPE (ltype) == POINTER)
9120     {
9121       genDataPointerGet (left, result, ic);
9122       return;
9123     }
9124
9125   /* if the value is already in a pointer register
9126      then don't need anything more */
9127   if (!AOP_INPREG (AOP (left)))
9128     {
9129       /* otherwise get a free pointer register */
9130       aop = newAsmop (0);
9131       preg = getFreePtr (ic, &aop, FALSE);
9132       emitcode ("mov", "%s,%s",
9133                 preg->name,
9134                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9135       rname = preg->name;
9136     }
9137   else
9138     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9139
9140   freeAsmop (left, NULL, ic, TRUE);
9141   aopOp (result, ic, FALSE, FALSE);
9142
9143   /* if bitfield then unpack the bits */
9144   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9145     genUnpackBits (result, rname, POINTER);
9146   else
9147     {
9148       /* we have can just get the values */
9149       int size = AOP_SIZE (result);
9150       int offset = 0;
9151
9152       while (size--)
9153         {
9154           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9155             {
9156
9157               emitcode ("mov", "a,@%s", rname);
9158               aopPut (AOP (result), "a", offset);
9159             }
9160           else
9161             {
9162               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9163               aopPut (AOP (result), buff, offset);
9164             }
9165           offset++;
9166           if (size || pi)
9167             {
9168                 emitcode ("inc", "%s", rname);
9169             }
9170         }
9171     }
9172
9173   /* now some housekeeping stuff */
9174   if (aop)
9175     {
9176       /* we had to allocate for this iCode */
9177       if (pi) { /* post increment present */
9178         aopPut(AOP ( left ),rname,0);
9179       }
9180       freeAsmop (NULL, aop, ic, TRUE);
9181     }
9182   else
9183     {
9184       /* we did not allocate which means left
9185          already in a pointer register, then
9186          if size > 0 && this could be used again
9187          we have to point it back to where it
9188          belongs */
9189       if (AOP_SIZE (result) > 1 &&
9190           !OP_SYMBOL (left)->remat &&
9191           (OP_SYMBOL (left)->liveTo > ic->seq ||
9192            ic->depth) &&
9193           !pi)
9194         {
9195           int size = AOP_SIZE (result) - 1;
9196           while (size--)
9197             emitcode ("dec", "%s", rname);
9198         }
9199     }
9200
9201   /* done */
9202   freeAsmop (result, NULL, ic, TRUE);
9203   if (pi) pi->generated = 1;
9204 }
9205
9206 /*-----------------------------------------------------------------*/
9207 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9208 /*-----------------------------------------------------------------*/
9209 static void
9210 genPagedPointerGet (operand * left,
9211                     operand * result,
9212                     iCode * ic,
9213                     iCode * pi)
9214 {
9215   asmop *aop = NULL;
9216   regs *preg;
9217   char *rname;
9218   sym_link *rtype, *retype, *letype;
9219
9220   rtype = operandType (result);
9221   retype = getSpec (rtype);
9222   letype = getSpec (operandType (left));
9223   aopOp (left, ic, FALSE, FALSE);
9224
9225   /* if the value is already in a pointer register
9226      then don't need anything more */
9227   if (!AOP_INPREG (AOP (left)))
9228     {
9229       /* otherwise get a free pointer register */
9230       aop = newAsmop (0);
9231       preg = getFreePtr (ic, &aop, FALSE);
9232       emitcode ("mov", "%s,%s",
9233                 preg->name,
9234                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9235       rname = preg->name;
9236     }
9237   else
9238     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9239
9240   freeAsmop (left, NULL, ic, TRUE);
9241   aopOp (result, ic, FALSE, FALSE);
9242
9243   /* if bitfield then unpack the bits */
9244   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9245     genUnpackBits (result, rname, PPOINTER);
9246   else
9247     {
9248       /* we have can just get the values */
9249       int size = AOP_SIZE (result);
9250       int offset = 0;
9251
9252       while (size--)
9253         {
9254
9255           emitcode ("movx", "a,@%s", rname);
9256           aopPut (AOP (result), "a", offset);
9257
9258           offset++;
9259
9260           if (size || pi)
9261             emitcode ("inc", "%s", rname);
9262         }
9263     }
9264
9265   /* now some housekeeping stuff */
9266   if (aop)
9267     {
9268       /* we had to allocate for this iCode */
9269       if (pi) aopPut ( AOP (left), rname, 0);
9270       freeAsmop (NULL, aop, ic, TRUE);
9271     }
9272   else
9273     {
9274       /* we did not allocate which means left
9275          already in a pointer register, then
9276          if size > 0 && this could be used again
9277          we have to point it back to where it
9278          belongs */
9279       if (AOP_SIZE (result) > 1 &&
9280           !OP_SYMBOL (left)->remat &&
9281           (OP_SYMBOL (left)->liveTo > ic->seq ||
9282            ic->depth) &&
9283           !pi)
9284         {
9285           int size = AOP_SIZE (result) - 1;
9286           while (size--)
9287             emitcode ("dec", "%s", rname);
9288         }
9289     }
9290
9291   /* done */
9292   freeAsmop (result, NULL, ic, TRUE);
9293   if (pi) pi->generated = 1;
9294 }
9295
9296 /*-----------------------------------------------------------------*/
9297 /* genFarPointerGet - gget value from far space                    */
9298 /*-----------------------------------------------------------------*/
9299 static void
9300 genFarPointerGet (operand * left,
9301                   operand * result, iCode * ic, iCode *pi)
9302 {
9303     int size, offset, dopi=1;
9304   sym_link *retype = getSpec (operandType (result));
9305   sym_link *letype = getSpec (operandType (left));
9306   D (emitcode (";", "genFarPointerGet"););
9307
9308   aopOp (left, ic, FALSE, FALSE);
9309
9310   /* if the operand is already in dptr
9311      then we do nothing else we move the value to dptr */
9312   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9313     {
9314       /* if this is remateriazable */
9315       if (AOP_TYPE (left) == AOP_IMMD)
9316         {
9317           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9318         }
9319       else
9320         {
9321           /* we need to get it byte by byte */
9322           _startLazyDPSEvaluation ();
9323           if (AOP_TYPE (left) != AOP_DPTR)
9324             {
9325               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9326               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9327               if (options.model == MODEL_FLAT24)
9328                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9329             }
9330           else
9331             {
9332               /* We need to generate a load to DPTR indirect through DPTR. */
9333               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9334               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9335               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9336               if (options.model == MODEL_FLAT24)
9337                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9338               emitcode ("pop", "dph");
9339               emitcode ("pop", "dpl");
9340               dopi =0;
9341             }
9342           _endLazyDPSEvaluation ();
9343         }
9344     }
9345   /* so dptr know contains the address */
9346   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9347
9348   /* if bit then unpack */
9349   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9350       if (AOP_INDPTRn(left)) {
9351           genSetDPTR(AOP(left)->aopu.dptr);
9352       }
9353       genUnpackBits (result, "dptr", FPOINTER);
9354       if (AOP_INDPTRn(left)) {
9355           genSetDPTR(0);
9356       }
9357   } else
9358     {
9359       size = AOP_SIZE (result);
9360       offset = 0;
9361
9362       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9363           while (size--) {
9364               genSetDPTR(AOP(left)->aopu.dptr);
9365               emitcode ("movx", "a,@dptr");
9366               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9367                   emitcode ("inc", "dptr");
9368               genSetDPTR (0);
9369               aopPut (AOP (result), "a", offset++);
9370           }
9371       } else {
9372           _startLazyDPSEvaluation ();
9373           while (size--) {
9374               if (AOP_INDPTRn(left)) {
9375                   genSetDPTR(AOP(left)->aopu.dptr);
9376               } else {
9377                   genSetDPTR (0);
9378               }
9379               _flushLazyDPS ();
9380               
9381               emitcode ("movx", "a,@dptr");
9382               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9383                   emitcode ("inc", "dptr");
9384               
9385               aopPut (AOP (result), "a", offset++);
9386           }
9387           _endLazyDPSEvaluation ();
9388       }
9389     }
9390   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9391       if (!AOP_INDPTRn(left)) {
9392           _startLazyDPSEvaluation ();
9393           aopPut ( AOP (left), "dpl", 0);
9394           aopPut ( AOP (left), "dph", 1);
9395           if (options.model == MODEL_FLAT24)
9396               aopPut ( AOP (left), "dpx", 2);
9397           _endLazyDPSEvaluation ();
9398       }
9399     pi->generated = 1;
9400   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9401              AOP_SIZE(result) > 1 &&
9402              IS_SYMOP(left) &&
9403              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9404       
9405       size = AOP_SIZE (result) - 1;
9406       if (AOP_INDPTRn(left)) {
9407           genSetDPTR(AOP(left)->aopu.dptr);
9408       }
9409       while (size--) emitcode ("lcall","__decdptr");
9410       if (AOP_INDPTRn(left)) {
9411           genSetDPTR(0);
9412       }
9413   }
9414
9415   freeAsmop (left, NULL, ic, TRUE);
9416   freeAsmop (result, NULL, ic, TRUE);
9417 }
9418
9419 /*-----------------------------------------------------------------*/
9420 /* genCodePointerGet - get value from code space                  */
9421 /*-----------------------------------------------------------------*/
9422 static void
9423 genCodePointerGet (operand * left,
9424                     operand * result, iCode * ic, iCode *pi)
9425 {
9426   int size, offset, dopi=1;
9427   sym_link *retype = getSpec (operandType (result));
9428
9429   aopOp (left, ic, FALSE, FALSE);
9430
9431   /* if the operand is already in dptr
9432      then we do nothing else we move the value to dptr */
9433   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9434     {
9435       /* if this is remateriazable */
9436       if (AOP_TYPE (left) == AOP_IMMD)
9437         {
9438           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9439         }
9440       else
9441         {                       /* we need to get it byte by byte */
9442           _startLazyDPSEvaluation ();
9443           if (AOP_TYPE (left) != AOP_DPTR)
9444             {
9445               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9446               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9447               if (options.model == MODEL_FLAT24)
9448                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9449             }
9450           else
9451             {
9452               /* We need to generate a load to DPTR indirect through DPTR. */
9453               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9454               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9455               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9456               if (options.model == MODEL_FLAT24)
9457                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9458               emitcode ("pop", "dph");
9459               emitcode ("pop", "dpl");
9460               dopi=0;
9461             }
9462           _endLazyDPSEvaluation ();
9463         }
9464     }
9465   /* so dptr know contains the address */
9466   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9467
9468   /* if bit then unpack */
9469   if (IS_BITVAR (retype)) {
9470       if (AOP_INDPTRn(left)) {
9471           genSetDPTR(AOP(left)->aopu.dptr);
9472       }
9473       genUnpackBits (result, "dptr", CPOINTER);
9474       if (AOP_INDPTRn(left)) {
9475           genSetDPTR(0);
9476       }
9477   } else
9478     {
9479       size = AOP_SIZE (result);
9480       offset = 0;
9481       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9482           while (size--) {
9483               genSetDPTR(AOP(left)->aopu.dptr);
9484               emitcode ("clr", "a");
9485               emitcode ("movc", "a,@a+dptr");
9486               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9487                   emitcode ("inc", "dptr");
9488               genSetDPTR (0);
9489               aopPut (AOP (result), "a", offset++);
9490           }
9491       } else {
9492           _startLazyDPSEvaluation ();
9493           while (size--)
9494               {
9495                   if (AOP_INDPTRn(left)) {
9496                       genSetDPTR(AOP(left)->aopu.dptr);
9497                   } else {
9498                       genSetDPTR (0);
9499                   }
9500                   _flushLazyDPS ();
9501                   
9502                   emitcode ("clr", "a");
9503                   emitcode ("movc", "a,@a+dptr");
9504                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9505                       emitcode ("inc", "dptr");
9506                   aopPut (AOP (result), "a", offset++);
9507               }
9508           _endLazyDPSEvaluation ();
9509       }
9510     }
9511   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9512       if (!AOP_INDPTRn(left)) {
9513           _startLazyDPSEvaluation ();
9514           
9515           aopPut ( AOP (left), "dpl", 0);
9516           aopPut ( AOP (left), "dph", 1);
9517           if (options.model == MODEL_FLAT24)
9518               aopPut ( AOP (left), "dpx", 2);
9519
9520           _endLazyDPSEvaluation ();
9521       }
9522       pi->generated = 1;
9523   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9524              AOP_SIZE(result) > 1 &&
9525              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9526       
9527       size = AOP_SIZE (result) - 1;
9528       if (AOP_INDPTRn(left)) {
9529           genSetDPTR(AOP(left)->aopu.dptr);
9530       }
9531       while (size--) emitcode ("lcall","__decdptr");
9532       if (AOP_INDPTRn(left)) {
9533           genSetDPTR(0);
9534       }
9535   }
9536   
9537   freeAsmop (left, NULL, ic, TRUE);
9538   freeAsmop (result, NULL, ic, TRUE);
9539 }
9540
9541 /*-----------------------------------------------------------------*/
9542 /* genGenPointerGet - gget value from generic pointer space        */
9543 /*-----------------------------------------------------------------*/
9544 static void
9545 genGenPointerGet (operand * left,
9546                   operand * result, iCode * ic, iCode * pi)
9547 {
9548   int size, offset;
9549   sym_link *retype = getSpec (operandType (result));
9550   sym_link *letype = getSpec (operandType (left));
9551
9552   D (emitcode (";", "genGenPointerGet "); );
9553
9554   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9555
9556   /* if the operand is already in dptr
9557      then we do nothing else we move the value to dptr */
9558   if (AOP_TYPE (left) != AOP_STR)
9559     {
9560       /* if this is remateriazable */
9561       if (AOP_TYPE (left) == AOP_IMMD)
9562         {
9563           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9564           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9565             {
9566                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9567             }
9568             else
9569             {
9570                 emitcode ("mov", "b,#%d", pointerCode (retype));
9571             }
9572         }
9573       else
9574         {                       /* we need to get it byte by byte */
9575             _startLazyDPSEvaluation ();
9576             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9577             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9578             if (options.model == MODEL_FLAT24) {
9579                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9580                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9581             } else {
9582                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9583             }
9584             _endLazyDPSEvaluation ();
9585         }
9586     }
9587
9588   /* so dptr-b now contains the address */
9589   _G.bInUse++;
9590   aopOp (result, ic, FALSE, TRUE);
9591   _G.bInUse--;
9592
9593   /* if bit then unpack */
9594   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9595   {
9596     genUnpackBits (result, "dptr", GPOINTER);
9597   }
9598   else
9599     {
9600         size = AOP_SIZE (result);
9601         offset = 0;
9602
9603         while (size--)
9604         {
9605             if (size)
9606             {
9607                 // Get two bytes at a time, results in _AP & A.
9608                 // dptr will be incremented ONCE by __gptrgetWord.
9609                 //
9610                 // Note: any change here must be coordinated
9611                 // with the implementation of __gptrgetWord
9612                 // in device/lib/_gptrget.c
9613                 emitcode ("lcall", "__gptrgetWord");
9614                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9615                 aopPut (AOP (result), "a", offset++);
9616                 size--;
9617             }
9618             else
9619             {
9620                 // Only one byte to get.
9621                 emitcode ("lcall", "__gptrget");
9622                 aopPut (AOP (result), "a", offset++);
9623             }
9624             
9625             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9626             {
9627                 emitcode ("inc", "dptr");
9628             }
9629         }
9630     }
9631
9632   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9633     _startLazyDPSEvaluation ();
9634       
9635     aopPut ( AOP (left), "dpl", 0);
9636     aopPut ( AOP (left), "dph", 1);
9637     if (options.model == MODEL_FLAT24) {
9638         aopPut ( AOP (left), "dpx", 2);
9639         aopPut ( AOP (left), "b", 3);   
9640     } else  aopPut ( AOP (left), "b", 2);       
9641     
9642     _endLazyDPSEvaluation ();
9643       
9644     pi->generated = 1;
9645   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9646              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9647       
9648       size = AOP_SIZE (result) - 1;
9649       while (size--) emitcode ("lcall","__decdptr");
9650   }
9651
9652   freeAsmop (left, NULL, ic, TRUE);
9653   freeAsmop (result, NULL, ic, TRUE);
9654 }
9655
9656 /*-----------------------------------------------------------------*/
9657 /* genPointerGet - generate code for pointer get                   */
9658 /*-----------------------------------------------------------------*/
9659 static void
9660 genPointerGet (iCode * ic, iCode *pi)
9661 {
9662   operand *left, *result;
9663   sym_link *type, *etype;
9664   int p_type;
9665
9666   D (emitcode (";", "genPointerGet ");
9667     );
9668
9669   left = IC_LEFT (ic);
9670   result = IC_RESULT (ic);
9671
9672   /* depending on the type of pointer we need to
9673      move it to the correct pointer register */
9674   type = operandType (left);
9675   etype = getSpec (type);
9676   /* if left is of type of pointer then it is simple */
9677   if (IS_PTR (type) && !IS_FUNC (type->next))
9678     p_type = DCL_TYPE (type);
9679   else
9680     {
9681       /* we have to go by the storage class */
9682       p_type = PTR_TYPE (SPEC_OCLS (etype));
9683     }
9684   /* special case when cast remat */
9685   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9686       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9687           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9688           type = operandType (left);
9689           p_type = DCL_TYPE (type);
9690   }
9691   /* now that we have the pointer type we assign
9692      the pointer values */
9693   switch (p_type)
9694     {
9695
9696     case POINTER:
9697     case IPOINTER:
9698       genNearPointerGet (left, result, ic, pi);
9699       break;
9700
9701     case PPOINTER:
9702       genPagedPointerGet (left, result, ic, pi);
9703       break;
9704
9705     case FPOINTER:
9706       genFarPointerGet (left, result, ic, pi);
9707       break;
9708
9709     case CPOINTER:
9710       genCodePointerGet (left, result, ic, pi);
9711       break;
9712
9713     case GPOINTER:
9714       genGenPointerGet (left, result, ic, pi);
9715       break;
9716     }
9717
9718 }
9719
9720 /*-----------------------------------------------------------------*/
9721 /* genPackBits - generates code for packed bit storage             */
9722 /*-----------------------------------------------------------------*/
9723 static void
9724 genPackBits (sym_link * etype,
9725              operand * right,
9726              char *rname, int p_type)
9727 {
9728   int offset = 0;
9729   int rLen;
9730   int blen, bstr;
9731   char *l;
9732
9733   blen = SPEC_BLEN (etype);
9734   bstr = SPEC_BSTR (etype);
9735
9736   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9737
9738   /* if the bit lenth is less than or    */
9739   /* it exactly fits a byte then         */
9740   if (SPEC_BLEN (etype) <= 8)
9741     {
9742       /* shift left acc */
9743       AccLsh (SPEC_BSTR (etype));
9744
9745       if (SPEC_BLEN (etype) < 8)
9746         {                       /* if smaller than a byte */
9747
9748
9749           switch (p_type)
9750             {
9751             case POINTER:
9752               emitcode ("mov", "b,a");
9753               emitcode ("mov", "a,@%s", rname);
9754               break;
9755
9756             case FPOINTER:
9757               emitcode ("mov", "b,a");
9758               emitcode ("movx", "a,@dptr");
9759               break;
9760
9761             case GPOINTER:
9762               emitcode ("push", "b");
9763               emitcode ("push", "acc");
9764               emitcode ("lcall", "__gptrget");
9765               emitcode ("pop", "b");
9766               break;
9767             }
9768
9769           emitcode ("anl", "a,#!constbyte", (unsigned char)
9770                     ((unsigned char) (0xFF << (blen + bstr)) |
9771                      (unsigned char) (0xFF >> (8 - bstr))));
9772           emitcode ("orl", "a,b");
9773           if (p_type == GPOINTER)
9774             emitcode ("pop", "b");
9775         }
9776     }
9777
9778   switch (p_type)
9779     {
9780     case POINTER:
9781       emitcode ("mov", "@%s,a", rname);
9782       break;
9783
9784     case FPOINTER:
9785       emitcode ("movx", "@dptr,a");
9786       break;
9787
9788     case GPOINTER:
9789       emitcode ("lcall", "__gptrput");
9790       break;
9791     }
9792
9793   /* if we r done */
9794   if (SPEC_BLEN (etype) <= 8)
9795     return;
9796
9797   emitcode ("inc", "%s", rname);
9798   rLen = SPEC_BLEN (etype);
9799
9800   /* now generate for lengths greater than one byte */
9801   while (1)
9802     {
9803
9804       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9805
9806       rLen -= 8;
9807       if (rLen < 8)
9808         break;
9809
9810       switch (p_type)
9811         {
9812         case POINTER:
9813           if (*l == '@')
9814             {
9815               MOVA (l);
9816               emitcode ("mov", "@%s,a", rname);
9817             }
9818           else
9819             emitcode ("mov", "@%s,%s", rname, l);
9820           break;
9821
9822         case FPOINTER:
9823           MOVA (l);
9824           emitcode ("movx", "@dptr,a");
9825           break;
9826
9827         case GPOINTER:
9828           MOVA (l);
9829           emitcode ("lcall", "__gptrput");
9830           break;
9831         }
9832       emitcode ("inc", "%s", rname);
9833     }
9834
9835   MOVA (l);
9836
9837   /* last last was not complete */
9838   if (rLen)
9839     {
9840       /* save the byte & read byte */
9841       switch (p_type)
9842         {
9843         case POINTER:
9844           emitcode ("mov", "b,a");
9845           emitcode ("mov", "a,@%s", rname);
9846           break;
9847
9848         case FPOINTER:
9849           emitcode ("mov", "b,a");
9850           emitcode ("movx", "a,@dptr");
9851           break;
9852
9853         case GPOINTER:
9854           emitcode ("push", "b");
9855           emitcode ("push", "acc");
9856           emitcode ("lcall", "__gptrget");
9857           emitcode ("pop", "b");
9858           break;
9859         }
9860
9861       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9862       emitcode ("orl", "a,b");
9863     }
9864
9865   if (p_type == GPOINTER)
9866     emitcode ("pop", "b");
9867
9868   switch (p_type)
9869     {
9870
9871     case POINTER:
9872       emitcode ("mov", "@%s,a", rname);
9873       break;
9874
9875     case FPOINTER:
9876       emitcode ("movx", "@dptr,a");
9877       break;
9878
9879     case GPOINTER:
9880       emitcode ("lcall", "__gptrput");
9881       break;
9882     }
9883 }
9884 /*-----------------------------------------------------------------*/
9885 /* genDataPointerSet - remat pointer to data space                 */
9886 /*-----------------------------------------------------------------*/
9887 static void
9888 genDataPointerSet (operand * right,
9889                    operand * result,
9890                    iCode * ic)
9891 {
9892   int size, offset = 0;
9893   char *l, buff[256];
9894
9895   aopOp (right, ic, FALSE, FALSE);
9896
9897   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9898   size = AOP_SIZE (right);
9899   while (size--)
9900     {
9901       if (offset)
9902         {
9903             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9904         }
9905       else
9906         {
9907             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9908         }
9909         
9910       emitcode ("mov", "%s,%s", buff,
9911                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9912     }
9913
9914   freeAsmop (right, NULL, ic, TRUE);
9915   freeAsmop (result, NULL, ic, TRUE);
9916 }
9917
9918 /*-----------------------------------------------------------------*/
9919 /* genNearPointerSet - emitcode for near pointer put                */
9920 /*-----------------------------------------------------------------*/
9921 static void
9922 genNearPointerSet (operand * right,
9923                    operand * result,
9924                    iCode * ic,
9925                    iCode * pi)
9926 {
9927   asmop *aop = NULL;
9928   char *rname, *l;
9929   sym_link *retype, *letype;
9930   sym_link *ptype = operandType (result);
9931
9932   retype = getSpec (operandType (right));
9933   letype = getSpec (ptype);
9934
9935   aopOp (result, ic, FALSE, FALSE);
9936
9937   /* if the result is rematerializable &
9938      in data space & not a bit variable */
9939   if (AOP_TYPE (result) == AOP_IMMD &&
9940       DCL_TYPE (ptype) == POINTER &&
9941       !IS_BITVAR (retype) &&
9942       !IS_BITVAR (letype))
9943     {
9944       genDataPointerSet (right, result, ic);
9945       return;
9946     }
9947
9948   /* if the value is already in a pointer register
9949      then don't need anything more */
9950   if (!AOP_INPREG (AOP (result)))
9951     {
9952       /* otherwise get a free pointer register */
9953       regs *preg;
9954         
9955       aop = newAsmop (0);
9956       preg = getFreePtr (ic, &aop, FALSE);
9957       emitcode ("mov", "%s,%s",
9958                 preg->name,
9959                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9960       rname = preg->name;
9961     }
9962   else
9963     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9964
9965   aopOp (right, ic, FALSE, FALSE);
9966
9967   /* if bitfield then unpack the bits */
9968   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9969     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9970   else
9971     {
9972       /* we have can just get the values */
9973       int size = AOP_SIZE (right);
9974       int offset = 0;
9975
9976       while (size--)
9977         {
9978           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9979           if (*l == '@')
9980             {
9981               MOVA (l);
9982               emitcode ("mov", "@%s,a", rname);
9983             }
9984           else
9985             emitcode ("mov", "@%s,%s", rname, l);
9986           if (size || pi)
9987             emitcode ("inc", "%s", rname);
9988           offset++;
9989         }
9990     }
9991
9992   /* now some housekeeping stuff */
9993   if (aop)
9994     {
9995       /* we had to allocate for this iCode */
9996       if (pi) aopPut (AOP (result),rname,0);
9997       freeAsmop (NULL, aop, ic, TRUE);
9998     }
9999   else
10000     {
10001       /* we did not allocate which means left
10002          already in a pointer register, then
10003          if size > 0 && this could be used again
10004          we have to point it back to where it
10005          belongs */
10006       if (AOP_SIZE (right) > 1 &&
10007           !OP_SYMBOL (result)->remat &&
10008           (OP_SYMBOL (result)->liveTo > ic->seq ||
10009            ic->depth) &&
10010           !pi)
10011         {
10012           int size = AOP_SIZE (right) - 1;
10013           while (size--)
10014             emitcode ("dec", "%s", rname);
10015         }
10016     }
10017
10018   /* done */
10019   if (pi) pi->generated = 1;
10020   freeAsmop (result, NULL, ic, TRUE);
10021   freeAsmop (right, NULL, ic, TRUE);
10022
10023
10024 }
10025
10026 /*-----------------------------------------------------------------*/
10027 /* genPagedPointerSet - emitcode for Paged pointer put             */
10028 /*-----------------------------------------------------------------*/
10029 static void
10030 genPagedPointerSet (operand * right,
10031                     operand * result,
10032                     iCode * ic,
10033                     iCode *pi)
10034 {
10035   asmop *aop = NULL;
10036   char *rname;
10037   sym_link *retype, *letype;
10038
10039   retype = getSpec (operandType (right));
10040   letype = getSpec (operandType (result));
10041
10042   aopOp (result, ic, FALSE, FALSE);
10043
10044   /* if the value is already in a pointer register
10045      then don't need anything more */
10046   if (!AOP_INPREG (AOP (result)))
10047     {
10048       /* otherwise get a free pointer register */
10049       regs *preg;
10050         
10051       aop = newAsmop (0);
10052       preg = getFreePtr (ic, &aop, FALSE);
10053       emitcode ("mov", "%s,%s",
10054                 preg->name,
10055                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10056       rname = preg->name;
10057     }
10058   else
10059     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10060
10061   aopOp (right, ic, FALSE, FALSE);
10062
10063   /* if bitfield then unpack the bits */
10064   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10065     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10066   else
10067     {
10068       /* we have can just get the values */
10069       int size = AOP_SIZE (right);
10070       int offset = 0;
10071
10072       while (size--)
10073         {
10074           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10075
10076           emitcode ("movx", "@%s,a", rname);
10077
10078           if (size || pi)
10079             emitcode ("inc", "%s", rname);
10080
10081           offset++;
10082         }
10083     }
10084
10085   /* now some housekeeping stuff */
10086   if (aop)
10087     {
10088       if (pi) aopPut (AOP (result),rname,0);
10089       /* we had to allocate for this iCode */
10090       freeAsmop (NULL, aop, ic, TRUE);
10091     }
10092   else
10093     {
10094       /* we did not allocate which means left
10095          already in a pointer register, then
10096          if size > 0 && this could be used again
10097          we have to point it back to where it
10098          belongs */
10099       if (AOP_SIZE (right) > 1 &&
10100           !OP_SYMBOL (result)->remat &&
10101           (OP_SYMBOL (result)->liveTo > ic->seq ||
10102            ic->depth) &&
10103           !pi)
10104         {
10105           int size = AOP_SIZE (right) - 1;
10106           while (size--)
10107             emitcode ("dec", "%s", rname);
10108         }
10109     }
10110
10111   /* done */
10112   if (pi) pi->generated = 1;
10113   freeAsmop (result, NULL, ic, TRUE);
10114   freeAsmop (right, NULL, ic, TRUE);
10115
10116
10117 }
10118
10119 /*-----------------------------------------------------------------*/
10120 /* genFarPointerSet - set value from far space                     */
10121 /*-----------------------------------------------------------------*/
10122 static void
10123 genFarPointerSet (operand * right,
10124                   operand * result, iCode * ic, iCode *pi)
10125 {
10126   int size, offset, dopi=1;
10127   sym_link *retype = getSpec (operandType (right));
10128   sym_link *letype = getSpec (operandType (result));
10129
10130   aopOp (result, ic, FALSE, FALSE);
10131
10132   /* if the operand is already in dptr
10133      then we do nothing else we move the value to dptr */
10134   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10135     {
10136       /* if this is remateriazable */
10137       if (AOP_TYPE (result) == AOP_IMMD)
10138         emitcode ("mov", "dptr,%s", 
10139                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10140       else
10141         {
10142           /* we need to get it byte by byte */
10143           _startLazyDPSEvaluation ();
10144           if (AOP_TYPE (result) != AOP_DPTR)
10145             {
10146               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10147               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10148               if (options.model == MODEL_FLAT24)
10149                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10150             }
10151           else
10152             {
10153               /* We need to generate a load to DPTR indirect through DPTR. */
10154               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10155                 
10156               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10157               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10158               if (options.model == MODEL_FLAT24)
10159                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10160               emitcode ("pop", "dph");
10161               emitcode ("pop", "dpl");
10162               dopi=0;
10163             }
10164           _endLazyDPSEvaluation ();
10165         }
10166     }
10167   /* so dptr know contains the address */
10168   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10169
10170   /* if bit then unpack */
10171   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10172       if (AOP_INDPTRn(result)) {
10173           genSetDPTR(AOP(result)->aopu.dptr);
10174       }
10175       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10176       if (AOP_INDPTRn(result)) {
10177           genSetDPTR(0);
10178       }
10179   } else {
10180       size = AOP_SIZE (right);
10181       offset = 0;
10182       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10183           while (size--) {
10184               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10185               
10186               genSetDPTR(AOP(result)->aopu.dptr);
10187               emitcode ("movx", "@dptr,a");
10188               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10189                   emitcode ("inc", "dptr");
10190               genSetDPTR (0);
10191           }
10192       } else {
10193           _startLazyDPSEvaluation ();
10194           while (size--) {
10195               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10196               
10197               if (AOP_INDPTRn(result)) {
10198                   genSetDPTR(AOP(result)->aopu.dptr);
10199               } else {
10200                   genSetDPTR (0);
10201               }
10202               _flushLazyDPS ();
10203               
10204               emitcode ("movx", "@dptr,a");
10205               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10206                   emitcode ("inc", "dptr");
10207           }
10208           _endLazyDPSEvaluation ();
10209       }
10210   }
10211   
10212   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10213       if (!AOP_INDPTRn(result)) {
10214           _startLazyDPSEvaluation ();
10215           
10216           aopPut (AOP(result),"dpl",0);
10217           aopPut (AOP(result),"dph",1);
10218           if (options.model == MODEL_FLAT24)
10219               aopPut (AOP(result),"dpx",2);
10220
10221           _endLazyDPSEvaluation ();
10222       }
10223       pi->generated=1;
10224   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10225              AOP_SIZE(right) > 1 &&
10226              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10227       
10228       size = AOP_SIZE (right) - 1;
10229       if (AOP_INDPTRn(result)) {
10230           genSetDPTR(AOP(result)->aopu.dptr);
10231       } 
10232       while (size--) emitcode ("lcall","__decdptr");
10233       if (AOP_INDPTRn(result)) {
10234           genSetDPTR(0);
10235       }
10236   }
10237   freeAsmop (result, NULL, ic, TRUE);
10238   freeAsmop (right, NULL, ic, TRUE);
10239 }
10240
10241 /*-----------------------------------------------------------------*/
10242 /* genGenPointerSet - set value from generic pointer space         */
10243 /*-----------------------------------------------------------------*/
10244 static void
10245 genGenPointerSet (operand * right,
10246                   operand * result, iCode * ic, iCode *pi)
10247 {
10248   int size, offset;
10249   sym_link *retype = getSpec (operandType (right));
10250   sym_link *letype = getSpec (operandType (result));
10251
10252   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10253
10254   /* if the operand is already in dptr
10255      then we do nothing else we move the value to dptr */
10256   if (AOP_TYPE (result) != AOP_STR)
10257     {
10258       _startLazyDPSEvaluation ();
10259       /* if this is remateriazable */
10260       if (AOP_TYPE (result) == AOP_IMMD)
10261         {
10262           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10263           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10264           {
10265               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10266           }
10267           else
10268           {
10269               emitcode ("mov", 
10270                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10271           }
10272         }
10273       else
10274         {                       /* we need to get it byte by byte */
10275           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10276           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10277           if (options.model == MODEL_FLAT24) {
10278             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10279             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10280           } else {
10281             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10282           }
10283         }
10284       _endLazyDPSEvaluation ();
10285     }
10286   /* so dptr + b now contains the address */
10287   _G.bInUse++;
10288   aopOp (right, ic, FALSE, TRUE);
10289   _G.bInUse--;
10290     
10291
10292   /* if bit then unpack */
10293   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10294     {
10295         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10296     }
10297   else
10298     {
10299         size = AOP_SIZE (right);
10300         offset = 0;
10301
10302         _startLazyDPSEvaluation ();
10303         while (size--)
10304         {
10305             if (size)
10306             {
10307                 // Set two bytes at a time, passed in _AP & A.
10308                 // dptr will be incremented ONCE by __gptrputWord.
10309                 //
10310                 // Note: any change here must be coordinated
10311                 // with the implementation of __gptrputWord
10312                 // in device/lib/_gptrput.c
10313                 emitcode("mov", "_ap, %s", 
10314                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10315                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10316                 
10317                 genSetDPTR (0);
10318                 _flushLazyDPS ();
10319                 emitcode ("lcall", "__gptrputWord");
10320                 size--;
10321             }
10322             else
10323             {
10324                 // Only one byte to put.
10325                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10326
10327                 genSetDPTR (0);
10328                 _flushLazyDPS ();               
10329                 emitcode ("lcall", "__gptrput");
10330             }
10331             
10332             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10333             {
10334                 emitcode ("inc", "dptr");
10335             }
10336         }
10337         _endLazyDPSEvaluation ();
10338     }
10339
10340   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10341       _startLazyDPSEvaluation ();
10342       
10343       aopPut (AOP(result),"dpl",0);
10344       aopPut (AOP(result),"dph",1);
10345       if (options.model == MODEL_FLAT24) {
10346           aopPut (AOP(result),"dpx",2);
10347           aopPut (AOP(result),"b",3);
10348       } else {
10349           aopPut (AOP(result),"b",2);
10350       }
10351       _endLazyDPSEvaluation ();
10352       
10353       pi->generated=1;
10354   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10355              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10356       
10357       size = AOP_SIZE (right) - 1;
10358       while (size--) emitcode ("lcall","__decdptr");
10359   }
10360   freeAsmop (result, NULL, ic, TRUE);
10361   freeAsmop (right, NULL, ic, TRUE);
10362 }
10363
10364 /*-----------------------------------------------------------------*/
10365 /* genPointerSet - stores the value into a pointer location        */
10366 /*-----------------------------------------------------------------*/
10367 static void
10368 genPointerSet (iCode * ic, iCode *pi)
10369 {
10370   operand *right, *result;
10371   sym_link *type, *etype;
10372   int p_type;
10373
10374   D (emitcode (";", "genPointerSet "););
10375
10376   right = IC_RIGHT (ic);
10377   result = IC_RESULT (ic);
10378
10379   /* depending on the type of pointer we need to
10380      move it to the correct pointer register */
10381   type = operandType (result);
10382   etype = getSpec (type);
10383   /* if left is of type of pointer then it is simple */
10384   if (IS_PTR (type) && !IS_FUNC (type->next))
10385     {
10386       p_type = DCL_TYPE (type);
10387     }
10388   else
10389     {
10390       /* we have to go by the storage class */
10391       p_type = PTR_TYPE (SPEC_OCLS (etype));
10392     }
10393   /* special case when cast remat */
10394   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10395       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10396           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10397           type = operandType (result);
10398           p_type = DCL_TYPE (type);
10399   }
10400
10401   /* now that we have the pointer type we assign
10402      the pointer values */
10403   switch (p_type)
10404     {
10405
10406     case POINTER:
10407     case IPOINTER:
10408       genNearPointerSet (right, result, ic, pi);
10409       break;
10410
10411     case PPOINTER:
10412       genPagedPointerSet (right, result, ic, pi);
10413       break;
10414
10415     case FPOINTER:
10416       genFarPointerSet (right, result, ic, pi);
10417       break;
10418
10419     case GPOINTER:
10420       genGenPointerSet (right, result, ic, pi);
10421       break;
10422
10423     default:
10424       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10425               "genPointerSet: illegal pointer type");
10426     }
10427
10428 }
10429
10430 /*-----------------------------------------------------------------*/
10431 /* genIfx - generate code for Ifx statement                        */
10432 /*-----------------------------------------------------------------*/
10433 static void
10434 genIfx (iCode * ic, iCode * popIc)
10435 {
10436   operand *cond = IC_COND (ic);
10437   int isbit = 0;
10438
10439   D (emitcode (";", "genIfx "););
10440
10441   aopOp (cond, ic, FALSE, FALSE);
10442
10443   /* get the value into acc */
10444   if (AOP_TYPE (cond) != AOP_CRY)
10445     {
10446         toBoolean (cond);
10447     }
10448   else
10449     {
10450         isbit = 1;
10451     }
10452     
10453   /* the result is now in the accumulator */
10454   freeAsmop (cond, NULL, ic, TRUE);
10455
10456   /* if there was something to be popped then do it */
10457   if (popIc)
10458     genIpop (popIc);
10459
10460   /* if the condition is  a bit variable */
10461   if (isbit && IS_ITEMP (cond) &&
10462       SPIL_LOC (cond))
10463     {
10464         genIfxJump (ic, SPIL_LOC (cond)->rname);
10465     }
10466   else if (isbit && !IS_ITEMP (cond))
10467     {
10468         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10469     }
10470   else
10471     {
10472         genIfxJump (ic, "a");
10473     }
10474
10475   ic->generated = 1;
10476 }
10477
10478 /*-----------------------------------------------------------------*/
10479 /* genAddrOf - generates code for address of                       */
10480 /*-----------------------------------------------------------------*/
10481 static void
10482 genAddrOf (iCode * ic)
10483 {
10484   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10485   int size, offset;
10486
10487   D (emitcode (";", "genAddrOf ");
10488     );
10489
10490   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10491
10492   /* if the operand is on the stack then we
10493      need to get the stack offset of this
10494      variable */
10495   if (sym->onStack) {
10496       
10497       /* if 10 bit stack */
10498       if (options.stack10bit) {
10499           char buff[10];
10500           tsprintf(buff, sizeof(buff), 
10501                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10502           /* if it has an offset then we need to compute it */
10503 /*        emitcode ("subb", "a,#!constbyte", */
10504 /*                  -((sym->stack < 0) ? */
10505 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10506 /*                    ((short) sym->stack)) & 0xff); */
10507 /*        emitcode ("mov","b,a"); */
10508 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10509 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10510 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10511           if (sym->stack) {
10512               emitcode ("mov", "a,_bpx");
10513               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10514                                              ((char) (sym->stack - _G.nRegsSaved)) :
10515                                              ((char) sym->stack )) & 0xff);
10516               emitcode ("mov", "b,a");
10517               emitcode ("mov", "a,_bpx+1");
10518               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10519                                               ((short) (sym->stack - _G.nRegsSaved)) :
10520                                               ((short) sym->stack )) >> 8) & 0xff);
10521               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10522               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10523               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10524           } else {
10525               /* we can just move _bp */
10526               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10527               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10528               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10529           }       
10530       } else {
10531           /* if it has an offset then we need to compute it */
10532           if (sym->stack) {
10533               emitcode ("mov", "a,_bp");
10534               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10535               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10536           } else {
10537               /* we can just move _bp */
10538               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10539           }
10540           /* fill the result with zero */
10541           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10542           
10543           
10544           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10545               fprintf (stderr,
10546                        "*** warning: pointer to stack var truncated.\n");
10547           }
10548
10549           offset = 1;
10550           while (size--) {
10551               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10552           }      
10553       }
10554       goto release;
10555   }
10556
10557   /* object not on stack then we need the name */
10558   size = AOP_SIZE (IC_RESULT (ic));
10559   offset = 0;
10560
10561   while (size--)
10562     {
10563       char s[SDCC_NAME_MAX];
10564       if (offset) {
10565           switch (offset) {
10566           case 1:
10567               tsprintf(s, sizeof(s), "!his",sym->rname);
10568               break;
10569           case 2:
10570               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10571               break;
10572           case 3:
10573               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10574               break;
10575           default: /* should not need this (just in case) */
10576               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10577                        sym->rname,
10578                        offset * 8);
10579           }
10580       } 
10581       else
10582       {
10583           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10584       }
10585         
10586       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10587     }
10588
10589 release:
10590   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10591
10592 }
10593
10594 /*-----------------------------------------------------------------*/
10595 /* genArrayInit - generates code for address of                       */
10596 /*-----------------------------------------------------------------*/
10597 static void
10598 genArrayInit (iCode * ic)
10599 {
10600     literalList *iLoop;
10601     int         ix, count;
10602     int         elementSize = 0, eIndex;
10603     unsigned    val, lastVal;
10604     sym_link    *type;
10605     operand     *left=IC_LEFT(ic);
10606     
10607     D (emitcode (";", "genArrayInit "););
10608
10609     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10610     
10611     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10612     {
10613         // Load immediate value into DPTR.
10614         emitcode("mov", "dptr, %s",
10615              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10616     }
10617     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10618     {
10619 #if 0
10620       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10621               "Unexpected operand to genArrayInit.\n");
10622       exit(1);
10623 #else
10624       // a regression because of SDCCcse.c:1.52
10625       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10626       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10627       if (options.model == MODEL_FLAT24)
10628         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10629 #endif
10630     }
10631     
10632     type = operandType(IC_LEFT(ic));
10633     
10634     if (type && type->next)
10635     {
10636         elementSize = getSize(type->next);
10637     }
10638     else
10639     {
10640         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10641                                 "can't determine element size in genArrayInit.\n");
10642         exit(1);
10643     }
10644     
10645     iLoop = IC_ARRAYILIST(ic);
10646     lastVal = 0xffff;
10647     
10648     while (iLoop)
10649     {
10650         bool firstpass = TRUE;
10651         
10652         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10653                  iLoop->count, (int)iLoop->literalValue, elementSize);
10654         
10655         ix = iLoop->count;
10656         
10657         while (ix)
10658         {
10659             symbol *tlbl = NULL;
10660             
10661             count = ix > 256 ? 256 : ix;
10662             
10663             if (count > 1)
10664             {
10665                 tlbl = newiTempLabel (NULL);
10666                 if (firstpass || (count & 0xff))
10667                 {
10668                     emitcode("mov", "b, #!constbyte", count & 0xff);
10669                 }
10670                 
10671                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10672             }
10673             
10674             firstpass = FALSE;
10675                 
10676             for (eIndex = 0; eIndex < elementSize; eIndex++)
10677             {
10678                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10679                 if (val != lastVal)
10680                 {
10681                     emitcode("mov", "a, #!constbyte", val);
10682                     lastVal = val;
10683                 }
10684                 
10685                 emitcode("movx", "@dptr, a");
10686                 emitcode("inc", "dptr");
10687             }
10688             
10689             if (count > 1)
10690             {
10691                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10692             }
10693             
10694             ix -= count;
10695         }
10696         
10697         iLoop = iLoop->next;
10698     }
10699     
10700     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10701 }
10702
10703 /*-----------------------------------------------------------------*/
10704 /* genFarFarAssign - assignment when both are in far space         */
10705 /*-----------------------------------------------------------------*/
10706 static void
10707 genFarFarAssign (operand * result, operand * right, iCode * ic)
10708 {
10709   int size = AOP_SIZE (right);
10710   int offset = 0;
10711   symbol *rSym = NULL;
10712
10713   if (size == 1)
10714   {
10715       /* quick & easy case. */
10716       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10717       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10718       freeAsmop (right, NULL, ic, FALSE);
10719       /* now assign DPTR to result */
10720       _G.accInUse++;
10721       aopOp(result, ic, FALSE, FALSE);
10722       _G.accInUse--;
10723       aopPut(AOP(result), "a", 0);
10724       freeAsmop(result, NULL, ic, FALSE);
10725       return;
10726   }
10727   
10728   /* See if we've got an underlying symbol to abuse. */
10729   if (IS_SYMOP(result) && OP_SYMBOL(result))
10730   {
10731       if (IS_TRUE_SYMOP(result))
10732       {
10733           rSym = OP_SYMBOL(result);
10734       }
10735       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10736       {
10737           rSym = OP_SYMBOL(result)->usl.spillLoc;
10738       }
10739   }
10740              
10741   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10742   {
10743       /* We can use the '390 auto-toggle feature to good effect here. */
10744       
10745       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10746       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10747       emitcode ("mov", "dptr,#%s", rSym->rname); 
10748       /* DP2 = result, DP1 = right, DP1 is current. */
10749       while (size)
10750       {
10751           emitcode("movx", "a,@dptr");
10752           emitcode("movx", "@dptr,a");
10753           if (--size)
10754           {
10755                emitcode("inc", "dptr");
10756                emitcode("inc", "dptr");
10757           }
10758       }
10759       emitcode("mov", "dps,#0");
10760       freeAsmop (right, NULL, ic, FALSE);
10761 #if 0
10762 some alternative code for processors without auto-toggle
10763 no time to test now, so later well put in...kpb
10764         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10765         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10766         emitcode ("mov", "dptr,#%s", rSym->rname); 
10767         /* DP2 = result, DP1 = right, DP1 is current. */
10768         while (size)
10769         {
10770           --size;
10771           emitcode("movx", "a,@dptr");
10772           if (size)
10773             emitcode("inc", "dptr");
10774           emitcode("inc", "dps");
10775           emitcode("movx", "@dptr,a");
10776           if (size)
10777             emitcode("inc", "dptr");
10778           emitcode("inc", "dps");
10779         }
10780         emitcode("mov", "dps,#0");
10781         freeAsmop (right, NULL, ic, FALSE);
10782 #endif
10783   }
10784   else
10785   {
10786       D (emitcode (";", "genFarFarAssign"););
10787       aopOp (result, ic, TRUE, TRUE);
10788
10789       _startLazyDPSEvaluation ();
10790       
10791       while (size--)
10792         {
10793           aopPut (AOP (result),
10794                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10795           offset++;
10796         }
10797       _endLazyDPSEvaluation ();
10798       freeAsmop (result, NULL, ic, FALSE);
10799       freeAsmop (right, NULL, ic, FALSE);
10800   }
10801 }
10802
10803 /*-----------------------------------------------------------------*/
10804 /* genAssign - generate code for assignment                        */
10805 /*-----------------------------------------------------------------*/
10806 static void
10807 genAssign (iCode * ic)
10808 {
10809   operand *result, *right;
10810   int size, offset;
10811   unsigned long lit = 0L;
10812
10813   D (emitcode (";", "genAssign ");
10814     );
10815
10816   result = IC_RESULT (ic);
10817   right = IC_RIGHT (ic);
10818
10819   /* if they are the same */
10820   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10821     return;
10822
10823   aopOp (right, ic, FALSE, FALSE);
10824
10825   emitcode (";", "genAssign: resultIsFar = %s",
10826             isOperandInFarSpace (result) ?
10827             "TRUE" : "FALSE");
10828
10829   /* special case both in far space */
10830   if ((AOP_TYPE (right) == AOP_DPTR ||
10831        AOP_TYPE (right) == AOP_DPTR2) &&
10832   /* IS_TRUE_SYMOP(result)       && */
10833       isOperandInFarSpace (result))
10834     {
10835       genFarFarAssign (result, right, ic);
10836       return;
10837     }
10838
10839   aopOp (result, ic, TRUE, FALSE);
10840
10841   /* if they are the same registers */
10842   if (sameRegs (AOP (right), AOP (result)))
10843     goto release;
10844
10845   /* if the result is a bit */
10846   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10847     {
10848       /* if the right size is a literal then
10849          we know what the value is */
10850       if (AOP_TYPE (right) == AOP_LIT)
10851         {
10852           if (((int) operandLitValue (right)))
10853             aopPut (AOP (result), one, 0);
10854           else
10855             aopPut (AOP (result), zero, 0);
10856           goto release;
10857         }
10858
10859       /* the right is also a bit variable */
10860       if (AOP_TYPE (right) == AOP_CRY)
10861         {
10862           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10863           aopPut (AOP (result), "c", 0);
10864           goto release;
10865         }
10866
10867       /* we need to or */
10868       toBoolean (right);
10869       aopPut (AOP (result), "a", 0);
10870       goto release;
10871     }
10872
10873   /* bit variables done */
10874   /* general case */
10875   size = AOP_SIZE (result);
10876   offset = 0;
10877   if (AOP_TYPE (right) == AOP_LIT)
10878     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10879
10880   if ((size > 1) &&
10881       (AOP_TYPE (result) != AOP_REG) &&
10882       (AOP_TYPE (right) == AOP_LIT) &&
10883       !IS_FLOAT (operandType (right)))
10884     {
10885       _startLazyDPSEvaluation ();
10886       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10887         {
10888           aopPut (AOP (result),
10889                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10890                   offset);
10891           offset++;
10892           size--;
10893         }
10894       /* And now fill the rest with zeros. */
10895       if (size)
10896         {
10897           emitcode ("clr", "a");
10898         }
10899       while (size--)
10900         {
10901           aopPut (AOP (result), "a", offset++);
10902         }
10903       _endLazyDPSEvaluation ();
10904     }
10905   else
10906     {
10907       _startLazyDPSEvaluation ();
10908       while (size--)
10909         {
10910           aopPut (AOP (result),
10911                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10912                   offset);
10913           offset++;
10914         }
10915       _endLazyDPSEvaluation ();
10916     }
10917
10918 release:
10919   freeAsmop (right, NULL, ic, FALSE);
10920   freeAsmop (result, NULL, ic, TRUE);
10921 }
10922
10923 /*-----------------------------------------------------------------*/
10924 /* genJumpTab - generates code for jump table                      */
10925 /*-----------------------------------------------------------------*/
10926 static void
10927 genJumpTab (iCode * ic)
10928 {
10929   symbol *jtab;
10930   char *l;
10931
10932   D (emitcode (";", "genJumpTab ");
10933     );
10934
10935   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10936   /* get the condition into accumulator */
10937   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10938   MOVA (l);
10939   /* multiply by four! */
10940   emitcode ("add", "a,acc");
10941   emitcode ("add", "a,acc");
10942   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10943
10944   jtab = newiTempLabel (NULL);
10945   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10946   emitcode ("jmp", "@a+dptr");
10947   emitcode ("", "!tlabeldef", jtab->key + 100);
10948   /* now generate the jump labels */
10949   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10950        jtab = setNextItem (IC_JTLABELS (ic)))
10951     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10952
10953 }
10954
10955 /*-----------------------------------------------------------------*/
10956 /* genCast - gen code for casting                                  */
10957 /*-----------------------------------------------------------------*/
10958 static void
10959 genCast (iCode * ic)
10960 {
10961   operand *result = IC_RESULT (ic);
10962   sym_link *ctype = operandType (IC_LEFT (ic));
10963   sym_link *rtype = operandType (IC_RIGHT (ic));
10964   operand *right = IC_RIGHT (ic);
10965   int size, offset;
10966
10967   D (emitcode (";", "genCast "););
10968
10969   /* if they are equivalent then do nothing */
10970   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10971     return;
10972
10973   aopOp (right, ic, FALSE, FALSE);
10974   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10975
10976   /* if the result is a bit */
10977   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10978   if (IS_BITVAR(OP_SYMBOL(result)->type))
10979     {
10980       /* if the right size is a literal then
10981          we know what the value is */
10982       if (AOP_TYPE (right) == AOP_LIT)
10983         {
10984           if (((int) operandLitValue (right)))
10985             aopPut (AOP (result), one, 0);
10986           else
10987             aopPut (AOP (result), zero, 0);
10988
10989           goto release;
10990         }
10991
10992       /* the right is also a bit variable */
10993       if (AOP_TYPE (right) == AOP_CRY)
10994         {
10995           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10996           aopPut (AOP (result), "c", 0);
10997           goto release;
10998         }
10999
11000       /* we need to or */
11001       toBoolean (right);
11002       aopPut (AOP (result), "a", 0);
11003       goto release;
11004     }
11005
11006   /* if they are the same size : or less */
11007   if (AOP_SIZE (result) <= AOP_SIZE (right))
11008     {
11009
11010       /* if they are in the same place */
11011       if (sameRegs (AOP (right), AOP (result)))
11012         goto release;
11013
11014       /* if they in different places then copy */
11015       size = AOP_SIZE (result);
11016       offset = 0;
11017       _startLazyDPSEvaluation ();
11018       while (size--)
11019         {
11020           aopPut (AOP (result),
11021                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11022                   offset);
11023           offset++;
11024         }
11025       _endLazyDPSEvaluation ();
11026       goto release;
11027     }
11028
11029
11030   /* if the result is of type pointer */
11031   if (IS_PTR (ctype))
11032     {
11033
11034       int p_type;
11035       sym_link *type = operandType (right);
11036
11037       /* pointer to generic pointer */
11038       if (IS_GENPTR (ctype))
11039         {
11040           if (IS_PTR (type))
11041             {
11042               p_type = DCL_TYPE (type);
11043             }
11044           else
11045             {
11046 #if OLD_CAST_BEHAVIOR
11047               /* KV: we are converting a non-pointer type to
11048                * a generic pointer. This (ifdef'd out) code
11049                * says that the resulting generic pointer
11050                * should have the same class as the storage
11051                * location of the non-pointer variable.
11052                *
11053                * For example, converting an int (which happens
11054                * to be stored in DATA space) to a pointer results
11055                * in a DATA generic pointer; if the original int
11056                * in XDATA space, so will be the resulting pointer.
11057                *
11058                * I don't like that behavior, and thus this change:
11059                * all such conversions will be forced to XDATA and
11060                * throw a warning. If you want some non-XDATA
11061                * type, or you want to suppress the warning, you
11062                * must go through an intermediate cast, like so:
11063                *
11064                * char _generic *gp = (char _xdata *)(intVar);
11065                */
11066               sym_link *etype = getSpec (type);
11067
11068               /* we have to go by the storage class */
11069               if (SPEC_OCLS (etype) != generic)
11070                 {
11071                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11072                 }
11073               else
11074 #endif
11075                 {
11076                   /* Converting unknown class (i.e. register variable)
11077                    * to generic pointer. This is not good, but
11078                    * we'll make a guess (and throw a warning).
11079                    */
11080                   p_type = FPOINTER;
11081                   werror (W_INT_TO_GEN_PTR_CAST);
11082                 }
11083             }
11084
11085           /* the first two bytes are known */
11086           size = GPTRSIZE - 1;
11087           offset = 0;
11088           _startLazyDPSEvaluation ();
11089           while (size--)
11090             {
11091               aopPut (AOP (result),
11092                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11093                       offset);
11094               offset++;
11095             }
11096           _endLazyDPSEvaluation ();
11097
11098           /* the last byte depending on type */
11099             {
11100                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11101                 char gpValStr[10];
11102             
11103                 if (gpVal == -1)
11104                 {
11105                     // pointerTypeToGPByte will have bitched.
11106                     exit(1);
11107                 }
11108             
11109                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11110                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11111             }
11112           goto release;
11113         }
11114
11115       /* just copy the pointers */
11116       size = AOP_SIZE (result);
11117       offset = 0;
11118       _startLazyDPSEvaluation ();
11119       while (size--)
11120         {
11121           aopPut (AOP (result),
11122                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11123                   offset);
11124           offset++;
11125         }
11126       _endLazyDPSEvaluation ();
11127       goto release;
11128     }
11129
11130   /* so we now know that the size of destination is greater
11131      than the size of the source */
11132   /* we move to result for the size of source */
11133   size = AOP_SIZE (right);
11134   offset = 0;
11135   _startLazyDPSEvaluation ();
11136   while (size--)
11137     {
11138       aopPut (AOP (result),
11139               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11140               offset);
11141       offset++;
11142     }
11143   _endLazyDPSEvaluation ();
11144
11145   /* now depending on the sign of the source && destination */
11146   size = AOP_SIZE (result) - AOP_SIZE (right);
11147   /* if unsigned or not an integral type */
11148   /* also, if the source is a bit, we don't need to sign extend, because
11149    * it can't possibly have set the sign bit.
11150    */
11151   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11152     {
11153       while (size--)
11154         {
11155           aopPut (AOP (result), zero, offset++);
11156         }
11157     }
11158   else
11159     {
11160       /* we need to extend the sign :{ */
11161       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11162                         FALSE, FALSE, NULL));
11163       emitcode ("rlc", "a");
11164       emitcode ("subb", "a,acc");
11165       while (size--)
11166         aopPut (AOP (result), "a", offset++);
11167     }
11168
11169   /* we are done hurray !!!! */
11170
11171 release:
11172   freeAsmop (right, NULL, ic, TRUE);
11173   freeAsmop (result, NULL, ic, TRUE);
11174
11175 }
11176
11177 /*-----------------------------------------------------------------*/
11178 /* genDjnz - generate decrement & jump if not zero instrucion      */
11179 /*-----------------------------------------------------------------*/
11180 static int
11181 genDjnz (iCode * ic, iCode * ifx)
11182 {
11183   symbol *lbl, *lbl1;
11184   if (!ifx)
11185     return 0;
11186
11187   /* if the if condition has a false label
11188      then we cannot save */
11189   if (IC_FALSE (ifx))
11190     return 0;
11191
11192   /* if the minus is not of the form
11193      a = a - 1 */
11194   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11195       !IS_OP_LITERAL (IC_RIGHT (ic)))
11196     return 0;
11197
11198   if (operandLitValue (IC_RIGHT (ic)) != 1)
11199     return 0;
11200
11201   /* if the size of this greater than one then no
11202      saving */
11203   if (getSize (operandType (IC_RESULT (ic))) > 1)
11204     return 0;
11205
11206   /* otherwise we can save BIG */
11207   D(emitcode(";", "genDjnz"););
11208
11209   lbl = newiTempLabel (NULL);
11210   lbl1 = newiTempLabel (NULL);
11211
11212   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11213
11214   if (AOP_NEEDSACC(IC_RESULT(ic)))
11215   {
11216       /* If the result is accessed indirectly via
11217        * the accumulator, we must explicitly write
11218        * it back after the decrement.
11219        */
11220       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11221       
11222       if (strcmp(rByte, "a"))
11223       {
11224            /* Something is hopelessly wrong */
11225            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11226                    __FILE__, __LINE__);
11227            /* We can just give up; the generated code will be inefficient,
11228             * but what the hey.
11229             */
11230            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11231            return 0;
11232       }
11233       emitcode ("dec", "%s", rByte);
11234       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11235       emitcode ("jnz", "!tlabel", lbl->key + 100);
11236   }
11237   else if (IS_AOP_PREG (IC_RESULT (ic)))
11238     {
11239       emitcode ("dec", "%s",
11240                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11241       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11242       emitcode ("jnz", "!tlabel", lbl->key + 100);
11243     }
11244   else
11245     {
11246       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11247                 lbl->key + 100);
11248     }
11249   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11250   emitcode ("", "!tlabeldef", lbl->key + 100);
11251   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11252   emitcode ("", "!tlabeldef", lbl1->key + 100);
11253
11254   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11255   ifx->generated = 1;
11256   return 1;
11257 }
11258
11259 /*-----------------------------------------------------------------*/
11260 /* genReceive - generate code for a receive iCode                  */
11261 /*-----------------------------------------------------------------*/
11262 static void
11263 genReceive (iCode * ic)
11264 {
11265     int size = getSize (operandType (IC_RESULT (ic)));
11266     int offset = 0;
11267     int rb1off ;
11268     
11269     D (emitcode (";", "genReceive "););
11270
11271     if (ic->argreg == 1) 
11272     {
11273         /* first parameter */
11274         if (AOP_IS_STR(IC_RESULT(ic)))
11275         {
11276             /* Nothing to do: it's already in the proper place. */
11277             return;
11278         }
11279         else
11280         {
11281             bool useDp2;
11282             
11283             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11284                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11285                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11286             
11287             _G.accInUse++;
11288             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11289             _G.accInUse--; 
11290             
11291             /* Sanity checking... */
11292             if (AOP_USESDPTR(IC_RESULT(ic)))
11293             {
11294                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11295                         "genReceive got unexpected DPTR.");
11296             }
11297             assignResultValue (IC_RESULT (ic));
11298         }
11299     } 
11300     else 
11301     { 
11302         /* second receive onwards */
11303         /* this gets a little tricky since unused recevies will be
11304          eliminated, we have saved the reg in the type field . and
11305          we use that to figure out which register to use */
11306         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11307         rb1off = ic->argreg;
11308         while (size--) 
11309         {
11310             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11311         }
11312     }
11313     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11314 }
11315
11316 /*-----------------------------------------------------------------*/
11317 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11318 /*-----------------------------------------------------------------*/
11319 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11320 {
11321     operand *from , *to , *count;
11322     symbol *lbl;
11323     bitVect *rsave;
11324     int i;
11325
11326     /* we know it has to be 3 parameters */
11327     assert (nparms == 3);
11328     
11329     rsave = newBitVect(16);
11330     /* save DPTR if it needs to be saved */
11331     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11332             if (bitVectBitValue(ic->rMask,i))
11333                     rsave = bitVectSetBit(rsave,i);
11334     }
11335     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11336                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11337     savermask(rsave);
11338     
11339     to = parms[0];
11340     from = parms[1];
11341     count = parms[2];
11342
11343     aopOp (from, ic->next, FALSE, FALSE);
11344
11345     /* get from into DPTR1 */
11346     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11347     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11348     if (options.model == MODEL_FLAT24) {
11349         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11350     }
11351
11352     freeAsmop (from, NULL, ic, FALSE);
11353     aopOp (to, ic, FALSE, FALSE);
11354     /* get "to" into DPTR */
11355     /* if the operand is already in dptr
11356        then we do nothing else we move the value to dptr */
11357     if (AOP_TYPE (to) != AOP_STR) {
11358         /* if already in DPTR then we need to push */
11359         if (AOP_TYPE(to) == AOP_DPTR) {
11360             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11361             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11362             if (options.model == MODEL_FLAT24)
11363                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11364             emitcode ("pop", "dph");
11365             emitcode ("pop", "dpl");        
11366         } else {
11367             _startLazyDPSEvaluation ();
11368             /* if this is remateriazable */
11369             if (AOP_TYPE (to) == AOP_IMMD) {
11370                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11371             } else {                    /* we need to get it byte by byte */
11372                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11373                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11374                 if (options.model == MODEL_FLAT24) {
11375                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11376                 }
11377             }
11378             _endLazyDPSEvaluation ();
11379         }
11380     }
11381     freeAsmop (to, NULL, ic, FALSE);
11382     _G.dptrInUse = _G.dptr1InUse = 1;
11383     aopOp (count, ic->next->next, FALSE,FALSE);
11384     lbl =newiTempLabel(NULL);
11385
11386     /* now for the actual copy */
11387     if (AOP_TYPE(count) == AOP_LIT && 
11388         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11389         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11390         if (fromc) {
11391             emitcode ("lcall","__bi_memcpyc2x_s");
11392         } else {
11393             emitcode ("lcall","__bi_memcpyx2x_s");
11394         }
11395         freeAsmop (count, NULL, ic, FALSE);
11396     } else {
11397         symbol *lbl1 = newiTempLabel(NULL);
11398         
11399         emitcode (";"," Auto increment but no djnz");
11400         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11401         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11402         freeAsmop (count, NULL, ic, FALSE);
11403         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11404         emitcode ("","!tlabeldef",lbl->key+100);
11405         if (fromc) {
11406             emitcode ("clr","a");
11407             emitcode ("movc", "a,@a+dptr");
11408         } else 
11409             emitcode ("movx", "a,@dptr");
11410         emitcode ("movx", "@dptr,a");
11411         emitcode ("inc", "dptr");
11412         emitcode ("inc", "dptr");
11413         emitcode ("mov","a,b");
11414         emitcode ("orl","a,_ap");
11415         emitcode ("jz","!tlabel",lbl1->key+100);
11416         emitcode ("mov","a,_ap");
11417         emitcode ("add","a,#!constbyte",0xFF);
11418         emitcode ("mov","_ap,a");
11419         emitcode ("mov","a,b");
11420         emitcode ("addc","a,#!constbyte",0xFF);
11421         emitcode ("mov","b,a");
11422         emitcode ("sjmp","!tlabel",lbl->key+100);
11423         emitcode ("","!tlabeldef",lbl1->key+100);
11424     }
11425     emitcode ("mov", "dps,#0"); 
11426     _G.dptrInUse = _G.dptr1InUse = 0;
11427     unsavermask(rsave);
11428
11429 }
11430
11431 /*-----------------------------------------------------------------*/
11432 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11433 /*-----------------------------------------------------------------*/
11434 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11435 {
11436     operand *from , *to , *count;
11437     symbol *lbl,*lbl2;
11438     bitVect *rsave;
11439     int i;
11440
11441     /* we know it has to be 3 parameters */
11442     assert (nparms == 3);
11443     
11444     rsave = newBitVect(16);
11445     /* save DPTR if it needs to be saved */
11446     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11447             if (bitVectBitValue(ic->rMask,i))
11448                     rsave = bitVectSetBit(rsave,i);
11449     }
11450     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11451                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11452     savermask(rsave);
11453     
11454     to = parms[0];
11455     from = parms[1];
11456     count = parms[2];
11457
11458     aopOp (from, ic->next, FALSE, FALSE);
11459
11460     /* get from into DPTR1 */
11461     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11462     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11463     if (options.model == MODEL_FLAT24) {
11464         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11465     }
11466
11467     freeAsmop (from, NULL, ic, FALSE);
11468     aopOp (to, ic, FALSE, FALSE);
11469     /* get "to" into DPTR */
11470     /* if the operand is already in dptr
11471        then we do nothing else we move the value to dptr */
11472     if (AOP_TYPE (to) != AOP_STR) {
11473         /* if already in DPTR then we need to push */
11474         if (AOP_TYPE(to) == AOP_DPTR) {
11475             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11476             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11477             if (options.model == MODEL_FLAT24)
11478                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11479             emitcode ("pop", "dph");
11480             emitcode ("pop", "dpl");        
11481         } else {
11482             _startLazyDPSEvaluation ();
11483             /* if this is remateriazable */
11484             if (AOP_TYPE (to) == AOP_IMMD) {
11485                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11486             } else {                    /* we need to get it byte by byte */
11487                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11488                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11489                 if (options.model == MODEL_FLAT24) {
11490                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11491                 }
11492             }
11493             _endLazyDPSEvaluation ();
11494         }
11495     }
11496     freeAsmop (to, NULL, ic, FALSE);
11497     _G.dptrInUse = _G.dptr1InUse = 1;
11498     aopOp (count, ic->next->next, FALSE,FALSE);
11499     lbl =newiTempLabel(NULL);
11500     lbl2 =newiTempLabel(NULL);
11501
11502     /* now for the actual compare */
11503     if (AOP_TYPE(count) == AOP_LIT && 
11504         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11505         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11506         if (fromc)
11507             emitcode("lcall","__bi_memcmpc2x_s");
11508         else
11509             emitcode("lcall","__bi_memcmpx2x_s");
11510         freeAsmop (count, NULL, ic, FALSE);
11511         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11512         aopPut(AOP(IC_RESULT(ic)),"a",0);
11513         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11514     } else {
11515         symbol *lbl1 = newiTempLabel(NULL);
11516
11517         emitcode("push","ar0");         
11518         emitcode (";"," Auto increment but no djnz");
11519         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11520         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11521         freeAsmop (count, NULL, ic, FALSE);
11522         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11523         emitcode ("","!tlabeldef",lbl->key+100);
11524         if (fromc) {
11525             emitcode ("clr","a");
11526             emitcode ("movc", "a,@a+dptr");
11527         } else 
11528             emitcode ("movx", "a,@dptr");
11529         emitcode ("mov","r0,a");
11530         emitcode ("movx", "a,@dptr");
11531         emitcode ("clr","c");
11532         emitcode ("subb","a,r0");
11533         emitcode ("jnz","!tlabel",lbl2->key+100);
11534         emitcode ("inc", "dptr");
11535         emitcode ("inc", "dptr");
11536         emitcode ("mov","a,b");
11537         emitcode ("orl","a,_ap");
11538         emitcode ("jz","!tlabel",lbl1->key+100);
11539         emitcode ("mov","a,_ap");
11540         emitcode ("add","a,#!constbyte",0xFF);
11541         emitcode ("mov","_ap,a");
11542         emitcode ("mov","a,b");
11543         emitcode ("addc","a,#!constbyte",0xFF);
11544         emitcode ("mov","b,a");
11545         emitcode ("sjmp","!tlabel",lbl->key+100);
11546         emitcode ("","!tlabeldef",lbl1->key+100);
11547         emitcode ("clr","a");
11548         emitcode ("","!tlabeldef",lbl2->key+100);
11549         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11550         aopPut(AOP(IC_RESULT(ic)),"a",0);
11551         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11552         emitcode("pop","ar0");
11553         emitcode ("mov", "dps,#0");      
11554     }
11555     _G.dptrInUse = _G.dptr1InUse = 0;
11556     unsavermask(rsave);
11557
11558 }
11559
11560 /*-----------------------------------------------------------------*/
11561 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11562 /* port, first parameter output area second parameter pointer to   */
11563 /* port third parameter count                                      */
11564 /*-----------------------------------------------------------------*/
11565 static void genInp( iCode *ic, int nparms, operand **parms)
11566 {
11567     operand *from , *to , *count;
11568     symbol *lbl;
11569     bitVect *rsave;
11570     int i;
11571
11572     /* we know it has to be 3 parameters */
11573     assert (nparms == 3);
11574     
11575     rsave = newBitVect(16);
11576     /* save DPTR if it needs to be saved */
11577     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11578             if (bitVectBitValue(ic->rMask,i))
11579                     rsave = bitVectSetBit(rsave,i);
11580     }
11581     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11582                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11583     savermask(rsave);
11584     
11585     to = parms[0];
11586     from = parms[1];
11587     count = parms[2];
11588
11589     aopOp (from, ic->next, FALSE, FALSE);
11590
11591     /* get from into DPTR1 */
11592     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11593     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11594     if (options.model == MODEL_FLAT24) {
11595         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11596     }
11597
11598     freeAsmop (from, NULL, ic, FALSE);
11599     aopOp (to, ic, FALSE, FALSE);
11600     /* get "to" into DPTR */
11601     /* if the operand is already in dptr
11602        then we do nothing else we move the value to dptr */
11603     if (AOP_TYPE (to) != AOP_STR) {
11604         /* if already in DPTR then we need to push */
11605         if (AOP_TYPE(to) == AOP_DPTR) {
11606             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11607             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11608             if (options.model == MODEL_FLAT24)
11609                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11610             emitcode ("pop", "dph");
11611             emitcode ("pop", "dpl");        
11612         } else {
11613             _startLazyDPSEvaluation ();
11614             /* if this is remateriazable */
11615             if (AOP_TYPE (to) == AOP_IMMD) {
11616                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11617             } else {                    /* we need to get it byte by byte */
11618                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11619                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11620                 if (options.model == MODEL_FLAT24) {
11621                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11622                 }
11623             }
11624             _endLazyDPSEvaluation ();
11625         }
11626     }
11627     freeAsmop (to, NULL, ic, FALSE);
11628
11629     _G.dptrInUse = _G.dptr1InUse = 1;
11630     aopOp (count, ic->next->next, FALSE,FALSE);
11631     lbl =newiTempLabel(NULL);
11632
11633     /* now for the actual copy */
11634     if (AOP_TYPE(count) == AOP_LIT && 
11635         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11636         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11637         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11638         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11639         freeAsmop (count, NULL, ic, FALSE);
11640         emitcode ("","!tlabeldef",lbl->key+100);
11641         emitcode ("movx", "a,@dptr");   /* read data from port */
11642         emitcode ("dec","dps");         /* switch to DPTR */
11643         emitcode ("movx", "@dptr,a");   /* save into location */
11644         emitcode ("inc", "dptr");       /* point to next area */
11645         emitcode ("inc","dps");         /* switch to DPTR2 */
11646         emitcode ("djnz","b,!tlabel",lbl->key+100);
11647     } else {
11648         symbol *lbl1 = newiTempLabel(NULL);
11649         
11650         emitcode (";"," Auto increment but no djnz");
11651         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11652         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11653         freeAsmop (count, NULL, ic, FALSE);
11654         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11655         emitcode ("","!tlabeldef",lbl->key+100);
11656         emitcode ("movx", "a,@dptr");
11657         emitcode ("dec","dps");         /* switch to DPTR */
11658         emitcode ("movx", "@dptr,a");
11659         emitcode ("inc", "dptr");
11660         emitcode ("inc","dps");         /* switch to DPTR2 */
11661 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11662 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11663         emitcode ("mov","a,b");
11664         emitcode ("orl","a,_ap");
11665         emitcode ("jz","!tlabel",lbl1->key+100);
11666         emitcode ("mov","a,_ap");
11667         emitcode ("add","a,#!constbyte",0xFF);
11668         emitcode ("mov","_ap,a");
11669         emitcode ("mov","a,b");
11670         emitcode ("addc","a,#!constbyte",0xFF);
11671         emitcode ("mov","b,a");
11672         emitcode ("sjmp","!tlabel",lbl->key+100);
11673         emitcode ("","!tlabeldef",lbl1->key+100);
11674     }
11675     emitcode ("mov", "dps,#0"); 
11676     _G.dptrInUse = _G.dptr1InUse = 0;
11677     unsavermask(rsave);
11678
11679 }
11680
11681 /*-----------------------------------------------------------------*/
11682 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11683 /* port, first parameter output area second parameter pointer to   */
11684 /* port third parameter count                                      */
11685 /*-----------------------------------------------------------------*/
11686 static void genOutp( iCode *ic, int nparms, operand **parms)
11687 {
11688     operand *from , *to , *count;
11689     symbol *lbl;
11690     bitVect *rsave;
11691     int i;
11692
11693     /* we know it has to be 3 parameters */
11694     assert (nparms == 3);
11695     
11696     rsave = newBitVect(16);
11697     /* save DPTR if it needs to be saved */
11698     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11699             if (bitVectBitValue(ic->rMask,i))
11700                     rsave = bitVectSetBit(rsave,i);
11701     }
11702     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11703                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11704     savermask(rsave);
11705     
11706     to = parms[0];
11707     from = parms[1];
11708     count = parms[2];
11709
11710     aopOp (from, ic->next, FALSE, FALSE);
11711
11712     /* get from into DPTR1 */
11713     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11714     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11715     if (options.model == MODEL_FLAT24) {
11716         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11717     }
11718
11719     freeAsmop (from, NULL, ic, FALSE);
11720     aopOp (to, ic, FALSE, FALSE);
11721     /* get "to" into DPTR */
11722     /* if the operand is already in dptr
11723        then we do nothing else we move the value to dptr */
11724     if (AOP_TYPE (to) != AOP_STR) {
11725         /* if already in DPTR then we need to push */
11726         if (AOP_TYPE(to) == AOP_DPTR) {
11727             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11728             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11729             if (options.model == MODEL_FLAT24)
11730                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11731             emitcode ("pop", "dph");
11732             emitcode ("pop", "dpl");        
11733         } else {
11734             _startLazyDPSEvaluation ();
11735             /* if this is remateriazable */
11736             if (AOP_TYPE (to) == AOP_IMMD) {
11737                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11738             } else {                    /* we need to get it byte by byte */
11739                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11740                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11741                 if (options.model == MODEL_FLAT24) {
11742                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11743                 }
11744             }
11745             _endLazyDPSEvaluation ();
11746         }
11747     }
11748     freeAsmop (to, NULL, ic, FALSE);
11749
11750     _G.dptrInUse = _G.dptr1InUse = 1;
11751     aopOp (count, ic->next->next, FALSE,FALSE);
11752     lbl =newiTempLabel(NULL);
11753
11754     /* now for the actual copy */
11755     if (AOP_TYPE(count) == AOP_LIT && 
11756         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11757         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11758         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11759         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11760         emitcode ("","!tlabeldef",lbl->key+100);
11761         emitcode ("movx", "a,@dptr");   /* read data from port */
11762         emitcode ("inc","dps");         /* switch to DPTR2 */
11763         emitcode ("movx", "@dptr,a");   /* save into location */
11764         emitcode ("inc", "dptr");       /* point to next area */
11765         emitcode ("dec","dps");         /* switch to DPTR */
11766         emitcode ("djnz","b,!tlabel",lbl->key+100);
11767         freeAsmop (count, NULL, ic, FALSE);
11768     } else {
11769         symbol *lbl1 = newiTempLabel(NULL);
11770         
11771         emitcode (";"," Auto increment but no djnz");
11772         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11773         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11774         freeAsmop (count, NULL, ic, FALSE);
11775         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11776         emitcode ("","!tlabeldef",lbl->key+100);
11777         emitcode ("movx", "a,@dptr");
11778         emitcode ("inc", "dptr");
11779         emitcode ("inc","dps");         /* switch to DPTR2 */
11780         emitcode ("movx", "@dptr,a");
11781         emitcode ("dec","dps");         /* switch to DPTR */
11782         emitcode ("mov","a,b");
11783         emitcode ("orl","a,_ap");
11784         emitcode ("jz","!tlabel",lbl1->key+100);
11785         emitcode ("mov","a,_ap");
11786         emitcode ("add","a,#!constbyte",0xFF);
11787         emitcode ("mov","_ap,a");
11788         emitcode ("mov","a,b");
11789         emitcode ("addc","a,#!constbyte",0xFF);
11790         emitcode ("mov","b,a");
11791         emitcode ("sjmp","!tlabel",lbl->key+100);
11792         emitcode ("","!tlabeldef",lbl1->key+100);
11793     }
11794     emitcode ("mov", "dps,#0"); 
11795     _G.dptrInUse = _G.dptr1InUse = 0;
11796     unsavermask(rsave);
11797
11798 }
11799
11800 /*-----------------------------------------------------------------*/
11801 /* genSwapW - swap lower & high order bytes                        */
11802 /*-----------------------------------------------------------------*/
11803 static void genSwapW(iCode *ic, int nparms, operand **parms)
11804 {
11805     operand *dest;
11806     operand *src;
11807     assert (nparms==1);
11808
11809     src = parms[0];
11810     dest=IC_RESULT(ic);
11811
11812     assert(getSize(operandType(src))==2);
11813
11814     aopOp (src, ic, FALSE, FALSE);
11815     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11816     _G.accInUse++;
11817     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11818     _G.accInUse--;
11819     freeAsmop (src, NULL, ic, FALSE);
11820     
11821     aopOp (dest,ic, FALSE, FALSE);
11822     aopPut(AOP(dest),"b",0);
11823     aopPut(AOP(dest),"a",1);
11824     freeAsmop (dest, NULL, ic, FALSE);    
11825 }
11826
11827 /*-----------------------------------------------------------------*/
11828 /* genMemsetX - gencode for memSetX data                           */
11829 /*-----------------------------------------------------------------*/
11830 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11831 {
11832     operand *to , *val , *count;
11833     symbol *lbl;
11834     char *l;
11835     int i;
11836     bitVect *rsave;
11837
11838     /* we know it has to be 3 parameters */
11839     assert (nparms == 3);
11840     
11841     to = parms[0];
11842     val = parms[1];
11843     count = parms[2];
11844         
11845     /* save DPTR if it needs to be saved */
11846     rsave = newBitVect(16);
11847     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11848             if (bitVectBitValue(ic->rMask,i))
11849                     rsave = bitVectSetBit(rsave,i);
11850     }
11851     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11852                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11853     savermask(rsave);
11854
11855     aopOp (to, ic, FALSE, FALSE);
11856     /* get "to" into DPTR */
11857     /* if the operand is already in dptr
11858        then we do nothing else we move the value to dptr */
11859     if (AOP_TYPE (to) != AOP_STR) {
11860         /* if already in DPTR then we need to push */
11861         if (AOP_TYPE(to) == AOP_DPTR) {
11862             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11863             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11864             if (options.model == MODEL_FLAT24)
11865                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11866             emitcode ("pop", "dph");
11867             emitcode ("pop", "dpl");        
11868         } else {
11869             _startLazyDPSEvaluation ();
11870             /* if this is remateriazable */
11871             if (AOP_TYPE (to) == AOP_IMMD) {
11872                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11873             } else {                    /* we need to get it byte by byte */
11874                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11875                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11876                 if (options.model == MODEL_FLAT24) {
11877                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11878                 }
11879             }
11880             _endLazyDPSEvaluation ();
11881         }
11882     }
11883     freeAsmop (to, NULL, ic, FALSE);
11884
11885     aopOp (val, ic->next->next, FALSE,FALSE);
11886     aopOp (count, ic->next->next, FALSE,FALSE);    
11887     lbl =newiTempLabel(NULL);
11888     /* now for the actual copy */
11889     if (AOP_TYPE(count) == AOP_LIT && 
11890         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11891         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11892         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11893         MOVA(l);
11894         emitcode ("","!tlabeldef",lbl->key+100);
11895         emitcode ("movx", "@dptr,a");
11896         emitcode ("inc", "dptr");
11897         emitcode ("djnz","b,!tlabel",lbl->key+100);
11898     } else {
11899         symbol *lbl1 = newiTempLabel(NULL);
11900         
11901         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11902         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11903         emitcode ("","!tlabeldef",lbl->key+100);
11904         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11905         emitcode ("movx", "@dptr,a");
11906         emitcode ("inc", "dptr");
11907         emitcode ("mov","a,b");
11908         emitcode ("orl","a,_ap");
11909         emitcode ("jz","!tlabel",lbl1->key+100);
11910         emitcode ("mov","a,_ap");
11911         emitcode ("add","a,#!constbyte",0xFF);
11912         emitcode ("mov","_ap,a");
11913         emitcode ("mov","a,b");
11914         emitcode ("addc","a,#!constbyte",0xFF);
11915         emitcode ("mov","b,a");
11916         emitcode ("sjmp","!tlabel",lbl->key+100);
11917         emitcode ("","!tlabeldef",lbl1->key+100);
11918     }
11919     freeAsmop (count, NULL, ic, FALSE);
11920     unsavermask(rsave);
11921 }
11922
11923 /*-----------------------------------------------------------------*/
11924 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11925 /*-----------------------------------------------------------------*/
11926 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11927 {
11928         bitVect *rsave ;
11929         operand *pnum, *result;
11930         int i;
11931     
11932         assert (nparms==1);
11933         /* save registers that need to be saved */
11934         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11935                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11936     
11937         pnum = parms[0]; 
11938         aopOp (pnum, ic, FALSE, FALSE);
11939         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11940         freeAsmop (pnum, NULL, ic, FALSE);
11941         emitcode ("lcall","NatLib_LoadPrimitive");
11942         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11943         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11944             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11945                 for (i = (size-1) ; i >= 0 ; i-- ) {
11946                         emitcode ("push","a%s",javaRet[i]);
11947                 }
11948                 for (i=0; i < size ; i++ ) {
11949                         emitcode ("pop","a%s",
11950                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11951                 }
11952         } else {
11953                 for (i = 0 ; i < size ; i++ ) {
11954                         aopPut(AOP(result),javaRet[i],i);
11955                 }
11956         }    
11957         freeAsmop (result, NULL, ic, FALSE);
11958         unsavermask(rsave);
11959 }
11960
11961 /*-----------------------------------------------------------------*/
11962 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11963 /*-----------------------------------------------------------------*/
11964 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11965 {
11966         bitVect *rsave ;
11967         operand *pnum, *result;
11968         int size = 3;
11969         int i;
11970     
11971         assert (nparms==1);
11972         /* save registers that need to be saved */
11973         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11974                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11975     
11976         pnum = parms[0]; 
11977         aopOp (pnum, ic, FALSE, FALSE);
11978         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11979         freeAsmop (pnum, NULL, ic, FALSE);
11980         emitcode ("lcall","NatLib_LoadPointer");
11981         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11982         if (AOP_TYPE(result)!=AOP_STR) {
11983                 for (i = 0 ; i < size ; i++ ) {
11984                         aopPut(AOP(result),fReturn[i],i);
11985                 }
11986         }    
11987         freeAsmop (result, NULL, ic, FALSE);
11988         unsavermask(rsave);
11989 }
11990
11991 /*-----------------------------------------------------------------*/
11992 /* genNatLibInstallStateBlock -                                    */
11993 /*-----------------------------------------------------------------*/
11994 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11995                                        operand **parms, const char *name)
11996 {
11997         bitVect *rsave ;
11998         operand *psb, *handle;
11999         assert (nparms==2);
12000
12001         /* save registers that need to be saved */
12002         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12003                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12004         psb = parms[0];
12005         handle = parms[1];
12006
12007         /* put pointer to state block into DPTR1 */
12008         aopOp (psb, ic, FALSE, FALSE);
12009         if (AOP_TYPE (psb) == AOP_IMMD) {
12010                 emitcode ("mov","dps,#1");
12011                 emitcode ("mov", "dptr,%s",
12012                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12013                 emitcode ("mov","dps,#0");
12014         } else {
12015                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12016                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12017                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12018         }
12019         freeAsmop (psb, NULL, ic, FALSE);
12020
12021         /* put libraryID into DPTR */
12022         emitcode ("mov","dptr,#LibraryID");
12023
12024         /* put handle into r3:r2 */
12025         aopOp (handle, ic, FALSE, FALSE);
12026         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12027                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12028                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12029                 emitcode ("pop","ar3");
12030                 emitcode ("pop","ar2");
12031         } else {        
12032                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12033                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12034         }
12035         freeAsmop (psb, NULL, ic, FALSE);
12036
12037         /* make the call */
12038         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12039
12040         /* put return value into place*/
12041         _G.accInUse++;
12042         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12043         _G.accInUse--;
12044         aopPut(AOP(IC_RESULT(ic)),"a",0);
12045         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12046         unsavermask(rsave);
12047 }
12048
12049 /*-----------------------------------------------------------------*/
12050 /* genNatLibRemoveStateBlock -                                     */
12051 /*-----------------------------------------------------------------*/
12052 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12053 {
12054         bitVect *rsave ;
12055
12056         assert(nparms==0);
12057
12058         /* save registers that need to be saved */
12059         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12060                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12061
12062         /* put libraryID into DPTR */
12063         emitcode ("mov","dptr,#LibraryID");
12064         /* make the call */
12065         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12066         unsavermask(rsave);
12067 }
12068
12069 /*-----------------------------------------------------------------*/
12070 /* genNatLibGetStateBlock -                                        */
12071 /*-----------------------------------------------------------------*/
12072 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12073                                    operand **parms,const char *name)
12074 {
12075         bitVect *rsave ;
12076         symbol *lbl = newiTempLabel(NULL);
12077         
12078         assert(nparms==0);
12079         /* save registers that need to be saved */
12080         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12081                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12082
12083         /* put libraryID into DPTR */
12084         emitcode ("mov","dptr,#LibraryID");
12085         /* make the call */
12086         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12087         emitcode ("jnz","!tlabel",lbl->key+100);
12088
12089         /* put return value into place */
12090         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12091         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12092                 emitcode ("push","ar3");
12093                 emitcode ("push","ar2");
12094                 emitcode ("pop","%s",
12095                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12096                 emitcode ("pop","%s",
12097                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12098         } else {
12099                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12100                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12101         }
12102         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12103         emitcode ("","!tlabeldef",lbl->key+100);
12104         unsavermask(rsave);
12105 }
12106
12107 /*-----------------------------------------------------------------*/
12108 /* genMMMalloc -                                                   */
12109 /*-----------------------------------------------------------------*/
12110 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12111                          int size, const char *name)
12112 {
12113         bitVect *rsave ;
12114         operand *bsize;
12115         symbol *rsym;
12116         symbol *lbl = newiTempLabel(NULL);
12117
12118         assert (nparms == 1);
12119         /* save registers that need to be saved */
12120         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12121                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12122         
12123         bsize=parms[0];
12124         aopOp (bsize,ic,FALSE,FALSE);
12125
12126         /* put the size in R4-R2 */
12127         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12128                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12129                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12130                 if (size==3) {
12131                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12132                         emitcode("pop","ar4");
12133                 }
12134                 emitcode("pop","ar3");
12135                 emitcode("pop","ar2");          
12136         } else {
12137                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12138                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12139                 if (size==3) {
12140                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12141                 }
12142         }
12143         freeAsmop (bsize, NULL, ic, FALSE);
12144
12145         /* make the call */
12146         emitcode ("lcall","MM_%s",name);
12147         emitcode ("jz","!tlabel",lbl->key+100);
12148         emitcode ("mov","r2,#!constbyte",0xff);
12149         emitcode ("mov","r3,#!constbyte",0xff);
12150         emitcode ("","!tlabeldef",lbl->key+100);
12151         /* we don't care about the pointer : we just save the handle */
12152         rsym = OP_SYMBOL(IC_RESULT(ic));
12153         if (rsym->liveFrom != rsym->liveTo) {
12154                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12155                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12156                         emitcode ("push","ar3");
12157                         emitcode ("push","ar2");
12158                         emitcode ("pop","%s",
12159                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12160                         emitcode ("pop","%s",
12161                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12162                 } else {
12163                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12164                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12165                 }
12166                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12167         }
12168         unsavermask(rsave);
12169 }
12170
12171 /*-----------------------------------------------------------------*/
12172 /* genMMDeref -                                                    */
12173 /*-----------------------------------------------------------------*/
12174 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12175 {
12176         bitVect *rsave ;
12177         operand *handle;
12178
12179         assert (nparms == 1);
12180         /* save registers that need to be saved */
12181         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12182                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12183         
12184         handle=parms[0];
12185         aopOp (handle,ic,FALSE,FALSE);
12186
12187         /* put the size in R4-R2 */
12188         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12189                 emitcode("push","%s",
12190                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12191                 emitcode("push","%s",
12192                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12193                 emitcode("pop","ar3");
12194                 emitcode("pop","ar2");          
12195         } else {
12196                 emitcode ("mov","r2,%s",
12197                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12198                 emitcode ("mov","r3,%s",
12199                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12200         }
12201         freeAsmop (handle, NULL, ic, FALSE);
12202
12203         /* make the call */
12204         emitcode ("lcall","MM_Deref");
12205         
12206         {
12207                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12208                 if (rsym->liveFrom != rsym->liveTo) {                   
12209                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12210                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12211                             _startLazyDPSEvaluation ();
12212                             
12213                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12214                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12215                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12216
12217                             _endLazyDPSEvaluation ();
12218                             
12219                         }
12220                 }
12221         }
12222         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12223         unsavermask(rsave);
12224 }
12225
12226 /*-----------------------------------------------------------------*/
12227 /* genMMUnrestrictedPersist -                                      */
12228 /*-----------------------------------------------------------------*/
12229 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12230 {
12231         bitVect *rsave ;
12232         operand *handle;
12233
12234         assert (nparms == 1);
12235         /* save registers that need to be saved */
12236         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12237                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12238         
12239         handle=parms[0];
12240         aopOp (handle,ic,FALSE,FALSE);
12241
12242         /* put the size in R3-R2 */
12243         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12244                 emitcode("push","%s",
12245                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12246                 emitcode("push","%s",
12247                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12248                 emitcode("pop","ar3");
12249                 emitcode("pop","ar2");          
12250         } else {
12251                 emitcode ("mov","r2,%s",
12252                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12253                 emitcode ("mov","r3,%s",
12254                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12255         }
12256         freeAsmop (handle, NULL, ic, FALSE);
12257
12258         /* make the call */
12259         emitcode ("lcall","MM_UnrestrictedPersist");
12260
12261         {
12262                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12263                 if (rsym->liveFrom != rsym->liveTo) {   
12264                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12265                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12266                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12267                 }
12268         }
12269         unsavermask(rsave);
12270 }
12271
12272 /*-----------------------------------------------------------------*/
12273 /* genSystemExecJavaProcess -                                      */
12274 /*-----------------------------------------------------------------*/
12275 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12276 {
12277         bitVect *rsave ;
12278         operand *handle, *pp;
12279
12280         assert (nparms==2);
12281         /* save registers that need to be saved */
12282         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12283                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12284         
12285         pp = parms[0];
12286         handle = parms[1];
12287         
12288         /* put the handle in R3-R2 */
12289         aopOp (handle,ic,FALSE,FALSE);
12290         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12291                 emitcode("push","%s",
12292                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12293                 emitcode("push","%s",
12294                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12295                 emitcode("pop","ar3");
12296                 emitcode("pop","ar2");          
12297         } else {
12298                 emitcode ("mov","r2,%s",
12299                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12300                 emitcode ("mov","r3,%s",
12301                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12302         }
12303         freeAsmop (handle, NULL, ic, FALSE);
12304         
12305         /* put pointer in DPTR */
12306         aopOp (pp,ic,FALSE,FALSE);
12307         if (AOP_TYPE(pp) == AOP_IMMD) {
12308                 emitcode ("mov", "dptr,%s",
12309                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12310         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12311                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12312                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12313                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12314         }
12315         freeAsmop (handle, NULL, ic, FALSE);
12316
12317         /* make the call */
12318         emitcode ("lcall","System_ExecJavaProcess");
12319         
12320         /* put result in place */
12321         {
12322                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12323                 if (rsym->liveFrom != rsym->liveTo) {   
12324                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12325                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12326                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12327                 }
12328         }
12329         
12330         unsavermask(rsave);
12331 }
12332
12333 /*-----------------------------------------------------------------*/
12334 /* genSystemRTCRegisters -                                         */
12335 /*-----------------------------------------------------------------*/
12336 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12337                                   char *name)
12338 {
12339         bitVect *rsave ;
12340         operand *pp;
12341
12342         assert (nparms==1);
12343         /* save registers that need to be saved */
12344         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12345                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12346         
12347         pp=parms[0];
12348         /* put pointer in DPTR */
12349         aopOp (pp,ic,FALSE,FALSE);
12350         if (AOP_TYPE (pp) == AOP_IMMD) {
12351                 emitcode ("mov","dps,#1");
12352                 emitcode ("mov", "dptr,%s", 
12353                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12354                 emitcode ("mov","dps,#0");
12355         } else {
12356                 emitcode ("mov","dpl1,%s",
12357                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12358                 emitcode ("mov","dph1,%s",
12359                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12360                 emitcode ("mov","dpx1,%s",
12361                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12362         }
12363         freeAsmop (pp, NULL, ic, FALSE);
12364
12365         /* make the call */
12366         emitcode ("lcall","System_%sRTCRegisters",name);
12367
12368         unsavermask(rsave);
12369 }
12370
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemThreadSleep -                                          */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12375 {
12376         bitVect *rsave ;
12377         operand *to, *s;
12378
12379         assert (nparms==1);
12380         /* save registers that need to be saved */
12381         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12382                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12383
12384         to = parms[0];
12385         aopOp(to,ic,FALSE,FALSE);
12386         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12387             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12388                 emitcode ("push","%s",
12389                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12390                 emitcode ("push","%s",
12391                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12392                 emitcode ("push","%s",
12393                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12394                 emitcode ("push","%s",
12395                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12396                 emitcode ("pop","ar3");
12397                 emitcode ("pop","ar2");
12398                 emitcode ("pop","ar1");
12399                 emitcode ("pop","ar0");
12400         } else {
12401                 emitcode ("mov","r0,%s",
12402                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12403                 emitcode ("mov","r1,%s",
12404                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12405                 emitcode ("mov","r2,%s",
12406                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12407                 emitcode ("mov","r3,%s",
12408                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12409         }
12410         freeAsmop (to, NULL, ic, FALSE);
12411
12412         /* suspend in acc */
12413         s = parms[1];
12414         aopOp(s,ic,FALSE,FALSE);
12415         emitcode ("mov","a,%s",
12416                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12417         freeAsmop (s, NULL, ic, FALSE);
12418
12419         /* make the call */
12420         emitcode ("lcall","System_%s",name);
12421
12422         unsavermask(rsave);
12423 }
12424
12425 /*-----------------------------------------------------------------*/
12426 /* genSystemThreadResume -                                         */
12427 /*-----------------------------------------------------------------*/
12428 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12429 {
12430         bitVect *rsave ;
12431         operand *tid,*pid;
12432
12433         assert (nparms==2);
12434         /* save registers that need to be saved */
12435         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12436                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12437         
12438         tid = parms[0];
12439         pid = parms[1];
12440         
12441         /* PID in R0 */
12442         aopOp(pid,ic,FALSE,FALSE);
12443         emitcode ("mov","r0,%s",
12444                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12445         freeAsmop (pid, NULL, ic, FALSE);
12446         
12447         /* tid into ACC */
12448         aopOp(tid,ic,FALSE,FALSE);
12449         emitcode ("mov","a,%s",
12450                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12451         freeAsmop (tid, NULL, ic, FALSE);
12452         
12453         emitcode ("lcall","System_ThreadResume");
12454
12455         /* put result into place */
12456         {
12457                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12458                 if (rsym->liveFrom != rsym->liveTo) {   
12459                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12460                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12461                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12462                 }
12463         }
12464         unsavermask(rsave);
12465 }
12466
12467 /*-----------------------------------------------------------------*/
12468 /* genSystemProcessResume -                                        */
12469 /*-----------------------------------------------------------------*/
12470 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12471 {
12472         bitVect *rsave ;
12473         operand *pid;
12474
12475         assert (nparms==1);
12476         /* save registers that need to be saved */
12477         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12478                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12479         
12480         pid = parms[0];
12481         
12482         /* pid into ACC */
12483         aopOp(pid,ic,FALSE,FALSE);
12484         emitcode ("mov","a,%s",
12485                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12486         freeAsmop (pid, NULL, ic, FALSE);
12487         
12488         emitcode ("lcall","System_ProcessResume");
12489
12490         unsavermask(rsave);
12491 }
12492
12493 /*-----------------------------------------------------------------*/
12494 /* genSystem -                                                     */
12495 /*-----------------------------------------------------------------*/
12496 static void genSystem (iCode *ic,int nparms,char *name)
12497 {
12498         assert(nparms == 0);
12499
12500         emitcode ("lcall","System_%s",name);
12501 }
12502
12503 /*-----------------------------------------------------------------*/
12504 /* genSystemPoll -                                                  */
12505 /*-----------------------------------------------------------------*/
12506 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12507 {
12508         bitVect *rsave ;
12509         operand *fp;
12510
12511         assert (nparms==1);
12512         /* save registers that need to be saved */
12513         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12514                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12515
12516         fp = parms[0];
12517         aopOp (fp,ic,FALSE,FALSE);
12518         if (AOP_TYPE (fp) == AOP_IMMD) {
12519                 emitcode ("mov", "dptr,%s", 
12520                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12521         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12522                 emitcode ("mov","dpl,%s",
12523                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12524                 emitcode ("mov","dph,%s",
12525                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12526                 emitcode ("mov","dpx,%s",
12527                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12528         }
12529         freeAsmop (fp, NULL, ic, FALSE);
12530
12531         emitcode ("lcall","System_%sPoll",name);
12532
12533         /* put result into place */
12534         {
12535                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12536                 if (rsym->liveFrom != rsym->liveTo) {   
12537                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12538                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12539                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12540                 }
12541         }
12542         unsavermask(rsave);
12543 }
12544
12545 /*-----------------------------------------------------------------*/
12546 /* genSystemGetCurrentID -                                         */
12547 /*-----------------------------------------------------------------*/
12548 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12549 {
12550         assert (nparms==0);
12551
12552         emitcode ("lcall","System_GetCurrent%sId",name);
12553         /* put result into place */
12554         {
12555                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12556                 if (rsym->liveFrom != rsym->liveTo) {   
12557                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12558                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12559                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12560                 }
12561         }
12562 }
12563
12564 /*-----------------------------------------------------------------*/
12565 /* genBuiltIn - calls the appropriate function to  generating code */
12566 /* for a built in function                                         */
12567 /*-----------------------------------------------------------------*/
12568 static void genBuiltIn (iCode *ic)
12569 {
12570         operand *bi_parms[MAX_BUILTIN_ARGS];
12571         int nbi_parms;
12572         iCode *bi_iCode;
12573         symbol *bif;
12574
12575         /* get all the arguments for a built in function */
12576         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12577
12578         /* which function is it */
12579         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12580         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12581                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12582         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12583                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12584         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12585                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12586         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12587                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12588         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12589                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12590         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12591                 genInp(bi_iCode,nbi_parms,bi_parms);
12592         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12593                 genOutp(bi_iCode,nbi_parms,bi_parms);
12594         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12595                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12596                 /* JavaNative builtIns */               
12597         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12598                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12599         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12600                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12601         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12602                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12603         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12604                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12605         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12606                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12607         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12608                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12609         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12610                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12611         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12612                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12613         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12614                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12615         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12616                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12617         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12618                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12619         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12620                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12621         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12622                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12623         } else if (strcmp(bif->name,"MM_Free")==0) {
12624                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12625         } else if (strcmp(bif->name,"MM_Deref")==0) {
12626                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12627         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12628                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12629         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12630                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12631         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12632                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12633         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12634                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12635         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12636                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12637         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12638                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12639         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12640                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12641         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12642                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12643         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12644                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12645         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12646                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12647         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12648                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12649         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12650                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12651         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12652                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12653         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12654                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12655         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12656                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12657         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12658                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12659         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12660                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12661         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12662                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12663         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12664                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12665         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12666                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12667         } else {
12668                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12669                 return ;
12670         }
12671         return ;    
12672 }
12673
12674 /*-----------------------------------------------------------------*/
12675 /* gen390Code - generate code for Dallas 390 based controllers     */
12676 /*-----------------------------------------------------------------*/
12677 void
12678 gen390Code (iCode * lic)
12679 {
12680   iCode *ic;
12681   int cln = 0;
12682
12683   lineHead = lineCurr = NULL;
12684   dptrn[1][0] = "dpl1";
12685   dptrn[1][1] = "dph1";
12686   dptrn[1][2] = "dpx1";
12687   
12688   if (options.model == MODEL_FLAT24) {
12689     fReturnSizeDS390 = 5;
12690     fReturn = fReturn24;
12691   } else {
12692     fReturnSizeDS390 = 4;
12693     fReturn = fReturn16;
12694     options.stack10bit=0;
12695   }
12696 #if 1
12697   /* print the allocation information */
12698   if (allocInfo)
12699     printAllocInfo (currFunc, codeOutFile);
12700 #endif
12701   /* if debug information required */
12702   if (options.debug && currFunc)
12703     {
12704       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12705       _G.debugLine = 1;
12706       if (IS_STATIC (currFunc->etype))
12707         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12708       else
12709         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12710       _G.debugLine = 0;
12711     }
12712   /* stack pointer name */
12713   if (options.useXstack)
12714     spname = "_spx";
12715   else
12716     spname = "sp";
12717
12718
12719   for (ic = lic; ic; ic = ic->next)
12720     {
12721
12722       if (ic->lineno && cln != ic->lineno)
12723         {
12724           if (options.debug)
12725             {
12726               _G.debugLine = 1;
12727               emitcode ("", "C$%s$%d$%d$%d ==.",
12728                         FileBaseName (ic->filename), ic->lineno,
12729                         ic->level, ic->block);
12730               _G.debugLine = 0;
12731             }
12732           if (!options.noCcodeInAsm) {
12733             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12734                       printCLine(ic->filename, ic->lineno));
12735           }
12736           cln = ic->lineno;
12737         }
12738       if (options.iCodeInAsm) {
12739         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12740       }
12741       /* if the result is marked as
12742          spilt and rematerializable or code for
12743          this has already been generated then
12744          do nothing */
12745       if (resultRemat (ic) || ic->generated)
12746         continue;
12747
12748       /* depending on the operation */
12749       switch (ic->op)
12750         {
12751         case '!':
12752           genNot (ic);
12753           break;
12754
12755         case '~':
12756           genCpl (ic);
12757           break;
12758
12759         case UNARYMINUS:
12760           genUminus (ic);
12761           break;
12762
12763         case IPUSH:
12764           genIpush (ic);
12765           break;
12766
12767         case IPOP:
12768           /* IPOP happens only when trying to restore a
12769              spilt live range, if there is an ifx statement
12770              following this pop then the if statement might
12771              be using some of the registers being popped which
12772              would destory the contents of the register so
12773              we need to check for this condition and handle it */
12774           if (ic->next &&
12775               ic->next->op == IFX &&
12776               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12777             genIfx (ic->next, ic);
12778           else
12779             genIpop (ic);
12780           break;
12781
12782         case CALL:
12783           genCall (ic);
12784           break;
12785
12786         case PCALL:
12787           genPcall (ic);
12788           break;
12789
12790         case FUNCTION:
12791           genFunction (ic);
12792           break;
12793
12794         case ENDFUNCTION:
12795           genEndFunction (ic);
12796           break;
12797
12798         case RETURN:
12799           genRet (ic);
12800           break;
12801
12802         case LABEL:
12803           genLabel (ic);
12804           break;
12805
12806         case GOTO:
12807           genGoto (ic);
12808           break;
12809
12810         case '+':
12811           genPlus (ic);
12812           break;
12813
12814         case '-':
12815           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12816             genMinus (ic);
12817           break;
12818
12819         case '*':
12820           genMult (ic);
12821           break;
12822
12823         case '/':
12824           genDiv (ic);
12825           break;
12826
12827         case '%':
12828           genMod (ic);
12829           break;
12830
12831         case '>':
12832           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12833           break;
12834
12835         case '<':
12836           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12837           break;
12838
12839         case LE_OP:
12840         case GE_OP:
12841         case NE_OP:
12842
12843           /* note these two are xlated by algebraic equivalence
12844              during parsing SDCC.y */
12845           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12846                   "got '>=' or '<=' shouldn't have come here");
12847           break;
12848
12849         case EQ_OP:
12850           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12851           break;
12852
12853         case AND_OP:
12854           genAndOp (ic);
12855           break;
12856
12857         case OR_OP:
12858           genOrOp (ic);
12859           break;
12860
12861         case '^':
12862           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12863           break;
12864
12865         case '|':
12866           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12867           break;
12868
12869         case BITWISEAND:
12870           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12871           break;
12872
12873         case INLINEASM:
12874           genInline (ic);
12875           break;
12876
12877         case RRC:
12878           genRRC (ic);
12879           break;
12880
12881         case RLC:
12882           genRLC (ic);
12883           break;
12884
12885         case GETHBIT:
12886           genGetHbit (ic);
12887           break;
12888
12889         case LEFT_OP:
12890           genLeftShift (ic);
12891           break;
12892
12893         case RIGHT_OP:
12894           genRightShift (ic);
12895           break;
12896
12897         case GET_VALUE_AT_ADDRESS:
12898           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12899           break;
12900
12901         case '=':
12902           if (POINTER_SET (ic))
12903             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12904           else
12905             genAssign (ic);
12906           break;
12907
12908         case IFX:
12909           genIfx (ic, NULL);
12910           break;
12911
12912         case ADDRESS_OF:
12913           genAddrOf (ic);
12914           break;
12915
12916         case JUMPTABLE:
12917           genJumpTab (ic);
12918           break;
12919
12920         case CAST:
12921           genCast (ic);
12922           break;
12923
12924         case RECEIVE:
12925           genReceive (ic);
12926           break;
12927
12928         case SEND:
12929           if (ic->builtinSEND) genBuiltIn(ic);
12930           else addSet (&_G.sendSet, ic);
12931           break;
12932
12933         case ARRAYINIT:
12934             genArrayInit(ic);
12935             break;
12936             
12937         default:
12938           ic = ic;
12939         }
12940     }
12941
12942
12943   /* now we are ready to call the
12944      peep hole optimizer */
12945   if (!options.nopeep)
12946     peepHole (&lineHead);
12947
12948   /* now do the actual printing */
12949   printLine (lineHead, codeOutFile);
12950   return;
12951 }