OP_SYMBOL and OP_VALUE check their parameters are the proper type
[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 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59 extern int allocInfo;
60
61 /* this is the down and dirty file with all kinds of
62    kludgy & hacky stuff. This is what it is all about
63    CODE GENERATION for a specific MCU . some of the
64    routines may be reusable, will have to see */
65
66 static char *zero = "#0";
67 static char *one = "#1";
68 static char *spname;
69
70 #define D(x) x
71
72 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
73 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
74
75 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
76 static char *fReturn24[] =
77 {"dpl", "dph", "dpx", "b", "a"};
78 static char *fReturn16[] =
79 {"dpl", "dph", "b", "a"};
80 static char **fReturn = fReturn24;
81 static char *accUse[] =
82 {"a", "b"};
83 static char *dptrn[2][3];
84 static char *javaRet[] = { "r0","r1","r2","r3"};
85 static short rbank = -1;
86
87 static struct
88   {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short bInUse;
93     short inLine;
94     short debugLine;
95     short nRegsSaved;
96     short dptrInUse;
97     short dptr1InUse;
98     set *sendSet;
99   }
100 _G;
101
102 static char *rb1regs[] = {
103     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
104 };
105
106 static void saveRBank (int, iCode *, bool);
107
108 #define RESULTONSTACK(x) \
109                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
110                          IC_RESULT(x)->aop->type == AOP_STK )
111
112 #define MOVA(x) _movA(x)
113 #define MOVB(x) _movB(x)
114                 
115 #define CLRC    emitcode("clr","c")
116 #define SETC    emitcode("setb","c")
117
118 // A scratch register which will be used to hold
119 // result bytes from operands in far space via DPTR2.
120 #define DP2_RESULT_REG  "_ap"
121
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
124
125 static unsigned char SLMask[] =
126 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
127  0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char SRMask[] =
129 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
130  0x07, 0x03, 0x01, 0x00};
131
132 #define LSB     0
133 #define MSB16   1
134 #define MSB24   2
135 #define MSB32   3
136 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
137                                 symbol *lbl = newiTempLabel(NULL);              \
138                                 emitcode ("setb","F1");                         \
139                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
140                                 emitcode ("clr","F1");                          \
141                                 emitcode ("","!tlabeldef",lbl->key+100);        \
142                         }}
143 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
144                                 symbol *lbl = newiTempLabel(NULL);              \
145                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
146                                 emitcode ("setb","EA");                         \
147                                 emitcode ("","!tlabeldef",lbl->key+100);        \
148                         }}
149
150
151 /*-----------------------------------------------------------------*/
152 /* emitcode - writes the code into a file : for now it is simple    */
153 /*-----------------------------------------------------------------*/
154 static void
155 emitcode (char *inst, char *fmt,...)
156 {
157     va_list ap;
158     char lb[INITIAL_INLINEASM];
159     char *lbp = lb;
160     
161     va_start (ap, fmt);
162     
163     if (inst && *inst)
164     {
165         if (fmt && *fmt)
166         {
167             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
168         }
169         else
170         {
171             SNPRINTF (lb, sizeof(lb), "%s", inst);
172         }
173         
174         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
175                    fmt, ap);
176     }
177     else
178     {
179         tvsprintf (lb, sizeof(lb), fmt, ap);
180     }
181     
182
183     while (isspace (*lbp))
184     {
185         lbp++;
186     }
187
188     if (lbp && *lbp)
189     {
190         lineCurr = (lineCurr ?
191                     connectLine (lineCurr, newLineNode (lb)) :
192                     (lineHead = newLineNode (lb)));
193     }
194     
195     lineCurr->isInline = _G.inLine;
196     lineCurr->isDebug = _G.debugLine;
197     va_end (ap);
198 }
199
200 //
201 // Move the passed value into A unless it is already there.
202 // 
203 static void
204 _movA(const char *s)
205 {
206     if (strcmp(s,"a") && strcmp(s,"acc"))
207     { 
208         emitcode("mov","a,%s",s);
209     } 
210 }
211
212 //
213 // Move the passed value into B unless it is already there.
214 // 
215 static void
216 _movB(const char *s)
217 {
218     if (strcmp(s,"b"))
219     { 
220         emitcode("mov","b,%s",s);
221     } 
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
227 static regs *
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
229 {
230   bool r0iu, r1iu;
231   bool r0ou, r1ou;
232
233   /* the logic: if r0 & r1 used in the instruction
234      then we are in trouble otherwise */
235
236   /* first check if r0 & r1 are used by this
237      instruction, in which case we are in trouble */
238   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
240   if (r0iu && r1iu) {
241       goto endOfWorld;
242     }
243
244   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
246
247   /* if no usage of r0 then return it */
248   if (!r0iu && !r0ou)
249     {
250       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251       (*aopp)->type = AOP_R0;
252
253       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
254     }
255
256   /* if no usage of r1 then return it */
257   if (!r1iu && !r1ou)
258     {
259       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260       (*aopp)->type = AOP_R1;
261
262       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
263     }
264
265   /* now we know they both have usage */
266   /* if r0 not used in this instruction */
267   if (!r0iu)
268     {
269       /* push it if not already pushed */
270       if (!_G.r0Pushed)
271         {
272           emitcode ("push", "%s",
273                     ds390_regWithIdx (R0_IDX)->dname);
274           _G.r0Pushed++;
275         }
276
277       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278       (*aopp)->type = AOP_R0;
279
280       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
281     }
282
283   /* if r1 not used then */
284
285   if (!r1iu)
286     {
287       /* push it if not already pushed */
288       if (!_G.r1Pushed)
289         {
290           emitcode ("push", "%s",
291                     ds390_regWithIdx (R1_IDX)->dname);
292           _G.r1Pushed++;
293         }
294
295       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296       (*aopp)->type = AOP_R1;
297       return ds390_regWithIdx (R1_IDX);
298     }
299
300 endOfWorld:
301   /* I said end of world but not quite end of world yet */
302   /* if this is a result then we can push it on the stack */
303   if (result)
304     {
305       (*aopp)->type = AOP_STK;
306       return NULL;
307     }
308
309   /* other wise this is true end of the world */
310   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311           "getFreePtr should never reach here");
312   exit (1);
313     
314   return NULL; // notreached, but makes compiler happy.
315 }
316
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp                                  */
319 /*-----------------------------------------------------------------*/
320 static asmop *
321 newAsmop (short type)
322 {
323   asmop *aop;
324
325   aop = Safe_calloc (1, sizeof (asmop));
326   aop->type = type;
327   return aop;
328 }
329
330 static int _currentDPS;         /* Current processor DPS. */
331 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
332 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
333
334 /*-----------------------------------------------------------------*/
335 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
336 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
337 /* alternate DPTR (DPL1/DPH1/DPX1).          */
338 /*-----------------------------------------------------------------*/
339 static void
340 genSetDPTR (int n)
341 {
342
343   /* If we are doing lazy evaluation, simply note the desired
344    * change, but don't emit any code yet.
345    */
346   if (_lazyDPS)
347     {
348       _desiredDPS = n;
349       return;
350     }
351
352   if (!n)
353     {
354       emitcode ("mov", "dps,#0");
355     }
356   else
357     {
358       TR_DPTR("#1");
359       emitcode ("mov", "dps,#1");
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
365 /*                   */
366 /* Any code that operates on DPTR (NB: not on the individual     */
367 /* components, like DPH) *must* call _flushLazyDPS() before using  */
368 /* DPTR within a lazy DPS evaluation block.        */
369 /*                   */
370 /* Note that aopPut and aopGet already contain the proper calls to */
371 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
372 /* DPS evaluation block.             */
373 /*                   */
374 /* Also, _flushLazyDPS must be called before any flow control      */
375 /* operations that could potentially branch out of the block.    */
376 /*                         */
377 /* Lazy DPS evaluation is simply an optimization (though an      */
378 /* important one), so if in doubt, leave it out.       */
379 /*-----------------------------------------------------------------*/
380 static void
381 _startLazyDPSEvaluation (void)
382 {
383   _currentDPS = 0;
384   _desiredDPS = 0;
385 #ifdef BETTER_LITERAL_SHIFT  
386   _lazyDPS++;
387 #else
388   _lazyDPS = 1;
389 #endif  
390 }
391
392 /*-----------------------------------------------------------------*/
393 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
394 /* desired one. Call before using DPTR within a lazy DPS evaluation */
395 /* block.                */
396 /*-----------------------------------------------------------------*/
397 static void
398 _flushLazyDPS (void)
399 {
400   if (!_lazyDPS)
401     {
402       /* nothing to do. */
403       return;
404     }
405
406   if (_desiredDPS != _currentDPS)
407     {
408       if (_desiredDPS)
409         {
410           emitcode ("inc", "dps");
411         }
412       else
413         {
414           emitcode ("dec", "dps");
415         }
416       _currentDPS = _desiredDPS;
417     }
418 }
419
420 /*-----------------------------------------------------------------*/
421 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
422 /*                   */
423 /* Forces us back to the safe state (standard DPTR selected).    */
424 /*-----------------------------------------------------------------*/
425 static void
426 _endLazyDPSEvaluation (void)
427 {
428 #ifdef BETTER_LITERAL_SHIFT  
429   _lazyDPS--;
430 #else
431   _lazyDPS = 0;
432 #endif    
433   if (!_lazyDPS)
434   {
435     if (_currentDPS)
436     {
437       genSetDPTR (0);
438       _flushLazyDPS ();
439     }
440     _currentDPS = 0;
441     _desiredDPS = 0;
442   }
443 }
444
445
446
447 /*-----------------------------------------------------------------*/
448 /* pointerCode - returns the code for a pointer type               */
449 /*-----------------------------------------------------------------*/
450 static int
451 pointerCode (sym_link * etype)
452 {
453
454   return PTR_TYPE (SPEC_OCLS (etype));
455
456 }
457
458 /*-----------------------------------------------------------------*/
459 /* aopForSym - for a true symbol                                   */
460 /*-----------------------------------------------------------------*/
461 static asmop *
462 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
463 {
464   asmop *aop;
465   memmap *space = SPEC_OCLS (sym->etype);
466
467   /* if already has one */
468   if (sym->aop)
469     return sym->aop;
470
471   /* assign depending on the storage class */
472   /* if it is on the stack or indirectly addressable */
473   /* space we need to assign either r0 or r1 to it   */
474   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
475     {
476       sym->aop = aop = newAsmop (0);
477       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
478       aop->size = getSize (sym->type);
479
480       /* now assign the address of the variable to
481          the pointer register */
482       if (aop->type != AOP_STK)
483         {
484
485           if (sym->onStack)
486             {
487               if (_G.accInUse)
488                 emitcode ("push", "acc");
489
490               if (_G.bInUse)
491                 emitcode ("push", "b");
492
493               emitcode ("mov", "a,_bp");
494               emitcode ("add", "a,#!constbyte",
495                         ((sym->stack < 0) ?
496                          ((char) (sym->stack - _G.nRegsSaved)) :
497                          ((char) sym->stack)) & 0xff);
498               emitcode ("mov", "%s,a",
499                         aop->aopu.aop_ptr->name);
500
501               if (_G.bInUse)
502                 emitcode ("pop", "b");
503
504               if (_G.accInUse)
505                 emitcode ("pop", "acc");
506             }
507           else
508             emitcode ("mov", "%s,#%s",
509                       aop->aopu.aop_ptr->name,
510                       sym->rname);
511           aop->paged = space->paged;
512         }
513       else
514         aop->aopu.aop_stk = sym->stack;
515       return aop;
516     }
517
518   if (sym->onStack && options.stack10bit)
519     {
520         short stack_val = -((sym->stack < 0) ?
521                             ((short) (sym->stack - _G.nRegsSaved)) :
522                             ((short) sym->stack)) ;
523         if (useDP2 && _G.dptr1InUse) {
524             emitcode ("push","dpl1");
525             emitcode ("push","dph1");
526             emitcode ("push","dpx1");
527         } else if (_G.dptrInUse ) {
528             emitcode ("push","dpl");
529             emitcode ("push","dph");
530             emitcode ("push","dpx");
531         }
532       /* It's on the 10 bit stack, which is located in
533        * far data space.
534        */           
535         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
536             if (useDP2) {
537                 if (options.model == MODEL_FLAT24)
538                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
539                 TR_DPTR("#2");
540                 emitcode ("mov", "dph1,_bpx+1");
541                 emitcode ("mov", "dpl1,_bpx");
542                 emitcode ("mov","dps,#1");
543             } else {
544                 if (options.model == MODEL_FLAT24)
545                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
546                 emitcode ("mov", "dph,_bpx+1");
547                 emitcode ("mov", "dpl,_bpx");
548             }
549             stack_val = -stack_val;
550             while (stack_val--) {
551                 emitcode ("inc","dptr");
552             }
553             if (useDP2) {
554                 emitcode("mov","dps,#0");
555             }
556         }  else {
557             if (_G.accInUse)
558                 emitcode ("push", "acc");
559             
560             if (_G.bInUse)
561                 emitcode ("push", "b");
562         
563             emitcode ("mov", "a,_bpx");
564             emitcode ("clr","c");
565             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
566             emitcode ("mov","b,a");
567             emitcode ("mov","a,_bpx+1");
568             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
569             if (useDP2) {
570                 if (options.model == MODEL_FLAT24)
571                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
572                 TR_DPTR("#2");
573                 emitcode ("mov", "dph1,a");
574                 emitcode ("mov", "dpl1,b");
575             } else {
576                 if (options.model == MODEL_FLAT24)
577                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
578                 emitcode ("mov", "dph,a");
579                 emitcode ("mov", "dpl,b");
580             }
581             
582             if (_G.bInUse)
583                 emitcode ("pop", "b");
584             
585             if (_G.accInUse)
586                 emitcode ("pop", "acc");
587         }
588         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
589         aop->size = getSize (sym->type);
590         return aop;
591     }
592
593   /* if in bit space */
594   if (IN_BITSPACE (space))
595     {
596       sym->aop = aop = newAsmop (AOP_CRY);
597       aop->aopu.aop_dir = sym->rname;
598       aop->size = getSize (sym->type);
599       return aop;
600     }
601   /* if it is in direct space */
602   if (IN_DIRSPACE (space))
603     {
604       sym->aop = aop = newAsmop (AOP_DIR);
605       aop->aopu.aop_dir = sym->rname;
606       aop->size = getSize (sym->type);
607       return aop;
608     }
609
610   /* special case for a function */
611   if (IS_FUNC (sym->type))
612     {
613       sym->aop = aop = newAsmop (AOP_IMMD);
614       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
615       aop->size = FPTRSIZE;
616       return aop;
617     }
618   
619   /* only remaining is far space */
620   /* in which case DPTR gets the address */
621   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
622   if (useDP2)
623     {
624       genSetDPTR (1);
625       _flushLazyDPS ();
626       emitcode ("mov", "dptr,#%s", sym->rname);
627       genSetDPTR (0);
628     }
629   else
630     {
631       emitcode ("mov", "dptr,#%s", sym->rname);
632     }
633   aop->size = getSize (sym->type);
634
635   /* if it is in code space */
636   if (IN_CODESPACE (space))
637     aop->code = 1;
638
639   return aop;
640 }
641
642 /*-----------------------------------------------------------------*/
643 /* aopForRemat - rematerialzes an object                           */
644 /*-----------------------------------------------------------------*/
645 static asmop *
646 aopForRemat (symbol * sym)
647 {
648   iCode *ic = sym->rematiCode;
649   asmop *aop = newAsmop (AOP_IMMD);
650   int ptr_type =0;
651   int val = 0;
652
653   for (;;)
654     {
655       if (ic->op == '+')
656         val += (int) operandLitValue (IC_RIGHT (ic));
657       else if (ic->op == '-')
658         val -= (int) operandLitValue (IC_RIGHT (ic));
659       else if (IS_CAST_ICODE(ic)) {
660               sym_link *from_type = operandType(IC_RIGHT(ic));
661               aop->aopu.aop_immd.from_cast_remat = 1;
662               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
663               ptr_type = DCL_TYPE(from_type);
664               if (ptr_type == IPOINTER) {
665                 // bug #481053
666                 ptr_type = POINTER;
667               }
668               continue ;
669       } else break;
670       
671       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
672     }
673
674   if (val)
675   {
676       SNPRINTF (buffer, sizeof(buffer),
677                 "(%s %c 0x%04x)",
678                 OP_SYMBOL (IC_LEFT (ic))->rname,
679                 val >= 0 ? '+' : '-',
680                 abs (val) & 0xffff);
681   }
682   else 
683   {
684       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
685       {
686           SNPRINTF(buffer, sizeof(buffer), 
687                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
688       }
689       else
690       {
691           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
692       }
693   }
694
695   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
696   /* set immd2 field if required */
697   if (aop->aopu.aop_immd.from_cast_remat) 
698   {
699       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
700       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
701   }
702
703   return aop;
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* aopHasRegs - returns true if aop has regs between from-to       */
708 /*-----------------------------------------------------------------*/
709 static int aopHasRegs(asmop *aop, int from, int to)
710 {
711     int size =0;
712
713     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
714
715     for (; size < aop->size ; size++) {
716         int reg;
717         for (reg = from ; reg <= to ; reg++)
718             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
719     }
720     return 0;
721 }
722
723 /*-----------------------------------------------------------------*/
724 /* regsInCommon - two operands have some registers in common       */
725 /*-----------------------------------------------------------------*/
726 static bool
727 regsInCommon (operand * op1, operand * op2)
728 {
729   symbol *sym1, *sym2;
730   int i;
731
732   /* if they have registers in common */
733   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
734     return FALSE;
735
736   sym1 = OP_SYMBOL (op1);
737   sym2 = OP_SYMBOL (op2);
738
739   if (sym1->nRegs == 0 || sym2->nRegs == 0)
740     return FALSE;
741
742   for (i = 0; i < sym1->nRegs; i++)
743     {
744       int j;
745       if (!sym1->regs[i])
746         continue;
747
748       for (j = 0; j < sym2->nRegs; j++)
749         {
750           if (!sym2->regs[j])
751             continue;
752
753           if (sym2->regs[j] == sym1->regs[i])
754             return TRUE;
755         }
756     }
757
758   return FALSE;
759 }
760
761 /*-----------------------------------------------------------------*/
762 /* operandsEqu - equivalent                                        */
763 /*-----------------------------------------------------------------*/
764 static bool
765 operandsEqu (operand * op1, operand * op2)
766 {
767   symbol *sym1, *sym2;
768
769   /* if they not symbols */
770   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
771     return FALSE;
772
773   sym1 = OP_SYMBOL (op1);
774   sym2 = OP_SYMBOL (op2);
775
776   /* if both are itemps & one is spilt
777      and the other is not then false */
778   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
779       sym1->isspilt != sym2->isspilt)
780     return FALSE;
781
782   /* if they are the same */
783   if (sym1 == sym2)
784     return TRUE;
785
786   if (strcmp (sym1->rname, sym2->rname) == 0)
787     return TRUE;
788
789
790   /* if left is a tmp & right is not */
791   if (IS_ITEMP (op1) &&
792       !IS_ITEMP (op2) &&
793       sym1->isspilt &&
794       (sym1->usl.spillLoc == sym2))
795     return TRUE;
796
797   if (IS_ITEMP (op2) &&
798       !IS_ITEMP (op1) &&
799       sym2->isspilt &&
800       sym1->level > 0 &&
801       (sym2->usl.spillLoc == sym1))
802     return TRUE;
803
804   return FALSE;
805 }
806
807 /*-----------------------------------------------------------------*/
808 /* sameRegs - two asmops have the same registers                   */
809 /*-----------------------------------------------------------------*/
810 static bool
811 sameRegs (asmop * aop1, asmop * aop2)
812 {
813   int i;
814
815   if (aop1 == aop2)
816     {
817       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
818         {
819           return FALSE;
820         }
821       return TRUE;
822     }
823
824   if (aop1->type != AOP_REG ||
825       aop2->type != AOP_REG)
826     return FALSE;
827
828   if (aop1->size != aop2->size)
829     return FALSE;
830
831   for (i = 0; i < aop1->size; i++)
832     if (aop1->aopu.aop_reg[i] !=
833         aop2->aopu.aop_reg[i])
834       return FALSE;
835
836   return TRUE;
837 }
838
839 /*-----------------------------------------------------------------*/
840 /* aopOp - allocates an asmop for an operand  :                    */
841 /*-----------------------------------------------------------------*/
842 static void
843 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
844 {
845   asmop *aop;
846   symbol *sym;
847   int i;
848
849   if (!op)
850     return;
851
852   /* if this a literal */
853   if (IS_OP_LITERAL (op))
854     {
855       op->aop = aop = newAsmop (AOP_LIT);
856       aop->aopu.aop_lit = op->operand.valOperand;
857       aop->size = getSize (operandType (op));
858       return;
859     }
860
861   /* if already has a asmop then continue */
862   if (op->aop)
863     return;
864
865   /* if the underlying symbol has a aop */
866   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
867     {
868       op->aop = OP_SYMBOL (op)->aop;
869       return;
870     }
871
872   /* if this is a true symbol */
873   if (IS_TRUE_SYMOP (op))
874     {
875       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
876       return;
877     }
878
879   /* this is a temporary : this has
880      only four choices :
881      a) register
882      b) spillocation
883      c) rematerialize
884      d) conditional
885      e) can be a return use only */
886
887   sym = OP_SYMBOL (op);
888
889
890   /* if the type is a conditional */
891   if (sym->regType == REG_CND)
892     {
893       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
894       aop->size = 0;
895       return;
896     }
897
898   /* if it is spilt then two situations
899      a) is rematerialize
900      b) has a spill location */
901   if (sym->isspilt || sym->nRegs == 0)
902     {
903
904       /* rematerialize it NOW */
905       if (sym->remat)
906         {
907           sym->aop = op->aop = aop =
908             aopForRemat (sym);
909           aop->size = getSize (sym->type);
910           return;
911         }
912
913       if (sym->accuse)
914         {
915           int i;
916           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
917           aop->size = getSize (sym->type);
918           for (i = 0; i < 2; i++)
919             aop->aopu.aop_str[i] = accUse[i];
920           return;
921         }
922
923       if (sym->ruonly)
924         {
925           int i;
926
927           if (useDP2)
928             {
929               /* a AOP_STR uses DPTR, but DPTR is already in use;
930                * we're just hosed.
931                */
932                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
933             }
934
935           aop = op->aop = sym->aop = newAsmop (AOP_STR);
936           aop->size = getSize (sym->type);
937           for (i = 0; i < (int) fReturnSizeDS390; i++)
938             aop->aopu.aop_str[i] = fReturn[i];
939           return;
940         }
941       
942       if (sym->dptr) { /* has been allocated to a DPTRn */
943           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
944           aop->size = getSize (sym->type);
945           aop->aopu.dptr = sym->dptr;
946           return ;
947       }
948       /* else spill location  */
949       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
950           /* force a new aop if sizes differ */
951           sym->usl.spillLoc->aop = NULL;
952       }
953       sym->aop = op->aop = aop =
954         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
955       aop->size = getSize (sym->type);
956       return;
957     }
958
959   /* must be in a register */
960   sym->aop = op->aop = aop = newAsmop (AOP_REG);
961   aop->size = sym->nRegs;
962   for (i = 0; i < sym->nRegs; i++)
963     aop->aopu.aop_reg[i] = sym->regs[i];
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand               */
968 /*----------------------------------------------------------------*/
969 static void
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
971 {
972   asmop *aop;
973
974   if (!op)
975     aop = aaop;
976   else
977     aop = op->aop;
978
979   if (!aop)
980     return;
981
982   if (aop->freed)
983     goto dealloc;
984
985   aop->freed = 1;
986
987   /* depending on the asmop type only three cases need work AOP_RO
988      , AOP_R1 && AOP_STK */
989   switch (aop->type)
990     {
991     case AOP_R0:
992       if (_G.r0Pushed)
993         {
994           if (pop)
995             {
996               emitcode ("pop", "ar0");
997               _G.r0Pushed--;
998             }
999         }
1000       bitVectUnSetBit (ic->rUsed, R0_IDX);
1001       break;
1002
1003     case AOP_R1:
1004       if (_G.r1Pushed)
1005         {
1006           if (pop)
1007             {
1008               emitcode ("pop", "ar1");
1009               _G.r1Pushed--;
1010             }
1011         }
1012       bitVectUnSetBit (ic->rUsed, R1_IDX);
1013       break;
1014
1015     case AOP_STK:
1016       {
1017         int sz = aop->size;
1018         int stk = aop->aopu.aop_stk + aop->size;
1019         bitVectUnSetBit (ic->rUsed, R0_IDX);
1020         bitVectUnSetBit (ic->rUsed, R1_IDX);
1021
1022         getFreePtr (ic, &aop, FALSE);
1023
1024         if (options.stack10bit)
1025           {
1026             /* I'm not sure what to do here yet... */
1027             /* #STUB */
1028             fprintf (stderr,
1029                      "*** Warning: probably generating bad code for "
1030                      "10 bit stack mode.\n");
1031           }
1032
1033         if (stk)
1034           {
1035             emitcode ("mov", "a,_bp");
1036             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1037             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1038           }
1039         else
1040           {
1041             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1042           }
1043
1044         while (sz--)
1045           {
1046             emitcode ("pop", "acc");
1047             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1048             if (!sz)
1049               break;
1050             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1051           }
1052         op->aop = aop;
1053         freeAsmop (op, NULL, ic, TRUE);
1054         if (_G.r0Pushed)
1055           {
1056             emitcode ("pop", "ar0");
1057             _G.r0Pushed--;
1058           }
1059
1060         if (_G.r1Pushed)
1061           {
1062             emitcode ("pop", "ar1");
1063             _G.r1Pushed--;
1064           }
1065       }
1066     case AOP_DPTR2:
1067         if (_G.dptr1InUse) {
1068             emitcode ("pop","dpx1");
1069             emitcode ("pop","dph1");
1070             emitcode ("pop","dpl1");
1071         }
1072         break;
1073     case AOP_DPTR:
1074         if (_G.dptrInUse) {
1075             emitcode ("pop","dpx");
1076             emitcode ("pop","dph");
1077             emitcode ("pop","dpl");
1078         }
1079         break;
1080     }
1081 dealloc:
1082   /* all other cases just dealloc */
1083   if (op)
1084     {
1085       op->aop = NULL;
1086       if (IS_SYMOP (op))
1087         {
1088           OP_SYMBOL (op)->aop = NULL;
1089           /* if the symbol has a spill */
1090           if (SPIL_LOC (op))
1091             SPIL_LOC (op)->aop = NULL;
1092         }
1093     }
1094 }
1095
1096 #define DEFAULT_ACC_WARNING 0
1097 static int saveAccWarn = DEFAULT_ACC_WARNING;
1098
1099 /*-------------------------------------------------------------------*/
1100 /* aopGet - for fetching value of the aop                            */
1101 /*                                                                   */
1102 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1103 /* in the accumulator. Set it to the name of a free register         */
1104 /* if acc must be preserved; the register will be used to preserve   */
1105 /* acc temporarily and to return the result byte.                    */
1106 /*-------------------------------------------------------------------*/
1107
1108 static char *
1109 aopGet (asmop *aop,
1110         int   offset,
1111         bool  bit16,
1112         bool  dname,
1113         char  *saveAcc)
1114 {
1115   /* offset is greater than
1116      size then zero */
1117   if (offset > (aop->size - 1) &&
1118       aop->type != AOP_LIT)
1119     return zero;
1120
1121   /* depending on type */
1122   switch (aop->type)
1123     {
1124
1125     case AOP_R0:
1126     case AOP_R1:
1127       /* if we need to increment it */
1128       while (offset > aop->coff)
1129         {
1130           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1131           aop->coff++;
1132         }
1133
1134       while (offset < aop->coff)
1135         {
1136           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1137           aop->coff--;
1138         }
1139
1140       aop->coff = offset;
1141       if (aop->paged)
1142         {
1143           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1144           return (dname ? "acc" : "a");
1145         }
1146       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1147       return Safe_strdup(buffer);       
1148
1149     case AOP_DPTRn:
1150         assert(offset <= 3);
1151         return dptrn[aop->aopu.dptr][offset];
1152
1153     case AOP_DPTR:
1154     case AOP_DPTR2:
1155
1156       if (aop->type == AOP_DPTR2)
1157         {
1158           genSetDPTR (1);
1159         }
1160         
1161       if (saveAcc)
1162         {
1163             TR_AP("#1");
1164 //          if (aop->type != AOP_DPTR2)
1165 //          {
1166 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1167 //              emitcode(";", "spanky: saveAcc for DPTR");
1168 //          }
1169             
1170             emitcode ("xch", "a, %s", saveAcc);
1171         }
1172
1173       _flushLazyDPS ();
1174
1175       while (offset > aop->coff)
1176         {
1177           emitcode ("inc", "dptr");
1178           aop->coff++;
1179         }
1180
1181       while (offset < aop->coff)
1182         {
1183           emitcode ("lcall", "__decdptr");
1184           aop->coff--;
1185         }
1186
1187       aop->coff = offset;
1188       if (aop->code)
1189         {
1190           emitcode ("clr", "a");
1191           emitcode ("movc", "a,@a+dptr");
1192         }
1193       else
1194         {
1195           emitcode ("movx", "a,@dptr");
1196         }
1197
1198       if (aop->type == AOP_DPTR2)
1199         {
1200           genSetDPTR (0);
1201         }
1202         
1203         if (saveAcc)
1204         {
1205        TR_AP("#2");
1206               emitcode ("xch", "a, %s", saveAcc);
1207 //            if (strcmp(saveAcc, "_ap"))
1208 //            {
1209 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1210 //            }
1211                   
1212               return saveAcc;
1213         }
1214       return (dname ? "acc" : "a");
1215
1216     case AOP_IMMD:
1217       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1218       {
1219           SNPRINTF(buffer, sizeof(buffer), 
1220                    "%s",aop->aopu.aop_immd.aop_immd2);
1221       } 
1222       else if (bit16)
1223       {
1224          SNPRINTF(buffer, sizeof(buffer), 
1225                   "#%s", aop->aopu.aop_immd.aop_immd1);
1226       }
1227       else if (offset) 
1228       {
1229           switch (offset) {
1230           case 1:
1231               tsprintf(buffer, sizeof(buffer),
1232                        "#!his",aop->aopu.aop_immd.aop_immd1);
1233               break;
1234           case 2:
1235               tsprintf(buffer, sizeof(buffer), 
1236                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1237               break;
1238           case 3:
1239               tsprintf(buffer, sizeof(buffer),
1240                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1241               break;
1242           default: /* should not need this (just in case) */
1243               SNPRINTF (buffer, sizeof(buffer), 
1244                         "#(%s >> %d)",
1245                        aop->aopu.aop_immd.aop_immd1,
1246                        offset * 8);
1247           }
1248       }
1249       else
1250       {
1251         SNPRINTF (buffer, sizeof(buffer), 
1252                   "#%s", aop->aopu.aop_immd.aop_immd1);
1253       }
1254       return Safe_strdup(buffer);       
1255
1256     case AOP_DIR:
1257       if (offset)
1258       {
1259         SNPRINTF (buffer, sizeof(buffer),
1260                   "(%s + %d)",
1261                  aop->aopu.aop_dir,
1262                  offset);
1263       }
1264       else
1265       {
1266         SNPRINTF(buffer, sizeof(buffer), 
1267                  "%s", aop->aopu.aop_dir);
1268       }
1269
1270       return Safe_strdup(buffer);
1271
1272     case AOP_REG:
1273       if (dname)
1274         return aop->aopu.aop_reg[offset]->dname;
1275       else
1276         return aop->aopu.aop_reg[offset]->name;
1277
1278     case AOP_CRY:
1279       emitcode ("clr", "a");
1280       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1281       emitcode ("rlc", "a");
1282       return (dname ? "acc" : "a");
1283
1284     case AOP_ACC:
1285       if (!offset && dname)
1286         return "acc";
1287       return aop->aopu.aop_str[offset];
1288
1289     case AOP_LIT:
1290       return aopLiteral (aop->aopu.aop_lit, offset);
1291
1292     case AOP_STR:
1293       aop->coff = offset;
1294       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1295           dname)
1296         return "acc";
1297
1298       return aop->aopu.aop_str[offset];
1299
1300     }
1301
1302   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1303           "aopget got unsupported aop->type");
1304   exit (1);
1305     
1306   return NULL;  // not reached, but makes compiler happy.
1307 }
1308 /*-----------------------------------------------------------------*/
1309 /* aopPut - puts a string for a aop                                */
1310 /*-----------------------------------------------------------------*/
1311 static void
1312 aopPut (asmop * aop, char *s, int offset)
1313 {
1314   if (aop->size && offset > (aop->size - 1))
1315     {
1316       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1317               "aopPut got offset > aop->size");
1318       exit (1);
1319     }
1320
1321   /* will assign value to value */
1322   /* depending on where it is ofcourse */
1323   switch (aop->type)
1324     {
1325     case AOP_DIR:
1326         if (offset)
1327         {
1328             SNPRINTF (buffer, sizeof(buffer),
1329                       "(%s + %d)",
1330                       aop->aopu.aop_dir, offset);
1331         }
1332         else
1333         {
1334             SNPRINTF (buffer, sizeof(buffer), 
1335                      "%s", aop->aopu.aop_dir);
1336         }
1337         
1338
1339         if (strcmp (buffer, s))
1340         {
1341             emitcode ("mov", "%s,%s", buffer, s);
1342         }
1343       break;
1344
1345     case AOP_REG:
1346       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1347           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1348         {
1349           if (*s == '@' ||
1350               strcmp (s, "r0") == 0 ||
1351               strcmp (s, "r1") == 0 ||
1352               strcmp (s, "r2") == 0 ||
1353               strcmp (s, "r3") == 0 ||
1354               strcmp (s, "r4") == 0 ||
1355               strcmp (s, "r5") == 0 ||
1356               strcmp (s, "r6") == 0 ||
1357               strcmp (s, "r7") == 0)
1358             {
1359                 emitcode ("mov", "%s,%s",
1360                           aop->aopu.aop_reg[offset]->dname, s);
1361             }
1362             else
1363             {
1364                 emitcode ("mov", "%s,%s",
1365                           aop->aopu.aop_reg[offset]->name, s);
1366             }
1367         }
1368       break;
1369
1370     case AOP_DPTRn:
1371         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1372         break;
1373
1374     case AOP_DPTR:
1375     case AOP_DPTR2:
1376
1377       if (aop->type == AOP_DPTR2)
1378         {
1379           genSetDPTR (1);
1380         }
1381       _flushLazyDPS ();
1382
1383       if (aop->code)
1384         {
1385           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1386                   "aopPut writting to code space");
1387           exit (1);
1388         }
1389
1390       while (offset > aop->coff)
1391         {
1392           aop->coff++;
1393           emitcode ("inc", "dptr");
1394         }
1395
1396       while (offset < aop->coff)
1397         {
1398           aop->coff--;
1399           emitcode ("lcall", "__decdptr");
1400         }
1401
1402       aop->coff = offset;
1403
1404       /* if not in accumulater */
1405       MOVA (s);
1406
1407       emitcode ("movx", "@dptr,a");
1408
1409       if (aop->type == AOP_DPTR2)
1410         {
1411           genSetDPTR (0);
1412         }
1413       break;
1414
1415     case AOP_R0:
1416     case AOP_R1:
1417       while (offset > aop->coff)
1418         {
1419           aop->coff++;
1420           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1421         }
1422       while (offset < aop->coff)
1423         {
1424           aop->coff--;
1425           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1426         }
1427       aop->coff = offset;
1428
1429       if (aop->paged)
1430         {
1431           MOVA (s);
1432           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1433
1434         }
1435       else if (*s == '@')
1436         {
1437           MOVA (s);
1438           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1439         }
1440       else if (strcmp (s, "r0") == 0 ||
1441                strcmp (s, "r1") == 0 ||
1442                strcmp (s, "r2") == 0 ||
1443                strcmp (s, "r3") == 0 ||
1444                strcmp (s, "r4") == 0 ||
1445                strcmp (s, "r5") == 0 ||
1446                strcmp (s, "r6") == 0 ||
1447                strcmp (s, "r7") == 0)
1448         {
1449           char buff[10];
1450           SNPRINTF(buff, sizeof(buff), 
1451                    "a%s", s);
1452           emitcode ("mov", "@%s,%s",
1453                     aop->aopu.aop_ptr->name, buff);
1454         }
1455         else
1456         {
1457             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1458         }
1459       break;
1460
1461     case AOP_STK:
1462       if (strcmp (s, "a") == 0)
1463         emitcode ("push", "acc");
1464       else
1465         if (*s=='@') {
1466           MOVA(s);
1467           emitcode ("push", "acc");
1468         } else {
1469           emitcode ("push", s);
1470         }
1471
1472       break;
1473
1474     case AOP_CRY:
1475       /* if bit variable */
1476       if (!aop->aopu.aop_dir)
1477         {
1478           emitcode ("clr", "a");
1479           emitcode ("rlc", "a");
1480         }
1481       else
1482         {
1483           if (s == zero)
1484             emitcode ("clr", "%s", aop->aopu.aop_dir);
1485           else if (s == one)
1486             emitcode ("setb", "%s", aop->aopu.aop_dir);
1487           else if (!strcmp (s, "c"))
1488             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1489           else
1490             {
1491               if (strcmp (s, "a"))
1492                 {
1493                   MOVA (s);
1494                 }
1495               {
1496                 /* set C, if a >= 1 */
1497                 emitcode ("add", "a,#!constbyte",0xff);
1498                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1499               }
1500             }
1501         }
1502       break;
1503
1504     case AOP_STR:
1505       aop->coff = offset;
1506       if (strcmp (aop->aopu.aop_str[offset], s))
1507         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1508       break;
1509
1510     case AOP_ACC:
1511       aop->coff = offset;
1512       if (!offset && (strcmp (s, "acc") == 0))
1513         break;
1514
1515       if (strcmp (aop->aopu.aop_str[offset], s))
1516         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1517       break;
1518
1519     default:
1520       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1521               "aopPut got unsupported aop->type");
1522       exit (1);
1523     }
1524
1525 }
1526
1527
1528 /*--------------------------------------------------------------------*/
1529 /* reAdjustPreg - points a register back to where it should (coff==0) */
1530 /*--------------------------------------------------------------------*/
1531 static void
1532 reAdjustPreg (asmop * aop)
1533 {
1534   if ((aop->coff==0) || (aop->size <= 1)) {
1535     return;
1536   }
1537
1538   switch (aop->type)
1539     {
1540     case AOP_R0:
1541     case AOP_R1:
1542       while (aop->coff--)
1543         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1544       break;
1545     case AOP_DPTR:
1546     case AOP_DPTR2:
1547       if (aop->type == AOP_DPTR2)
1548         {
1549           genSetDPTR (1);
1550           _flushLazyDPS ();
1551         }
1552       while (aop->coff--)
1553         {
1554           emitcode ("lcall", "__decdptr");
1555         }
1556
1557       if (aop->type == AOP_DPTR2)
1558         {
1559           genSetDPTR (0);
1560         }
1561       break;
1562
1563     }
1564   aop->coff=0;
1565 }
1566
1567 #define AOP(op) op->aop
1568 #define AOP_TYPE(op) AOP(op)->type
1569 #define AOP_SIZE(op) AOP(op)->size
1570 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1571                        AOP_TYPE(x) == AOP_R0))
1572
1573 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1574                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1575                          AOP(x)->paged))
1576
1577 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1578                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1579                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1580 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1581 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1582 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1583
1584 // The following two macros can be used even if the aop has not yet been aopOp'd.
1585 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1586 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1587
1588 /* Workaround for DS80C390 bug: div ab may return bogus results
1589  * if A is accessed in instruction immediately before the div.
1590  *
1591  * Will be fixed in B4 rev of processor, Dallas claims.
1592  */
1593
1594 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1595     if (!AOP_NEEDSACC(RIGHT))         \
1596     {               \
1597       /* We can load A first, then B, since     \
1598        * B (the RIGHT operand) won't clobber A,   \
1599        * thus avoiding touching A right before the div. \
1600        */             \
1601       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1602       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1603       MOVA(L);            \
1604       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1605       MOVB(L); \
1606     }               \
1607     else              \
1608     {               \
1609       /* Just stuff in a nop after loading A. */    \
1610       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1611       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1612       MOVA(L);            \
1613       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1614     }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* genNotFloat - generates not for float operations              */
1618 /*-----------------------------------------------------------------*/
1619 static void
1620 genNotFloat (operand * op, operand * res)
1621 {
1622   int size, offset;
1623   symbol *tlbl;
1624
1625   D (emitcode (";", "genNotFloat "););
1626
1627   /* we will put 127 in the first byte of
1628      the result */
1629   aopPut (AOP (res), "#127", 0);
1630   size = AOP_SIZE (op) - 1;
1631   offset = 1;
1632
1633   _startLazyDPSEvaluation ();
1634   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1635
1636   while (size--)
1637     {
1638       emitcode ("orl", "a,%s",
1639                 aopGet (op->aop,
1640                         offset++, FALSE, FALSE,
1641                         DP2_RESULT_REG));
1642     }
1643   _endLazyDPSEvaluation ();
1644
1645   tlbl = newiTempLabel (NULL);
1646   aopPut (res->aop, one, 1);
1647   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1648   aopPut (res->aop, zero, 1);
1649   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1650
1651   size = res->aop->size - 2;
1652   offset = 2;
1653   /* put zeros in the rest */
1654   while (size--)
1655     aopPut (res->aop, zero, offset++);
1656 }
1657
1658 /*-----------------------------------------------------------------*/
1659 /* opIsGptr: returns non-zero if the passed operand is       */
1660 /* a generic pointer type.             */
1661 /*-----------------------------------------------------------------*/
1662 static int
1663 opIsGptr (operand * op)
1664 {
1665   sym_link *type = operandType (op);
1666
1667   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1668     {
1669       return 1;
1670     }
1671   return 0;
1672 }
1673
1674 /*-----------------------------------------------------------------*/
1675 /* getDataSize - get the operand data size                         */
1676 /*-----------------------------------------------------------------*/
1677 static int
1678 getDataSize (operand * op)
1679 {
1680   int size;
1681   size = AOP_SIZE (op);
1682   if (size == GPTRSIZE)
1683     {
1684       sym_link *type = operandType (op);
1685       if (IS_GENPTR (type))
1686         {
1687           /* generic pointer; arithmetic operations
1688            * should ignore the high byte (pointer type).
1689            */
1690           size--;
1691         }
1692     }
1693   return size;
1694 }
1695
1696 /*-----------------------------------------------------------------*/
1697 /* outAcc - output Acc                                             */
1698 /*-----------------------------------------------------------------*/
1699 static void
1700 outAcc (operand * result)
1701 {
1702   int size, offset;
1703   size = getDataSize (result);
1704   if (size)
1705     {
1706       aopPut (AOP (result), "a", 0);
1707       size--;
1708       offset = 1;
1709       /* unsigned or positive */
1710       while (size--)
1711         {
1712           aopPut (AOP (result), zero, offset++);
1713         }
1714     }
1715 }
1716
1717 /*-----------------------------------------------------------------*/
1718 /* outBitC - output a bit C                                        */
1719 /*-----------------------------------------------------------------*/
1720 static void
1721 outBitC (operand * result)
1722 {
1723   /* if the result is bit */
1724   if (AOP_TYPE (result) == AOP_CRY)
1725     {
1726       aopPut (AOP (result), "c", 0);
1727     }
1728   else
1729     {
1730       emitcode ("clr", "a");
1731       emitcode ("rlc", "a");
1732       outAcc (result);
1733     }
1734 }
1735
1736 /*-----------------------------------------------------------------*/
1737 /* toBoolean - emit code for orl a,operator(sizeop)                */
1738 /*-----------------------------------------------------------------*/
1739 static void
1740 toBoolean (operand * oper)
1741 {
1742   int   size = AOP_SIZE (oper) - 1;
1743   int   offset = 1;
1744   bool usedB = FALSE;
1745
1746   /* The generic part of a generic pointer should
1747    * not participate in it's truth value.
1748    *
1749    * i.e. 0x10000000 is zero.
1750    */
1751   if (opIsGptr (oper))
1752     {
1753       D (emitcode (";", "toBoolean: generic ptr special case."););
1754       size--;
1755     }
1756
1757   _startLazyDPSEvaluation ();
1758   if (AOP_NEEDSACC (oper) && size)
1759     {
1760       usedB = TRUE;
1761       if (_G.bInUse)
1762       {
1763           emitcode ("push", "b");
1764       }
1765       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1766     }
1767   else
1768     {
1769       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1770     }
1771     
1772   while (size--)
1773     {
1774       if (usedB)
1775         {
1776           emitcode ("orl", "b,%s",
1777                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1778         }
1779       else
1780         {
1781           emitcode ("orl", "a,%s",
1782                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1783         }
1784     }
1785   _endLazyDPSEvaluation ();
1786
1787   if (usedB)
1788     {
1789       emitcode ("mov", "a,b");
1790       if (_G.bInUse)
1791       {
1792           emitcode ("pop", "b");
1793       }
1794         
1795     }
1796 }
1797
1798
1799 /*-----------------------------------------------------------------*/
1800 /* genNot - generate code for ! operation                          */
1801 /*-----------------------------------------------------------------*/
1802 static void
1803 genNot (iCode * ic)
1804 {
1805   symbol *tlbl;
1806   sym_link *optype = operandType (IC_LEFT (ic));
1807
1808   D (emitcode (";", "genNot "););
1809
1810   /* assign asmOps to operand & result */
1811   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1812   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1813
1814   /* if in bit space then a special case */
1815   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1816     {
1817       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1818       emitcode ("cpl", "c");
1819       outBitC (IC_RESULT (ic));
1820       goto release;
1821     }
1822
1823   /* if type float then do float */
1824   if (IS_FLOAT (optype))
1825     {
1826       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1827       goto release;
1828     }
1829
1830   toBoolean (IC_LEFT (ic));
1831
1832   tlbl = newiTempLabel (NULL);
1833   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1834   emitcode ("", "!tlabeldef", tlbl->key + 100);
1835   outBitC (IC_RESULT (ic));
1836
1837 release:
1838   /* release the aops */
1839   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1840   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1841 }
1842
1843
1844 /*-----------------------------------------------------------------*/
1845 /* genCpl - generate code for complement                           */
1846 /*-----------------------------------------------------------------*/
1847 static void
1848 genCpl (iCode * ic)
1849 {
1850   int offset = 0;
1851   int size;
1852   symbol *tlbl;
1853
1854   D (emitcode (";", "genCpl "););
1855
1856
1857   /* assign asmOps to operand & result */
1858   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1859   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1860
1861   /* special case if in bit space */
1862   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1863     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1864       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1865       emitcode ("cpl", "c");
1866       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1867       goto release;
1868     }
1869     tlbl=newiTempLabel(NULL);
1870     emitcode ("cjne", "%s,#0x01,%05d$", 
1871               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1872     emitcode ("", "%05d$:", tlbl->key+100);
1873     outBitC (IC_RESULT(ic));
1874     goto release;
1875   }
1876
1877   size = AOP_SIZE (IC_RESULT (ic));
1878   _startLazyDPSEvaluation ();
1879   while (size--)
1880     {
1881       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1882       emitcode ("cpl", "a");
1883       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1884     }
1885   _endLazyDPSEvaluation ();
1886
1887
1888 release:
1889   /* release the aops */
1890   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1891   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* genUminusFloat - unary minus for floating points                */
1896 /*-----------------------------------------------------------------*/
1897 static void
1898 genUminusFloat (operand * op, operand * result)
1899 {
1900   int size, offset = 0;
1901     
1902   D(emitcode (";", "genUminusFloat"););
1903   
1904   /* for this we just copy and then flip the bit */
1905     
1906   _startLazyDPSEvaluation ();
1907   size = AOP_SIZE (op) - 1;
1908
1909   while (size--)
1910   {
1911       aopPut (AOP (result),
1912               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1913               offset);
1914       offset++;
1915     }
1916   
1917   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1918
1919   emitcode ("cpl", "acc.7");
1920   aopPut (AOP (result), "a", offset);    
1921   _endLazyDPSEvaluation ();
1922 }
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genUminus - unary minus code generation                         */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genUminus (iCode * ic)
1929 {
1930   int offset, size;
1931   sym_link *optype;
1932
1933   D (emitcode (";", "genUminus "););
1934
1935   /* assign asmops */
1936   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1937   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1938
1939   /* if both in bit space then special
1940      case */
1941   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1942       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1943     {
1944
1945       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1946       emitcode ("cpl", "c");
1947       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1948       goto release;
1949     }
1950
1951   optype = operandType (IC_LEFT (ic));
1952
1953   /* if float then do float stuff */
1954   if (IS_FLOAT (optype))
1955     {
1956       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1957       goto release;
1958     }
1959
1960   /* otherwise subtract from zero */
1961   size = AOP_SIZE (IC_LEFT (ic));
1962   offset = 0;
1963   _startLazyDPSEvaluation ();
1964   while (size--)
1965     {
1966       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1967       if (!strcmp (l, "a"))
1968         {
1969           if (offset == 0)
1970             SETC;
1971           emitcode ("cpl", "a");
1972           emitcode ("addc", "a,#0");
1973         }
1974       else
1975         {
1976           if (offset == 0)
1977             CLRC;
1978           emitcode ("clr", "a");
1979           emitcode ("subb", "a,%s", l);
1980         }
1981       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1982     }
1983   _endLazyDPSEvaluation ();
1984
1985   /* if any remaining bytes in the result */
1986   /* we just need to propagate the sign   */
1987   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1988     {
1989       emitcode ("rlc", "a");
1990       emitcode ("subb", "a,acc");
1991       while (size--)
1992         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1993     }
1994
1995 release:
1996   /* release the aops */
1997   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1998   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1999 }
2000
2001 /*-----------------------------------------------------------------*/
2002 /* savermask - saves registers in the mask                         */
2003 /*-----------------------------------------------------------------*/
2004 static void savermask(bitVect *rs_mask)
2005 {
2006     int i;
2007     if (options.useXstack) {
2008         if (bitVectBitValue (rs_mask, R0_IDX))
2009             emitcode ("mov", "b,r0");
2010         emitcode ("mov", "r0,%s", spname);
2011         for (i = 0; i < ds390_nRegs; i++) {
2012             if (bitVectBitValue (rs_mask, i)) {
2013                 if (i == R0_IDX)
2014                     emitcode ("mov", "a,b");
2015                 else
2016                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2017                 emitcode ("movx", "@r0,a");
2018                 emitcode ("inc", "r0");
2019             }
2020         }
2021         emitcode ("mov", "%s,r0", spname);
2022         if (bitVectBitValue (rs_mask, R0_IDX))
2023             emitcode ("mov", "r0,b");
2024     } else {
2025         for (i = 0; i < ds390_nRegs; i++) {
2026             if (bitVectBitValue (rs_mask, i))
2027                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2028         }
2029     }
2030 }
2031
2032 /*-----------------------------------------------------------------*/
2033 /* saveRegisters - will look for a call and save the registers     */
2034 /*-----------------------------------------------------------------*/
2035 static void
2036 saveRegisters (iCode * lic)
2037 {
2038   iCode *ic;
2039   bitVect *rsave;
2040
2041   /* look for call */
2042   for (ic = lic; ic; ic = ic->next)
2043     if (ic->op == CALL || ic->op == PCALL)
2044       break;
2045
2046   if (!ic)
2047     {
2048       fprintf (stderr, "found parameter push with no function call\n");
2049       return;
2050     }
2051
2052   /* if the registers have been saved already then
2053      do nothing */
2054   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2055
2056   /* special case if DPTR alive across a function call then must save it 
2057      even though callee saves */
2058   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2059       int i;
2060       rsave = newBitVect(ic->rMask->size);
2061       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2062           if (bitVectBitValue(ic->rMask,i))
2063               rsave = bitVectSetBit(rsave,i);
2064       }
2065       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2066   } else {
2067     /* safe the registers in use at this time but skip the
2068        ones for the result */
2069     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2070                            ds390_rUmaskForOp (IC_RESULT(ic)));
2071   }
2072   ic->regsSaved = 1;
2073   savermask(rsave);
2074 }
2075
2076 /*-----------------------------------------------------------------*/
2077 /* usavermask - restore registers with mask                        */
2078 /*-----------------------------------------------------------------*/
2079 static void unsavermask(bitVect *rs_mask)
2080 {
2081     int i;
2082     if (options.useXstack) {
2083         emitcode ("mov", "r0,%s", spname);
2084         for (i = ds390_nRegs; i >= 0; i--) {
2085             if (bitVectBitValue (rs_mask, i)) {
2086                 emitcode ("dec", "r0");
2087                 emitcode ("movx", "a,@r0");
2088                 if (i == R0_IDX)
2089                     emitcode ("mov", "b,a");
2090                 else
2091                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2092             }       
2093         }
2094         emitcode ("mov", "%s,r0", spname);
2095         if (bitVectBitValue (rs_mask, R0_IDX))
2096             emitcode ("mov", "r0,b");
2097     } else {
2098         for (i = ds390_nRegs; i >= 0; i--) {
2099             if (bitVectBitValue (rs_mask, i))
2100                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2101         }
2102     }
2103 }
2104
2105 /*-----------------------------------------------------------------*/
2106 /* unsaveRegisters - pop the pushed registers                      */
2107 /*-----------------------------------------------------------------*/
2108 static void
2109 unsaveRegisters (iCode * ic)
2110 {
2111   bitVect *rsave;
2112
2113   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2114       int i;
2115       rsave = newBitVect(ic->rMask->size);
2116       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2117           if (bitVectBitValue(ic->rMask,i))
2118               rsave = bitVectSetBit(rsave,i);
2119       }
2120       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2121   } else {
2122     /* restore the registers in use at this time but skip the
2123        ones for the result */
2124     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2125                            ds390_rUmaskForOp (IC_RESULT(ic)));
2126   }
2127   unsavermask(rsave);
2128 }
2129
2130
2131 /*-----------------------------------------------------------------*/
2132 /* pushSide -                */
2133 /*-----------------------------------------------------------------*/
2134 static void
2135 pushSide (operand * oper, int size)
2136 {
2137   int offset = 0;
2138   _startLazyDPSEvaluation ();
2139   while (size--)
2140     {
2141       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2142       if (AOP_TYPE (oper) != AOP_REG &&
2143           AOP_TYPE (oper) != AOP_DIR &&
2144           strcmp (l, "a"))
2145         {
2146           emitcode ("mov", "a,%s", l);
2147           emitcode ("push", "acc");
2148         }
2149       else
2150         emitcode ("push", "%s", l);
2151     }
2152   _endLazyDPSEvaluation ();
2153 }
2154
2155 /*-----------------------------------------------------------------*/
2156 /* assignResultValue -               */
2157 /*-----------------------------------------------------------------*/
2158 static void
2159 assignResultValue (operand * oper)
2160 {
2161   int offset = 0;
2162   int size = AOP_SIZE (oper);
2163   bool pushedAcc = FALSE;
2164
2165   if (size == fReturnSizeDS390)
2166   {
2167       /* I don't think this case can ever happen... */
2168       /* ACC is the last part of this. If writing the result
2169        * uses AC, we must preserve it.
2170        */
2171       if (AOP_NEEDSACC(oper))
2172       {
2173           emitcode(";", "assignResultValue special case for ACC.");
2174           emitcode("push", "acc");
2175           pushedAcc = TRUE;
2176           size--;
2177       }
2178   }
2179     
2180     
2181   _startLazyDPSEvaluation ();
2182   while (size--)
2183     {
2184       aopPut (AOP (oper), fReturn[offset], offset);
2185       offset++;
2186     }
2187   _endLazyDPSEvaluation ();
2188     
2189   if (pushedAcc)
2190     {
2191         emitcode("pop", "acc");
2192         aopPut(AOP(oper), "a", offset);
2193     }
2194 }
2195
2196
2197 /*-----------------------------------------------------------------*/
2198 /* genXpush - pushes onto the external stack                       */
2199 /*-----------------------------------------------------------------*/
2200 static void
2201 genXpush (iCode * ic)
2202 {
2203   asmop *aop = newAsmop (0);
2204   regs *r;
2205   int size, offset = 0;
2206
2207   D (emitcode (";", "genXpush ");
2208     );
2209
2210   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2211   r = getFreePtr (ic, &aop, FALSE);
2212
2213
2214   emitcode ("mov", "%s,_spx", r->name);
2215
2216   size = AOP_SIZE (IC_LEFT (ic));
2217   _startLazyDPSEvaluation ();
2218   while (size--)
2219     {
2220
2221       MOVA (aopGet (AOP (IC_LEFT (ic)),
2222                         offset++, FALSE, FALSE, NULL));
2223       emitcode ("movx", "@%s,a", r->name);
2224       emitcode ("inc", "%s", r->name);
2225
2226     }
2227   _endLazyDPSEvaluation ();
2228
2229
2230   emitcode ("mov", "_spx,%s", r->name);
2231
2232   freeAsmop (NULL, aop, ic, TRUE);
2233   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2234 }
2235
2236 /*-----------------------------------------------------------------*/
2237 /* genIpush - generate code for pushing this gets a little complex  */
2238 /*-----------------------------------------------------------------*/
2239 static void
2240 genIpush (iCode * ic)
2241 {
2242   int size, offset = 0;
2243   char *l;
2244
2245   D (emitcode (";", "genIpush ");
2246     );
2247
2248   /* if this is not a parm push : ie. it is spill push
2249      and spill push is always done on the local stack */
2250   if (!ic->parmPush)
2251     {
2252
2253       /* and the item is spilt then do nothing */
2254       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2255         return;
2256
2257       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2258       size = AOP_SIZE (IC_LEFT (ic));
2259       /* push it on the stack */
2260       _startLazyDPSEvaluation ();
2261       while (size--)
2262         {
2263           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2264           if (*l == '#')
2265             {
2266               MOVA (l);
2267               l = "acc";
2268             }
2269           emitcode ("push", "%s", l);
2270         }
2271       _endLazyDPSEvaluation ();
2272       return;
2273     }
2274
2275   /* this is a paramter push: in this case we call
2276      the routine to find the call and save those
2277      registers that need to be saved */
2278   saveRegisters (ic);
2279
2280   /* if use external stack then call the external
2281      stack pushing routine */
2282   if (options.useXstack)
2283     {
2284       genXpush (ic);
2285       return;
2286     }
2287
2288   /* then do the push */
2289   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2290
2291   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2292   size = AOP_SIZE (IC_LEFT (ic));
2293
2294   _startLazyDPSEvaluation ();
2295   while (size--)
2296     {
2297       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2298       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2299           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2300           strcmp (l, "acc"))
2301         {
2302           emitcode ("mov", "a,%s", l);
2303           emitcode ("push", "acc");
2304         }
2305       else
2306         {
2307             emitcode ("push", "%s", l);
2308         }
2309     }
2310   _endLazyDPSEvaluation ();
2311
2312   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2313 }
2314
2315 /*-----------------------------------------------------------------*/
2316 /* genIpop - recover the registers: can happen only for spilling   */
2317 /*-----------------------------------------------------------------*/
2318 static void
2319 genIpop (iCode * ic)
2320 {
2321   int size, offset;
2322
2323   D (emitcode (";", "genIpop ");
2324     );
2325
2326
2327   /* if the temp was not pushed then */
2328   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2329     return;
2330
2331   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2332   size = AOP_SIZE (IC_LEFT (ic));
2333   offset = (size - 1);
2334   _startLazyDPSEvaluation ();
2335   while (size--)
2336     {
2337       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2338                                      FALSE, TRUE, NULL));
2339     }
2340   _endLazyDPSEvaluation ();
2341
2342   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /* unsaveRBank - restores the resgister bank from stack            */
2347 /*-----------------------------------------------------------------*/
2348 static void
2349 unsaveRBank (int bank, iCode * ic, bool popPsw)
2350 {
2351   int i;
2352   asmop *aop = NULL;
2353   regs *r = NULL;
2354
2355   if (options.useXstack)
2356   {
2357       if (!ic)
2358       {
2359           /* Assume r0 is available for use. */
2360           r = ds390_regWithIdx (R0_IDX);;          
2361       } 
2362       else
2363       {
2364           aop = newAsmop (0);
2365           r = getFreePtr (ic, &aop, FALSE);
2366       }
2367       emitcode ("mov", "%s,_spx", r->name);      
2368   }
2369   
2370   if (popPsw)
2371     {
2372       if (options.useXstack)
2373       {
2374           emitcode ("movx", "a,@%s", r->name);
2375           emitcode ("mov", "psw,a");
2376           emitcode ("dec", "%s", r->name);
2377         }
2378       else
2379       {
2380         emitcode ("pop", "psw");
2381       }
2382     }
2383
2384   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2385     {
2386       if (options.useXstack)
2387         {
2388           emitcode ("movx", "a,@%s", r->name);
2389           emitcode ("mov", "(%s+%d),a",
2390                     regs390[i].base, 8 * bank + regs390[i].offset);
2391           emitcode ("dec", "%s", r->name);
2392
2393         }
2394       else
2395         emitcode ("pop", "(%s+%d)",
2396                   regs390[i].base, 8 * bank + regs390[i].offset);
2397     }
2398
2399   if (options.useXstack)
2400     {
2401       emitcode ("mov", "_spx,%s", r->name);
2402     }
2403     
2404   if (aop)
2405   {
2406       freeAsmop (NULL, aop, ic, TRUE);  
2407   }    
2408 }
2409
2410 /*-----------------------------------------------------------------*/
2411 /* saveRBank - saves an entire register bank on the stack          */
2412 /*-----------------------------------------------------------------*/
2413 static void
2414 saveRBank (int bank, iCode * ic, bool pushPsw)
2415 {
2416   int i;
2417   asmop *aop = NULL;
2418   regs *r = NULL;
2419
2420   if (options.useXstack)
2421     {
2422         if (!ic)
2423         {
2424           /* Assume r0 is available for use. */
2425                   r = ds390_regWithIdx (R0_IDX);;
2426         }
2427         else
2428         {
2429           aop = newAsmop (0);
2430           r = getFreePtr (ic, &aop, FALSE);
2431         }
2432         emitcode ("mov", "%s,_spx", r->name);    
2433     }
2434
2435   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2436     {
2437       if (options.useXstack)
2438         {
2439           emitcode ("inc", "%s", r->name);
2440           emitcode ("mov", "a,(%s+%d)",
2441                     regs390[i].base, 8 * bank + regs390[i].offset);
2442           emitcode ("movx", "@%s,a", r->name);
2443         }
2444       else
2445         emitcode ("push", "(%s+%d)",
2446                   regs390[i].base, 8 * bank + regs390[i].offset);
2447     }
2448
2449   if (pushPsw)
2450     {
2451       if (options.useXstack)
2452         {
2453           emitcode ("mov", "a,psw");
2454           emitcode ("movx", "@%s,a", r->name);
2455           emitcode ("inc", "%s", r->name);
2456           emitcode ("mov", "_spx,%s", r->name);
2457         }
2458       else
2459       {
2460         emitcode ("push", "psw");
2461       }
2462
2463       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2464     }
2465   
2466   if (aop)
2467   {
2468        freeAsmop (NULL, aop, ic, TRUE);
2469   }    
2470     
2471   if (ic)
2472   {  
2473       ic->bankSaved = 1;
2474   }
2475 }
2476
2477 /*-----------------------------------------------------------------*/
2478 /* genSend - gen code for SEND                                     */
2479 /*-----------------------------------------------------------------*/
2480 static void genSend(set *sendSet)
2481 {
2482     iCode *sic;
2483     int sendCount = 0 ;
2484     static int rb1_count = 0;
2485
2486     for (sic = setFirstItem (sendSet); sic;
2487          sic = setNextItem (sendSet)) {     
2488         int size, offset = 0;
2489         
2490         size=getSize(operandType(IC_LEFT(sic)));
2491         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2492         if (sendCount == 0) { /* first parameter */
2493             // we know that dpl(hxb) is the result, so
2494             rb1_count = 0 ;
2495             _startLazyDPSEvaluation ();
2496             if (size>1) {
2497                 aopOp (IC_LEFT (sic), sic, FALSE, 
2498                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2499             } else {
2500                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2501             }
2502             while (size--) {
2503                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2504                                   FALSE, FALSE, NULL);
2505                 if (strcmp (l, fReturn[offset])) {
2506                     emitcode ("mov", "%s,%s",
2507                               fReturn[offset],
2508                               l);
2509                 }
2510                 offset++;
2511             }
2512             _endLazyDPSEvaluation ();
2513             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2514             rb1_count =0;
2515         } else { /* if more parameter in registers */
2516             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2517             while (size--) {
2518                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2519                                                                 FALSE, FALSE, NULL));
2520             }
2521             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2522         }
2523         sendCount++;
2524     }
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* genCall - generates a call statement                            */
2529 /*-----------------------------------------------------------------*/
2530 static void
2531 genCall (iCode * ic)
2532 {
2533   sym_link *dtype;
2534   bool restoreBank = FALSE;
2535   bool swapBanks = FALSE;
2536
2537   D (emitcode (";", "genCall "););
2538
2539   /* if we are calling a not _naked function that is not using
2540      the same register bank then we need to save the
2541      destination registers on the stack */
2542   dtype = operandType (IC_LEFT (ic));
2543   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2544       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2545       IFFUNC_ISISR (currFunc->type))
2546   {
2547       if (!ic->bankSaved) 
2548       {
2549            /* This is unexpected; the bank should have been saved in
2550             * genFunction.
2551             */
2552            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2553            restoreBank = TRUE;
2554       }
2555       swapBanks = TRUE;
2556   }
2557   
2558     /* if caller saves & we have not saved then */
2559     if (!ic->regsSaved)
2560       saveRegisters (ic);
2561   
2562   /* if send set is not empty the assign */
2563   /* We've saved all the registers we care about;
2564   * therefore, we may clobber any register not used
2565   * in the calling convention (i.e. anything not in
2566   * fReturn.
2567   */
2568   if (_G.sendSet)
2569     {
2570         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2571             genSend(reverseSet(_G.sendSet));
2572         } else {
2573             genSend(_G.sendSet);
2574         }
2575       _G.sendSet = NULL;
2576     }  
2577     
2578   if (swapBanks)
2579   {
2580         emitcode ("mov", "psw,#!constbyte", 
2581            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2582   }
2583
2584   /* make the call */
2585   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2586                             OP_SYMBOL (IC_LEFT (ic))->rname :
2587                             OP_SYMBOL (IC_LEFT (ic))->name));
2588
2589   if (swapBanks)
2590   {
2591        emitcode ("mov", "psw,#!constbyte", 
2592           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2593   }
2594
2595   /* if we need assign a result value */
2596   if ((IS_ITEMP (IC_RESULT (ic)) &&
2597        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2598         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2599         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2600       IS_TRUE_SYMOP (IC_RESULT (ic)))
2601     {
2602       if (isOperandInFarSpace (IC_RESULT (ic))
2603           && getSize (operandType (IC_RESULT (ic))) <= 2)
2604         {
2605           int size = getSize (operandType (IC_RESULT (ic)));
2606
2607           /* Special case for 1 or 2 byte return in far space. */
2608           MOVA (fReturn[0]);
2609           if (size > 1)
2610             {
2611               emitcode ("mov", "b,%s", fReturn[1]);
2612             }
2613
2614           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2615           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2616
2617           if (size > 1)
2618             {
2619               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2620             }
2621           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2622         }
2623       else
2624         {
2625           _G.accInUse++;
2626           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2627           _G.accInUse--;
2628
2629           assignResultValue (IC_RESULT (ic));
2630
2631           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2632         }
2633     }
2634
2635   /* adjust the stack for parameters if
2636      required */
2637   if (ic->parmBytes) {
2638       int i;
2639       if (options.stack10bit) {
2640           if (ic->parmBytes <= 10) {
2641               emitcode(";","stack adjustment for parms");
2642               for (i=0; i < ic->parmBytes ; i++) {
2643                   emitcode("pop","acc");
2644               }
2645           } else {            
2646               PROTECT_SP;
2647               emitcode ("clr","c");
2648               emitcode ("mov","a,sp");
2649               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2650               emitcode ("mov","sp,a");
2651               emitcode ("mov","a,esp");
2652               emitcode ("anl","a,#3");
2653               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2654               emitcode ("mov","esp,a");   
2655               UNPROTECT_SP;
2656           }
2657       } else {
2658           if (ic->parmBytes > 3) {
2659               emitcode ("mov", "a,%s", spname);
2660               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2661               emitcode ("mov", "%s,a", spname);
2662           } else
2663               for (i = 0; i < ic->parmBytes; i++)
2664                   emitcode ("dec", "%s", spname);
2665       }
2666   }
2667
2668   /* if we hade saved some registers then unsave them */
2669   if (ic->regsSaved)
2670     unsaveRegisters (ic);
2671
2672   /* if register bank was saved then pop them */
2673   if (restoreBank)
2674     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2675 }
2676
2677 /*-----------------------------------------------------------------*/
2678 /* genPcall - generates a call by pointer statement                */
2679 /*-----------------------------------------------------------------*/
2680 static void
2681 genPcall (iCode * ic)
2682 {
2683   sym_link *dtype;
2684   symbol *rlbl = newiTempLabel (NULL);
2685   bool restoreBank=FALSE;
2686
2687   D (emitcode (";", "genPcall ");
2688     );
2689
2690
2691   /* if caller saves & we have not saved then */
2692   if (!ic->regsSaved)
2693     saveRegisters (ic);
2694
2695   /* if we are calling a function that is not using
2696      the same register bank then we need to save the
2697      destination registers on the stack */
2698   dtype = operandType (IC_LEFT (ic));
2699   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2700       IFFUNC_ISISR (currFunc->type) &&
2701       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2702     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2703     restoreBank=TRUE;
2704   }
2705
2706   /* push the return address on to the stack */
2707   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2708   emitcode ("push", "acc");
2709   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2710   emitcode ("push", "acc");
2711
2712   if (options.model == MODEL_FLAT24)
2713     {
2714       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2715       emitcode ("push", "acc");
2716     }
2717
2718   /* now push the calling address */
2719   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2720
2721   pushSide (IC_LEFT (ic), FPTRSIZE);
2722
2723   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2724
2725   /* if send set is not empty the assign */
2726   if (_G.sendSet)
2727     {
2728         genSend(reverseSet(_G.sendSet));
2729         _G.sendSet = NULL;
2730     }
2731
2732   emitcode ("ret", "");
2733   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2734
2735
2736   /* if we need assign a result value */
2737   if ((IS_ITEMP (IC_RESULT (ic)) &&
2738        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2739         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2740       IS_TRUE_SYMOP (IC_RESULT (ic)))
2741     {
2742
2743       _G.accInUse++;
2744       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2745       _G.accInUse--;
2746
2747       assignResultValue (IC_RESULT (ic));
2748
2749       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2750     }
2751
2752   /* adjust the stack for parameters if
2753      required */
2754   if (ic->parmBytes)
2755     {
2756       int i;
2757       if (options.stack10bit) {
2758           if (ic->parmBytes <= 10) {
2759               emitcode(";","stack adjustment for parms");
2760               for (i=0; i < ic->parmBytes ; i++) {
2761                   emitcode("pop","acc");
2762               }
2763           } else {            
2764               PROTECT_SP;
2765               emitcode ("clr","c");
2766               emitcode ("mov","a,sp");
2767               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2768               emitcode ("mov","sp,a");
2769               emitcode ("mov","a,esp");
2770               emitcode ("anl","a,#3");
2771               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2772               emitcode ("mov","esp,a");   
2773               UNPROTECT_SP;
2774           }
2775       } else {
2776           if (ic->parmBytes > 3) {
2777               emitcode ("mov", "a,%s", spname);
2778               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2779               emitcode ("mov", "%s,a", spname);
2780           }
2781           else
2782               for (i = 0; i < ic->parmBytes; i++)
2783                   emitcode ("dec", "%s", spname);
2784           
2785       }
2786     }
2787   /* if register bank was saved then unsave them */
2788   if (restoreBank)
2789     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2790   
2791   /* if we hade saved some registers then
2792      unsave them */
2793   if (ic->regsSaved)
2794     unsaveRegisters (ic);
2795
2796 }
2797
2798 /*-----------------------------------------------------------------*/
2799 /* resultRemat - result  is rematerializable                       */
2800 /*-----------------------------------------------------------------*/
2801 static int
2802 resultRemat (iCode * ic)
2803 {
2804   if (SKIP_IC (ic) || ic->op == IFX)
2805     return 0;
2806
2807   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2808     {
2809       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2810       if (sym->remat && !POINTER_SET (ic))
2811         return 1;
2812     }
2813
2814   return 0;
2815 }
2816
2817 #if defined(__BORLANDC__) || defined(_MSC_VER)
2818 #define STRCASECMP stricmp
2819 #else
2820 #define STRCASECMP strcasecmp
2821 #endif
2822
2823 /*-----------------------------------------------------------------*/
2824 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2825 /*-----------------------------------------------------------------*/
2826 static bool
2827 inExcludeList (char *s)
2828 {
2829   int i = 0;
2830
2831   if (options.excludeRegs[i] &&
2832       STRCASECMP (options.excludeRegs[i], "none") == 0)
2833     return FALSE;
2834
2835   for (i = 0; options.excludeRegs[i]; i++)
2836     {
2837       if (options.excludeRegs[i] &&
2838           STRCASECMP (s, options.excludeRegs[i]) == 0)
2839         return TRUE;
2840     }
2841   return FALSE;
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* genFunction - generated code for function entry                 */
2846 /*-----------------------------------------------------------------*/
2847 static void
2848 genFunction (iCode * ic)
2849 {
2850   symbol *sym;
2851   sym_link *ftype;
2852   bool   switchedPSW = FALSE;
2853
2854   D (emitcode (";", "genFunction "););
2855
2856   _G.nRegsSaved = 0;
2857   /* create the function header */
2858   emitcode (";", "-----------------------------------------");
2859   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2860   emitcode (";", "-----------------------------------------");
2861
2862   emitcode ("", "%s:", sym->rname);
2863   ftype = operandType (IC_LEFT (ic));
2864
2865   if (IFFUNC_ISNAKED(ftype))
2866   {
2867       emitcode(";", "naked function: no prologue.");
2868       return;
2869   }
2870   
2871   if (options.stack_probe) 
2872       emitcode ("lcall","__stack_probe");
2873   /* if critical function then turn interrupts off */
2874   if (IFFUNC_ISCRITICAL (ftype))
2875     emitcode ("clr", "ea");
2876
2877   /* here we need to generate the equates for the
2878      register bank if required */
2879   if (FUNC_REGBANK (ftype) != rbank)
2880     {
2881       int i;
2882
2883       rbank = FUNC_REGBANK (ftype);
2884       for (i = 0; i < ds390_nRegs; i++)
2885         {
2886           if (regs390[i].print) {
2887               if (strcmp (regs390[i].base, "0") == 0)
2888                   emitcode ("", "%s !equ !constbyte",
2889                             regs390[i].dname,
2890                             8 * rbank + regs390[i].offset);
2891               else
2892                   emitcode ("", "%s !equ %s + !constbyte",
2893                             regs390[i].dname,
2894                             regs390[i].base,
2895                             8 * rbank + regs390[i].offset);
2896           }
2897         }
2898     }
2899
2900   /* if this is an interrupt service routine then
2901      save acc, b, dpl, dph  */
2902   if (IFFUNC_ISISR (sym->type))
2903       { /* is ISR */
2904       if (!inExcludeList ("acc"))
2905         emitcode ("push", "acc");
2906       if (!inExcludeList ("b"))
2907         emitcode ("push", "b");
2908       if (!inExcludeList ("dpl"))
2909         emitcode ("push", "dpl");
2910       if (!inExcludeList ("dph"))
2911         emitcode ("push", "dph");
2912       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2913         {
2914           emitcode ("push", "dpx");
2915           /* Make sure we're using standard DPTR */
2916           emitcode ("push", "dps");
2917           emitcode ("mov", "dps,#0");
2918           if (options.stack10bit)
2919             {
2920               /* This ISR could conceivably use DPTR2. Better save it. */
2921               emitcode ("push", "dpl1");
2922               emitcode ("push", "dph1");
2923               emitcode ("push", "dpx1");
2924               emitcode ("push",  DP2_RESULT_REG);
2925             }
2926         }
2927       /* if this isr has no bank i.e. is going to
2928          run with bank 0 , then we need to save more
2929          registers :-) */
2930       if (!FUNC_REGBANK (sym->type))
2931         {
2932             int i;
2933
2934           /* if this function does not call any other
2935              function then we can be economical and
2936              save only those registers that are used */
2937           if (!IFFUNC_HASFCALL(sym->type))
2938             {
2939
2940               /* if any registers used */
2941               if (sym->regsUsed)
2942                 {
2943                   /* save the registers used */
2944                   for (i = 0; i < sym->regsUsed->size; i++)
2945                     {
2946                       if (bitVectBitValue (sym->regsUsed, i) ||
2947                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2948                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2949                     }
2950                 }
2951
2952             }
2953           else
2954             {
2955               /* this function has  a function call cannot
2956                  determines register usage so we will have to push the
2957                  entire bank */
2958               saveRBank (0, ic, FALSE);
2959               if (options.parms_in_bank1) {
2960                   for (i=0; i < 8 ; i++ ) {
2961                       emitcode ("push","%s",rb1regs[i]);
2962                   }
2963               }
2964             }
2965         }
2966         else
2967         {
2968             /* This ISR uses a non-zero bank.
2969              *
2970              * We assume that the bank is available for our
2971              * exclusive use.
2972              *
2973              * However, if this ISR calls a function which uses some
2974              * other bank, we must save that bank entirely.
2975              */
2976             unsigned long banksToSave = 0;
2977             
2978             if (IFFUNC_HASFCALL(sym->type))
2979             {
2980
2981 #define MAX_REGISTER_BANKS 4
2982
2983                 iCode *i;
2984                 int ix;
2985
2986                 for (i = ic; i; i = i->next)
2987                 {
2988                     if (i->op == ENDFUNCTION)
2989                     {
2990                         /* we got to the end OK. */
2991                         break;
2992                     }
2993                     
2994                     if (i->op == CALL)
2995                     {
2996                         sym_link *dtype;
2997                         
2998                         dtype = operandType (IC_LEFT(i));
2999                         if (dtype 
3000                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3001                         {
3002                              /* Mark this bank for saving. */
3003                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3004                              {
3005                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3006                              }
3007                              else
3008                              {
3009                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3010                              }
3011                              
3012                              /* And note that we don't need to do it in 
3013                               * genCall.
3014                               */
3015                              i->bankSaved = 1;
3016                         }
3017                     }
3018                     if (i->op == PCALL)
3019                     {
3020                         /* This is a mess; we have no idea what
3021                          * register bank the called function might
3022                          * use.
3023                          *
3024                          * The only thing I can think of to do is
3025                          * throw a warning and hope.
3026                          */
3027                         werror(W_FUNCPTR_IN_USING_ISR);   
3028                     }
3029                 }
3030
3031                 if (banksToSave && options.useXstack)
3032                 {
3033                     /* Since we aren't passing it an ic, 
3034                      * saveRBank will assume r0 is available to abuse.
3035                      *
3036                      * So switch to our (trashable) bank now, so
3037                      * the caller's R0 isn't trashed.
3038                      */
3039                     emitcode ("push", "psw");
3040                     emitcode ("mov", "psw,#!constbyte", 
3041                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3042                     switchedPSW = TRUE;
3043                 }
3044                 
3045                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3046                 {
3047                      if (banksToSave & (1 << ix))
3048                      {
3049                          saveRBank(ix, NULL, FALSE);
3050                      }
3051                 }
3052             }
3053             // jwk: this needs a closer look
3054             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3055         }
3056     }
3057   else
3058     {
3059       /* if callee-save to be used for this function
3060          then save the registers being used in this function */
3061       if (IFFUNC_CALLEESAVES(sym->type))
3062         {
3063           int i;
3064
3065           /* if any registers used */
3066           if (sym->regsUsed)
3067             {
3068               /* save the registers used */
3069               for (i = 0; i < sym->regsUsed->size; i++)
3070                 {
3071                   if (bitVectBitValue (sym->regsUsed, i) ||
3072                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3073                     {
3074                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3075                       _G.nRegsSaved++;
3076                     }
3077                 }
3078             }
3079         }
3080     }
3081
3082   /* set the register bank to the desired value */
3083   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3084    && !switchedPSW)
3085     {
3086       emitcode ("push", "psw");
3087       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3088     }
3089
3090   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3091        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3092       if (options.stack10bit) {
3093           emitcode ("push","_bpx");
3094           emitcode ("push","_bpx+1");
3095           emitcode ("mov","_bpx,%s",spname);
3096           emitcode ("mov","_bpx+1,esp");
3097           emitcode ("anl","_bpx+1,#3");
3098       } else {
3099           if (options.useXstack) {
3100               emitcode ("mov", "r0,%s", spname);
3101               emitcode ("mov", "a,_bp");
3102               emitcode ("movx", "@r0,a");
3103               emitcode ("inc", "%s", spname);
3104           } else {
3105               /* set up the stack */
3106               emitcode ("push", "_bp"); /* save the callers stack  */
3107           }
3108           emitcode ("mov", "_bp,%s", spname);
3109       }
3110   }
3111
3112   /* adjust the stack for the function */
3113   if (sym->stack) {
3114       int i = sym->stack;
3115       if (options.stack10bit) {
3116           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3117           assert (sym->recvSize <= 4);
3118           if (sym->stack <= 8) {
3119               while (i--) emitcode ("push","acc");
3120           } else {
3121               PROTECT_SP;
3122               emitcode ("mov","a,sp");
3123               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3124               emitcode ("mov","sp,a");
3125               emitcode ("mov","a,esp");
3126               emitcode ("anl","a,#3");
3127               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3128               emitcode ("mov","esp,a");
3129               UNPROTECT_SP;
3130           }
3131       } else {
3132           if (i > 256)
3133               werror (W_STACK_OVERFLOW, sym->name);
3134           
3135           if (i > 3 && sym->recvSize < 4) {
3136               
3137               emitcode ("mov", "a,sp");
3138               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3139               emitcode ("mov", "sp,a");
3140               
3141           } else
3142               while (i--)
3143                   emitcode ("inc", "sp");
3144       }
3145   }
3146
3147   if (sym->xstack)
3148     {
3149
3150       emitcode ("mov", "a,_spx");
3151       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3152       emitcode ("mov", "_spx,a");
3153     }
3154
3155 }
3156
3157 /*-----------------------------------------------------------------*/
3158 /* genEndFunction - generates epilogue for functions               */
3159 /*-----------------------------------------------------------------*/
3160 static void
3161 genEndFunction (iCode * ic)
3162 {
3163   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3164
3165   D (emitcode (";", "genEndFunction "););
3166
3167   if (IFFUNC_ISNAKED(sym->type))
3168   {
3169       emitcode(";", "naked function: no epilogue.");
3170       return;
3171   }
3172
3173   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3174        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3175
3176       if (options.stack10bit) {
3177           PROTECT_SP;     
3178           emitcode ("mov", "sp,_bpx", spname);
3179           emitcode ("mov", "esp,_bpx+1", spname);
3180           UNPROTECT_SP;
3181       } else {
3182           emitcode ("mov", "%s,_bp", spname);
3183       }
3184   }
3185
3186   /* if use external stack but some variables were
3187      added to the local stack then decrement the
3188      local stack */
3189   if (options.useXstack && sym->stack) {
3190       emitcode ("mov", "a,sp");
3191       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3192       emitcode ("mov", "sp,a");
3193   }
3194
3195
3196   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3197        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3198
3199       if (options.useXstack) {
3200           emitcode ("mov", "r0,%s", spname);
3201           emitcode ("movx", "a,@r0");
3202           emitcode ("mov", "_bp,a");
3203           emitcode ("dec", "%s", spname);
3204       } else {
3205           if (options.stack10bit) {
3206               emitcode ("pop", "_bpx+1");
3207               emitcode ("pop", "_bpx");
3208           } else {
3209               emitcode ("pop", "_bp");
3210           }
3211       }
3212   }
3213
3214   /* restore the register bank  */
3215   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3216   {
3217     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3218      || !options.useXstack)
3219     {
3220         /* Special case of ISR using non-zero bank with useXstack
3221          * is handled below.
3222          */
3223         emitcode ("pop", "psw");
3224     }
3225   } 
3226
3227   if (IFFUNC_ISISR (sym->type))
3228       { /* is ISR */  
3229
3230       /* now we need to restore the registers */
3231       /* if this isr has no bank i.e. is going to
3232          run with bank 0 , then we need to save more
3233          registers :-) */
3234       if (!FUNC_REGBANK (sym->type))
3235         {
3236             int i;
3237           /* if this function does not call any other
3238              function then we can be economical and
3239              save only those registers that are used */
3240           if (!IFFUNC_HASFCALL(sym->type))
3241             {
3242
3243               /* if any registers used */
3244               if (sym->regsUsed)
3245                 {
3246                   /* save the registers used */
3247                   for (i = sym->regsUsed->size; i >= 0; i--)
3248                     {
3249                       if (bitVectBitValue (sym->regsUsed, i) ||
3250                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3251                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3252                     }
3253                 }
3254
3255             }
3256           else
3257             {
3258               /* this function has  a function call cannot
3259                  determines register usage so we will have to pop the
3260                  entire bank */
3261               if (options.parms_in_bank1) {
3262                   for (i = 7 ; i >= 0 ; i-- ) {
3263                       emitcode ("pop","%s",rb1regs[i]);
3264                   }
3265               }
3266               unsaveRBank (0, ic, FALSE);
3267             }
3268         }
3269         else
3270         {
3271             /* This ISR uses a non-zero bank.
3272              *
3273              * Restore any register banks saved by genFunction
3274              * in reverse order.
3275              */
3276           // jwk: this needs a closer look
3277             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3278             int ix;
3279           
3280             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3281             {
3282                 if (savedBanks & (1 << ix))
3283                 {
3284                     unsaveRBank(ix, NULL, FALSE);
3285                 }
3286             }
3287             
3288             if (options.useXstack)
3289             {
3290                 /* Restore bank AFTER calling unsaveRBank,
3291                  * since it can trash r0.
3292                  */
3293                 emitcode ("pop", "psw");
3294             }
3295         }
3296
3297       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3298         {
3299           if (options.stack10bit)
3300             {
3301               emitcode ("pop", DP2_RESULT_REG);
3302               emitcode ("pop", "dpx1");
3303               emitcode ("pop", "dph1");
3304               emitcode ("pop", "dpl1");
3305             }
3306           emitcode ("pop", "dps");
3307           emitcode ("pop", "dpx");
3308         }
3309       if (!inExcludeList ("dph"))
3310         emitcode ("pop", "dph");
3311       if (!inExcludeList ("dpl"))
3312         emitcode ("pop", "dpl");
3313       if (!inExcludeList ("b"))
3314         emitcode ("pop", "b");
3315       if (!inExcludeList ("acc"))
3316         emitcode ("pop", "acc");
3317
3318       if (IFFUNC_ISCRITICAL (sym->type))
3319         emitcode ("setb", "ea");
3320
3321       /* if debug then send end of function */
3322       if (options.debug && currFunc) {
3323           _G.debugLine = 1;
3324           emitcode ("", "C$%s$%d$%d$%d ==.",
3325                     FileBaseName (ic->filename), currFunc->lastLine,
3326                     ic->level, ic->block);
3327           if (IS_STATIC (currFunc->etype))
3328             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3329           else
3330             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3331           _G.debugLine = 0;
3332         }
3333
3334       emitcode ("reti", "");
3335     }
3336   else
3337     {
3338       if (IFFUNC_ISCRITICAL (sym->type))
3339         emitcode ("setb", "ea");
3340
3341       if (IFFUNC_CALLEESAVES(sym->type))
3342         {
3343           int i;
3344
3345           /* if any registers used */
3346           if (sym->regsUsed)
3347             {
3348               /* save the registers used */
3349               for (i = sym->regsUsed->size; i >= 0; i--)
3350                 {
3351                   if (bitVectBitValue (sym->regsUsed, i) ||
3352                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3353                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3354                 }
3355             }
3356
3357         }
3358
3359       /* if debug then send end of function */
3360       if (options.debug && currFunc)
3361         {
3362           _G.debugLine = 1;
3363           emitcode ("", "C$%s$%d$%d$%d ==.",
3364                     FileBaseName (ic->filename), currFunc->lastLine,
3365                     ic->level, ic->block);
3366           if (IS_STATIC (currFunc->etype))
3367             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3368           else
3369             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3370           _G.debugLine = 0;
3371         }
3372
3373       emitcode ("ret", "");
3374     }
3375
3376 }
3377
3378 /*-----------------------------------------------------------------*/
3379 /* genJavaNativeRet - generate code for return JavaNative          */
3380 /*-----------------------------------------------------------------*/
3381 static void genJavaNativeRet(iCode *ic)
3382 {
3383     int i, size;
3384
3385     aopOp (IC_LEFT (ic), ic, FALSE, 
3386            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3387     size = AOP_SIZE (IC_LEFT (ic));
3388
3389     assert (size <= 4);
3390
3391     /* it is assigned to GPR0-R3 then push them */
3392     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3393         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3394         for (i = 0 ; i < size ; i++ ) {
3395             emitcode ("push","%s",
3396                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3397         }
3398         for (i = (size-1) ; i >= 0 ; i--) {
3399             emitcode ("pop","a%s",javaRet[i]);
3400         }
3401     } else {
3402         for (i = 0 ; i < size ; i++) 
3403             emitcode ("mov","%s,%s",javaRet[i],
3404                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3405     }
3406     for (i = size ; i < 4 ; i++ )
3407             emitcode ("mov","%s,#0",javaRet[i]);
3408     return;
3409 }
3410
3411 /*-----------------------------------------------------------------*/
3412 /* genRet - generate code for return statement                     */
3413 /*-----------------------------------------------------------------*/
3414 static void
3415 genRet (iCode * ic)
3416 {
3417   int size, offset = 0, pushed = 0;
3418
3419   D (emitcode (";", "genRet "););
3420
3421   /* if we have no return value then
3422      just generate the "ret" */
3423   if (!IC_LEFT (ic))
3424     goto jumpret;
3425
3426   /* if this is a JavaNative function then return 
3427      value in different register */
3428   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3429       genJavaNativeRet(ic);
3430       goto jumpret;
3431   }
3432   /* we have something to return then
3433      move the return value into place */
3434   aopOp (IC_LEFT (ic), ic, FALSE, 
3435          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3436   size = AOP_SIZE (IC_LEFT (ic));
3437
3438   _startLazyDPSEvaluation ();
3439   while (size--)
3440     {
3441       char *l;
3442       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3443         {
3444           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3445                       FALSE, TRUE, NULL);
3446           emitcode ("push", "%s", l);
3447           pushed++;
3448         }
3449       else
3450         {
3451           /* Since A is the last element of fReturn,
3452            * is is OK to clobber it in the aopGet.
3453            */
3454           l = aopGet (AOP (IC_LEFT (ic)), offset,
3455                       FALSE, FALSE, NULL);
3456           if (strcmp (fReturn[offset], l))
3457             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3458         }
3459     }
3460   _endLazyDPSEvaluation ();
3461
3462   if (pushed)
3463     {
3464       while (pushed)
3465         {
3466           pushed--;
3467           if (strcmp (fReturn[pushed], "a"))
3468             emitcode ("pop", fReturn[pushed]);
3469           else
3470             emitcode ("pop", "acc");
3471         }
3472     }
3473   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3474
3475 jumpret:
3476   /* generate a jump to the return label
3477      if the next is not the return statement */
3478   if (!(ic->next && ic->next->op == LABEL &&
3479         IC_LABEL (ic->next) == returnLabel))
3480
3481     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3482
3483 }
3484
3485 /*-----------------------------------------------------------------*/
3486 /* genLabel - generates a label                                    */
3487 /*-----------------------------------------------------------------*/
3488 static void
3489 genLabel (iCode * ic)
3490 {
3491   /* special case never generate */
3492   if (IC_LABEL (ic) == entryLabel)
3493     return;
3494
3495   D (emitcode (";", "genLabel ");
3496     );
3497
3498   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* genGoto - generates a ljmp                                      */
3503 /*-----------------------------------------------------------------*/
3504 static void
3505 genGoto (iCode * ic)
3506 {
3507   D (emitcode (";", "genGoto ");
3508     );
3509   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3510 }
3511
3512 /*-----------------------------------------------------------------*/
3513 /* findLabelBackwards: walks back through the iCode chain looking  */
3514 /* for the given label. Returns number of iCode instructions     */
3515 /* between that label and given ic.          */
3516 /* Returns zero if label not found.          */
3517 /*-----------------------------------------------------------------*/
3518 static int
3519 findLabelBackwards (iCode * ic, int key)
3520 {
3521   int count = 0;
3522
3523   while (ic->prev)
3524     {
3525       ic = ic->prev;
3526       count++;
3527
3528       /* If we have any pushes or pops, we cannot predict the distance.
3529          I don't like this at all, this should be dealt with in the 
3530          back-end */
3531       if (ic->op == IPUSH || ic->op == IPOP) {
3532         return 0;
3533       }
3534
3535       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3536         {
3537           /* printf("findLabelBackwards = %d\n", count); */
3538           return count;
3539         }
3540     }
3541
3542   return 0;
3543 }
3544
3545 /*-----------------------------------------------------------------*/
3546 /* genPlusIncr :- does addition with increment if possible         */
3547 /*-----------------------------------------------------------------*/
3548 static bool
3549 genPlusIncr (iCode * ic)
3550 {
3551   unsigned int icount;
3552   unsigned int size = getDataSize (IC_RESULT (ic));
3553
3554   /* will try to generate an increment */
3555   /* if the right side is not a literal
3556      we cannot */
3557   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3558     return FALSE;
3559
3560   /* if the literal value of the right hand side
3561      is greater than 4 then it is not worth it */
3562   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3563     return FALSE;
3564
3565   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3566       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3567       while (icount--) {
3568           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3569       }
3570       return TRUE;
3571   }
3572   /* if increment 16 bits in register */
3573   if (
3574        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3575        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3576        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3577        (size > 1) &&
3578        (icount == 1))
3579     {
3580       symbol  *tlbl;
3581       int     emitTlbl;
3582       int     labelRange;
3583       char    *l;
3584
3585       /* If the next instruction is a goto and the goto target
3586        * is <= 5 instructions previous to this, we can generate
3587        * jumps straight to that target.
3588        */
3589       if (ic->next && ic->next->op == GOTO
3590           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3591           && labelRange <= 5)
3592         {
3593           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3594           tlbl = IC_LABEL (ic->next);
3595           emitTlbl = 0;
3596         }
3597       else
3598         {
3599           tlbl = newiTempLabel (NULL);
3600           emitTlbl = 1;
3601         }
3602         
3603       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3604       emitcode ("inc", "%s", l);
3605       
3606       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3607           IS_AOP_PREG (IC_RESULT (ic)))
3608       {   
3609         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3610       }
3611       else
3612       {
3613           emitcode ("clr", "a");
3614           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3615       }
3616
3617       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3618       emitcode ("inc", "%s", l);
3619       if (size > 2)
3620         {
3621             if (!strcmp(l, "acc"))
3622             {
3623                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3624             }
3625             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3626                      IS_AOP_PREG (IC_RESULT (ic)))
3627             {
3628                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3629             }
3630             else
3631             {
3632                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3633             }
3634
3635             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3636             emitcode ("inc", "%s", l);
3637         }
3638       if (size > 3)
3639         {
3640             if (!strcmp(l, "acc"))
3641             {
3642                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3643             }
3644             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3645                      IS_AOP_PREG (IC_RESULT (ic)))
3646             {
3647                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3648             }
3649             else
3650             {
3651                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3652             }
3653
3654             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3655             emitcode ("inc", "%s", l);  }
3656
3657       if (emitTlbl)
3658         {
3659           emitcode ("", "!tlabeldef", tlbl->key + 100);
3660         }
3661       return TRUE;
3662     }
3663
3664   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3665       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3666       options.model == MODEL_FLAT24 ) {
3667
3668       switch (size) {
3669       case 3:
3670           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3671       case 2:
3672           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3673       case 1:
3674           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3675           break;
3676       }
3677       while (icount--) emitcode ("inc","dptr");      
3678       return TRUE;
3679   }
3680
3681   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3682       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3683       icount <= 5 ) {
3684       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3685       while (icount--) emitcode ("inc","dptr");
3686       emitcode ("mov","dps,#0");
3687       return TRUE;
3688   }
3689
3690   /* if the sizes are greater than 1 then we cannot */
3691   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3692       AOP_SIZE (IC_LEFT (ic)) > 1)
3693     return FALSE;
3694
3695   /* we can if the aops of the left & result match or
3696      if they are in registers and the registers are the
3697      same */
3698   if (
3699        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3700        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3701        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3702     {
3703
3704       if (icount > 3)
3705         {
3706           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3707           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3708           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3709         }
3710       else
3711         {
3712
3713           _startLazyDPSEvaluation ();
3714           while (icount--)
3715             {
3716               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3717             }
3718           _endLazyDPSEvaluation ();
3719         }
3720
3721       return TRUE;
3722     }
3723
3724   return FALSE;
3725 }
3726
3727 /*-----------------------------------------------------------------*/
3728 /* outBitAcc - output a bit in acc                                 */
3729 /*-----------------------------------------------------------------*/
3730 static void
3731 outBitAcc (operand * result)
3732 {
3733   symbol *tlbl = newiTempLabel (NULL);
3734   /* if the result is a bit */
3735   if (AOP_TYPE (result) == AOP_CRY)
3736     {
3737       aopPut (AOP (result), "a", 0);
3738     }
3739   else
3740     {
3741       emitcode ("jz", "!tlabel", tlbl->key + 100);
3742       emitcode ("mov", "a,%s", one);
3743       emitcode ("", "!tlabeldef", tlbl->key + 100);
3744       outAcc (result);
3745     }
3746 }
3747
3748 /*-----------------------------------------------------------------*/
3749 /* genPlusBits - generates code for addition of two bits           */
3750 /*-----------------------------------------------------------------*/
3751 static void
3752 genPlusBits (iCode * ic)
3753 {
3754   D (emitcode (";", "genPlusBits "););
3755     
3756   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3757     {
3758       symbol *lbl = newiTempLabel (NULL);
3759       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3760       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3761       emitcode ("cpl", "c");
3762       emitcode ("", "!tlabeldef", (lbl->key + 100));
3763       outBitC (IC_RESULT (ic));
3764     }
3765   else
3766     {
3767       emitcode ("clr", "a");
3768       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3769       emitcode ("rlc", "a");
3770       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3771       emitcode ("addc", "a,#0");
3772       outAcc (IC_RESULT (ic));
3773     }
3774 }
3775
3776 static void
3777 adjustArithmeticResult (iCode * ic)
3778 {
3779   if (opIsGptr (IC_RESULT (ic)) &&
3780       opIsGptr (IC_LEFT (ic)) &&
3781       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3782     {
3783       aopPut (AOP (IC_RESULT (ic)),
3784               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3785               GPTRSIZE - 1);
3786     }
3787
3788   if (opIsGptr (IC_RESULT (ic)) &&
3789       opIsGptr (IC_RIGHT (ic)) &&
3790       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3791     {
3792       aopPut (AOP (IC_RESULT (ic)),
3793             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3794               GPTRSIZE - 1);
3795     }
3796
3797   if (opIsGptr (IC_RESULT (ic)) &&
3798       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3799       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3800       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3801       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3802     {
3803       char buff[5];
3804       SNPRINTF (buff, sizeof(buff), 
3805                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3806       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3807     }
3808 }
3809
3810 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3811 // generates the result if possible. If result is generated, returns TRUE; otherwise
3812 // returns false and caller must deal with fact that result isn't aopOp'd.
3813 bool aopOp3(iCode * ic)
3814 {
3815     bool dp1InUse, dp2InUse;
3816     bool useDp2;
3817     
3818     // First, generate the right opcode. DPTR may be used if neither left nor result are
3819     // of type AOP_STR.
3820     
3821 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3822 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3823 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3824 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3825 //      );
3826 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3827 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3828 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3829 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3830 //      );      
3831
3832     
3833     // Right uses DPTR unless left or result is an AOP_STR.
3834     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3835     
3836     // if the right used DPTR, left MUST use DPTR2.
3837     // if the right used DPTR2, left MUST use DPTR.
3838     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3839     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3840     // enabling us to assign DPTR to result.
3841      
3842     if (AOP_USESDPTR(IC_RIGHT(ic)))
3843     {
3844         useDp2 = TRUE;
3845     }
3846     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3847     {
3848         useDp2 = FALSE;
3849     }
3850     else
3851     {
3852         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3853         {
3854             useDp2 = TRUE;
3855         }
3856         else
3857         {
3858             useDp2 = FALSE;
3859         }
3860     }
3861
3862     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3863     
3864     // We've op'd the left & right. So, if left or right are the same operand as result, 
3865     // we know aopOp will succeed, and we can just do it & bail.
3866     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3867         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3868     {
3869 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3870         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3871         return TRUE;
3872     }
3873     
3874     // Note which dptrs are currently in use.
3875     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3876     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3877     
3878     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3879     // generate it.
3880     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3881     {
3882         return FALSE;
3883     }
3884     
3885     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3886     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3887     {
3888         return FALSE;
3889     }
3890     
3891     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3892     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3893     {
3894         return FALSE;
3895     }
3896
3897     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3898
3899     // Some sanity checking...
3900     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3901     {
3902         fprintf(stderr,
3903                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3904                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3905         emitcode(";", ">>> unexpected DPTR here.");
3906     }
3907     
3908     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3909     {
3910         fprintf(stderr,
3911                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3912                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3913         emitcode(";", ">>> unexpected DPTR2 here.");
3914     }    
3915     
3916     return TRUE;
3917 }
3918
3919 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3920 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3921 // will be set TRUE. The caller must then handle the case specially, noting
3922 // that the IC_RESULT operand is not aopOp'd.
3923 // 
3924 #define AOP_OP_3_NOFATAL(ic, rc) \
3925             do { rc = !aopOp3(ic); } while (0)
3926
3927 // aopOp the left & right operands of an ic.
3928 #define AOP_OP_2(ic) \
3929     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3930     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3931
3932 // convienience macro.
3933 #define AOP_SET_LOCALS(ic) \
3934     left = IC_LEFT(ic); \
3935     right = IC_RIGHT(ic); \
3936     result = IC_RESULT(ic);
3937
3938
3939 // Given an integer value of pushedSize bytes on the stack,
3940 // adjust it to be resultSize bytes, either by discarding
3941 // the most significant bytes or by zero-padding.
3942 //
3943 // On exit from this macro, pushedSize will have been adjusted to
3944 // equal resultSize, and ACC may be trashed.
3945 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3946       /* If the pushed data is bigger than the result,          \
3947        * simply discard unused bytes. Icky, but works.          \
3948        */                                                       \
3949       while (pushedSize > resultSize)                           \
3950       {                                                         \
3951           D (emitcode (";", "discarding unused result byte."););\
3952           emitcode ("pop", "acc");                              \
3953           pushedSize--;                                         \
3954       }                                                         \
3955       if (pushedSize < resultSize)                              \
3956       {                                                         \
3957           emitcode ("clr", "a");                                \
3958           /* Conversly, we haven't pushed enough here.          \
3959            * just zero-pad, and all is well.                    \
3960            */                                                   \
3961           while (pushedSize < resultSize)                       \
3962           {                                                     \
3963               emitcode("push", "acc");                          \
3964               pushedSize++;                                     \
3965           }                                                     \
3966       }                                                         \
3967       assert(pushedSize == resultSize);
3968
3969 /*-----------------------------------------------------------------*/
3970 /* genPlus - generates code for addition                           */
3971 /*-----------------------------------------------------------------*/
3972 static void
3973 genPlus (iCode * ic)
3974 {
3975   int size, offset = 0;
3976   bool pushResult;
3977   int rSize;
3978
3979   D (emitcode (";", "genPlus "););
3980
3981   /* special cases :- */
3982   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3983       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3984       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3985       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3986       if (size <= 9) {
3987           while (size--) emitcode ("inc","dptr");
3988       } else {
3989           emitcode ("mov","a,dpl");
3990           emitcode ("add","a,#!constbyte",size & 0xff);
3991           emitcode ("mov","dpl,a");
3992           emitcode ("mov","a,dph");
3993           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3994           emitcode ("mov","dph,a");
3995           emitcode ("mov","a,dpx");
3996           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3997           emitcode ("mov","dpx,a");
3998       }
3999       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4000       return ;
4001   }
4002   if ( IS_SYMOP(IC_LEFT(ic)) && 
4003        OP_SYMBOL(IC_LEFT(ic))->remat &&
4004        isOperandInFarSpace(IC_RIGHT(ic))) {
4005       operand *op = IC_RIGHT(ic);
4006       IC_RIGHT(ic) = IC_LEFT(ic);
4007       IC_LEFT(ic) = op;
4008   }
4009                 
4010   AOP_OP_3_NOFATAL (ic, pushResult);
4011     
4012   if (pushResult)
4013     {
4014       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4015     }
4016
4017   if (!pushResult)
4018     {
4019       /* if literal, literal on the right or
4020          if left requires ACC or right is already
4021          in ACC */
4022       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4023        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4024           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4025         {
4026           operand *t = IC_RIGHT (ic);
4027           IC_RIGHT (ic) = IC_LEFT (ic);
4028           IC_LEFT (ic) = t;
4029           emitcode (";", "Swapped plus args.");
4030         }
4031
4032       /* if both left & right are in bit
4033          space */
4034       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4035           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4036         {
4037           genPlusBits (ic);
4038           goto release;
4039         }
4040
4041       /* if left in bit space & right literal */
4042       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4043           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4044         {
4045           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4046           /* if result in bit space */
4047           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4048             {
4049               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4050                 emitcode ("cpl", "c");
4051               outBitC (IC_RESULT (ic));
4052             }
4053           else
4054             {
4055               size = getDataSize (IC_RESULT (ic));
4056               _startLazyDPSEvaluation ();
4057               while (size--)
4058                 {
4059                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4060                   emitcode ("addc", "a,#0");
4061                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4062                 }
4063               _endLazyDPSEvaluation ();
4064             }
4065           goto release;
4066         }
4067
4068       /* if I can do an increment instead
4069          of add then GOOD for ME */
4070       if (genPlusIncr (ic) == TRUE)
4071         {
4072           emitcode (";", "did genPlusIncr");
4073           goto release;
4074         }
4075
4076     }
4077   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4078
4079   _startLazyDPSEvaluation ();
4080   while (size--)
4081     {
4082       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4083         {
4084           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4085           if (offset == 0)
4086             emitcode ("add", "a,%s",
4087                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4088           else
4089             emitcode ("addc", "a,%s",
4090                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4091         }
4092       else
4093         {
4094           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4095           {
4096               /* right is going to use ACC or we would have taken the
4097                * above branch.
4098                */
4099               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4100        TR_AP("#3");
4101               D(emitcode(";", "+ AOP_ACC special case."););
4102               emitcode("xch", "a, %s", DP2_RESULT_REG);
4103           }
4104           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4105           if (offset == 0)
4106           {
4107             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4108             {
4109          TR_AP("#4");
4110                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4111             }
4112             else
4113             {
4114                 emitcode ("add", "a,%s",
4115                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4116                                   DP2_RESULT_REG));
4117             }
4118           }
4119           else
4120           {
4121             emitcode ("addc", "a,%s",
4122                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4123                           DP2_RESULT_REG));
4124           }
4125         }
4126       if (!pushResult)
4127         {
4128           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4129         }
4130       else
4131         {
4132           emitcode ("push", "acc");
4133         }
4134       offset++;
4135     }
4136   _endLazyDPSEvaluation ();
4137
4138   if (pushResult)
4139     {
4140       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4141
4142       size = getDataSize (IC_LEFT (ic));
4143       rSize = getDataSize (IC_RESULT (ic));
4144
4145       ADJUST_PUSHED_RESULT(size, rSize);
4146
4147       _startLazyDPSEvaluation ();
4148       while (size--)
4149         {
4150           emitcode ("pop", "acc");
4151           aopPut (AOP (IC_RESULT (ic)), "a", size);
4152         }
4153       _endLazyDPSEvaluation ();
4154     }
4155
4156   adjustArithmeticResult (ic);
4157
4158 release:
4159   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4160   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4161   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4162 }
4163
4164 /*-----------------------------------------------------------------*/
4165 /* genMinusDec :- does subtraction with deccrement if possible     */
4166 /*-----------------------------------------------------------------*/
4167 static bool
4168 genMinusDec (iCode * ic)
4169 {
4170   unsigned int icount;
4171   unsigned int size = getDataSize (IC_RESULT (ic));
4172
4173   /* will try to generate an increment */
4174   /* if the right side is not a literal
4175      we cannot */
4176   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4177     return FALSE;
4178
4179   /* if the literal value of the right hand side
4180      is greater than 4 then it is not worth it */
4181   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4182     return FALSE;
4183
4184   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4185       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4186       while (icount--) {
4187           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4188       }
4189       return TRUE;
4190   }
4191   /* if decrement 16 bits in register */
4192   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4193       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4194       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4195       (size > 1) &&
4196       (icount == 1))
4197     {
4198       symbol *tlbl;
4199       int    emitTlbl;
4200       int    labelRange;
4201       char   *l;
4202
4203       /* If the next instruction is a goto and the goto target
4204          * is <= 5 instructions previous to this, we can generate
4205          * jumps straight to that target.
4206        */
4207       if (ic->next && ic->next->op == GOTO
4208           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4209           && labelRange <= 5)
4210         {
4211           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4212           tlbl = IC_LABEL (ic->next);
4213           emitTlbl = 0;
4214         }
4215       else
4216         {
4217           tlbl = newiTempLabel (NULL);
4218           emitTlbl = 1;
4219         }
4220
4221       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4222       emitcode ("dec", "%s", l);
4223  
4224       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4225           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4226           IS_AOP_PREG (IC_RESULT (ic)))
4227       {     
4228           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4229       }
4230       else
4231       {
4232           emitcode ("mov", "a,#!constbyte",0xff);
4233           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4234       }
4235       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4236       emitcode ("dec", "%s", l);
4237       if (size > 2)
4238         {
4239             if (!strcmp(l, "acc"))
4240             {
4241                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4242             }
4243             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4244                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4245                      IS_AOP_PREG (IC_RESULT (ic)))
4246             {       
4247                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4248             }
4249             else
4250             {
4251                 emitcode ("mov", "a,#!constbyte",0xff);
4252                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4253             }
4254             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4255             emitcode ("dec", "%s", l);
4256         }
4257       if (size > 3)
4258         {
4259             if (!strcmp(l, "acc"))
4260             {
4261                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4262             }
4263             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4264                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4265                      IS_AOP_PREG (IC_RESULT (ic)))
4266             {       
4267                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4268             }
4269             else
4270             {
4271                 emitcode ("mov", "a,#!constbyte",0xff);
4272                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4273             }       
4274             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4275             emitcode ("dec", "%s", l);
4276         }
4277       if (emitTlbl)
4278         {
4279           emitcode ("", "!tlabeldef", tlbl->key + 100);
4280         }
4281       return TRUE;
4282     }
4283
4284   /* if the sizes are greater than 1 then we cannot */
4285   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4286       AOP_SIZE (IC_LEFT (ic)) > 1)
4287     return FALSE;
4288
4289   /* we can if the aops of the left & result match or
4290      if they are in registers and the registers are the
4291      same */
4292   if (
4293        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4294        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4295        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4296     {
4297
4298       _startLazyDPSEvaluation ();
4299       while (icount--)
4300         {
4301           emitcode ("dec", "%s",
4302                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4303         }
4304       _endLazyDPSEvaluation ();
4305
4306       return TRUE;
4307     }
4308
4309   return FALSE;
4310 }
4311
4312 /*-----------------------------------------------------------------*/
4313 /* addSign - complete with sign                                    */
4314 /*-----------------------------------------------------------------*/
4315 static void
4316 addSign (operand * result, int offset, int sign)
4317 {
4318   int size = (getDataSize (result) - offset);
4319   if (size > 0)
4320     {
4321       _startLazyDPSEvaluation();
4322       if (sign)
4323         {
4324           emitcode ("rlc", "a");
4325           emitcode ("subb", "a,acc");
4326           while (size--)
4327           {
4328             aopPut (AOP (result), "a", offset++);
4329           }
4330         }
4331       else
4332       {
4333         while (size--)
4334         {
4335           aopPut (AOP (result), zero, offset++);
4336         }
4337       }
4338       _endLazyDPSEvaluation();
4339     }
4340 }
4341
4342 /*-----------------------------------------------------------------*/
4343 /* genMinusBits - generates code for subtraction  of two bits      */
4344 /*-----------------------------------------------------------------*/
4345 static void
4346 genMinusBits (iCode * ic)
4347 {
4348   symbol *lbl = newiTempLabel (NULL);
4349
4350   D (emitcode (";", "genMinusBits "););
4351
4352   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4353     {
4354       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4355       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4356       emitcode ("cpl", "c");
4357       emitcode ("", "!tlabeldef", (lbl->key + 100));
4358       outBitC (IC_RESULT (ic));
4359     }
4360   else
4361     {
4362       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4363       emitcode ("subb", "a,acc");
4364       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4365       emitcode ("inc", "a");
4366       emitcode ("", "!tlabeldef", (lbl->key + 100));
4367       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4368       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4369     }
4370 }
4371
4372 /*-----------------------------------------------------------------*/
4373 /* genMinus - generates code for subtraction                       */
4374 /*-----------------------------------------------------------------*/
4375 static void
4376 genMinus (iCode * ic)
4377 {
4378     int size, offset = 0;
4379     int rSize;
4380     long lit = 0L;
4381     bool pushResult;
4382
4383     D (emitcode (";", "genMinus "););
4384
4385     AOP_OP_3_NOFATAL(ic, pushResult);   
4386
4387     if (!pushResult)
4388     {
4389       /* special cases :- */
4390       /* if both left & right are in bit space */
4391       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4392           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4393         {
4394           genMinusBits (ic);
4395           goto release;
4396         }
4397
4398       /* if I can do an decrement instead
4399          of subtract then GOOD for ME */
4400       if (genMinusDec (ic) == TRUE)
4401         goto release;
4402
4403     }
4404
4405   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4406
4407   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4408     {
4409       CLRC;
4410     }
4411   else
4412     {
4413       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4414       lit = -lit;
4415     }
4416
4417
4418   /* if literal, add a,#-lit, else normal subb */
4419   _startLazyDPSEvaluation ();
4420   while (size--) {
4421       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4422           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4423               emitcode ("mov","b,%s",
4424                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4425               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4426               emitcode ("subb","a,b");
4427           } else {
4428               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4429               emitcode ("subb", "a,%s",
4430                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4431                                 DP2_RESULT_REG));
4432           }
4433       } else {
4434           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4435           /* first add without previous c */
4436           if (!offset) {
4437               if (!size && lit==-1) {
4438                   emitcode ("dec", "a");
4439               } else {
4440                   emitcode ("add", "a,#!constbyte",
4441                             (unsigned int) (lit & 0x0FFL));
4442               }
4443           } else {
4444               emitcode ("addc", "a,#!constbyte",
4445                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4446           }
4447       }
4448       
4449       if (pushResult) {
4450           emitcode ("push", "acc");
4451       } else {
4452           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4453       }
4454       offset++;
4455   }
4456   _endLazyDPSEvaluation ();
4457   
4458   if (pushResult)
4459     {
4460       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4461
4462       size = getDataSize (IC_LEFT (ic));
4463       rSize = getDataSize (IC_RESULT (ic));
4464
4465       ADJUST_PUSHED_RESULT(size, rSize);
4466
4467       _startLazyDPSEvaluation ();
4468       while (size--)
4469         {
4470           emitcode ("pop", "acc");
4471           aopPut (AOP (IC_RESULT (ic)), "a", size);
4472         }
4473       _endLazyDPSEvaluation ();
4474     }
4475
4476   adjustArithmeticResult (ic);
4477
4478 release:
4479   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4480   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4481   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4482 }
4483
4484
4485 /*-----------------------------------------------------------------*/
4486 /* genMultbits :- multiplication of bits                           */
4487 /*-----------------------------------------------------------------*/
4488 static void
4489 genMultbits (operand * left,
4490              operand * right,
4491              operand * result,
4492              iCode   * ic)
4493 {
4494   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4495   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4496   aopOp(result, ic, TRUE, FALSE);
4497   outBitC (result);
4498 }
4499
4500
4501 /*-----------------------------------------------------------------*/
4502 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4503 /*-----------------------------------------------------------------*/
4504 static void
4505 genMultOneByte (operand * left,
4506                 operand * right,
4507                 operand * result,
4508                 iCode   * ic)
4509 {
4510   sym_link *opetype = operandType (result);
4511   symbol *lbl;
4512
4513
4514   /* (if two literals: the value is computed before) */
4515   /* if one literal, literal on the right */
4516   if (AOP_TYPE (left) == AOP_LIT)
4517     {
4518       operand *t = right;
4519       right = left;
4520       left = t;
4521       emitcode (";", "swapped left and right");
4522     }
4523
4524   if (SPEC_USIGN(opetype)
4525       // ignore the sign of left and right, what else can we do?
4526       || (SPEC_USIGN(operandType(left)) && 
4527           SPEC_USIGN(operandType(right)))) {
4528     // just an unsigned 8*8=8/16 multiply
4529     //emitcode (";","unsigned");
4530     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4531     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4532     emitcode ("mul", "ab");
4533    
4534     _G.accInUse++; _G.bInUse++;
4535     aopOp(result, ic, TRUE, FALSE);
4536       
4537       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4538       {
4539           // this should never happen
4540           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4541                    AOP_SIZE(result), __FILE__, lineno);
4542           exit (1);
4543       }      
4544       
4545     aopPut (AOP (result), "a", 0);
4546     _G.accInUse--; _G.bInUse--;
4547     if (AOP_SIZE(result)==2) 
4548     {
4549       aopPut (AOP (result), "b", 1);
4550     }
4551     return;
4552   }
4553
4554   // we have to do a signed multiply
4555
4556   emitcode (";", "signed");
4557   emitcode ("clr", "F0"); // reset sign flag
4558   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4559
4560   lbl=newiTempLabel(NULL);
4561   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4562   // left side is negative, 8-bit two's complement, this fails for -128
4563   emitcode ("setb", "F0"); // set sign flag
4564   emitcode ("cpl", "a");
4565   emitcode ("inc", "a");
4566
4567   emitcode ("", "!tlabeldef", lbl->key+100);
4568
4569   /* if literal */
4570   if (AOP_TYPE(right)==AOP_LIT) {
4571     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4572     /* AND literal negative */
4573     if ((int) val < 0) {
4574       emitcode ("cpl", "F0"); // complement sign flag
4575       emitcode ("mov", "b,#!constbyte", -val);
4576     } else {
4577       emitcode ("mov", "b,#!constbyte", val);
4578     }
4579   } else {
4580     lbl=newiTempLabel(NULL);
4581     emitcode ("mov", "b,a");
4582     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4583     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4584     // right side is negative, 8-bit two's complement
4585     emitcode ("cpl", "F0"); // complement sign flag
4586     emitcode ("cpl", "a");
4587     emitcode ("inc", "a");
4588     emitcode ("", "!tlabeldef", lbl->key+100);
4589   }
4590   emitcode ("mul", "ab");
4591     
4592   _G.accInUse++;_G.bInUse++;
4593   aopOp(result, ic, TRUE, FALSE);
4594     
4595   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4596   {
4597     // this should never happen
4598       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4599                AOP_SIZE(result), __FILE__, lineno);
4600       exit (1);
4601   }    
4602     
4603   lbl=newiTempLabel(NULL);
4604   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4605   // only ONE op was negative, we have to do a 8/16-bit two's complement
4606   emitcode ("cpl", "a"); // lsb
4607   if (AOP_SIZE(result)==1) {
4608     emitcode ("inc", "a");
4609   } else {
4610     emitcode ("add", "a,#1");
4611     emitcode ("xch", "a,b");
4612     emitcode ("cpl", "a"); // msb
4613     emitcode ("addc", "a,#0");
4614     emitcode ("xch", "a,b");
4615   }
4616
4617   emitcode ("", "!tlabeldef", lbl->key+100);
4618   aopPut (AOP (result), "a", 0);
4619   _G.accInUse--;_G.bInUse--;
4620   if (AOP_SIZE(result)==2) {
4621     aopPut (AOP (result), "b", 1);
4622   }
4623 }
4624
4625 /*-----------------------------------------------------------------*/
4626 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4627 /*-----------------------------------------------------------------*/
4628 static void genMultTwoByte (operand *left, operand *right, 
4629                             operand *result, iCode *ic)
4630 {
4631         sym_link *retype = getSpec(operandType(right));
4632         sym_link *letype = getSpec(operandType(left));
4633         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4634         symbol *lbl;
4635
4636         if (AOP_TYPE (left) == AOP_LIT) {
4637                 operand *t = right;
4638                 right = left;
4639                 left = t;
4640         }
4641         /* save EA bit in F1 */
4642         lbl = newiTempLabel(NULL);
4643         emitcode ("setb","F1");
4644         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4645         emitcode ("clr","F1");
4646         emitcode("","!tlabeldef",lbl->key+100);
4647
4648         /* load up MB with right */
4649         if (!umult) {
4650                 emitcode("clr","F0");
4651                 if (AOP_TYPE(right) == AOP_LIT) {
4652                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4653                         if (val < 0) {
4654                                 emitcode("setb","F0");
4655                                 val = -val;
4656                         }
4657                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4658                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4659                 } else {
4660                         lbl = newiTempLabel(NULL);
4661                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4662                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4663                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4664                         emitcode ("xch", "a,b");
4665                         emitcode ("cpl","a");
4666                         emitcode ("add", "a,#1");
4667                         emitcode ("xch", "a,b");
4668                         emitcode ("cpl", "a"); // msb
4669                         emitcode ("addc", "a,#0");
4670                         emitcode ("setb","F0");
4671                         emitcode ("","!tlabeldef",lbl->key+100);
4672                         emitcode ("mov","mb,b");
4673                         emitcode ("mov","mb,a");
4674                 }
4675         } else {
4676                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4677                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4678         }
4679         /* load up MA with left */
4680         if (!umult) {
4681                 lbl = newiTempLabel(NULL);
4682                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4683                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4684                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4685                 emitcode ("xch", "a,b");
4686                 emitcode ("cpl","a");
4687                 emitcode ("add", "a,#1");
4688                 emitcode ("xch", "a,b");
4689                 emitcode ("cpl", "a"); // msb
4690                 emitcode ("addc","a,#0");
4691                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4692                 emitcode ("setb","F0");
4693                 emitcode ("","!tlabeldef",lbl->key+100);
4694                 emitcode ("mov","ma,b");
4695                 emitcode ("mov","ma,a");
4696         } else {
4697                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4698                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4699         }
4700         /* wait for multiplication to finish */
4701         lbl = newiTempLabel(NULL);
4702         emitcode("","!tlabeldef", lbl->key+100);
4703         emitcode("mov","a,mcnt1");
4704         emitcode("anl","a,#!constbyte",0x80);
4705         emitcode("jnz","!tlabel",lbl->key+100);
4706         
4707         freeAsmop (left, NULL, ic, TRUE);
4708         freeAsmop (right, NULL, ic,TRUE);
4709         aopOp(result, ic, TRUE, FALSE);
4710
4711         /* if unsigned then simple */   
4712         if (umult) {
4713                 emitcode ("mov","a,ma");
4714                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4715                 emitcode ("mov","a,ma");
4716                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4717                 aopPut(AOP(result),"ma",1);
4718                 aopPut(AOP(result),"ma",0);
4719         } else {
4720                 emitcode("push","ma");
4721                 emitcode("push","ma");
4722                 emitcode("push","ma");
4723                 MOVA("ma");
4724                 /* negate result if needed */
4725                 lbl = newiTempLabel(NULL);      
4726                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4727                 emitcode("cpl","a");
4728                 emitcode("add","a,#1");
4729                 emitcode("","!tlabeldef", lbl->key+100);
4730                 if (AOP_TYPE(result) == AOP_ACC)
4731                 {
4732                     D(emitcode(";", "ACC special case."););
4733                     /* We know result is the only live aop, and 
4734                      * it's obviously not a DPTR2, so AP is available.
4735                      */
4736                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4737                 }
4738                 else
4739                 {
4740                     aopPut(AOP(result),"a",0);
4741                 }
4742             
4743                 emitcode("pop","acc");
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",1);
4750                 emitcode("pop","acc");
4751                 if (AOP_SIZE(result) >= 3) {
4752                         lbl = newiTempLabel(NULL);      
4753                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4754                         emitcode("cpl","a");
4755                         emitcode("addc","a,#0");                        
4756                         emitcode("","!tlabeldef", lbl->key+100);
4757                         aopPut(AOP(result),"a",2);
4758                 }
4759                 emitcode("pop","acc");
4760                 if (AOP_SIZE(result) >= 4) {
4761                         lbl = newiTempLabel(NULL);      
4762                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4763                         emitcode("cpl","a");
4764                         emitcode("addc","a,#0");                        
4765                         emitcode("","!tlabeldef", lbl->key+100);
4766                         aopPut(AOP(result),"a",3);
4767                 }
4768                 if (AOP_TYPE(result) == AOP_ACC)
4769                 {
4770                     /* We stashed the result away above. */
4771                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4772                 }           
4773                 
4774         }
4775         freeAsmop (result, NULL, ic, TRUE);
4776
4777         /* restore EA bit in F1 */
4778         lbl = newiTempLabel(NULL);
4779         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4780         emitcode ("setb","EA");
4781         emitcode("","!tlabeldef",lbl->key+100);
4782         return ;
4783 }
4784
4785 /*-----------------------------------------------------------------*/
4786 /* genMult - generates code for multiplication                     */
4787 /*-----------------------------------------------------------------*/
4788 static void
4789 genMult (iCode * ic)
4790 {
4791   operand *left = IC_LEFT (ic);
4792   operand *right = IC_RIGHT (ic);
4793   operand *result = IC_RESULT (ic);
4794
4795   D (emitcode (";", "genMult "););
4796
4797   /* assign the amsops */
4798   AOP_OP_2 (ic);
4799
4800   /* special cases first */
4801   /* both are bits */
4802   if (AOP_TYPE (left) == AOP_CRY &&
4803       AOP_TYPE (right) == AOP_CRY)
4804     {
4805       genMultbits (left, right, result, ic);
4806       goto release;
4807     }
4808
4809   /* if both are of size == 1 */
4810   if (AOP_SIZE (left) == 1 &&
4811       AOP_SIZE (right) == 1)
4812     {
4813       genMultOneByte (left, right, result, ic);
4814       goto release;
4815     }
4816
4817   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4818           /* use the ds390 ARITHMETIC accel UNIT */
4819           genMultTwoByte (left, right, result, ic);
4820           return ;
4821   }
4822   /* should have been converted to function call */
4823   assert (0);
4824
4825 release:
4826   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4827   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828   freeAsmop (result, NULL, ic, TRUE);
4829 }
4830
4831 /*-----------------------------------------------------------------*/
4832 /* genDivbits :- division of bits                                  */
4833 /*-----------------------------------------------------------------*/
4834 static void
4835 genDivbits (operand * left,
4836             operand * right,
4837             operand * result,
4838             iCode   * ic)
4839 {
4840
4841   char *l;
4842
4843   /* the result must be bit */
4844   LOAD_AB_FOR_DIV (left, right, l);
4845   emitcode ("div", "ab");
4846   emitcode ("rrc", "a");
4847   aopOp(result, ic, TRUE, FALSE);
4848     
4849   aopPut (AOP (result), "c", 0);
4850 }
4851
4852 /*-----------------------------------------------------------------*/
4853 /* genDivOneByte : 8 bit division                                  */
4854 /*-----------------------------------------------------------------*/
4855 static void
4856 genDivOneByte (operand * left,
4857                operand * right,
4858                operand * result,
4859                iCode   * ic)
4860 {
4861   sym_link *opetype = operandType (result);
4862   char *l;
4863   symbol *lbl;
4864   int size, offset;
4865
4866   offset = 1;
4867   /* signed or unsigned */
4868   if (SPEC_USIGN (opetype))
4869     {
4870         /* unsigned is easy */
4871         LOAD_AB_FOR_DIV (left, right, l);
4872         emitcode ("div", "ab");
4873
4874         _G.accInUse++;
4875         aopOp(result, ic, TRUE, FALSE);
4876         aopPut (AOP (result), "a", 0);
4877         _G.accInUse--;
4878
4879         size = AOP_SIZE (result) - 1;
4880         
4881         while (size--)
4882         {
4883             aopPut (AOP (result), zero, offset++);
4884         }
4885       return;
4886     }
4887
4888   /* signed is a little bit more difficult */
4889
4890   /* save the signs of the operands */
4891   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4892   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4893   emitcode ("push", "acc");     /* save it on the stack */
4894
4895   /* now sign adjust for both left & right */
4896   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4897   lbl = newiTempLabel (NULL);
4898   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4899   emitcode ("cpl", "a");
4900   emitcode ("inc", "a");
4901   emitcode ("", "!tlabeldef", (lbl->key + 100));
4902   emitcode ("mov", "b,a");
4903
4904   /* sign adjust left side */
4905   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4906
4907   lbl = newiTempLabel (NULL);
4908   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4909   emitcode ("cpl", "a");
4910   emitcode ("inc", "a");
4911   emitcode ("", "!tlabeldef", (lbl->key + 100));
4912
4913   /* now the division */
4914   emitcode ("nop", "; workaround for DS80C390 div bug.");
4915   emitcode ("div", "ab");
4916   /* we are interested in the lower order
4917      only */
4918   emitcode ("mov", "b,a");
4919   lbl = newiTempLabel (NULL);
4920   emitcode ("pop", "acc");
4921   /* if there was an over flow we don't
4922      adjust the sign of the result */
4923   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4924   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4925   CLRC;
4926   emitcode ("clr", "a");
4927   emitcode ("subb", "a,b");
4928   emitcode ("mov", "b,a");
4929   emitcode ("", "!tlabeldef", (lbl->key + 100));
4930
4931   /* now we are done */
4932   _G.accInUse++;     _G.bInUse++;
4933     aopOp(result, ic, TRUE, FALSE);
4934     
4935     aopPut (AOP (result), "b", 0);
4936     
4937     size = AOP_SIZE (result) - 1;
4938     
4939     if (size > 0)
4940     {
4941       emitcode ("mov", "c,b.7");
4942       emitcode ("subb", "a,acc");
4943     }
4944     while (size--)
4945     {
4946         aopPut (AOP (result), "a", offset++);
4947     }
4948     _G.accInUse--;     _G.bInUse--;
4949
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4954 /*-----------------------------------------------------------------*/
4955 static void genDivTwoByte (operand *left, operand *right, 
4956                             operand *result, iCode *ic)
4957 {
4958         sym_link *retype = getSpec(operandType(right));
4959         sym_link *letype = getSpec(operandType(left));
4960         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4961         symbol *lbl;
4962
4963         /* save EA bit in F1 */
4964         lbl = newiTempLabel(NULL);
4965         emitcode ("setb","F1");
4966         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4967         emitcode ("clr","F1");
4968         emitcode("","!tlabeldef",lbl->key+100);
4969
4970         /* load up MA with left */
4971         if (!umult) {
4972                 emitcode("clr","F0");
4973                 lbl = newiTempLabel(NULL);
4974                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4975                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4976                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4977                 emitcode ("xch", "a,b");
4978                 emitcode ("cpl","a");
4979                 emitcode ("add", "a,#1");
4980                 emitcode ("xch", "a,b");
4981                 emitcode ("cpl", "a"); // msb
4982                 emitcode ("addc","a,#0");
4983                 emitcode ("setb","F0");
4984                 emitcode ("","!tlabeldef",lbl->key+100);
4985                 emitcode ("mov","ma,b");
4986                 emitcode ("mov","ma,a");
4987         } else {
4988                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4989                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4990         }
4991
4992         /* load up MB with right */
4993         if (!umult) {
4994                 if (AOP_TYPE(right) == AOP_LIT) {
4995                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4996                         if (val < 0) {
4997                                 lbl = newiTempLabel(NULL);
4998                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4999                                 emitcode("setb","F0");
5000                                 emitcode ("","!tlabeldef",lbl->key+100);
5001                                 val = -val;
5002                         } 
5003                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5004                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5005                 } else {
5006                         lbl = newiTempLabel(NULL);
5007                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5008                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5009                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5010                         emitcode ("xch", "a,b");
5011                         emitcode ("cpl","a");
5012                         emitcode ("add", "a,#1");
5013                         emitcode ("xch", "a,b");
5014                         emitcode ("cpl", "a"); // msb
5015                         emitcode ("addc", "a,#0");
5016                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017                         emitcode ("setb","F0");
5018                         emitcode ("","!tlabeldef",lbl->key+100);
5019                         emitcode ("mov","mb,b");
5020                         emitcode ("mov","mb,a");
5021                 }
5022         } else {
5023                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5024                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5025         }
5026
5027         /* wait for multiplication to finish */
5028         lbl = newiTempLabel(NULL);
5029         emitcode("","!tlabeldef", lbl->key+100);
5030         emitcode("mov","a,mcnt1");
5031         emitcode("anl","a,#!constbyte",0x80);
5032         emitcode("jnz","!tlabel",lbl->key+100);
5033         
5034         freeAsmop (left, NULL, ic, TRUE);
5035         freeAsmop (right, NULL, ic,TRUE);
5036         aopOp(result, ic, TRUE, FALSE);
5037
5038         /* if unsigned then simple */   
5039         if (umult) {
5040                 aopPut(AOP(result),"ma",1);
5041                 aopPut(AOP(result),"ma",0);
5042         } else {
5043                 emitcode("push","ma");
5044                 MOVA("ma");
5045                 /* negate result if needed */
5046                 lbl = newiTempLabel(NULL);      
5047                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5048                 emitcode("cpl","a");
5049                 emitcode("add","a,#1");
5050                 emitcode("","!tlabeldef", lbl->key+100);
5051                 aopPut(AOP(result),"a",0);
5052                 emitcode("pop","acc");
5053                 lbl = newiTempLabel(NULL);      
5054                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5055                 emitcode("cpl","a");
5056                 emitcode("addc","a,#0");
5057                 emitcode("","!tlabeldef", lbl->key+100);
5058                 aopPut(AOP(result),"a",1);
5059         }
5060         freeAsmop (result, NULL, ic, TRUE);
5061         /* restore EA bit in F1 */
5062         lbl = newiTempLabel(NULL);
5063         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5064         emitcode ("setb","EA");
5065         emitcode("","!tlabeldef",lbl->key+100);
5066         return ;
5067 }
5068
5069 /*-----------------------------------------------------------------*/
5070 /* genDiv - generates code for division                            */
5071 /*-----------------------------------------------------------------*/
5072 static void
5073 genDiv (iCode * ic)
5074 {
5075   operand *left = IC_LEFT (ic);
5076   operand *right = IC_RIGHT (ic);
5077   operand *result = IC_RESULT (ic);
5078
5079   D (emitcode (";", "genDiv "););
5080
5081   /* assign the amsops */
5082   AOP_OP_2 (ic);
5083
5084   /* special cases first */
5085   /* both are bits */
5086   if (AOP_TYPE (left) == AOP_CRY &&
5087       AOP_TYPE (right) == AOP_CRY)
5088     {
5089       genDivbits (left, right, result, ic);
5090       goto release;
5091     }
5092
5093   /* if both are of size == 1 */
5094   if (AOP_SIZE (left) == 1 &&
5095       AOP_SIZE (right) == 1)
5096     {
5097       genDivOneByte (left, right, result, ic);
5098       goto release;
5099     }
5100
5101   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5102           /* use the ds390 ARITHMETIC accel UNIT */
5103           genDivTwoByte (left, right, result, ic);
5104           return ;
5105   }
5106   /* should have been converted to function call */
5107   assert (0);
5108 release:
5109   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5110   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5111   freeAsmop (result, NULL, ic, TRUE);
5112 }
5113
5114 /*-----------------------------------------------------------------*/
5115 /* genModbits :- modulus of bits                                   */
5116 /*-----------------------------------------------------------------*/
5117 static void
5118 genModbits (operand * left,
5119             operand * right,
5120             operand * result,
5121             iCode   * ic)
5122 {
5123
5124   char *l;
5125
5126   /* the result must be bit */
5127   LOAD_AB_FOR_DIV (left, right, l);
5128   emitcode ("div", "ab");
5129   emitcode ("mov", "a,b");
5130   emitcode ("rrc", "a");
5131   aopOp(result, ic, TRUE, FALSE);
5132   aopPut (AOP (result), "c", 0);
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* genModOneByte : 8 bit modulus                                   */
5137 /*-----------------------------------------------------------------*/
5138 static void
5139 genModOneByte (operand * left,
5140                operand * right,
5141                operand * result,
5142                iCode   * ic)
5143 {
5144   sym_link *opetype = operandType (result);
5145   char *l;
5146   symbol *lbl;
5147
5148   /* signed or unsigned */
5149   if (SPEC_USIGN (opetype))
5150     {
5151       /* unsigned is easy */
5152       LOAD_AB_FOR_DIV (left, right, l);
5153       emitcode ("div", "ab");
5154       aopOp(result, ic, TRUE, FALSE);   
5155       aopPut (AOP (result), "b", 0);
5156       return;
5157     }
5158
5159   /* signed is a little bit more difficult */
5160
5161   /* save the signs of the operands */
5162   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5163
5164   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5165   emitcode ("push", "acc");     /* save it on the stack */
5166
5167   /* now sign adjust for both left & right */
5168   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5169
5170   lbl = newiTempLabel (NULL);
5171   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5172   emitcode ("cpl", "a");
5173   emitcode ("inc", "a");
5174   emitcode ("", "!tlabeldef", (lbl->key + 100));
5175   emitcode ("mov", "b,a");
5176
5177   /* sign adjust left side */
5178   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5179
5180   lbl = newiTempLabel (NULL);
5181   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5182   emitcode ("cpl", "a");
5183   emitcode ("inc", "a");
5184   emitcode ("", "!tlabeldef", (lbl->key + 100));
5185
5186   /* now the multiplication */
5187   emitcode ("nop", "; workaround for DS80C390 div bug.");
5188   emitcode ("div", "ab");
5189   /* we are interested in the lower order
5190      only */
5191   lbl = newiTempLabel (NULL);
5192   emitcode ("pop", "acc");
5193   /* if there was an over flow we don't
5194      adjust the sign of the result */
5195   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5196   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5197   CLRC;
5198   emitcode ("clr", "a");
5199   emitcode ("subb", "a,b");
5200   emitcode ("mov", "b,a");
5201   emitcode ("", "!tlabeldef", (lbl->key + 100));
5202   
5203   _G.bInUse++;
5204   /* now we are done */
5205   aopOp(result, ic, TRUE, FALSE);    
5206   aopPut (AOP (result), "b", 0);
5207   _G.bInUse--;
5208
5209 }
5210
5211 /*-----------------------------------------------------------------*/
5212 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5213 /*-----------------------------------------------------------------*/
5214 static void genModTwoByte (operand *left, operand *right, 
5215                             operand *result, iCode *ic)
5216 {
5217         sym_link *retype = getSpec(operandType(right));
5218         sym_link *letype = getSpec(operandType(left));
5219         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5220         symbol *lbl;
5221
5222         /* load up MA with left */
5223         /* save EA bit in F1 */
5224         lbl = newiTempLabel(NULL);
5225         emitcode ("setb","F1");
5226         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5227         emitcode ("clr","F1");
5228         emitcode("","!tlabeldef",lbl->key+100);
5229
5230         if (!umult) {
5231                 lbl = newiTempLabel(NULL);
5232                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5233                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5234                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5235                 emitcode ("xch", "a,b");
5236                 emitcode ("cpl","a");
5237                 emitcode ("add", "a,#1");
5238                 emitcode ("xch", "a,b");
5239                 emitcode ("cpl", "a"); // msb
5240                 emitcode ("addc","a,#0");
5241                 emitcode ("","!tlabeldef",lbl->key+100);
5242                 emitcode ("mov","ma,b");
5243                 emitcode ("mov","ma,a");
5244         } else {
5245                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5246                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5247         }
5248
5249         /* load up MB with right */
5250         if (!umult) {
5251                 if (AOP_TYPE(right) == AOP_LIT) {
5252                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5253                         if (val < 0) {
5254                                 val = -val;
5255                         } 
5256                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5257                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5258                 } else {
5259                         lbl = newiTempLabel(NULL);
5260                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5261                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5262                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5263                         emitcode ("xch", "a,b");
5264                         emitcode ("cpl","a");
5265                         emitcode ("add", "a,#1");
5266                         emitcode ("xch", "a,b");
5267                         emitcode ("cpl", "a"); // msb
5268                         emitcode ("addc", "a,#0");
5269                         emitcode ("","!tlabeldef",lbl->key+100);
5270                         emitcode ("mov","mb,b");
5271                         emitcode ("mov","mb,a");
5272                 }
5273         } else {
5274                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5275                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5276         }
5277
5278         /* wait for multiplication to finish */
5279         lbl = newiTempLabel(NULL);
5280         emitcode("","!tlabeldef", lbl->key+100);
5281         emitcode("mov","a,mcnt1");
5282         emitcode("anl","a,#!constbyte",0x80);
5283         emitcode("jnz","!tlabel",lbl->key+100);
5284         
5285         freeAsmop (left, NULL, ic, TRUE);
5286         freeAsmop (right, NULL, ic,TRUE);
5287         aopOp(result, ic, TRUE, FALSE);
5288
5289         aopPut(AOP(result),"mb",1);
5290         aopPut(AOP(result),"mb",0);
5291         freeAsmop (result, NULL, ic, TRUE);
5292
5293         /* restore EA bit in F1 */
5294         lbl = newiTempLabel(NULL);
5295         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5296         emitcode ("setb","EA");
5297         emitcode("","!tlabeldef",lbl->key+100);
5298         return ;
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* genMod - generates code for division                            */
5303 /*-----------------------------------------------------------------*/
5304 static void
5305 genMod (iCode * ic)
5306 {
5307   operand *left = IC_LEFT (ic);
5308   operand *right = IC_RIGHT (ic);
5309   operand *result = IC_RESULT (ic);
5310
5311   D (emitcode (";", "genMod "); );
5312
5313   /* assign the amsops */
5314   AOP_OP_2 (ic);
5315
5316   /* special cases first */
5317   /* both are bits */
5318   if (AOP_TYPE (left) == AOP_CRY &&
5319       AOP_TYPE (right) == AOP_CRY)
5320     {
5321       genModbits (left, right, result, ic);
5322       goto release;
5323     }
5324
5325   /* if both are of size == 1 */
5326   if (AOP_SIZE (left) == 1 &&
5327       AOP_SIZE (right) == 1)
5328     {
5329       genModOneByte (left, right, result, ic);
5330       goto release;
5331     }
5332
5333   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5334           /* use the ds390 ARITHMETIC accel UNIT */
5335           genModTwoByte (left, right, result, ic);
5336           return ;
5337   }
5338
5339   /* should have been converted to function call */
5340   assert (0);
5341
5342 release:
5343   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5344   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5345   freeAsmop (result, NULL, ic, TRUE);
5346 }
5347
5348 /*-----------------------------------------------------------------*/
5349 /* genIfxJump :- will create a jump depending on the ifx           */
5350 /*-----------------------------------------------------------------*/
5351 static void
5352 genIfxJump (iCode * ic, char *jval)
5353 {
5354   symbol *jlbl;
5355   symbol *tlbl = newiTempLabel (NULL);
5356   char *inst;
5357
5358   D (emitcode (";", "genIfxJump"););
5359
5360   /* if true label then we jump if condition
5361      supplied is true */
5362   if (IC_TRUE (ic))
5363     {
5364       jlbl = IC_TRUE (ic);
5365       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5366                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5367     }
5368   else
5369     {
5370       /* false label is present */
5371       jlbl = IC_FALSE (ic);
5372       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5373                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5374     }
5375   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5376     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5377   else
5378     emitcode (inst, "!tlabel", tlbl->key + 100);
5379   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5380   emitcode ("", "!tlabeldef", tlbl->key + 100);
5381
5382   /* mark the icode as generated */
5383   ic->generated = 1;
5384 }
5385
5386 /*-----------------------------------------------------------------*/
5387 /* genCmp :- greater or less than comparison                       */
5388 /*-----------------------------------------------------------------*/
5389 static void
5390 genCmp (operand * left, operand * right,
5391         iCode * ic, iCode * ifx, int sign)
5392 {
5393   int size, offset = 0;
5394   unsigned long lit = 0L;
5395   operand *result;
5396
5397   D (emitcode (";", "genCmp"););
5398
5399   result = IC_RESULT (ic);
5400
5401   /* if left & right are bit variables */
5402   if (AOP_TYPE (left) == AOP_CRY &&
5403       AOP_TYPE (right) == AOP_CRY)
5404     {
5405       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5406       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5407     }
5408   else
5409     {
5410       /* subtract right from left if at the
5411          end the carry flag is set then we know that
5412          left is greater than right */
5413       size = max (AOP_SIZE (left), AOP_SIZE (right));
5414
5415       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5416       if ((size == 1) && !sign 
5417           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5418         {
5419           symbol *lbl = newiTempLabel (NULL);
5420           emitcode ("cjne", "%s,%s,!tlabel",
5421                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5422                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5423                     lbl->key + 100);
5424           emitcode ("", "!tlabeldef", lbl->key + 100);
5425         }
5426       else
5427         {
5428           if (AOP_TYPE (right) == AOP_LIT)
5429             {
5430               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5431               /* optimize if(x < 0) or if(x >= 0) */
5432               if (lit == 0L)
5433                 {
5434                   if (!sign)
5435                     {
5436                       CLRC;
5437                     }
5438                   else
5439                     {
5440                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5441
5442                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5443                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5444
5445                       aopOp (result, ic, FALSE, FALSE);
5446
5447                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5448                         {
5449                           freeAsmop (result, NULL, ic, TRUE);
5450                           genIfxJump (ifx, "acc.7");
5451                           return;
5452                         }
5453                       else
5454                         {
5455                           emitcode ("rlc", "a");
5456                         }
5457                       goto release_freedLR;
5458                     }
5459                   goto release;
5460                 }
5461             }
5462           CLRC;
5463           while (size--)
5464             {
5465               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5466               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5467               // emitcode (";", "genCmp #2");
5468               if (sign && (size == 0))
5469                 {
5470                   // emitcode (";", "genCmp #3");
5471                   emitcode ("xrl", "a,#!constbyte",0x80);
5472                   if (AOP_TYPE (right) == AOP_LIT)
5473                     {
5474                       unsigned long lit = (unsigned long)
5475                       floatFromVal (AOP (right)->aopu.aop_lit);
5476                       // emitcode (";", "genCmp #3.1");
5477                       emitcode ("subb", "a,#!constbyte",
5478                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5479                     }
5480                   else
5481                     {
5482                       // emitcode (";", "genCmp #3.2");
5483                       saveAccWarn = 0;  
5484                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5485                       saveAccWarn = DEFAULT_ACC_WARNING;
5486                       emitcode ("xrl", "b,#!constbyte",0x80);
5487                       emitcode ("subb", "a,b");
5488                     }
5489                 }
5490               else
5491                 {
5492                   const char *s;
5493
5494                   // emitcode (";", "genCmp #4");
5495                   saveAccWarn = 0;
5496                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5497                   saveAccWarn = DEFAULT_ACC_WARNING;
5498
5499                   emitcode ("subb", "a,%s", s);
5500                 }
5501             }
5502         }
5503     }
5504
5505 release:
5506 /* Don't need the left & right operands any more; do need the result. */
5507   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5509
5510   aopOp (result, ic, FALSE, FALSE);
5511
5512 release_freedLR:
5513
5514   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5515     {
5516       outBitC (result);
5517     }
5518   else
5519     {
5520       /* if the result is used in the next
5521          ifx conditional branch then generate
5522          code a little differently */
5523       if (ifx)
5524         {
5525           genIfxJump (ifx, "c");
5526         }
5527       else
5528         {
5529           outBitC (result);
5530         }
5531       /* leave the result in acc */
5532     }
5533   freeAsmop (result, NULL, ic, TRUE);
5534 }
5535
5536 /*-----------------------------------------------------------------*/
5537 /* genCmpGt :- greater than comparison                             */
5538 /*-----------------------------------------------------------------*/
5539 static void
5540 genCmpGt (iCode * ic, iCode * ifx)
5541 {
5542   operand *left, *right;
5543   sym_link *letype, *retype;
5544   int sign;
5545
5546   D (emitcode (";", "genCmpGt ");
5547     );
5548
5549   left = IC_LEFT (ic);
5550   right = IC_RIGHT (ic);
5551
5552   letype = getSpec (operandType (left));
5553   retype = getSpec (operandType (right));
5554   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5555
5556   /* assign the left & right amsops */
5557   AOP_OP_2 (ic);
5558
5559   genCmp (right, left, ic, ifx, sign);
5560 }
5561
5562 /*-----------------------------------------------------------------*/
5563 /* genCmpLt - less than comparisons                                */
5564 /*-----------------------------------------------------------------*/
5565 static void
5566 genCmpLt (iCode * ic, iCode * ifx)
5567 {
5568   operand *left, *right;
5569   sym_link *letype, *retype;
5570   int sign;
5571
5572   D (emitcode (";", "genCmpLt "););
5573
5574   left = IC_LEFT (ic);
5575   right = IC_RIGHT (ic);
5576
5577   letype = getSpec (operandType (left));
5578   retype = getSpec (operandType (right));
5579   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5580
5581   /* assign the left & right amsops */
5582   AOP_OP_2 (ic);
5583
5584   genCmp (left, right, ic, ifx, sign);
5585 }
5586
5587 /*-----------------------------------------------------------------*/
5588 /* gencjneshort - compare and jump if not equal                    */
5589 /*-----------------------------------------------------------------*/
5590 static void
5591 gencjneshort (operand * left, operand * right, symbol * lbl)
5592 {
5593   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5594   int offset = 0;
5595   unsigned long lit = 0L;
5596
5597   D (emitcode (";", "gencjneshort");
5598     );
5599
5600   /* if the left side is a literal or
5601      if the right is in a pointer register and left
5602      is not */
5603   if ((AOP_TYPE (left) == AOP_LIT) ||
5604       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5605     {
5606       operand *t = right;
5607       right = left;
5608       left = t;
5609     }
5610
5611   if (AOP_TYPE (right) == AOP_LIT)
5612     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5613
5614   if (opIsGptr (left) || opIsGptr (right))
5615     {
5616       /* We are comparing a generic pointer to something.
5617        * Exclude the generic type byte from the comparison.
5618        */
5619       size--;
5620       D (emitcode (";", "cjneshort: generic ptr special case."););
5621     }
5622
5623
5624   /* if the right side is a literal then anything goes */
5625   if (AOP_TYPE (right) == AOP_LIT &&
5626       AOP_TYPE (left) != AOP_DIR)
5627     {
5628       while (size--)
5629         {
5630           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5631           emitcode ("cjne", "a,%s,!tlabel",
5632                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5633                     lbl->key + 100);
5634           offset++;
5635         }
5636     }
5637
5638   /* if the right side is in a register or in direct space or
5639      if the left is a pointer register & right is not */
5640   else if (AOP_TYPE (right) == AOP_REG ||
5641            AOP_TYPE (right) == AOP_DIR ||
5642            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5643            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5644     {
5645       while (size--)
5646         {
5647           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5648           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5649               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5650             emitcode ("jnz", "!tlabel", lbl->key + 100);
5651           else
5652             emitcode ("cjne", "a,%s,!tlabel",
5653                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5654                       lbl->key + 100);
5655           offset++;
5656         }
5657     }
5658   else
5659     {
5660       /* right is a pointer reg need both a & b */
5661       while (size--)
5662         {
5663           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5664           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5665           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5666           offset++;
5667         }
5668     }
5669 }
5670
5671 /*-----------------------------------------------------------------*/
5672 /* gencjne - compare and jump if not equal                         */
5673 /*-----------------------------------------------------------------*/
5674 static void
5675 gencjne (operand * left, operand * right, symbol * lbl)
5676 {
5677   symbol *tlbl = newiTempLabel (NULL);
5678
5679   D (emitcode (";", "gencjne");
5680     );
5681
5682   gencjneshort (left, right, lbl);
5683
5684   emitcode ("mov", "a,%s", one);
5685   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5686   emitcode ("", "!tlabeldef", lbl->key + 100);
5687   emitcode ("clr", "a");
5688   emitcode ("", "!tlabeldef", tlbl->key + 100);
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* genCmpEq - generates code for equal to                          */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 genCmpEq (iCode * ic, iCode * ifx)
5696 {
5697   operand *left, *right, *result;
5698
5699   D (emitcode (";", "genCmpEq ");
5700     );
5701
5702   AOP_OP_2 (ic);
5703   AOP_SET_LOCALS (ic);
5704
5705   /* if literal, literal on the right or
5706      if the right is in a pointer register and left
5707      is not */
5708   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5709       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5710     {
5711       operand *t = IC_RIGHT (ic);
5712       IC_RIGHT (ic) = IC_LEFT (ic);
5713       IC_LEFT (ic) = t;
5714     }
5715
5716   if (ifx &&                    /* !AOP_SIZE(result) */
5717       OP_SYMBOL (result) &&
5718       OP_SYMBOL (result)->regType == REG_CND)
5719     {
5720       symbol *tlbl;
5721       /* if they are both bit variables */
5722       if (AOP_TYPE (left) == AOP_CRY &&
5723           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5724         {
5725           if (AOP_TYPE (right) == AOP_LIT)
5726             {
5727               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5728               if (lit == 0L)
5729                 {
5730                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5731                   emitcode ("cpl", "c");
5732                 }
5733               else if (lit == 1L)
5734                 {
5735                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5736                 }
5737               else
5738                 {
5739                   emitcode ("clr", "c");
5740                 }
5741               /* AOP_TYPE(right) == AOP_CRY */
5742             }
5743           else
5744             {
5745               symbol *lbl = newiTempLabel (NULL);
5746               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5747               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5748               emitcode ("cpl", "c");
5749               emitcode ("", "!tlabeldef", (lbl->key + 100));
5750             }
5751           /* if true label then we jump if condition
5752              supplied is true */
5753           tlbl = newiTempLabel (NULL);
5754           if (IC_TRUE (ifx))
5755             {
5756               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5757               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5758             }
5759           else
5760             {
5761               emitcode ("jc", "!tlabel", tlbl->key + 100);
5762               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5763             }
5764           emitcode ("", "!tlabeldef", tlbl->key + 100);
5765         }
5766       else
5767         {
5768           tlbl = newiTempLabel (NULL);
5769           gencjneshort (left, right, tlbl);
5770           if (IC_TRUE (ifx))
5771             {
5772               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5773               emitcode ("", "!tlabeldef", tlbl->key + 100);
5774             }
5775           else
5776             {
5777               symbol *lbl = newiTempLabel (NULL);
5778               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5779               emitcode ("", "!tlabeldef", tlbl->key + 100);
5780               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5781               emitcode ("", "!tlabeldef", lbl->key + 100);
5782             }
5783         }
5784       /* mark the icode as generated */
5785       ifx->generated = 1;
5786
5787       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5788       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5789       return;
5790     }
5791
5792   /* if they are both bit variables */
5793   if (AOP_TYPE (left) == AOP_CRY &&
5794       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5795     {
5796       if (AOP_TYPE (right) == AOP_LIT)
5797         {
5798           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5799           if (lit == 0L)
5800             {
5801               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5802               emitcode ("cpl", "c");
5803             }
5804           else if (lit == 1L)
5805             {
5806               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5807             }
5808           else
5809             {
5810               emitcode ("clr", "c");
5811             }
5812           /* AOP_TYPE(right) == AOP_CRY */
5813         }
5814       else
5815         {
5816           symbol *lbl = newiTempLabel (NULL);
5817           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5818           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5819           emitcode ("cpl", "c");
5820           emitcode ("", "!tlabeldef", (lbl->key + 100));
5821         }
5822
5823       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5824       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5825
5826       aopOp (result, ic, TRUE, FALSE);
5827
5828       /* c = 1 if egal */
5829       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5830         {
5831           outBitC (result);
5832           goto release;
5833         }
5834       if (ifx)
5835         {
5836           genIfxJump (ifx, "c");
5837           goto release;
5838         }
5839       /* if the result is used in an arithmetic operation
5840          then put the result in place */
5841       outBitC (result);
5842     }
5843   else
5844     {
5845       gencjne (left, right, newiTempLabel (NULL));
5846
5847       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5849
5850       aopOp (result, ic, TRUE, FALSE);
5851
5852       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5853         {
5854           aopPut (AOP (result), "a", 0);
5855           goto release;
5856         }
5857       if (ifx)
5858         {
5859           genIfxJump (ifx, "a");
5860           goto release;
5861         }
5862       /* if the result is used in an arithmetic operation
5863          then put the result in place */
5864       if (AOP_TYPE (result) != AOP_CRY)
5865         outAcc (result);
5866       /* leave the result in acc */
5867     }
5868
5869 release:
5870   freeAsmop (result, NULL, ic, TRUE);
5871 }
5872
5873 /*-----------------------------------------------------------------*/
5874 /* ifxForOp - returns the icode containing the ifx for operand     */
5875 /*-----------------------------------------------------------------*/
5876 static iCode *
5877 ifxForOp (operand * op, iCode * ic)
5878 {
5879   /* if true symbol then needs to be assigned */
5880   if (IS_TRUE_SYMOP (op))
5881     return NULL;
5882
5883   /* if this has register type condition and
5884      the next instruction is ifx with the same operand
5885      and live to of the operand is upto the ifx only then */
5886   if (ic->next &&
5887       ic->next->op == IFX &&
5888       IC_COND (ic->next)->key == op->key &&
5889       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5890     return ic->next;
5891
5892   return NULL;
5893 }
5894 /*-----------------------------------------------------------------*/
5895 /* hasInc - operand is incremented before any other use            */
5896 /*-----------------------------------------------------------------*/
5897 static iCode *
5898 hasInc (operand *op, iCode *ic, int osize)
5899 {
5900   sym_link *type = operandType(op);
5901   sym_link *retype = getSpec (type);
5902   iCode *lic = ic->next;
5903   int isize ;
5904   
5905   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5906   if (!IS_SYMOP(op)) return NULL;
5907
5908   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5909   if (IS_AGGREGATE(type->next)) return NULL;
5910   if (osize != (isize = getSize(type->next))) return NULL;
5911
5912   while (lic) {
5913       /* if operand of the form op = op + <sizeof *op> */
5914       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5915           isOperandEqual(IC_RESULT(lic),op) && 
5916           isOperandLiteral(IC_RIGHT(lic)) &&
5917           operandLitValue(IC_RIGHT(lic)) == isize) {
5918           return lic;
5919       }
5920       /* if the operand used or deffed */
5921       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5922           return NULL;
5923       }
5924       /* if GOTO or IFX */
5925       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5926       lic = lic->next;
5927   }
5928   return NULL;
5929 }
5930
5931 /*-----------------------------------------------------------------*/
5932 /* genAndOp - for && operation                                     */
5933 /*-----------------------------------------------------------------*/
5934 static void
5935 genAndOp (iCode * ic)
5936 {
5937   operand *left, *right, *result;
5938   symbol *tlbl;
5939
5940   D (emitcode (";", "genAndOp "););
5941
5942   /* note here that && operations that are in an
5943      if statement are taken away by backPatchLabels
5944      only those used in arthmetic operations remain */
5945   AOP_OP_2 (ic);
5946   AOP_SET_LOCALS (ic);
5947
5948   /* if both are bit variables */
5949   if (AOP_TYPE (left) == AOP_CRY &&
5950       AOP_TYPE (right) == AOP_CRY)
5951     {
5952       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5953       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5954       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5956   
5957       aopOp (result,ic,FALSE, FALSE);
5958       outBitC (result);
5959     }
5960   else
5961     {
5962       tlbl = newiTempLabel (NULL);
5963       toBoolean (left);
5964       emitcode ("jz", "!tlabel", tlbl->key + 100);
5965       toBoolean (right);
5966       emitcode ("", "!tlabeldef", tlbl->key + 100);
5967       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5968       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5969   
5970       aopOp (result,ic,FALSE, FALSE);
5971       outBitAcc (result);
5972     }
5973     freeAsmop (result, NULL, ic, TRUE);
5974 }
5975
5976
5977 /*-----------------------------------------------------------------*/
5978 /* genOrOp - for || operation                                      */
5979 /*-----------------------------------------------------------------*/
5980 static void
5981 genOrOp (iCode * ic)
5982 {
5983   operand *left, *right, *result;
5984   symbol *tlbl;
5985
5986   D (emitcode (";", "genOrOp "););
5987
5988   /* note here that || operations that are in an
5989      if statement are taken away by backPatchLabels
5990      only those used in arthmetic operations remain */
5991   AOP_OP_2 (ic);
5992   AOP_SET_LOCALS (ic);
5993
5994   /* if both are bit variables */
5995   if (AOP_TYPE (left) == AOP_CRY &&
5996       AOP_TYPE (right) == AOP_CRY)
5997     {
5998       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5999       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6000       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002   
6003       aopOp (result,ic,FALSE, FALSE);
6004       
6005       outBitC (result);
6006     }
6007   else
6008     {
6009       tlbl = newiTempLabel (NULL);
6010       toBoolean (left);
6011       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6012       toBoolean (right);
6013       emitcode ("", "!tlabeldef", tlbl->key + 100);
6014       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6015       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6016   
6017       aopOp (result,ic,FALSE, FALSE);
6018       
6019       outBitAcc (result);
6020     }
6021
6022   freeAsmop (result, NULL, ic, TRUE);
6023 }
6024
6025 /*-----------------------------------------------------------------*/
6026 /* isLiteralBit - test if lit == 2^n                               */
6027 /*-----------------------------------------------------------------*/
6028 static int
6029 isLiteralBit (unsigned long lit)
6030 {
6031   unsigned long pw[32] =
6032   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6033    0x100L, 0x200L, 0x400L, 0x800L,
6034    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6035    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6036    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6037    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6038    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6039   int idx;
6040
6041   for (idx = 0; idx < 32; idx++)
6042     if (lit == pw[idx])
6043       return idx + 1;
6044   return 0;
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* continueIfTrue -                                                */
6049 /*-----------------------------------------------------------------*/
6050 static void
6051 continueIfTrue (iCode * ic)
6052 {
6053   if (IC_TRUE (ic))
6054     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6055   ic->generated = 1;
6056 }
6057
6058 /*-----------------------------------------------------------------*/
6059 /* jmpIfTrue -                                                     */
6060 /*-----------------------------------------------------------------*/
6061 static void
6062 jumpIfTrue (iCode * ic)
6063 {
6064   if (!IC_TRUE (ic))
6065     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6066   ic->generated = 1;
6067 }
6068
6069 /*-----------------------------------------------------------------*/
6070 /* jmpTrueOrFalse -                                                */
6071 /*-----------------------------------------------------------------*/
6072 static void
6073 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6074 {
6075   // ugly but optimized by peephole
6076   if (IC_TRUE (ic))
6077     {
6078       symbol *nlbl = newiTempLabel (NULL);
6079       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6080       emitcode ("", "!tlabeldef", tlbl->key + 100);
6081       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6082       emitcode ("", "!tlabeldef", nlbl->key + 100);
6083     }
6084   else
6085     {
6086       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6087       emitcode ("", "!tlabeldef", tlbl->key + 100);
6088     }
6089   ic->generated = 1;
6090 }
6091
6092 // Generate code to perform a bit-wise logic operation
6093 // on two operands in far space (assumed to already have been 
6094 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6095 // in far space. This requires pushing the result on the stack
6096 // then popping it into the result.
6097 static void
6098 genFarFarLogicOp(iCode *ic, char *logicOp)
6099 {
6100       int size, resultSize, compSize;
6101       int offset = 0;
6102       
6103       TR_AP("#5");
6104       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6105       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6106                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6107       
6108       _startLazyDPSEvaluation();
6109       for (size = compSize; (size--); offset++)
6110       {
6111           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6112           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6113           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6114           
6115           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6116           emitcode ("push", "acc");
6117       }
6118       _endLazyDPSEvaluation();
6119      
6120       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6121       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6122       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6123      
6124       resultSize = AOP_SIZE(IC_RESULT(ic));
6125
6126       ADJUST_PUSHED_RESULT(compSize, resultSize);
6127
6128       _startLazyDPSEvaluation();
6129       while (compSize--)
6130       {
6131           emitcode ("pop", "acc");
6132           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6133       }
6134       _endLazyDPSEvaluation();
6135       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6136 }
6137
6138
6139 /*-----------------------------------------------------------------*/
6140 /* genAnd  - code for and                                          */
6141 /*-----------------------------------------------------------------*/
6142 static void
6143 genAnd (iCode * ic, iCode * ifx)
6144 {
6145   operand *left, *right, *result;
6146   int size, offset = 0;
6147   unsigned long lit = 0L;
6148   int bytelit;
6149   char buff[10];
6150   bool pushResult;
6151
6152   D (emitcode (";", "genAnd "););
6153
6154   AOP_OP_3_NOFATAL (ic, pushResult);
6155   AOP_SET_LOCALS (ic);
6156
6157   if (pushResult)
6158   {
6159       genFarFarLogicOp(ic, "anl");
6160       return;
6161   }  
6162
6163 #ifdef DEBUG_TYPE
6164   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6165             AOP_TYPE (result),
6166             AOP_TYPE (left), AOP_TYPE (right));
6167   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6168             AOP_SIZE (result),
6169             AOP_SIZE (left), AOP_SIZE (right));
6170 #endif
6171
6172   /* if left is a literal & right is not then exchange them */
6173   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6174 #ifdef LOGIC_OPS_BROKEN      
6175     ||  AOP_NEEDSACC (left)
6176 #endif
6177     )
6178     {
6179       operand *tmp = right;
6180       right = left;
6181       left = tmp;
6182     }
6183
6184   /* if result = right then exchange them */
6185   if (sameRegs (AOP (result), AOP (right)))
6186     {
6187       operand *tmp = right;
6188       right = left;
6189       left = tmp;
6190     }
6191
6192   /* if right is bit then exchange them */
6193   if (AOP_TYPE (right) == AOP_CRY &&
6194       AOP_TYPE (left) != AOP_CRY)
6195     {
6196       operand *tmp = right;
6197       right = left;
6198       left = tmp;
6199     }
6200   if (AOP_TYPE (right) == AOP_LIT)
6201     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6202
6203   size = AOP_SIZE (result);
6204
6205   // if(bit & yy)
6206   // result = bit & yy;
6207   if (AOP_TYPE (left) == AOP_CRY)
6208     {
6209       // c = bit & literal;
6210       if (AOP_TYPE (right) == AOP_LIT)
6211         {
6212           if (lit & 1)
6213             {
6214               if (size && sameRegs (AOP (result), AOP (left)))
6215                 // no change
6216                 goto release;
6217               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6218             }
6219           else
6220             {
6221               // bit(result) = 0;
6222               if (size && (AOP_TYPE (result) == AOP_CRY))
6223                 {
6224                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6225                   goto release;
6226                 }
6227               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6228                 {
6229                   jumpIfTrue (ifx);
6230                   goto release;
6231                 }
6232               emitcode ("clr", "c");
6233             }
6234         }
6235       else
6236         {
6237           if (AOP_TYPE (right) == AOP_CRY)
6238             {
6239               // c = bit & bit;
6240               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6241               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6242             }
6243           else
6244             {
6245               // c = bit & val;
6246               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6247               // c = lsb
6248               emitcode ("rrc", "a");
6249               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6250             }
6251         }
6252       // bit = c
6253       // val = c
6254       if (size)
6255         outBitC (result);
6256       // if(bit & ...)
6257       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6258         genIfxJump (ifx, "c");
6259       goto release;
6260     }
6261
6262   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6263   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6264   if ((AOP_TYPE (right) == AOP_LIT) &&
6265       (AOP_TYPE (result) == AOP_CRY) &&
6266       (AOP_TYPE (left) != AOP_CRY))
6267     {
6268       int posbit = isLiteralBit (lit);
6269       /* left &  2^n */
6270       if (posbit)
6271         {
6272           posbit--;
6273           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6274           // bit = left & 2^n
6275           if (size)
6276             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6277           // if(left &  2^n)
6278           else
6279             {
6280               if (ifx)
6281                 {
6282                   SNPRINTF (buff, sizeof(buff), 
6283                             "acc.%d", posbit & 0x07);
6284                   genIfxJump (ifx, buff);
6285                 }
6286               else 
6287                   {
6288                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6289                   }
6290               goto release;
6291             }
6292         }
6293       else
6294         {
6295           symbol *tlbl = newiTempLabel (NULL);
6296           int sizel = AOP_SIZE (left);
6297           if (size)
6298             emitcode ("setb", "c");
6299           while (sizel--)
6300             {
6301               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6302                 {
6303                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6304                   // byte ==  2^n ?
6305                   if ((posbit = isLiteralBit (bytelit)) != 0)
6306                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6307                   else
6308                     {
6309                       if (bytelit != 0x0FFL)
6310                         emitcode ("anl", "a,%s",
6311                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6312                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6313                     }
6314                 }
6315               offset++;
6316             }
6317           // bit = left & literal
6318           if (size)
6319             {
6320               emitcode ("clr", "c");
6321               emitcode ("", "!tlabeldef", tlbl->key + 100);
6322             }
6323           // if(left & literal)
6324           else
6325             {
6326               if (ifx)
6327                 jmpTrueOrFalse (ifx, tlbl);
6328               goto release;
6329             }
6330         }
6331       outBitC (result);
6332       goto release;
6333     }
6334
6335   /* if left is same as result */
6336   if (sameRegs (AOP (result), AOP (left)))
6337     {
6338       for (; size--; offset++)
6339         {
6340           if (AOP_TYPE (right) == AOP_LIT)
6341             {
6342               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6343                 continue;
6344               else if (bytelit == 0)
6345                 aopPut (AOP (result), zero, offset);
6346               else if (IS_AOP_PREG (result))
6347                 {
6348                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6349                   emitcode ("anl", "a,%s",
6350                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6351                   aopPut (AOP (result), "a", offset);
6352                 }
6353               else
6354                 emitcode ("anl", "%s,%s",
6355                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6356                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6357             }
6358           else
6359             {
6360               if (AOP_TYPE (left) == AOP_ACC)
6361                 emitcode ("anl", "a,%s",
6362                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6363               else
6364                 {
6365                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6366                   if (IS_AOP_PREG (result))
6367                     {
6368                       emitcode ("anl", "a,%s",
6369                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6370                       aopPut (AOP (result), "a", offset);
6371                     }
6372                   else
6373                     emitcode ("anl", "%s,a",
6374                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6375                 }
6376             }
6377         }
6378     }
6379   else
6380     {
6381       // left & result in different registers
6382       if (AOP_TYPE (result) == AOP_CRY)
6383         {
6384           // result = bit
6385           // if(size), result in bit
6386           // if(!size && ifx), conditional oper: if(left & right)
6387           symbol *tlbl = newiTempLabel (NULL);
6388           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6389           if (size)
6390             emitcode ("setb", "c");
6391           while (sizer--)
6392             {
6393               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6394                 emitcode ("anl", "a,%s",
6395                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6396               } else {
6397                 if (AOP_TYPE(left)==AOP_ACC) {
6398                   emitcode("mov", "b,a");
6399                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6400                   emitcode("anl", "a,b");
6401                 }else {
6402                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6403                   emitcode ("anl", "a,%s",
6404                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6405                 }
6406               }
6407               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6408               offset++;
6409             }
6410           if (size)
6411             {
6412               CLRC;
6413               emitcode ("", "!tlabeldef", tlbl->key + 100);
6414               outBitC (result);
6415             }
6416           else if (ifx)
6417             jmpTrueOrFalse (ifx, tlbl);
6418         }
6419       else
6420         {
6421           for (; (size--); offset++)
6422             {
6423               // normal case
6424               // result = left & right
6425               if (AOP_TYPE (right) == AOP_LIT)
6426                 {
6427                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6428                     {
6429                       aopPut (AOP (result),
6430                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6431                               offset);
6432                       continue;
6433                     }
6434                   else if (bytelit == 0)
6435                     {
6436                       aopPut (AOP (result), zero, offset);
6437                       continue;
6438                     }
6439                   D (emitcode (";", "better literal AND."););
6440                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6441                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6442                                                     FALSE, FALSE, DP2_RESULT_REG));
6443
6444                 }
6445               else
6446                 {
6447                   // faster than result <- left, anl result,right
6448                   // and better if result is SFR
6449                   if (AOP_TYPE (left) == AOP_ACC)
6450                     {
6451                       emitcode ("anl", "a,%s", 
6452                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6453                     }
6454                   else
6455                     {
6456                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6457                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6458                       {
6459                           emitcode("mov", "b,a");
6460                           rOp = "b";
6461                       }
6462                         
6463                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6464                       emitcode ("anl", "a,%s", rOp);
6465                     }                   
6466                 }
6467               aopPut (AOP (result), "a", offset);
6468             }
6469         }
6470     }
6471
6472 release:
6473   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6475   freeAsmop (result, NULL, ic, TRUE);
6476 }
6477
6478
6479 /*-----------------------------------------------------------------*/
6480 /* genOr  - code for or                                            */
6481 /*-----------------------------------------------------------------*/
6482 static void
6483 genOr (iCode * ic, iCode * ifx)
6484 {
6485   operand *left, *right, *result;
6486   int size, offset = 0;
6487   unsigned long lit = 0L;
6488   bool     pushResult;
6489
6490   D (emitcode (";", "genOr "););
6491
6492   AOP_OP_3_NOFATAL (ic, pushResult);
6493   AOP_SET_LOCALS (ic);
6494
6495   if (pushResult)
6496   {
6497       genFarFarLogicOp(ic, "orl");
6498       return;
6499   }
6500
6501
6502 #ifdef DEBUG_TYPE
6503   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6504             AOP_TYPE (result),
6505             AOP_TYPE (left), AOP_TYPE (right));
6506   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6507             AOP_SIZE (result),
6508             AOP_SIZE (left), AOP_SIZE (right));
6509 #endif
6510
6511   /* if left is a literal & right is not then exchange them */
6512   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6513 #ifdef LOGIC_OPS_BROKEN
6514    || AOP_NEEDSACC (left) // I think this is a net loss now.
6515 #endif      
6516       )
6517     {
6518       operand *tmp = right;
6519       right = left;
6520       left = tmp;
6521     }
6522
6523   /* if result = right then exchange them */
6524   if (sameRegs (AOP (result), AOP (right)))
6525     {
6526       operand *tmp = right;
6527       right = left;
6528       left = tmp;
6529     }
6530
6531   /* if right is bit then exchange them */
6532   if (AOP_TYPE (right) == AOP_CRY &&
6533       AOP_TYPE (left) != AOP_CRY)
6534     {
6535       operand *tmp = right;
6536       right = left;
6537       left = tmp;
6538     }
6539   if (AOP_TYPE (right) == AOP_LIT)
6540     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6541
6542   size = AOP_SIZE (result);
6543
6544   // if(bit | yy)
6545   // xx = bit | yy;
6546   if (AOP_TYPE (left) == AOP_CRY)
6547     {
6548       if (AOP_TYPE (right) == AOP_LIT)
6549         {
6550           // c = bit & literal;
6551           if (lit)
6552             {
6553               // lit != 0 => result = 1
6554               if (AOP_TYPE (result) == AOP_CRY)
6555                 {
6556                   if (size)
6557                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6558                   else if (ifx)
6559                     continueIfTrue (ifx);
6560                   goto release;
6561                 }
6562               emitcode ("setb", "c");
6563             }
6564           else
6565             {
6566               // lit == 0 => result = left
6567               if (size && sameRegs (AOP (result), AOP (left)))
6568                 goto release;
6569               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6570             }
6571         }
6572       else
6573         {
6574           if (AOP_TYPE (right) == AOP_CRY)
6575             {
6576               // c = bit | bit;
6577               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6578               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6579             }
6580           else
6581             {
6582               // c = bit | val;
6583               symbol *tlbl = newiTempLabel (NULL);
6584               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6585                 emitcode ("setb", "c");
6586               emitcode ("jb", "%s,!tlabel",
6587                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6588               toBoolean (right);
6589               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6590               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6591                 {
6592                   jmpTrueOrFalse (ifx, tlbl);
6593                   goto release;
6594                 }
6595               else
6596                 {
6597                   CLRC;
6598                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6599                 }
6600             }
6601         }
6602       // bit = c
6603       // val = c
6604       if (size)
6605         outBitC (result);
6606       // if(bit | ...)
6607       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6608            genIfxJump (ifx, "c");
6609       goto release;
6610     }
6611
6612   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6613   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6614   if ((AOP_TYPE (right) == AOP_LIT) &&
6615       (AOP_TYPE (result) == AOP_CRY) &&
6616       (AOP_TYPE (left) != AOP_CRY))
6617     {
6618       if (lit)
6619         {
6620           // result = 1
6621           if (size)
6622             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6623           else
6624             continueIfTrue (ifx);
6625           goto release;
6626         }
6627       else
6628         {
6629           // lit = 0, result = boolean(left)
6630           if (size)
6631             emitcode ("setb", "c");
6632           toBoolean (right);
6633           if (size)
6634             {
6635               symbol *tlbl = newiTempLabel (NULL);
6636               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6637               CLRC;
6638               emitcode ("", "!tlabeldef", tlbl->key + 100);
6639             }
6640           else
6641             {
6642               genIfxJump (ifx, "a");
6643               goto release;
6644             }
6645         }
6646       outBitC (result);
6647       goto release;
6648     }
6649
6650   /* if left is same as result */
6651   if (sameRegs (AOP (result), AOP (left)))
6652     {
6653       for (; size--; offset++)
6654         {
6655           if (AOP_TYPE (right) == AOP_LIT)
6656             {
6657               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6658                 {
6659                   continue;
6660                 }
6661               else
6662                 {
6663                   if (IS_AOP_PREG (left))
6664                     {
6665                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6666                       emitcode ("orl", "a,%s",
6667                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6668                       aopPut (AOP (result), "a", offset);
6669                     }
6670                   else
6671                     {
6672                       emitcode ("orl", "%s,%s",
6673                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6674                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6675                     }
6676                 }
6677             }
6678           else
6679             {
6680               if (AOP_TYPE (left) == AOP_ACC)
6681                 {
6682                   emitcode ("orl", "a,%s",
6683                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6684                 }
6685               else
6686                 {
6687                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6688                   if (IS_AOP_PREG (left))
6689                     {
6690                       emitcode ("orl", "a,%s", 
6691                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6692                       aopPut (AOP (result), "a", offset);
6693                     }
6694                   else
6695                     {
6696                       emitcode ("orl", "%s,a",
6697                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6698                     }
6699                 }
6700             }
6701         }
6702     }
6703   else
6704     {
6705       // left & result in different registers
6706       if (AOP_TYPE (result) == AOP_CRY)
6707         {
6708           // result = bit
6709           // if(size), result in bit
6710           // if(!size && ifx), conditional oper: if(left | right)
6711           symbol *tlbl = newiTempLabel (NULL);
6712           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6713           if (size)
6714             emitcode ("setb", "c");
6715           while (sizer--)
6716             {
6717               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6718                 emitcode ("orl", "a,%s",
6719                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6720               } else {
6721                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6722                 emitcode ("orl", "a,%s",
6723                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6724               }
6725               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6726               offset++;
6727             }
6728           if (size)
6729             {
6730               CLRC;
6731               emitcode ("", "!tlabeldef", tlbl->key + 100);
6732               outBitC (result);
6733             }
6734           else if (ifx)
6735             jmpTrueOrFalse (ifx, tlbl);
6736         }
6737       else
6738         {
6739             _startLazyDPSEvaluation();
6740           for (; (size--); offset++)
6741             {
6742               // normal case
6743               // result = left & right
6744               if (AOP_TYPE (right) == AOP_LIT)
6745                 {
6746                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6747                     {
6748                       aopPut (AOP (result),
6749                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6750                               offset);
6751                       continue;
6752                     }
6753                   D (emitcode (";", "better literal OR."););
6754                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6755                   emitcode ("orl", "a, %s",
6756                             aopGet (AOP (right), offset,
6757                                     FALSE, FALSE, DP2_RESULT_REG));
6758
6759                 }
6760               else
6761                 {
6762                   // faster than result <- left, anl result,right
6763                   // and better if result is SFR
6764                   if (AOP_TYPE (left) == AOP_ACC)
6765                     {
6766                       emitcode ("orl", "a,%s",
6767                                 aopGet (AOP (right), offset,
6768                                         FALSE, FALSE, DP2_RESULT_REG));
6769                     }
6770                   else
6771                     {
6772                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6773                         
6774                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6775                       {
6776                           emitcode("mov", "b,a");
6777                           rOp = "b";
6778                       }
6779                         
6780                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6781                       emitcode ("orl", "a,%s", rOp);
6782                     }
6783                 }
6784               aopPut (AOP (result), "a", offset);
6785             }
6786             _endLazyDPSEvaluation();
6787         }
6788     }
6789
6790 release:
6791   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6792   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6793   freeAsmop (result, NULL, ic, TRUE);
6794 }
6795
6796 /*-----------------------------------------------------------------*/
6797 /* genXor - code for xclusive or                                   */
6798 /*-----------------------------------------------------------------*/
6799 static void
6800 genXor (iCode * ic, iCode * ifx)
6801 {
6802   operand *left, *right, *result;
6803   int size, offset = 0;
6804   unsigned long lit = 0L;
6805   bool pushResult;
6806
6807   D (emitcode (";", "genXor "););
6808
6809   AOP_OP_3_NOFATAL (ic, pushResult);
6810   AOP_SET_LOCALS (ic);
6811
6812   if (pushResult)
6813   {
6814       genFarFarLogicOp(ic, "xrl");
6815       return;
6816   }  
6817
6818 #ifdef DEBUG_TYPE
6819   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6820             AOP_TYPE (result),
6821             AOP_TYPE (left), AOP_TYPE (right));
6822   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6823             AOP_SIZE (result),
6824             AOP_SIZE (left), AOP_SIZE (right));
6825 #endif
6826
6827   /* if left is a literal & right is not ||
6828      if left needs acc & right does not */
6829   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6830 #ifdef LOGIC_OPS_BROKEN      
6831       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6832 #endif
6833      )
6834     {
6835       operand *tmp = right;
6836       right = left;
6837       left = tmp;
6838     }
6839
6840   /* if result = right then exchange them */
6841   if (sameRegs (AOP (result), AOP (right)))
6842     {
6843       operand *tmp = right;
6844       right = left;
6845       left = tmp;
6846     }
6847
6848   /* if right is bit then exchange them */
6849   if (AOP_TYPE (right) == AOP_CRY &&
6850       AOP_TYPE (left) != AOP_CRY)
6851     {
6852       operand *tmp = right;
6853       right = left;
6854       left = tmp;
6855     }
6856   if (AOP_TYPE (right) == AOP_LIT)
6857     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6858
6859   size = AOP_SIZE (result);
6860
6861   // if(bit ^ yy)
6862   // xx = bit ^ yy;
6863   if (AOP_TYPE (left) == AOP_CRY)
6864     {
6865       if (AOP_TYPE (right) == AOP_LIT)
6866         {
6867           // c = bit & literal;
6868           if (lit >> 1)
6869             {
6870               // lit>>1  != 0 => result = 1
6871               if (AOP_TYPE (result) == AOP_CRY)
6872                 {
6873                   if (size)
6874                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6875                   else if (ifx)
6876                     continueIfTrue (ifx);
6877                   goto release;
6878                 }
6879               emitcode ("setb", "c");
6880             }
6881           else
6882             {
6883               // lit == (0 or 1)
6884               if (lit == 0)
6885                 {
6886                   // lit == 0, result = left
6887                   if (size && sameRegs (AOP (result), AOP (left)))
6888                     goto release;
6889                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6890                 }
6891               else
6892                 {
6893                   // lit == 1, result = not(left)
6894                   if (size && sameRegs (AOP (result), AOP (left)))
6895                     {
6896                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6897                       goto release;
6898                     }
6899                   else
6900                     {
6901                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6902                       emitcode ("cpl", "c");
6903                     }
6904                 }
6905             }
6906
6907         }
6908       else
6909         {
6910           // right != literal
6911           symbol *tlbl = newiTempLabel (NULL);
6912           if (AOP_TYPE (right) == AOP_CRY)
6913             {
6914               // c = bit ^ bit;
6915               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6916             }
6917           else
6918             {
6919               int sizer = AOP_SIZE (right);
6920               // c = bit ^ val
6921               // if val>>1 != 0, result = 1
6922               emitcode ("setb", "c");
6923               while (sizer)
6924                 {
6925                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6926                   if (sizer == 1)
6927                     // test the msb of the lsb
6928                     emitcode ("anl", "a,#!constbyte",0xfe);
6929                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6930                   sizer--;
6931                 }
6932               // val = (0,1)
6933               emitcode ("rrc", "a");
6934             }
6935           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6936           emitcode ("cpl", "c");
6937           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6938         }
6939       // bit = c
6940       // val = c
6941       if (size)
6942         outBitC (result);
6943       // if(bit | ...)
6944       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6945         genIfxJump (ifx, "c");
6946       goto release;
6947     }
6948
6949   if (sameRegs (AOP (result), AOP (left)))
6950     {
6951       /* if left is same as result */
6952       for (; size--; offset++)
6953         {
6954           if (AOP_TYPE (right) == AOP_LIT)
6955             {
6956               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6957                 continue;
6958               else if (IS_AOP_PREG (left))
6959                 {
6960                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6961                   emitcode ("xrl", "a,%s",
6962                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6963                   aopPut (AOP (result), "a", offset);
6964                 }
6965               else
6966                 emitcode ("xrl", "%s,%s",
6967                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6968                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6969             }
6970           else
6971             {
6972               if (AOP_TYPE (left) == AOP_ACC)
6973                 emitcode ("xrl", "a,%s",
6974                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6975               else
6976                 {
6977                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6978                   if (IS_AOP_PREG (left))
6979                     {
6980                       emitcode ("xrl", "a,%s",
6981                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6982                       aopPut (AOP (result), "a", offset);
6983                     }
6984                   else
6985                     emitcode ("xrl", "%s,a",
6986                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6987                 }
6988             }
6989         }
6990     }
6991   else
6992     {
6993       // left & result in different registers
6994       if (AOP_TYPE (result) == AOP_CRY)
6995         {
6996           // result = bit
6997           // if(size), result in bit
6998           // if(!size && ifx), conditional oper: if(left ^ right)
6999           symbol *tlbl = newiTempLabel (NULL);
7000           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7001                   
7002           if (size)
7003             emitcode ("setb", "c");
7004           while (sizer--)
7005             {
7006               if ((AOP_TYPE (right) == AOP_LIT) &&
7007                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7008                 {
7009                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7010                 }
7011               else
7012                 {
7013                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7014                     emitcode ("xrl", "a,%s",
7015                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7016                   } else {
7017                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7018                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7019                       {
7020                           emitcode("mov", "b,a");
7021                           rOp = "b";
7022                       }
7023                         
7024                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7025                       emitcode ("xrl", "a,%s", rOp);                  
7026                   }
7027                 }
7028               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7029               offset++;
7030             }
7031           if (size)
7032             {
7033               CLRC;
7034               emitcode ("", "!tlabeldef", tlbl->key + 100);
7035               outBitC (result);
7036             }
7037           else if (ifx)
7038             jmpTrueOrFalse (ifx, tlbl);
7039         }
7040       else
7041         {
7042         for (; (size--); offset++)
7043           {
7044             // normal case
7045             // result = left & right
7046             if (AOP_TYPE (right) == AOP_LIT)
7047               {
7048                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7049                   {
7050                     aopPut (AOP (result),
7051                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7052                             offset);
7053                     continue;
7054                   }
7055                 D (emitcode (";", "better literal XOR."););
7056                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7057                 emitcode ("xrl", "a, %s",
7058                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7059               }
7060             else
7061               {
7062                 // faster than result <- left, anl result,right
7063                 // and better if result is SFR
7064                 if (AOP_TYPE (left) == AOP_ACC)
7065                   {
7066                     emitcode ("xrl", "a,%s",
7067                               aopGet (AOP (right), offset,
7068                                       FALSE, FALSE, DP2_RESULT_REG));
7069                   }
7070                 else
7071                   {
7072                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7073                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7074                       {
7075                           emitcode("mov", "b,a");
7076                           rOp = "b";
7077                       }
7078                         
7079                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7080                       emitcode ("xrl", "a,%s", rOp);
7081                   }
7082               }
7083             aopPut (AOP (result), "a", offset);
7084           }
7085         }
7086         
7087     }
7088
7089 release:
7090   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7091   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7092   freeAsmop (result, NULL, ic, TRUE);
7093 }
7094
7095 /*-----------------------------------------------------------------*/
7096 /* genInline - write the inline code out                           */
7097 /*-----------------------------------------------------------------*/
7098 static void
7099 genInline (iCode * ic)
7100 {
7101   char *buffer, *bp, *bp1;
7102
7103   D (emitcode (";", "genInline "); );
7104
7105   _G.inLine += (!options.asmpeep);
7106
7107   buffer = Safe_strdup(IC_INLINE(ic));
7108   bp = buffer;
7109   bp1 = buffer;
7110
7111   /* emit each line as a code */
7112   while (*bp)
7113     {
7114       if (*bp == '\n')
7115         {
7116           *bp++ = '\0';
7117           emitcode (bp1, "");
7118           bp1 = bp;
7119         }
7120       else
7121         {
7122           if (*bp == ':')
7123             {
7124               bp++;
7125               *bp = '\0';
7126               bp++;
7127               emitcode (bp1, "");
7128               bp1 = bp;
7129             }
7130           else
7131             bp++;
7132         }
7133     }
7134   if (bp1 != bp)
7135     emitcode (bp1, "");
7136   /*     emitcode("",buffer); */
7137   _G.inLine -= (!options.asmpeep);
7138 }
7139
7140 /*-----------------------------------------------------------------*/
7141 /* genRRC - rotate right with carry                                */
7142 /*-----------------------------------------------------------------*/
7143 static void
7144 genRRC (iCode * ic)
7145 {
7146   operand *left, *result;
7147   int     size, offset;
7148
7149   D (emitcode (";", "genRRC "););
7150
7151   /* rotate right with carry */
7152   left = IC_LEFT (ic);
7153   result = IC_RESULT (ic);
7154   aopOp (left, ic, FALSE, FALSE);
7155   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7156
7157   /* move it to the result */
7158   size = AOP_SIZE (result);
7159   offset = size - 1;
7160   CLRC;
7161
7162   _startLazyDPSEvaluation ();
7163   while (size--)
7164     {
7165       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7166       emitcode ("rrc", "a");
7167       if (AOP_SIZE (result) > 1)
7168         aopPut (AOP (result), "a", offset--);
7169     }
7170   _endLazyDPSEvaluation ();
7171
7172   /* now we need to put the carry into the
7173      highest order byte of the result */
7174   if (AOP_SIZE (result) > 1)
7175     {
7176       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7177     }
7178   emitcode ("mov", "acc.7,c");
7179   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7180   freeAsmop (left, NULL, ic, TRUE);
7181   freeAsmop (result, NULL, ic, TRUE);
7182 }
7183
7184 /*-----------------------------------------------------------------*/
7185 /* genRLC - generate code for rotate left with carry               */
7186 /*-----------------------------------------------------------------*/
7187 static void
7188 genRLC (iCode * ic)
7189 {
7190   operand *left, *result;
7191   int size, offset;
7192   char *l;
7193
7194   D (emitcode (";", "genRLC "););
7195
7196   /* rotate right with carry */
7197   left = IC_LEFT (ic);
7198   result = IC_RESULT (ic);
7199   aopOp (left, ic, FALSE, FALSE);
7200   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7201
7202   /* move it to the result */
7203   size = AOP_SIZE (result);
7204   offset = 0;
7205   if (size--)
7206     {
7207       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7208       MOVA (l);
7209       emitcode ("add", "a,acc");
7210       if (AOP_SIZE (result) > 1)
7211         {
7212           aopPut (AOP (result), "a", offset++);
7213         }
7214
7215       _startLazyDPSEvaluation ();
7216       while (size--)
7217         {
7218           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7219           MOVA (l);
7220           emitcode ("rlc", "a");
7221           if (AOP_SIZE (result) > 1)
7222             aopPut (AOP (result), "a", offset++);
7223         }
7224       _endLazyDPSEvaluation ();
7225     }
7226   /* now we need to put the carry into the
7227      highest order byte of the result */
7228   if (AOP_SIZE (result) > 1)
7229     {
7230       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7231       MOVA (l);
7232     }
7233   emitcode ("mov", "acc.0,c");
7234   aopPut (AOP (result), "a", 0);
7235   freeAsmop (left, NULL, ic, TRUE);
7236   freeAsmop (result, NULL, ic, TRUE);
7237 }
7238
7239 /*-----------------------------------------------------------------*/
7240 /* genGetHbit - generates code get highest order bit               */
7241 /*-----------------------------------------------------------------*/
7242 static void
7243 genGetHbit (iCode * ic)
7244 {
7245   operand *left, *result;
7246   left = IC_LEFT (ic);
7247   result = IC_RESULT (ic);
7248   aopOp (left, ic, FALSE, FALSE);
7249   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7250
7251   D (emitcode (";", "genGetHbit "););
7252
7253   /* get the highest order byte into a */
7254   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7255   if (AOP_TYPE (result) == AOP_CRY)
7256     {
7257       emitcode ("rlc", "a");
7258       outBitC (result);
7259     }
7260   else
7261     {
7262       emitcode ("rl", "a");
7263       emitcode ("anl", "a,#1");
7264       outAcc (result);
7265     }
7266
7267
7268   freeAsmop (left, NULL, ic, TRUE);
7269   freeAsmop (result, NULL, ic, TRUE);
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* AccRol - rotate left accumulator by known count                 */
7274 /*-----------------------------------------------------------------*/
7275 static void
7276 AccRol (int shCount)
7277 {
7278   shCount &= 0x0007;            // shCount : 0..7
7279
7280   switch (shCount)
7281     {
7282     case 0:
7283       break;
7284     case 1:
7285       emitcode ("rl", "a");
7286       break;
7287     case 2:
7288       emitcode ("rl", "a");
7289       emitcode ("rl", "a");
7290       break;
7291     case 3:
7292       emitcode ("swap", "a");
7293       emitcode ("rr", "a");
7294       break;
7295     case 4:
7296       emitcode ("swap", "a");
7297       break;
7298     case 5:
7299       emitcode ("swap", "a");
7300       emitcode ("rl", "a");
7301       break;
7302     case 6:
7303       emitcode ("rr", "a");
7304       emitcode ("rr", "a");
7305       break;
7306     case 7:
7307       emitcode ("rr", "a");
7308       break;
7309     }
7310 }
7311
7312 /*-----------------------------------------------------------------*/
7313 /* AccLsh - left shift accumulator by known count                  */
7314 /*-----------------------------------------------------------------*/
7315 static void
7316 AccLsh (int shCount)
7317 {
7318   if (shCount != 0)
7319     {
7320       if (shCount == 1)
7321         emitcode ("add", "a,acc");
7322       else if (shCount == 2)
7323         {
7324           emitcode ("add", "a,acc");
7325           emitcode ("add", "a,acc");
7326         }
7327       else
7328         {
7329           /* rotate left accumulator */
7330           AccRol (shCount);
7331           /* and kill the lower order bits */
7332           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7333         }
7334     }
7335 }
7336
7337 /*-----------------------------------------------------------------*/
7338 /* AccRsh - right shift accumulator by known count                 */
7339 /*-----------------------------------------------------------------*/
7340 static void
7341 AccRsh (int shCount)
7342 {
7343   if (shCount != 0)
7344     {
7345       if (shCount == 1)
7346         {
7347           CLRC;
7348           emitcode ("rrc", "a");
7349         }
7350       else
7351         {
7352           /* rotate right accumulator */
7353           AccRol (8 - shCount);
7354           /* and kill the higher order bits */
7355           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7356         }
7357     }
7358 }
7359
7360 #ifdef BETTER_LITERAL_SHIFT
7361 /*-----------------------------------------------------------------*/
7362 /* AccSRsh - signed right shift accumulator by known count                 */
7363 /*-----------------------------------------------------------------*/
7364 static void
7365 AccSRsh (int shCount)
7366 {
7367   symbol *tlbl;
7368   if (shCount != 0)
7369     {
7370       if (shCount == 1)
7371         {
7372           emitcode ("mov", "c,acc.7");
7373           emitcode ("rrc", "a");
7374         }
7375       else if (shCount == 2)
7376         {
7377           emitcode ("mov", "c,acc.7");
7378           emitcode ("rrc", "a");
7379           emitcode ("mov", "c,acc.7");
7380           emitcode ("rrc", "a");
7381         }
7382       else
7383         {
7384           tlbl = newiTempLabel (NULL);
7385           /* rotate right accumulator */
7386           AccRol (8 - shCount);
7387           /* and kill the higher order bits */
7388           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7389           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7390           emitcode ("orl", "a,#!constbyte",
7391                     (unsigned char) ~SRMask[shCount]);
7392           emitcode ("", "!tlabeldef", tlbl->key + 100);
7393         }
7394     }
7395 }
7396 #endif
7397
7398 #ifdef BETTER_LITERAL_SHIFT
7399 /*-----------------------------------------------------------------*/
7400 /* shiftR1Left2Result - shift right one byte from left to result   */
7401 /*-----------------------------------------------------------------*/
7402 static void
7403 shiftR1Left2Result (operand * left, int offl,
7404                     operand * result, int offr,
7405                     int shCount, int sign)
7406 {
7407   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7408   /* shift right accumulator */
7409   if (sign)
7410     AccSRsh (shCount);
7411   else
7412     AccRsh (shCount);
7413   aopPut (AOP (result), "a", offr);
7414 }
7415 #endif
7416
7417 #ifdef BETTER_LITERAL_SHIFT
7418 /*-----------------------------------------------------------------*/
7419 /* shiftL1Left2Result - shift left one byte from left to result    */
7420 /*-----------------------------------------------------------------*/
7421 static void
7422 shiftL1Left2Result (operand * left, int offl,
7423                     operand * result, int offr, int shCount)
7424 {
7425   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426   /* shift left accumulator */
7427   AccLsh (shCount);
7428   aopPut (AOP (result), "a", offr);
7429 }
7430 #endif
7431
7432 #ifdef BETTER_LITERAL_SHIFT
7433 /*-----------------------------------------------------------------*/
7434 /* movLeft2Result - move byte from left to result                  */
7435 /*-----------------------------------------------------------------*/
7436 static void
7437 movLeft2Result (operand * left, int offl,
7438                 operand * result, int offr, int sign)
7439 {
7440   char *l;
7441   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7442   {
7443       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7444
7445       if (*l == '@' && (IS_AOP_PREG (result)))
7446       {
7447           emitcode ("mov", "a,%s", l);
7448           aopPut (AOP (result), "a", offr);
7449       }
7450       else
7451       {
7452           if (!sign)
7453           {
7454             aopPut (AOP (result), l, offr);
7455           }
7456           else
7457             {
7458               /* MSB sign in acc.7 ! */
7459               if (getDataSize (left) == offl + 1)
7460                 {
7461                   emitcode ("mov", "a,%s", l);
7462                   aopPut (AOP (result), "a", offr);
7463                 }
7464             }
7465       }
7466   }
7467 }
7468 #endif
7469
7470 #ifdef BETTER_LITERAL_SHIFT
7471 /*-----------------------------------------------------------------*/
7472 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7473 /*-----------------------------------------------------------------*/
7474 static void
7475 AccAXRrl1 (char *x)
7476 {
7477   emitcode ("rrc", "a");
7478   emitcode ("xch", "a,%s", x);
7479   emitcode ("rrc", "a");
7480   emitcode ("xch", "a,%s", x);
7481 }
7482 #endif
7483
7484 #ifdef BETTER_LITERAL_SHIFT
7485 //REMOVE ME!!!
7486 /*-----------------------------------------------------------------*/
7487 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7488 /*-----------------------------------------------------------------*/
7489 static void
7490 AccAXLrl1 (char *x)
7491 {
7492   emitcode ("xch", "a,%s", x);
7493   emitcode ("rlc", "a");
7494   emitcode ("xch", "a,%s", x);
7495   emitcode ("rlc", "a");
7496 }
7497 #endif
7498
7499 #ifdef BETTER_LITERAL_SHIFT
7500 /*-----------------------------------------------------------------*/
7501 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7502 /*-----------------------------------------------------------------*/
7503 static void
7504 AccAXLsh1 (char *x)
7505 {
7506   emitcode ("xch", "a,%s", x);
7507   emitcode ("add", "a,acc");
7508   emitcode ("xch", "a,%s", x);
7509   emitcode ("rlc", "a");
7510 }
7511 #endif
7512
7513 #ifdef BETTER_LITERAL_SHIFT
7514 /*-----------------------------------------------------------------*/
7515 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7516 /*-----------------------------------------------------------------*/
7517 static void
7518 AccAXLsh (char *x, int shCount)
7519 {
7520   switch (shCount)
7521     {
7522     case 0:
7523       break;
7524     case 1:
7525       AccAXLsh1 (x);
7526       break;
7527     case 2:
7528       AccAXLsh1 (x);
7529       AccAXLsh1 (x);
7530       break;
7531     case 3:
7532     case 4:
7533     case 5:                     // AAAAABBB:CCCCCDDD
7534
7535       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7536
7537       emitcode ("anl", "a,#!constbyte",
7538                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7539
7540       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7541
7542       AccRol (shCount);         // DDDCCCCC:BBB00000
7543
7544       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7545
7546       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7547
7548       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7549
7550       emitcode ("anl", "a,#!constbyte",
7551                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7552
7553       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7554
7555       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7556
7557       break;
7558     case 6:                     // AAAAAABB:CCCCCCDD
7559       emitcode ("anl", "a,#!constbyte",
7560                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7561       emitcode ("mov", "c,acc.0");      // c = B
7562       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7563 #if 0
7564       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7565       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7566 #else
7567       emitcode("rrc","a"); 
7568       emitcode("xch","a,%s", x); 
7569       emitcode("rrc","a"); 
7570       emitcode("mov","c,acc.0"); //<< get correct bit 
7571       emitcode("xch","a,%s", x); 
7572
7573       emitcode("rrc","a"); 
7574       emitcode("xch","a,%s", x); 
7575       emitcode("rrc","a"); 
7576       emitcode("xch","a,%s", x); 
7577 #endif
7578       break;
7579     case 7:                     // a:x <<= 7
7580
7581       emitcode ("anl", "a,#!constbyte",
7582                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7583
7584       emitcode ("mov", "c,acc.0");      // c = B
7585
7586       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7587
7588       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7589
7590       break;
7591     default:
7592       break;
7593     }
7594 }
7595 #endif
7596
7597 #ifdef BETTER_LITERAL_SHIFT
7598 //REMOVE ME!!!
7599 /*-----------------------------------------------------------------*/
7600 /* AccAXRsh - right shift a:x known count (0..7)                   */
7601 /*-----------------------------------------------------------------*/
7602 static void
7603 AccAXRsh (char *x, int shCount)
7604 {
7605   switch (shCount)
7606     {
7607     case 0:
7608       break;
7609     case 1:
7610       CLRC;
7611       AccAXRrl1 (x);            // 0->a:x
7612
7613       break;
7614     case 2:
7615       CLRC;
7616       AccAXRrl1 (x);            // 0->a:x
7617
7618       CLRC;
7619       AccAXRrl1 (x);            // 0->a:x
7620
7621       break;
7622     case 3:
7623     case 4:
7624     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7625
7626       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7627
7628       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7629
7630       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7631
7632       emitcode ("anl", "a,#!constbyte",
7633                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7634
7635       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7636
7637       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7638
7639       emitcode ("anl", "a,#!constbyte",
7640                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7641
7642       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7643
7644       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7645
7646       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7647
7648       break;
7649     case 6:                     // AABBBBBB:CCDDDDDD
7650
7651       emitcode ("mov", "c,acc.7");
7652       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7653
7654       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7655
7656       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7657
7658       emitcode ("anl", "a,#!constbyte",
7659                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7660
7661       break;
7662     case 7:                     // ABBBBBBB:CDDDDDDD
7663
7664       emitcode ("mov", "c,acc.7");      // c = A
7665
7666       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7667
7668       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7669
7670       emitcode ("anl", "a,#!constbyte",
7671                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7672
7673       break;
7674     default:
7675       break;
7676     }
7677 }
7678 #endif
7679
7680 #ifdef BETTER_LITERAL_SHIFT
7681 /*-----------------------------------------------------------------*/
7682 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7683 /*-----------------------------------------------------------------*/
7684 static void
7685 AccAXRshS (char *x, int shCount)
7686 {
7687   symbol *tlbl;
7688   switch (shCount)
7689     {
7690     case 0:
7691       break;
7692     case 1:
7693       emitcode ("mov", "c,acc.7");
7694       AccAXRrl1 (x);            // s->a:x
7695
7696       break;
7697     case 2:
7698       emitcode ("mov", "c,acc.7");
7699       AccAXRrl1 (x);            // s->a:x
7700
7701       emitcode ("mov", "c,acc.7");
7702       AccAXRrl1 (x);            // s->a:x
7703
7704       break;
7705     case 3:
7706     case 4:
7707     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7708
7709       tlbl = newiTempLabel (NULL);
7710       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7711
7712       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7713
7714       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7715
7716       emitcode ("anl", "a,#!constbyte",
7717                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7718
7719       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7720
7721       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7722
7723       emitcode ("anl", "a,#!constbyte",
7724                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7725
7726       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7727
7728       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7729
7730       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7731
7732       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7733       emitcode ("orl", "a,#!constbyte",
7734                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7735
7736       emitcode ("", "!tlabeldef", tlbl->key + 100);
7737       break;                    // SSSSAAAA:BBBCCCCC
7738
7739     case 6:                     // AABBBBBB:CCDDDDDD
7740
7741       tlbl = newiTempLabel (NULL);
7742       emitcode ("mov", "c,acc.7");
7743       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7744
7745       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7746
7747       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7748
7749       emitcode ("anl", "a,#!constbyte",
7750                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7751
7752       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7753       emitcode ("orl", "a,#!constbyte",
7754                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7755
7756       emitcode ("", "!tlabeldef", tlbl->key + 100);
7757       break;
7758     case 7:                     // ABBBBBBB:CDDDDDDD
7759
7760       tlbl = newiTempLabel (NULL);
7761       emitcode ("mov", "c,acc.7");      // c = A
7762
7763       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7764
7765       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7766
7767       emitcode ("anl", "a,#!constbyte",
7768                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7769
7770       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771       emitcode ("orl", "a,#!constbyte",
7772                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7773
7774       emitcode ("", "!tlabeldef", tlbl->key + 100);
7775       break;
7776     default:
7777       break;
7778     }
7779 }
7780 #endif
7781
7782 #ifdef BETTER_LITERAL_SHIFT
7783 static void
7784 _loadLeftIntoAx(char    **lsb, 
7785                 operand *left, 
7786                 operand *result,
7787                 int     offl,
7788                 int     offr)
7789 {
7790   // Get the initial value from left into a pair of registers.
7791   // MSB must be in A, LSB can be any register.
7792   //
7793   // If the result is held in registers, it is an optimization
7794   // if the LSB can be held in the register which will hold the,
7795   // result LSB since this saves us from having to copy it into
7796   // the result following AccAXLsh.
7797   //
7798   // If the result is addressed indirectly, this is not a gain.
7799   if (AOP_NEEDSACC(result))
7800   {
7801        char *leftByte;
7802        
7803        _startLazyDPSEvaluation();
7804       if (AOP_TYPE(left) == AOP_DPTR2)
7805        {
7806            // Get MSB in A.
7807            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7808            // get LSB in DP2_RESULT_REG.
7809            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7810            assert(!strcmp(leftByte, DP2_RESULT_REG));
7811        }
7812        else
7813        {
7814            // get LSB into DP2_RESULT_REG
7815            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7816            if (strcmp(leftByte, DP2_RESULT_REG))
7817            {
7818                TR_AP("#7");
7819                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7820            }
7821            // And MSB in A.
7822            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7823            assert(strcmp(leftByte, DP2_RESULT_REG));
7824            MOVA(leftByte);
7825        }
7826        _endLazyDPSEvaluation();
7827        *lsb = DP2_RESULT_REG;
7828   }
7829   else
7830   {
7831       if (sameRegs (AOP (result), AOP (left)) &&
7832         ((offl + MSB16) == offr))
7833       {
7834           /* don't crash result[offr] */
7835           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7836           emitcode ("xch", "a,%s", 
7837                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7838       }
7839       else
7840       {
7841           movLeft2Result (left, offl, result, offr, 0);
7842           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7843       }
7844       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7845       assert(strcmp(*lsb,"a"));      
7846   }
7847 }
7848
7849 static void
7850 _storeAxResults(char    *lsb,
7851                 operand *result,
7852                 int     offr)
7853 {
7854   _startLazyDPSEvaluation();
7855   if (AOP_NEEDSACC(result))
7856   {
7857       /* We have to explicitly update the result LSB.
7858        */
7859       emitcode("xch","a,%s", lsb);
7860       aopPut(AOP(result), "a", offr);
7861       emitcode("mov","a,%s", lsb);
7862   }
7863   if (getDataSize (result) > 1)
7864   {
7865       aopPut (AOP (result), "a", offr + MSB16);
7866   }
7867   _endLazyDPSEvaluation();
7868 }
7869
7870 /*-----------------------------------------------------------------*/
7871 /* shiftL2Left2Result - shift left two bytes from left to result   */
7872 /*-----------------------------------------------------------------*/
7873 static void
7874 shiftL2Left2Result (operand * left, int offl,
7875                     operand * result, int offr, int shCount)
7876 {
7877   char *lsb;
7878
7879   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7880   
7881   AccAXLsh (lsb, shCount);
7882   
7883   _storeAxResults(lsb, result, offr);
7884 }
7885 #endif
7886
7887 #ifdef BETTER_LITERAL_SHIFT
7888 /*-----------------------------------------------------------------*/
7889 /* shiftR2Left2Result - shift right two bytes from left to result  */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 shiftR2Left2Result (operand * left, int offl,
7893                     operand * result, int offr,
7894                     int shCount, int sign)
7895 {
7896   char *lsb;
7897   
7898   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7899   
7900   /* a:x >> shCount (x = lsb(result)) */
7901   if (sign)
7902   {
7903      AccAXRshS(lsb, shCount);
7904   }
7905   else
7906   {
7907     AccAXRsh(lsb, shCount);
7908   }
7909   
7910   _storeAxResults(lsb, result, offr);
7911 }
7912 #endif
7913
7914 #if 0
7915 //REMOVE ME!!!
7916 /*-----------------------------------------------------------------*/
7917 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7918 /*-----------------------------------------------------------------*/
7919 static void
7920 shiftLLeftOrResult (operand * left, int offl,
7921                     operand * result, int offr, int shCount)
7922 {
7923   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7924   /* shift left accumulator */
7925   AccLsh (shCount);
7926   /* or with result */
7927   emitcode ("orl", "a,%s",
7928             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7929   /* back to result */
7930   aopPut (AOP (result), "a", offr);
7931 }
7932 #endif
7933
7934 #if 0
7935 //REMOVE ME!!!
7936 /*-----------------------------------------------------------------*/
7937 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7938 /*-----------------------------------------------------------------*/
7939 static void
7940 shiftRLeftOrResult (operand * left, int offl,
7941                     operand * result, int offr, int shCount)
7942 {
7943   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7944   /* shift right accumulator */
7945   AccRsh (shCount);
7946   /* or with result */
7947   emitcode ("orl", "a,%s",
7948             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7949   /* back to result */
7950   aopPut (AOP (result), "a", offr);
7951 }
7952 #endif
7953
7954 #ifdef BETTER_LITERAL_SHIFT
7955 /*-----------------------------------------------------------------*/
7956 /* genlshOne - left shift a one byte quantity by known count       */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 genlshOne (operand * result, operand * left, int shCount)
7960 {
7961   D (emitcode (";", "genlshOne "););
7962   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7963 }
7964 #endif
7965
7966 #ifdef BETTER_LITERAL_SHIFT
7967 /*-----------------------------------------------------------------*/
7968 /* genlshTwo - left shift two bytes by known amount != 0           */
7969 /*-----------------------------------------------------------------*/
7970 static void
7971 genlshTwo (operand * result, operand * left, int shCount)
7972 {
7973   int size;
7974
7975   D (emitcode (";", "genlshTwo "););
7976
7977   size = getDataSize (result);
7978
7979   /* if shCount >= 8 */
7980   if (shCount >= 8)
7981   {
7982       shCount -= 8;
7983
7984       _startLazyDPSEvaluation();
7985
7986       if (size > 1)
7987         {
7988           if (shCount)
7989           {
7990             _endLazyDPSEvaluation();
7991             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7992             aopPut (AOP (result), zero, LSB);       
7993           }
7994           else
7995           {
7996             movLeft2Result (left, LSB, result, MSB16, 0);
7997             aopPut (AOP (result), zero, LSB);
7998             _endLazyDPSEvaluation();
7999           }
8000         }
8001         else
8002         {
8003           aopPut (AOP (result), zero, LSB);
8004           _endLazyDPSEvaluation();
8005         }
8006   }
8007
8008   /*  1 <= shCount <= 7 */
8009   else
8010     {
8011       if (size == 1)
8012       {
8013         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8014       }
8015       else
8016       {
8017         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8018       }
8019     }
8020 }
8021 #endif
8022
8023 #if 0
8024 //REMOVE ME!!!
8025 /*-----------------------------------------------------------------*/
8026 /* shiftLLong - shift left one long from left to result            */
8027 /* offl = LSB or MSB16                                             */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 shiftLLong (operand * left, operand * result, int offr)
8031 {
8032   char *l;
8033   int size = AOP_SIZE (result);
8034
8035   if (size >= LSB + offr)
8036     {
8037       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8038       MOVA (l);
8039       emitcode ("add", "a,acc");
8040       if (sameRegs (AOP (left), AOP (result)) &&
8041           size >= MSB16 + offr && offr != LSB)
8042         emitcode ("xch", "a,%s",
8043                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8044       else
8045         aopPut (AOP (result), "a", LSB + offr);
8046     }
8047
8048   if (size >= MSB16 + offr)
8049     {
8050       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8051         {
8052           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8053         }
8054       emitcode ("rlc", "a");
8055       if (sameRegs (AOP (left), AOP (result)) &&
8056           size >= MSB24 + offr && offr != LSB)
8057         emitcode ("xch", "a,%s",
8058                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8059       else
8060         aopPut (AOP (result), "a", MSB16 + offr);
8061     }
8062
8063   if (size >= MSB24 + offr)
8064     {
8065       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8066         {
8067           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8068         }
8069       emitcode ("rlc", "a");
8070       if (sameRegs (AOP (left), AOP (result)) &&
8071           size >= MSB32 + offr && offr != LSB)
8072         emitcode ("xch", "a,%s",
8073                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8074       else
8075         aopPut (AOP (result), "a", MSB24 + offr);
8076     }
8077
8078   if (size > MSB32 + offr)
8079     {
8080       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8081         {
8082           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8083         }
8084       emitcode ("rlc", "a");
8085       aopPut (AOP (result), "a", MSB32 + offr);
8086     }
8087   if (offr != LSB)
8088     aopPut (AOP (result), zero, LSB);
8089 }
8090 #endif
8091
8092 #if 0
8093 //REMOVE ME!!!
8094 /*-----------------------------------------------------------------*/
8095 /* genlshFour - shift four byte by a known amount != 0             */
8096 /*-----------------------------------------------------------------*/
8097 static void
8098 genlshFour (operand * result, operand * left, int shCount)
8099 {
8100   int size;
8101
8102   D (emitcode (";", "genlshFour ");
8103     );
8104
8105   size = AOP_SIZE (result);
8106
8107   /* if shifting more that 3 bytes */
8108   if (shCount >= 24)
8109     {
8110       shCount -= 24;
8111       if (shCount)
8112         /* lowest order of left goes to the highest
8113            order of the destination */
8114         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8115       else
8116         movLeft2Result (left, LSB, result, MSB32, 0);
8117       aopPut (AOP (result), zero, LSB);
8118       aopPut (AOP (result), zero, MSB16);
8119       aopPut (AOP (result), zero, MSB24);
8120       return;
8121     }
8122
8123   /* more than two bytes */
8124   else if (shCount >= 16)
8125     {
8126       /* lower order two bytes goes to higher order two bytes */
8127       shCount -= 16;
8128       /* if some more remaining */
8129       if (shCount)
8130         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8131       else
8132         {
8133           movLeft2Result (left, MSB16, result, MSB32, 0);
8134           movLeft2Result (left, LSB, result, MSB24, 0);
8135         }
8136       aopPut (AOP (result), zero, MSB16);
8137       aopPut (AOP (result), zero, LSB);
8138       return;
8139     }
8140
8141   /* if more than 1 byte */
8142   else if (shCount >= 8)
8143     {
8144       /* lower order three bytes goes to higher order  three bytes */
8145       shCount -= 8;
8146       if (size == 2)
8147         {
8148           if (shCount)
8149             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8150           else
8151             movLeft2Result (left, LSB, result, MSB16, 0);
8152         }
8153       else
8154         {                       /* size = 4 */
8155           if (shCount == 0)
8156             {
8157               movLeft2Result (left, MSB24, result, MSB32, 0);
8158               movLeft2Result (left, MSB16, result, MSB24, 0);
8159               movLeft2Result (left, LSB, result, MSB16, 0);
8160               aopPut (AOP (result), zero, LSB);
8161             }
8162           else if (shCount == 1)
8163             shiftLLong (left, result, MSB16);
8164           else
8165             {
8166               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8167               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8168               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8169               aopPut (AOP (result), zero, LSB);
8170             }
8171         }
8172     }
8173
8174   /* 1 <= shCount <= 7 */
8175   else if (shCount <= 2)
8176     {
8177       shiftLLong (left, result, LSB);
8178       if (shCount == 2)
8179         shiftLLong (result, result, LSB);
8180     }
8181   /* 3 <= shCount <= 7, optimize */
8182   else
8183     {
8184       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8185       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8186       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8187     }
8188 }
8189 #endif
8190
8191 #ifdef BETTER_LITERAL_SHIFT
8192 /*-----------------------------------------------------------------*/
8193 /* genLeftShiftLiteral - left shifting by known count              */
8194 /*-----------------------------------------------------------------*/
8195 static bool
8196 genLeftShiftLiteral (operand * left,
8197                      operand * right,
8198                      operand * result,
8199                      iCode * ic)
8200 {
8201   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8202   int size;
8203
8204   size = getSize (operandType (result));
8205
8206   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8207
8208   /* We only handle certain easy cases so far. */
8209   if ((shCount != 0)
8210    && (shCount < (size * 8))
8211    && (size != 1)
8212    && (size != 2))
8213   {
8214       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8215       return FALSE;
8216   }
8217
8218   freeAsmop (right, NULL, ic, TRUE);
8219
8220   aopOp(left, ic, FALSE, FALSE);
8221   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8222
8223 #if 0 // debug spew
8224   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8225   {
8226         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8227         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8228         {
8229            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8230         }
8231   }
8232   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8233   {
8234         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8235         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8236         {
8237            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8238         }       
8239   }  
8240 #endif
8241   
8242 #if VIEW_SIZE
8243   emitcode ("; shift left ", "result %d, left %d", size,
8244             AOP_SIZE (left));
8245 #endif
8246
8247   /* I suppose that the left size >= result size */
8248   if (shCount == 0)
8249   {
8250         _startLazyDPSEvaluation();
8251         while (size--)
8252         {
8253           movLeft2Result (left, size, result, size, 0);
8254         }
8255         _endLazyDPSEvaluation();
8256   }
8257   else if (shCount >= (size * 8))
8258   {
8259     _startLazyDPSEvaluation();
8260     while (size--)
8261     {
8262       aopPut (AOP (result), zero, size);
8263     }
8264     _endLazyDPSEvaluation();
8265   }
8266   else
8267   {
8268       switch (size)
8269         {
8270         case 1:
8271           genlshOne (result, left, shCount);
8272           break;
8273
8274         case 2:
8275           genlshTwo (result, left, shCount);
8276           break;
8277 #if 0
8278         case 4:
8279           genlshFour (result, left, shCount);
8280           break;
8281 #endif
8282         default:
8283           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8284           break;
8285         }
8286     }
8287   freeAsmop (left, NULL, ic, TRUE);
8288   freeAsmop (result, NULL, ic, TRUE);
8289   return TRUE;
8290 }
8291 #endif
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genLeftShift - generates code for left shifting                 */
8295 /*-----------------------------------------------------------------*/
8296 static void
8297 genLeftShift (iCode * ic)
8298 {
8299   operand *left, *right, *result;
8300   int size, offset;
8301   char *l;
8302   symbol *tlbl, *tlbl1;
8303
8304   D (emitcode (";", "genLeftShift "););
8305
8306   right = IC_RIGHT (ic);
8307   left = IC_LEFT (ic);
8308   result = IC_RESULT (ic);
8309
8310   aopOp (right, ic, FALSE, FALSE);
8311
8312
8313 #ifdef BETTER_LITERAL_SHIFT
8314   /* if the shift count is known then do it
8315      as efficiently as possible */
8316   if (AOP_TYPE (right) == AOP_LIT)
8317     {
8318       if (genLeftShiftLiteral (left, right, result, ic))
8319       {
8320         return;
8321       }
8322     }
8323 #endif
8324
8325   /* shift count is unknown then we have to form
8326      a loop get the loop count in B : Note: we take
8327      only the lower order byte since shifting
8328      more that 32 bits make no sense anyway, ( the
8329      largest size of an object can be only 32 bits ) */
8330
8331   if (AOP_TYPE (right) == AOP_LIT)
8332   {
8333       /* Really should be handled by genLeftShiftLiteral,
8334        * but since I'm too lazy to fix that today, at least we can make
8335        * some small improvement.
8336        */
8337        emitcode("mov", "b,#!constbyte",
8338                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8339   }
8340   else
8341   {
8342       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8343       emitcode ("inc", "b");
8344   }
8345   freeAsmop (right, NULL, ic, TRUE);
8346   aopOp (left, ic, FALSE, FALSE);
8347   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8348
8349   /* now move the left to the result if they are not the
8350      same */
8351   if (!sameRegs (AOP (left), AOP (result)) &&
8352       AOP_SIZE (result) > 1)
8353     {
8354
8355       size = AOP_SIZE (result);
8356       offset = 0;
8357       _startLazyDPSEvaluation ();
8358       while (size--)
8359         {
8360           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8361           if (*l == '@' && (IS_AOP_PREG (result)))
8362             {
8363
8364               emitcode ("mov", "a,%s", l);
8365               aopPut (AOP (result), "a", offset);
8366             }
8367           else
8368             aopPut (AOP (result), l, offset);
8369           offset++;
8370         }
8371       _endLazyDPSEvaluation ();
8372     }
8373
8374   tlbl = newiTempLabel (NULL);
8375   size = AOP_SIZE (result);
8376   offset = 0;
8377   tlbl1 = newiTempLabel (NULL);
8378
8379   /* if it is only one byte then */
8380   if (size == 1)
8381     {
8382       symbol *tlbl1 = newiTempLabel (NULL);
8383
8384       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8385       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8386       emitcode ("", "!tlabeldef", tlbl->key + 100);
8387       emitcode ("add", "a,acc");
8388       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8389       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8390       aopPut (AOP (result), "a", 0);
8391       goto release;
8392     }
8393
8394   reAdjustPreg (AOP (result));
8395
8396   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8397   emitcode ("", "!tlabeldef", tlbl->key + 100);
8398   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8399   emitcode ("add", "a,acc");
8400   aopPut (AOP (result), "a", offset++);
8401   _startLazyDPSEvaluation ();
8402   while (--size)
8403     {
8404       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8405       emitcode ("rlc", "a");
8406       aopPut (AOP (result), "a", offset++);
8407     }
8408   _endLazyDPSEvaluation ();
8409   reAdjustPreg (AOP (result));
8410
8411   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8412   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8413 release:
8414   freeAsmop (left, NULL, ic, TRUE);
8415   freeAsmop (result, NULL, ic, TRUE);
8416 }
8417
8418 #ifdef BETTER_LITERAL_SHIFT
8419 /*-----------------------------------------------------------------*/
8420 /* genrshOne - right shift a one byte quantity by known count      */
8421 /*-----------------------------------------------------------------*/
8422 static void
8423 genrshOne (operand * result, operand * left,
8424            int shCount, int sign)
8425 {
8426   D (emitcode (";", "genrshOne"););
8427   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8428 }
8429 #endif
8430
8431 #ifdef BETTER_LITERAL_SHIFT
8432 /*-----------------------------------------------------------------*/
8433 /* genrshTwo - right shift two bytes by known amount != 0          */
8434 /*-----------------------------------------------------------------*/
8435 static void
8436 genrshTwo (operand * result, operand * left,
8437            int shCount, int sign)
8438 {
8439   D (emitcode (";", "genrshTwo"););
8440
8441   /* if shCount >= 8 */
8442   if (shCount >= 8)
8443     {
8444       shCount -= 8;
8445       _startLazyDPSEvaluation();
8446       if (shCount)
8447       {
8448         shiftR1Left2Result (left, MSB16, result, LSB,
8449                             shCount, sign);
8450       }                     
8451       else
8452       {
8453         movLeft2Result (left, MSB16, result, LSB, sign);
8454       }
8455       addSign (result, MSB16, sign);
8456       _endLazyDPSEvaluation();
8457     }
8458
8459   /*  1 <= shCount <= 7 */
8460   else
8461   {
8462     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8463   }
8464 }
8465 #endif
8466
8467 #if 0
8468 //REMOVE ME!!!
8469 /*-----------------------------------------------------------------*/
8470 /* shiftRLong - shift right one long from left to result           */
8471 /* offl = LSB or MSB16                                             */
8472 /*-----------------------------------------------------------------*/
8473 static void
8474 shiftRLong (operand * left, int offl,
8475             operand * result, int sign)
8476 {
8477   int isSameRegs=sameRegs(AOP(left),AOP(result));
8478
8479   if (isSameRegs && offl>1) {
8480     // we are in big trouble, but this shouldn't happen
8481     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8482   }
8483
8484   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8485   
8486   if (offl==MSB16) {
8487     // shift is > 8
8488     if (sign) {
8489       emitcode ("rlc", "a");
8490       emitcode ("subb", "a,acc");
8491       emitcode ("xch", "a,%s",
8492                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8493     } else {
8494       aopPut (AOP(result), zero, MSB32);
8495     }
8496   }
8497
8498   if (!sign) {
8499     emitcode ("clr", "c");
8500   } else {
8501     emitcode ("mov", "c,acc.7");
8502   }
8503
8504   emitcode ("rrc", "a");
8505
8506   if (isSameRegs && offl==MSB16) {
8507     emitcode ("xch",
8508               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8509   } else {
8510     aopPut (AOP (result), "a", MSB32);
8511     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8512   }
8513
8514   emitcode ("rrc", "a");
8515   if (isSameRegs && offl==1) {
8516     emitcode ("xch", "a,%s",
8517               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8518   } else {
8519     aopPut (AOP (result), "a", MSB24);
8520     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8521   }
8522   emitcode ("rrc", "a");
8523   aopPut (AOP (result), "a", MSB16 - offl);
8524
8525   if (offl == LSB)
8526     {
8527       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8528       emitcode ("rrc", "a");
8529       aopPut (AOP (result), "a", LSB);
8530     }
8531 }
8532 #endif
8533
8534 #if 0
8535 //REMOVE ME!!!
8536 /*-----------------------------------------------------------------*/
8537 /* genrshFour - shift four byte by a known amount != 0             */
8538 /*-----------------------------------------------------------------*/
8539 static void
8540 genrshFour (operand * result, operand * left,
8541             int shCount, int sign)
8542 {
8543   D (emitcode (";", "genrshFour");
8544     );
8545
8546   /* if shifting more that 3 bytes */
8547   if (shCount >= 24)
8548     {
8549       shCount -= 24;
8550       if (shCount)
8551         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8552       else
8553         movLeft2Result (left, MSB32, result, LSB, sign);
8554       addSign (result, MSB16, sign);
8555     }
8556   else if (shCount >= 16)
8557     {
8558       shCount -= 16;
8559       if (shCount)
8560         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8561       else
8562         {
8563           movLeft2Result (left, MSB24, result, LSB, 0);
8564           movLeft2Result (left, MSB32, result, MSB16, sign);
8565         }
8566       addSign (result, MSB24, sign);
8567     }
8568   else if (shCount >= 8)
8569     {
8570       shCount -= 8;
8571       if (shCount == 1)
8572         shiftRLong (left, MSB16, result, sign);
8573       else if (shCount == 0)
8574         {
8575           movLeft2Result (left, MSB16, result, LSB, 0);
8576           movLeft2Result (left, MSB24, result, MSB16, 0);
8577           movLeft2Result (left, MSB32, result, MSB24, sign);
8578           addSign (result, MSB32, sign);
8579         }
8580       else
8581         {
8582           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8583           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8584           /* the last shift is signed */
8585           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8586           addSign (result, MSB32, sign);
8587         }
8588     }
8589   else
8590     {                           /* 1 <= shCount <= 7 */
8591       if (shCount <= 2)
8592         {
8593           shiftRLong (left, LSB, result, sign);
8594           if (shCount == 2)
8595             shiftRLong (result, LSB, result, sign);
8596         }
8597       else
8598         {
8599           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8600           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8601           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8602         }
8603     }
8604 }
8605 #endif
8606
8607 #ifdef BETTER_LITERAL_SHIFT
8608 /*-----------------------------------------------------------------*/
8609 /* genRightShiftLiteral - right shifting by known count            */
8610 /*-----------------------------------------------------------------*/
8611 static bool
8612 genRightShiftLiteral (operand * left,
8613                       operand * right,
8614                       operand * result,
8615                       iCode * ic,
8616                       int sign)
8617 {
8618   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8619   int size;
8620
8621   size = getSize (operandType (result));
8622
8623   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8624
8625   /* We only handle certain easy cases so far. */
8626   if ((shCount != 0)
8627    && (shCount < (size * 8))
8628    && (size != 1)
8629    && (size != 2))
8630   {
8631       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8632       return FALSE;
8633   }
8634
8635   freeAsmop (right, NULL, ic, TRUE);
8636
8637   aopOp (left, ic, FALSE, FALSE);
8638   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8639
8640 #if VIEW_SIZE
8641   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8642             AOP_SIZE (left));
8643 #endif
8644
8645   /* test the LEFT size !!! */
8646
8647   /* I suppose that the left size >= result size */
8648   if (shCount == 0)
8649   {
8650       size = getDataSize (result);
8651       _startLazyDPSEvaluation();
8652       while (size--)
8653       {
8654         movLeft2Result (left, size, result, size, 0);
8655       }
8656       _endLazyDPSEvaluation();
8657   }
8658   else if (shCount >= (size * 8))
8659     {
8660       if (sign)
8661       {
8662         /* get sign in acc.7 */
8663         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8664       }
8665       addSign (result, LSB, sign);
8666     }
8667   else
8668     {
8669       switch (size)
8670         {
8671         case 1:
8672           genrshOne (result, left, shCount, sign);
8673           break;
8674
8675         case 2:
8676           genrshTwo (result, left, shCount, sign);
8677           break;
8678 #if 0
8679         case 4:
8680           genrshFour (result, left, shCount, sign);
8681           break;
8682 #endif    
8683         default:
8684           break;
8685         }
8686     }
8687   freeAsmop (left, NULL, ic, TRUE);
8688   freeAsmop (result, NULL, ic, TRUE);
8689   
8690   return TRUE;
8691 }
8692 #endif
8693
8694 /*-----------------------------------------------------------------*/
8695 /* genSignedRightShift - right shift of signed number              */
8696 /*-----------------------------------------------------------------*/
8697 static void
8698 genSignedRightShift (iCode * ic)
8699 {
8700   operand *right, *left, *result;
8701   int size, offset;
8702   char *l;
8703   symbol *tlbl, *tlbl1;
8704
8705   D (emitcode (";", "genSignedRightShift "););
8706
8707   /* we do it the hard way put the shift count in b
8708      and loop thru preserving the sign */
8709
8710   right = IC_RIGHT (ic);
8711   left = IC_LEFT (ic);
8712   result = IC_RESULT (ic);
8713
8714   aopOp (right, ic, FALSE, FALSE);
8715
8716 #ifdef BETTER_LITERAL_SHIFT
8717   if (AOP_TYPE (right) == AOP_LIT)
8718     {
8719       if (genRightShiftLiteral (left, right, result, ic, 1))
8720       {
8721         return;
8722       }
8723     }
8724 #endif
8725   /* shift count is unknown then we have to form
8726      a loop get the loop count in B : Note: we take
8727      only the lower order byte since shifting
8728      more that 32 bits make no sense anyway, ( the
8729      largest size of an object can be only 32 bits ) */
8730
8731   if (AOP_TYPE (right) == AOP_LIT)
8732   {
8733       /* Really should be handled by genRightShiftLiteral,
8734        * but since I'm too lazy to fix that today, at least we can make
8735        * some small improvement.
8736        */
8737        emitcode("mov", "b,#!constbyte",
8738                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8739   }
8740   else
8741   {
8742         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8743         emitcode ("inc", "b");
8744   }
8745   freeAsmop (right, NULL, ic, TRUE);
8746   aopOp (left, ic, FALSE, FALSE);
8747   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8748
8749   /* now move the left to the result if they are not the
8750      same */
8751   if (!sameRegs (AOP (left), AOP (result)) &&
8752       AOP_SIZE (result) > 1)
8753     {
8754
8755       size = AOP_SIZE (result);
8756       offset = 0;
8757       _startLazyDPSEvaluation ();
8758       while (size--)
8759         {
8760           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8761           if (*l == '@' && IS_AOP_PREG (result))
8762             {
8763
8764               emitcode ("mov", "a,%s", l);
8765               aopPut (AOP (result), "a", offset);
8766             }
8767           else
8768             aopPut (AOP (result), l, offset);
8769           offset++;
8770         }
8771       _endLazyDPSEvaluation ();
8772     }
8773
8774   /* mov the highest order bit to OVR */
8775   tlbl = newiTempLabel (NULL);
8776   tlbl1 = newiTempLabel (NULL);
8777
8778   size = AOP_SIZE (result);
8779   offset = size - 1;
8780   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8781   emitcode ("rlc", "a");
8782   emitcode ("mov", "ov,c");
8783   /* if it is only one byte then */
8784   if (size == 1)
8785     {
8786       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8787       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8788       emitcode ("", "!tlabeldef", tlbl->key + 100);
8789       emitcode ("mov", "c,ov");
8790       emitcode ("rrc", "a");
8791       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8792       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8793       aopPut (AOP (result), "a", 0);
8794       goto release;
8795     }
8796
8797   reAdjustPreg (AOP (result));
8798   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8799   emitcode ("", "!tlabeldef", tlbl->key + 100);
8800   emitcode ("mov", "c,ov");
8801   _startLazyDPSEvaluation ();
8802   while (size--)
8803     {
8804       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8805       emitcode ("rrc", "a");
8806       aopPut (AOP (result), "a", offset--);
8807     }
8808   _endLazyDPSEvaluation ();
8809   reAdjustPreg (AOP (result));
8810   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8811   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8812
8813 release:
8814   freeAsmop (left, NULL, ic, TRUE);
8815   freeAsmop (result, NULL, ic, TRUE);
8816 }
8817
8818 /*-----------------------------------------------------------------*/
8819 /* genRightShift - generate code for right shifting                */
8820 /*-----------------------------------------------------------------*/
8821 static void
8822 genRightShift (iCode * ic)
8823 {
8824   operand *right, *left, *result;
8825   sym_link *retype;
8826   int size, offset;
8827   char *l;
8828   symbol *tlbl, *tlbl1;
8829
8830   D (emitcode (";", "genRightShift "););
8831
8832   /* if signed then we do it the hard way preserve the
8833      sign bit moving it inwards */
8834   retype = getSpec (operandType (IC_RESULT (ic)));
8835
8836   if (!SPEC_USIGN (retype))
8837     {
8838       genSignedRightShift (ic);
8839       return;
8840     }
8841
8842   /* signed & unsigned types are treated the same : i.e. the
8843      signed is NOT propagated inwards : quoting from the
8844      ANSI - standard : "for E1 >> E2, is equivalent to division
8845      by 2**E2 if unsigned or if it has a non-negative value,
8846      otherwise the result is implementation defined ", MY definition
8847      is that the sign does not get propagated */
8848
8849   right = IC_RIGHT (ic);
8850   left = IC_LEFT (ic);
8851   result = IC_RESULT (ic);
8852
8853   aopOp (right, ic, FALSE, FALSE);
8854
8855 #ifdef BETTER_LITERAL_SHIFT
8856   /* if the shift count is known then do it
8857      as efficiently as possible */
8858   if (AOP_TYPE (right) == AOP_LIT)
8859     {
8860       if (genRightShiftLiteral (left, right, result, ic, 0))
8861       {
8862         return;
8863       }
8864     }
8865 #endif
8866
8867   /* shift count is unknown then we have to form
8868      a loop get the loop count in B : Note: we take
8869      only the lower order byte since shifting
8870      more that 32 bits make no sense anyway, ( the
8871      largest size of an object can be only 32 bits ) */
8872   
8873   if (AOP_TYPE (right) == AOP_LIT)
8874   {
8875       /* Really should be handled by genRightShiftLiteral,
8876        * but since I'm too lazy to fix that today, at least we can make
8877        * some small improvement.
8878        */
8879        emitcode("mov", "b,#!constbyte",
8880                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8881   }
8882   else
8883   {
8884       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8885       emitcode ("inc", "b");
8886   }
8887   freeAsmop (right, NULL, ic, TRUE);
8888   aopOp (left, ic, FALSE, FALSE);
8889   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8890
8891   /* now move the left to the result if they are not the
8892      same */
8893   if (!sameRegs (AOP (left), AOP (result)) &&
8894       AOP_SIZE (result) > 1)
8895     {
8896
8897       size = AOP_SIZE (result);
8898       offset = 0;
8899       _startLazyDPSEvaluation ();
8900       while (size--)
8901         {
8902           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8903           if (*l == '@' && IS_AOP_PREG (result))
8904             {
8905
8906               emitcode ("mov", "a,%s", l);
8907               aopPut (AOP (result), "a", offset);
8908             }
8909           else
8910             aopPut (AOP (result), l, offset);
8911           offset++;
8912         }
8913       _endLazyDPSEvaluation ();
8914     }
8915
8916   tlbl = newiTempLabel (NULL);
8917   tlbl1 = newiTempLabel (NULL);
8918   size = AOP_SIZE (result);
8919   offset = size - 1;
8920
8921   /* if it is only one byte then */
8922   if (size == 1)
8923     {
8924       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8925       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8926       emitcode ("", "!tlabeldef", tlbl->key + 100);
8927       CLRC;
8928       emitcode ("rrc", "a");
8929       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8930       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8931       aopPut (AOP (result), "a", 0);
8932       goto release;
8933     }
8934
8935   reAdjustPreg (AOP (result));
8936   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8937   emitcode ("", "!tlabeldef", tlbl->key + 100);
8938   CLRC;
8939   _startLazyDPSEvaluation ();
8940   while (size--)
8941     {
8942       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8943       emitcode ("rrc", "a");
8944       aopPut (AOP (result), "a", offset--);
8945     }
8946   _endLazyDPSEvaluation ();
8947   reAdjustPreg (AOP (result));
8948
8949   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8950   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8951
8952 release:
8953   freeAsmop (left, NULL, ic, TRUE);
8954   freeAsmop (result, NULL, ic, TRUE);
8955 }
8956
8957 /*-----------------------------------------------------------------*/
8958 /* genUnpackBits - generates code for unpacking bits               */
8959 /*-----------------------------------------------------------------*/
8960 static void
8961 genUnpackBits (operand * result, char *rname, int ptype)
8962 {
8963   int shCnt;
8964   int rlen;
8965   sym_link *etype;
8966   int offset = 0;
8967
8968   D (emitcode (";", "genUnpackBits "););
8969
8970   etype = getSpec (operandType (result));
8971
8972   /* read the first byte  */
8973   switch (ptype)
8974     {
8975
8976     case POINTER:
8977     case IPOINTER:
8978       emitcode ("mov", "a,@%s", rname);
8979       break;
8980
8981     case PPOINTER:
8982       emitcode ("movx", "a,@%s", rname);
8983       break;
8984
8985     case FPOINTER:
8986       emitcode ("movx", "a,@dptr");
8987       break;
8988
8989     case CPOINTER:
8990       emitcode ("clr", "a");
8991       emitcode ("movc", "a,@a+dptr");
8992       break;
8993
8994     case GPOINTER:
8995       emitcode ("lcall", "__gptrget");
8996       break;
8997     }
8998
8999   /* if we have bitdisplacement then it fits   */
9000   /* into this byte completely or if length is */
9001   /* less than a byte                          */
9002   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9003     {
9004
9005       /* shift right acc */
9006       AccRsh (shCnt);
9007
9008       emitcode ("anl", "a,#!constbyte",
9009                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9010       aopPut (AOP (result), "a", offset);
9011       return;
9012     }
9013
9014   /* bit field did not fit in a byte  */
9015   rlen = SPEC_BLEN (etype) - 8;
9016   aopPut (AOP (result), "a", offset++);
9017
9018   while (1)
9019     {
9020
9021       switch (ptype)
9022         {
9023         case POINTER:
9024         case IPOINTER:
9025           emitcode ("inc", "%s", rname);
9026           emitcode ("mov", "a,@%s", rname);
9027           break;
9028
9029         case PPOINTER:
9030           emitcode ("inc", "%s", rname);
9031           emitcode ("movx", "a,@%s", rname);
9032           break;
9033
9034         case FPOINTER:
9035           emitcode ("inc", "dptr");
9036           emitcode ("movx", "a,@dptr");
9037           break;
9038
9039         case CPOINTER:
9040           emitcode ("clr", "a");
9041           emitcode ("inc", "dptr");
9042           emitcode ("movc", "a,@a+dptr");
9043           break;
9044
9045         case GPOINTER:
9046           emitcode ("inc", "dptr");
9047           emitcode ("lcall", "__gptrget");
9048           break;
9049         }
9050
9051       rlen -= 8;
9052       /* if we are done */
9053       if (rlen < 8)
9054         break;
9055
9056       aopPut (AOP (result), "a", offset++);
9057
9058     }
9059
9060   if (rlen)
9061     {
9062       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9063       aopPut (AOP (result), "a", offset);
9064     }
9065
9066   return;
9067 }
9068
9069
9070 /*-----------------------------------------------------------------*/
9071 /* genDataPointerGet - generates code when ptr offset is known     */
9072 /*-----------------------------------------------------------------*/
9073 static void
9074 genDataPointerGet (operand * left,
9075                    operand * result,
9076                    iCode * ic)
9077 {
9078   char *l;
9079   char buff[256];
9080   int size, offset = 0;
9081   aopOp (result, ic, TRUE, FALSE);
9082
9083   /* get the string representation of the name */
9084   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9085   size = AOP_SIZE (result);
9086   _startLazyDPSEvaluation ();
9087   while (size--)
9088     {
9089         if (offset)
9090         {
9091             SNPRINTF (buff, sizeof(buff), 
9092                       "(%s + %d)", l + 1, offset);
9093         }
9094         else
9095         {
9096             SNPRINTF (buff, sizeof(buff), 
9097                       "%s", l + 1);
9098         }
9099       aopPut (AOP (result), buff, offset++);
9100     }
9101   _endLazyDPSEvaluation ();
9102
9103   freeAsmop (left, NULL, ic, TRUE);
9104   freeAsmop (result, NULL, ic, TRUE);
9105 }
9106
9107 /*-----------------------------------------------------------------*/
9108 /* genNearPointerGet - emitcode for near pointer fetch             */
9109 /*-----------------------------------------------------------------*/
9110 static void
9111 genNearPointerGet (operand * left,
9112                    operand * result,
9113                    iCode * ic,
9114                    iCode *pi)
9115 {
9116   asmop *aop = NULL;
9117   regs *preg;
9118   char *rname;
9119   sym_link *rtype, *retype, *letype;
9120   sym_link *ltype = operandType (left);
9121   char buff[80];
9122
9123   rtype = operandType (result);
9124   retype = getSpec (rtype);
9125   letype = getSpec (ltype);
9126
9127   aopOp (left, ic, FALSE, FALSE);
9128
9129   /* if left is rematerialisable and
9130      result is not bit variable type and
9131      the left is pointer to data space i.e
9132      lower 128 bytes of space */
9133   if (AOP_TYPE (left) == AOP_IMMD &&
9134       !IS_BITVAR (retype) &&
9135       !IS_BITVAR (letype) &&
9136       DCL_TYPE (ltype) == POINTER)
9137     {
9138       genDataPointerGet (left, result, ic);
9139       return;
9140     }
9141
9142   /* if the value is already in a pointer register
9143      then don't need anything more */
9144   if (!AOP_INPREG (AOP (left)))
9145     {
9146       /* otherwise get a free pointer register */
9147       aop = newAsmop (0);
9148       preg = getFreePtr (ic, &aop, FALSE);
9149       emitcode ("mov", "%s,%s",
9150                 preg->name,
9151                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9152       rname = preg->name;
9153     }
9154   else
9155     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9156
9157   freeAsmop (left, NULL, ic, TRUE);
9158   aopOp (result, ic, FALSE, FALSE);
9159
9160   /* if bitfield then unpack the bits */
9161   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9162     genUnpackBits (result, rname, POINTER);
9163   else
9164     {
9165       /* we have can just get the values */
9166       int size = AOP_SIZE (result);
9167       int offset = 0;
9168
9169       while (size--)
9170         {
9171           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9172             {
9173
9174               emitcode ("mov", "a,@%s", rname);
9175               aopPut (AOP (result), "a", offset);
9176             }
9177           else
9178             {
9179               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9180               aopPut (AOP (result), buff, offset);
9181             }
9182           offset++;
9183           if (size || pi)
9184             {
9185                 emitcode ("inc", "%s", rname);
9186             }
9187         }
9188     }
9189
9190   /* now some housekeeping stuff */
9191   if (aop)
9192     {
9193       /* we had to allocate for this iCode */
9194       if (pi) { /* post increment present */
9195         aopPut(AOP ( left ),rname,0);
9196       }
9197       freeAsmop (NULL, aop, ic, TRUE);
9198     }
9199   else
9200     {
9201       /* we did not allocate which means left
9202          already in a pointer register, then
9203          if size > 0 && this could be used again
9204          we have to point it back to where it
9205          belongs */
9206       if (AOP_SIZE (result) > 1 &&
9207           !OP_SYMBOL (left)->remat &&
9208           (OP_SYMBOL (left)->liveTo > ic->seq ||
9209            ic->depth) &&
9210           !pi)
9211         {
9212           int size = AOP_SIZE (result) - 1;
9213           while (size--)
9214             emitcode ("dec", "%s", rname);
9215         }
9216     }
9217
9218   /* done */
9219   freeAsmop (result, NULL, ic, TRUE);
9220   if (pi) pi->generated = 1;
9221 }
9222
9223 /*-----------------------------------------------------------------*/
9224 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9225 /*-----------------------------------------------------------------*/
9226 static void
9227 genPagedPointerGet (operand * left,
9228                     operand * result,
9229                     iCode * ic,
9230                     iCode * pi)
9231 {
9232   asmop *aop = NULL;
9233   regs *preg;
9234   char *rname;
9235   sym_link *rtype, *retype, *letype;
9236
9237   rtype = operandType (result);
9238   retype = getSpec (rtype);
9239   letype = getSpec (operandType (left));
9240   aopOp (left, ic, FALSE, FALSE);
9241
9242   /* if the value is already in a pointer register
9243      then don't need anything more */
9244   if (!AOP_INPREG (AOP (left)))
9245     {
9246       /* otherwise get a free pointer register */
9247       aop = newAsmop (0);
9248       preg = getFreePtr (ic, &aop, FALSE);
9249       emitcode ("mov", "%s,%s",
9250                 preg->name,
9251                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9252       rname = preg->name;
9253     }
9254   else
9255     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9256
9257   freeAsmop (left, NULL, ic, TRUE);
9258   aopOp (result, ic, FALSE, FALSE);
9259
9260   /* if bitfield then unpack the bits */
9261   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9262     genUnpackBits (result, rname, PPOINTER);
9263   else
9264     {
9265       /* we have can just get the values */
9266       int size = AOP_SIZE (result);
9267       int offset = 0;
9268
9269       while (size--)
9270         {
9271
9272           emitcode ("movx", "a,@%s", rname);
9273           aopPut (AOP (result), "a", offset);
9274
9275           offset++;
9276
9277           if (size || pi)
9278             emitcode ("inc", "%s", rname);
9279         }
9280     }
9281
9282   /* now some housekeeping stuff */
9283   if (aop)
9284     {
9285       /* we had to allocate for this iCode */
9286       if (pi) aopPut ( AOP (left), rname, 0);
9287       freeAsmop (NULL, aop, ic, TRUE);
9288     }
9289   else
9290     {
9291       /* we did not allocate which means left
9292          already in a pointer register, then
9293          if size > 0 && this could be used again
9294          we have to point it back to where it
9295          belongs */
9296       if (AOP_SIZE (result) > 1 &&
9297           !OP_SYMBOL (left)->remat &&
9298           (OP_SYMBOL (left)->liveTo > ic->seq ||
9299            ic->depth) &&
9300           !pi)
9301         {
9302           int size = AOP_SIZE (result) - 1;
9303           while (size--)
9304             emitcode ("dec", "%s", rname);
9305         }
9306     }
9307
9308   /* done */
9309   freeAsmop (result, NULL, ic, TRUE);
9310   if (pi) pi->generated = 1;
9311 }
9312
9313 /*-----------------------------------------------------------------*/
9314 /* genFarPointerGet - gget value from far space                    */
9315 /*-----------------------------------------------------------------*/
9316 static void
9317 genFarPointerGet (operand * left,
9318                   operand * result, iCode * ic, iCode *pi)
9319 {
9320     int size, offset, dopi=1;
9321   sym_link *retype = getSpec (operandType (result));
9322   sym_link *letype = getSpec (operandType (left));
9323   D (emitcode (";", "genFarPointerGet"););
9324
9325   aopOp (left, ic, FALSE, FALSE);
9326
9327   /* if the operand is already in dptr
9328      then we do nothing else we move the value to dptr */
9329   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9330     {
9331       /* if this is remateriazable */
9332       if (AOP_TYPE (left) == AOP_IMMD)
9333         {
9334           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9335         }
9336       else
9337         {
9338           /* we need to get it byte by byte */
9339           _startLazyDPSEvaluation ();
9340           if (AOP_TYPE (left) != AOP_DPTR)
9341             {
9342               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9343               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9344               if (options.model == MODEL_FLAT24)
9345                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9346             }
9347           else
9348             {
9349               /* We need to generate a load to DPTR indirect through DPTR. */
9350               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9351               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9352               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9353               if (options.model == MODEL_FLAT24)
9354                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9355               emitcode ("pop", "dph");
9356               emitcode ("pop", "dpl");
9357               dopi =0;
9358             }
9359           _endLazyDPSEvaluation ();
9360         }
9361     }
9362   /* so dptr know contains the address */
9363   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9364
9365   /* if bit then unpack */
9366   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9367       if (AOP_INDPTRn(left)) {
9368           genSetDPTR(AOP(left)->aopu.dptr);
9369       }
9370       genUnpackBits (result, "dptr", FPOINTER);
9371       if (AOP_INDPTRn(left)) {
9372           genSetDPTR(0);
9373       }
9374   } else
9375     {
9376       size = AOP_SIZE (result);
9377       offset = 0;
9378
9379       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9380           while (size--) {
9381               genSetDPTR(AOP(left)->aopu.dptr);
9382               emitcode ("movx", "a,@dptr");
9383               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9384                   emitcode ("inc", "dptr");
9385               genSetDPTR (0);
9386               aopPut (AOP (result), "a", offset++);
9387           }
9388       } else {
9389           _startLazyDPSEvaluation ();
9390           while (size--) {
9391               if (AOP_INDPTRn(left)) {
9392                   genSetDPTR(AOP(left)->aopu.dptr);
9393               } else {
9394                   genSetDPTR (0);
9395               }
9396               _flushLazyDPS ();
9397               
9398               emitcode ("movx", "a,@dptr");
9399               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9400                   emitcode ("inc", "dptr");
9401               
9402               aopPut (AOP (result), "a", offset++);
9403           }
9404           _endLazyDPSEvaluation ();
9405       }
9406     }
9407   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9408       if (!AOP_INDPTRn(left)) {
9409           _startLazyDPSEvaluation ();
9410           aopPut ( AOP (left), "dpl", 0);
9411           aopPut ( AOP (left), "dph", 1);
9412           if (options.model == MODEL_FLAT24)
9413               aopPut ( AOP (left), "dpx", 2);
9414           _endLazyDPSEvaluation ();
9415       }
9416     pi->generated = 1;
9417   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9418              AOP_SIZE(result) > 1 &&
9419              IS_SYMOP(left) &&
9420              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9421       
9422       size = AOP_SIZE (result) - 1;
9423       if (AOP_INDPTRn(left)) {
9424           genSetDPTR(AOP(left)->aopu.dptr);
9425       }
9426       while (size--) emitcode ("lcall","__decdptr");
9427       if (AOP_INDPTRn(left)) {
9428           genSetDPTR(0);
9429       }
9430   }
9431
9432   freeAsmop (left, NULL, ic, TRUE);
9433   freeAsmop (result, NULL, ic, TRUE);
9434 }
9435
9436 /*-----------------------------------------------------------------*/
9437 /* genCodePointerGet - get value from code space                  */
9438 /*-----------------------------------------------------------------*/
9439 static void
9440 genCodePointerGet (operand * left,
9441                     operand * result, iCode * ic, iCode *pi)
9442 {
9443   int size, offset, dopi=1;
9444   sym_link *retype = getSpec (operandType (result));
9445
9446   aopOp (left, ic, FALSE, FALSE);
9447
9448   /* if the operand is already in dptr
9449      then we do nothing else we move the value to dptr */
9450   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9451     {
9452       /* if this is remateriazable */
9453       if (AOP_TYPE (left) == AOP_IMMD)
9454         {
9455           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9456         }
9457       else
9458         {                       /* we need to get it byte by byte */
9459           _startLazyDPSEvaluation ();
9460           if (AOP_TYPE (left) != AOP_DPTR)
9461             {
9462               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9463               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9464               if (options.model == MODEL_FLAT24)
9465                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9466             }
9467           else
9468             {
9469               /* We need to generate a load to DPTR indirect through DPTR. */
9470               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9471               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9472               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9473               if (options.model == MODEL_FLAT24)
9474                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9475               emitcode ("pop", "dph");
9476               emitcode ("pop", "dpl");
9477               dopi=0;
9478             }
9479           _endLazyDPSEvaluation ();
9480         }
9481     }
9482   /* so dptr know contains the address */
9483   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9484
9485   /* if bit then unpack */
9486   if (IS_BITVAR (retype)) {
9487       if (AOP_INDPTRn(left)) {
9488           genSetDPTR(AOP(left)->aopu.dptr);
9489       }
9490       genUnpackBits (result, "dptr", CPOINTER);
9491       if (AOP_INDPTRn(left)) {
9492           genSetDPTR(0);
9493       }
9494   } else
9495     {
9496       size = AOP_SIZE (result);
9497       offset = 0;
9498       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9499           while (size--) {
9500               genSetDPTR(AOP(left)->aopu.dptr);
9501               emitcode ("clr", "a");
9502               emitcode ("movc", "a,@a+dptr");
9503               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9504                   emitcode ("inc", "dptr");
9505               genSetDPTR (0);
9506               aopPut (AOP (result), "a", offset++);
9507           }
9508       } else {
9509           _startLazyDPSEvaluation ();
9510           while (size--)
9511               {
9512                   if (AOP_INDPTRn(left)) {
9513                       genSetDPTR(AOP(left)->aopu.dptr);
9514                   } else {
9515                       genSetDPTR (0);
9516                   }
9517                   _flushLazyDPS ();
9518                   
9519                   emitcode ("clr", "a");
9520                   emitcode ("movc", "a,@a+dptr");
9521                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9522                       emitcode ("inc", "dptr");
9523                   aopPut (AOP (result), "a", offset++);
9524               }
9525           _endLazyDPSEvaluation ();
9526       }
9527     }
9528   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9529       if (!AOP_INDPTRn(left)) {
9530           _startLazyDPSEvaluation ();
9531           
9532           aopPut ( AOP (left), "dpl", 0);
9533           aopPut ( AOP (left), "dph", 1);
9534           if (options.model == MODEL_FLAT24)
9535               aopPut ( AOP (left), "dpx", 2);
9536
9537           _endLazyDPSEvaluation ();
9538       }
9539       pi->generated = 1;
9540   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9541              AOP_SIZE(result) > 1 &&
9542              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9543       
9544       size = AOP_SIZE (result) - 1;
9545       if (AOP_INDPTRn(left)) {
9546           genSetDPTR(AOP(left)->aopu.dptr);
9547       }
9548       while (size--) emitcode ("lcall","__decdptr");
9549       if (AOP_INDPTRn(left)) {
9550           genSetDPTR(0);
9551       }
9552   }
9553   
9554   freeAsmop (left, NULL, ic, TRUE);
9555   freeAsmop (result, NULL, ic, TRUE);
9556 }
9557
9558 /*-----------------------------------------------------------------*/
9559 /* genGenPointerGet - gget value from generic pointer space        */
9560 /*-----------------------------------------------------------------*/
9561 static void
9562 genGenPointerGet (operand * left,
9563                   operand * result, iCode * ic, iCode * pi)
9564 {
9565   int size, offset;
9566   sym_link *retype = getSpec (operandType (result));
9567   sym_link *letype = getSpec (operandType (left));
9568
9569   D (emitcode (";", "genGenPointerGet "); );
9570
9571   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9572
9573   /* if the operand is already in dptr
9574      then we do nothing else we move the value to dptr */
9575   if (AOP_TYPE (left) != AOP_STR)
9576     {
9577       /* if this is remateriazable */
9578       if (AOP_TYPE (left) == AOP_IMMD)
9579         {
9580           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9581           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9582             {
9583                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9584             }
9585             else
9586             {
9587                 emitcode ("mov", "b,#%d", pointerCode (retype));
9588             }
9589         }
9590       else
9591         {                       /* we need to get it byte by byte */
9592             _startLazyDPSEvaluation ();
9593             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9594             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9595             if (options.model == MODEL_FLAT24) {
9596                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9597                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9598             } else {
9599                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9600             }
9601             _endLazyDPSEvaluation ();
9602         }
9603     }
9604
9605   /* so dptr-b now contains the address */
9606   _G.bInUse++;
9607   aopOp (result, ic, FALSE, TRUE);
9608   _G.bInUse--;
9609
9610   /* if bit then unpack */
9611   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9612   {
9613     genUnpackBits (result, "dptr", GPOINTER);
9614   }
9615   else
9616     {
9617         size = AOP_SIZE (result);
9618         offset = 0;
9619
9620         while (size--)
9621         {
9622             if (size)
9623             {
9624                 // Get two bytes at a time, results in _AP & A.
9625                 // dptr will be incremented ONCE by __gptrgetWord.
9626                 //
9627                 // Note: any change here must be coordinated
9628                 // with the implementation of __gptrgetWord
9629                 // in device/lib/_gptrget.c
9630                 emitcode ("lcall", "__gptrgetWord");
9631                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9632                 aopPut (AOP (result), "a", offset++);
9633                 size--;
9634             }
9635             else
9636             {
9637                 // Only one byte to get.
9638                 emitcode ("lcall", "__gptrget");
9639                 aopPut (AOP (result), "a", offset++);
9640             }
9641             
9642             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9643             {
9644                 emitcode ("inc", "dptr");
9645             }
9646         }
9647     }
9648
9649   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9650     _startLazyDPSEvaluation ();
9651       
9652     aopPut ( AOP (left), "dpl", 0);
9653     aopPut ( AOP (left), "dph", 1);
9654     if (options.model == MODEL_FLAT24) {
9655         aopPut ( AOP (left), "dpx", 2);
9656         aopPut ( AOP (left), "b", 3);   
9657     } else  aopPut ( AOP (left), "b", 2);       
9658     
9659     _endLazyDPSEvaluation ();
9660       
9661     pi->generated = 1;
9662   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9663              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9664       
9665       size = AOP_SIZE (result) - 1;
9666       while (size--) emitcode ("lcall","__decdptr");
9667   }
9668
9669   freeAsmop (left, NULL, ic, TRUE);
9670   freeAsmop (result, NULL, ic, TRUE);
9671 }
9672
9673 /*-----------------------------------------------------------------*/
9674 /* genPointerGet - generate code for pointer get                   */
9675 /*-----------------------------------------------------------------*/
9676 static void
9677 genPointerGet (iCode * ic, iCode *pi)
9678 {
9679   operand *left, *result;
9680   sym_link *type, *etype;
9681   int p_type;
9682
9683   D (emitcode (";", "genPointerGet ");
9684     );
9685
9686   left = IC_LEFT (ic);
9687   result = IC_RESULT (ic);
9688
9689   /* depending on the type of pointer we need to
9690      move it to the correct pointer register */
9691   type = operandType (left);
9692   etype = getSpec (type);
9693   /* if left is of type of pointer then it is simple */
9694   if (IS_PTR (type) && !IS_FUNC (type->next))
9695     p_type = DCL_TYPE (type);
9696   else
9697     {
9698       /* we have to go by the storage class */
9699       p_type = PTR_TYPE (SPEC_OCLS (etype));
9700     }
9701   /* special case when cast remat */
9702   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9703       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9704           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9705           type = operandType (left);
9706           p_type = DCL_TYPE (type);
9707   }
9708   /* now that we have the pointer type we assign
9709      the pointer values */
9710   switch (p_type)
9711     {
9712
9713     case POINTER:
9714     case IPOINTER:
9715       genNearPointerGet (left, result, ic, pi);
9716       break;
9717
9718     case PPOINTER:
9719       genPagedPointerGet (left, result, ic, pi);
9720       break;
9721
9722     case FPOINTER:
9723       genFarPointerGet (left, result, ic, pi);
9724       break;
9725
9726     case CPOINTER:
9727       genCodePointerGet (left, result, ic, pi);
9728       break;
9729
9730     case GPOINTER:
9731       genGenPointerGet (left, result, ic, pi);
9732       break;
9733     }
9734
9735 }
9736
9737 /*-----------------------------------------------------------------*/
9738 /* genPackBits - generates code for packed bit storage             */
9739 /*-----------------------------------------------------------------*/
9740 static void
9741 genPackBits (sym_link * etype,
9742              operand * right,
9743              char *rname, int p_type)
9744 {
9745   int offset = 0;
9746   int rLen;
9747   int blen, bstr;
9748   char *l;
9749
9750   blen = SPEC_BLEN (etype);
9751   bstr = SPEC_BSTR (etype);
9752
9753   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9754
9755   /* if the bit lenth is less than or    */
9756   /* it exactly fits a byte then         */
9757   if (SPEC_BLEN (etype) <= 8)
9758     {
9759       /* shift left acc */
9760       AccLsh (SPEC_BSTR (etype));
9761
9762       if (SPEC_BLEN (etype) < 8)
9763         {                       /* if smaller than a byte */
9764
9765
9766           switch (p_type)
9767             {
9768             case POINTER:
9769               emitcode ("mov", "b,a");
9770               emitcode ("mov", "a,@%s", rname);
9771               break;
9772
9773             case FPOINTER:
9774               emitcode ("mov", "b,a");
9775               emitcode ("movx", "a,@dptr");
9776               break;
9777
9778             case GPOINTER:
9779               emitcode ("push", "b");
9780               emitcode ("push", "acc");
9781               emitcode ("lcall", "__gptrget");
9782               emitcode ("pop", "b");
9783               break;
9784             }
9785
9786           emitcode ("anl", "a,#!constbyte", (unsigned char)
9787                     ((unsigned char) (0xFF << (blen + bstr)) |
9788                      (unsigned char) (0xFF >> (8 - bstr))));
9789           emitcode ("orl", "a,b");
9790           if (p_type == GPOINTER)
9791             emitcode ("pop", "b");
9792         }
9793     }
9794
9795   switch (p_type)
9796     {
9797     case POINTER:
9798       emitcode ("mov", "@%s,a", rname);
9799       break;
9800
9801     case FPOINTER:
9802       emitcode ("movx", "@dptr,a");
9803       break;
9804
9805     case GPOINTER:
9806       emitcode ("lcall", "__gptrput");
9807       break;
9808     }
9809
9810   /* if we r done */
9811   if (SPEC_BLEN (etype) <= 8)
9812     return;
9813
9814   emitcode ("inc", "%s", rname);
9815   rLen = SPEC_BLEN (etype);
9816
9817   /* now generate for lengths greater than one byte */
9818   while (1)
9819     {
9820
9821       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9822
9823       rLen -= 8;
9824       if (rLen < 8)
9825         break;
9826
9827       switch (p_type)
9828         {
9829         case POINTER:
9830           if (*l == '@')
9831             {
9832               MOVA (l);
9833               emitcode ("mov", "@%s,a", rname);
9834             }
9835           else
9836             emitcode ("mov", "@%s,%s", rname, l);
9837           break;
9838
9839         case FPOINTER:
9840           MOVA (l);
9841           emitcode ("movx", "@dptr,a");
9842           break;
9843
9844         case GPOINTER:
9845           MOVA (l);
9846           emitcode ("lcall", "__gptrput");
9847           break;
9848         }
9849       emitcode ("inc", "%s", rname);
9850     }
9851
9852   MOVA (l);
9853
9854   /* last last was not complete */
9855   if (rLen)
9856     {
9857       /* save the byte & read byte */
9858       switch (p_type)
9859         {
9860         case POINTER:
9861           emitcode ("mov", "b,a");
9862           emitcode ("mov", "a,@%s", rname);
9863           break;
9864
9865         case FPOINTER:
9866           emitcode ("mov", "b,a");
9867           emitcode ("movx", "a,@dptr");
9868           break;
9869
9870         case GPOINTER:
9871           emitcode ("push", "b");
9872           emitcode ("push", "acc");
9873           emitcode ("lcall", "__gptrget");
9874           emitcode ("pop", "b");
9875           break;
9876         }
9877
9878       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9879       emitcode ("orl", "a,b");
9880     }
9881
9882   if (p_type == GPOINTER)
9883     emitcode ("pop", "b");
9884
9885   switch (p_type)
9886     {
9887
9888     case POINTER:
9889       emitcode ("mov", "@%s,a", rname);
9890       break;
9891
9892     case FPOINTER:
9893       emitcode ("movx", "@dptr,a");
9894       break;
9895
9896     case GPOINTER:
9897       emitcode ("lcall", "__gptrput");
9898       break;
9899     }
9900 }
9901 /*-----------------------------------------------------------------*/
9902 /* genDataPointerSet - remat pointer to data space                 */
9903 /*-----------------------------------------------------------------*/
9904 static void
9905 genDataPointerSet (operand * right,
9906                    operand * result,
9907                    iCode * ic)
9908 {
9909   int size, offset = 0;
9910   char *l, buff[256];
9911
9912   aopOp (right, ic, FALSE, FALSE);
9913
9914   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9915   size = AOP_SIZE (right);
9916   while (size--)
9917     {
9918       if (offset)
9919         {
9920             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9921         }
9922       else
9923         {
9924             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9925         }
9926         
9927       emitcode ("mov", "%s,%s", buff,
9928                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9929     }
9930
9931   freeAsmop (right, NULL, ic, TRUE);
9932   freeAsmop (result, NULL, ic, TRUE);
9933 }
9934
9935 /*-----------------------------------------------------------------*/
9936 /* genNearPointerSet - emitcode for near pointer put                */
9937 /*-----------------------------------------------------------------*/
9938 static void
9939 genNearPointerSet (operand * right,
9940                    operand * result,
9941                    iCode * ic,
9942                    iCode * pi)
9943 {
9944   asmop *aop = NULL;
9945   char *rname, *l;
9946   sym_link *retype, *letype;
9947   sym_link *ptype = operandType (result);
9948
9949   retype = getSpec (operandType (right));
9950   letype = getSpec (ptype);
9951
9952   aopOp (result, ic, FALSE, FALSE);
9953
9954   /* if the result is rematerializable &
9955      in data space & not a bit variable */
9956   if (AOP_TYPE (result) == AOP_IMMD &&
9957       DCL_TYPE (ptype) == POINTER &&
9958       !IS_BITVAR (retype) &&
9959       !IS_BITVAR (letype))
9960     {
9961       genDataPointerSet (right, result, ic);
9962       return;
9963     }
9964
9965   /* if the value is already in a pointer register
9966      then don't need anything more */
9967   if (!AOP_INPREG (AOP (result)))
9968     {
9969       /* otherwise get a free pointer register */
9970       regs *preg;
9971         
9972       aop = newAsmop (0);
9973       preg = getFreePtr (ic, &aop, FALSE);
9974       emitcode ("mov", "%s,%s",
9975                 preg->name,
9976                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9977       rname = preg->name;
9978     }
9979   else
9980     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9981
9982   aopOp (right, ic, FALSE, FALSE);
9983
9984   /* if bitfield then unpack the bits */
9985   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9986     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9987   else
9988     {
9989       /* we have can just get the values */
9990       int size = AOP_SIZE (right);
9991       int offset = 0;
9992
9993       while (size--)
9994         {
9995           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9996           if (*l == '@')
9997             {
9998               MOVA (l);
9999               emitcode ("mov", "@%s,a", rname);
10000             }
10001           else
10002             emitcode ("mov", "@%s,%s", rname, l);
10003           if (size || pi)
10004             emitcode ("inc", "%s", rname);
10005           offset++;
10006         }
10007     }
10008
10009   /* now some housekeeping stuff */
10010   if (aop)
10011     {
10012       /* we had to allocate for this iCode */
10013       if (pi) aopPut (AOP (result),rname,0);
10014       freeAsmop (NULL, aop, ic, TRUE);
10015     }
10016   else
10017     {
10018       /* we did not allocate which means left
10019          already in a pointer register, then
10020          if size > 0 && this could be used again
10021          we have to point it back to where it
10022          belongs */
10023       if (AOP_SIZE (right) > 1 &&
10024           !OP_SYMBOL (result)->remat &&
10025           (OP_SYMBOL (result)->liveTo > ic->seq ||
10026            ic->depth) &&
10027           !pi)
10028         {
10029           int size = AOP_SIZE (right) - 1;
10030           while (size--)
10031             emitcode ("dec", "%s", rname);
10032         }
10033     }
10034
10035   /* done */
10036   if (pi) pi->generated = 1;
10037   freeAsmop (result, NULL, ic, TRUE);
10038   freeAsmop (right, NULL, ic, TRUE);
10039
10040
10041 }
10042
10043 /*-----------------------------------------------------------------*/
10044 /* genPagedPointerSet - emitcode for Paged pointer put             */
10045 /*-----------------------------------------------------------------*/
10046 static void
10047 genPagedPointerSet (operand * right,
10048                     operand * result,
10049                     iCode * ic,
10050                     iCode *pi)
10051 {
10052   asmop *aop = NULL;
10053   char *rname;
10054   sym_link *retype, *letype;
10055
10056   retype = getSpec (operandType (right));
10057   letype = getSpec (operandType (result));
10058
10059   aopOp (result, ic, FALSE, FALSE);
10060
10061   /* if the value is already in a pointer register
10062      then don't need anything more */
10063   if (!AOP_INPREG (AOP (result)))
10064     {
10065       /* otherwise get a free pointer register */
10066       regs *preg;
10067         
10068       aop = newAsmop (0);
10069       preg = getFreePtr (ic, &aop, FALSE);
10070       emitcode ("mov", "%s,%s",
10071                 preg->name,
10072                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10073       rname = preg->name;
10074     }
10075   else
10076     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10077
10078   aopOp (right, ic, FALSE, FALSE);
10079
10080   /* if bitfield then unpack the bits */
10081   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10082     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10083   else
10084     {
10085       /* we have can just get the values */
10086       int size = AOP_SIZE (right);
10087       int offset = 0;
10088
10089       while (size--)
10090         {
10091           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10092
10093           emitcode ("movx", "@%s,a", rname);
10094
10095           if (size || pi)
10096             emitcode ("inc", "%s", rname);
10097
10098           offset++;
10099         }
10100     }
10101
10102   /* now some housekeeping stuff */
10103   if (aop)
10104     {
10105       if (pi) aopPut (AOP (result),rname,0);
10106       /* we had to allocate for this iCode */
10107       freeAsmop (NULL, aop, ic, TRUE);
10108     }
10109   else
10110     {
10111       /* we did not allocate which means left
10112          already in a pointer register, then
10113          if size > 0 && this could be used again
10114          we have to point it back to where it
10115          belongs */
10116       if (AOP_SIZE (right) > 1 &&
10117           !OP_SYMBOL (result)->remat &&
10118           (OP_SYMBOL (result)->liveTo > ic->seq ||
10119            ic->depth) &&
10120           !pi)
10121         {
10122           int size = AOP_SIZE (right) - 1;
10123           while (size--)
10124             emitcode ("dec", "%s", rname);
10125         }
10126     }
10127
10128   /* done */
10129   if (pi) pi->generated = 1;
10130   freeAsmop (result, NULL, ic, TRUE);
10131   freeAsmop (right, NULL, ic, TRUE);
10132
10133
10134 }
10135
10136 /*-----------------------------------------------------------------*/
10137 /* genFarPointerSet - set value from far space                     */
10138 /*-----------------------------------------------------------------*/
10139 static void
10140 genFarPointerSet (operand * right,
10141                   operand * result, iCode * ic, iCode *pi)
10142 {
10143   int size, offset, dopi=1;
10144   sym_link *retype = getSpec (operandType (right));
10145   sym_link *letype = getSpec (operandType (result));
10146
10147   aopOp (result, ic, FALSE, FALSE);
10148
10149   /* if the operand is already in dptr
10150      then we do nothing else we move the value to dptr */
10151   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10152     {
10153       /* if this is remateriazable */
10154       if (AOP_TYPE (result) == AOP_IMMD)
10155         emitcode ("mov", "dptr,%s", 
10156                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10157       else
10158         {
10159           /* we need to get it byte by byte */
10160           _startLazyDPSEvaluation ();
10161           if (AOP_TYPE (result) != AOP_DPTR)
10162             {
10163               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10164               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10165               if (options.model == MODEL_FLAT24)
10166                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10167             }
10168           else
10169             {
10170               /* We need to generate a load to DPTR indirect through DPTR. */
10171               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10172                 
10173               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10174               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10175               if (options.model == MODEL_FLAT24)
10176                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10177               emitcode ("pop", "dph");
10178               emitcode ("pop", "dpl");
10179               dopi=0;
10180             }
10181           _endLazyDPSEvaluation ();
10182         }
10183     }
10184   /* so dptr know contains the address */
10185   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10186
10187   /* if bit then unpack */
10188   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10189       if (AOP_INDPTRn(result)) {
10190           genSetDPTR(AOP(result)->aopu.dptr);
10191       }
10192       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10193       if (AOP_INDPTRn(result)) {
10194           genSetDPTR(0);
10195       }
10196   } else {
10197       size = AOP_SIZE (right);
10198       offset = 0;
10199       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10200           while (size--) {
10201               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10202               
10203               genSetDPTR(AOP(result)->aopu.dptr);
10204               emitcode ("movx", "@dptr,a");
10205               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10206                   emitcode ("inc", "dptr");
10207               genSetDPTR (0);
10208           }
10209       } else {
10210           _startLazyDPSEvaluation ();
10211           while (size--) {
10212               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10213               
10214               if (AOP_INDPTRn(result)) {
10215                   genSetDPTR(AOP(result)->aopu.dptr);
10216               } else {
10217                   genSetDPTR (0);
10218               }
10219               _flushLazyDPS ();
10220               
10221               emitcode ("movx", "@dptr,a");
10222               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10223                   emitcode ("inc", "dptr");
10224           }
10225           _endLazyDPSEvaluation ();
10226       }
10227   }
10228   
10229   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10230       if (!AOP_INDPTRn(result)) {
10231           _startLazyDPSEvaluation ();
10232           
10233           aopPut (AOP(result),"dpl",0);
10234           aopPut (AOP(result),"dph",1);
10235           if (options.model == MODEL_FLAT24)
10236               aopPut (AOP(result),"dpx",2);
10237
10238           _endLazyDPSEvaluation ();
10239       }
10240       pi->generated=1;
10241   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10242              AOP_SIZE(right) > 1 &&
10243              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10244       
10245       size = AOP_SIZE (right) - 1;
10246       if (AOP_INDPTRn(result)) {
10247           genSetDPTR(AOP(result)->aopu.dptr);
10248       } 
10249       while (size--) emitcode ("lcall","__decdptr");
10250       if (AOP_INDPTRn(result)) {
10251           genSetDPTR(0);
10252       }
10253   }
10254   freeAsmop (result, NULL, ic, TRUE);
10255   freeAsmop (right, NULL, ic, TRUE);
10256 }
10257
10258 /*-----------------------------------------------------------------*/
10259 /* genGenPointerSet - set value from generic pointer space         */
10260 /*-----------------------------------------------------------------*/
10261 static void
10262 genGenPointerSet (operand * right,
10263                   operand * result, iCode * ic, iCode *pi)
10264 {
10265   int size, offset;
10266   sym_link *retype = getSpec (operandType (right));
10267   sym_link *letype = getSpec (operandType (result));
10268
10269   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10270
10271   /* if the operand is already in dptr
10272      then we do nothing else we move the value to dptr */
10273   if (AOP_TYPE (result) != AOP_STR)
10274     {
10275       _startLazyDPSEvaluation ();
10276       /* if this is remateriazable */
10277       if (AOP_TYPE (result) == AOP_IMMD)
10278         {
10279           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10280           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10281           {
10282               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10283           }
10284           else
10285           {
10286               emitcode ("mov", 
10287                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10288           }
10289         }
10290       else
10291         {                       /* we need to get it byte by byte */
10292           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10293           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10294           if (options.model == MODEL_FLAT24) {
10295             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10296             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10297           } else {
10298             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10299           }
10300         }
10301       _endLazyDPSEvaluation ();
10302     }
10303   /* so dptr + b now contains the address */
10304   _G.bInUse++;
10305   aopOp (right, ic, FALSE, TRUE);
10306   _G.bInUse--;
10307     
10308
10309   /* if bit then unpack */
10310   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10311     {
10312         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10313     }
10314   else
10315     {
10316         size = AOP_SIZE (right);
10317         offset = 0;
10318
10319         _startLazyDPSEvaluation ();
10320         while (size--)
10321         {
10322             if (size)
10323             {
10324                 // Set two bytes at a time, passed in _AP & A.
10325                 // dptr will be incremented ONCE by __gptrputWord.
10326                 //
10327                 // Note: any change here must be coordinated
10328                 // with the implementation of __gptrputWord
10329                 // in device/lib/_gptrput.c
10330                 emitcode("mov", "_ap, %s", 
10331                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10332                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10333                 
10334                 genSetDPTR (0);
10335                 _flushLazyDPS ();
10336                 emitcode ("lcall", "__gptrputWord");
10337                 size--;
10338             }
10339             else
10340             {
10341                 // Only one byte to put.
10342                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10343
10344                 genSetDPTR (0);
10345                 _flushLazyDPS ();               
10346                 emitcode ("lcall", "__gptrput");
10347             }
10348             
10349             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10350             {
10351                 emitcode ("inc", "dptr");
10352             }
10353         }
10354         _endLazyDPSEvaluation ();
10355     }
10356
10357   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10358       _startLazyDPSEvaluation ();
10359       
10360       aopPut (AOP(result),"dpl",0);
10361       aopPut (AOP(result),"dph",1);
10362       if (options.model == MODEL_FLAT24) {
10363           aopPut (AOP(result),"dpx",2);
10364           aopPut (AOP(result),"b",3);
10365       } else {
10366           aopPut (AOP(result),"b",2);
10367       }
10368       _endLazyDPSEvaluation ();
10369       
10370       pi->generated=1;
10371   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10372              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10373       
10374       size = AOP_SIZE (right) - 1;
10375       while (size--) emitcode ("lcall","__decdptr");
10376   }
10377   freeAsmop (result, NULL, ic, TRUE);
10378   freeAsmop (right, NULL, ic, TRUE);
10379 }
10380
10381 /*-----------------------------------------------------------------*/
10382 /* genPointerSet - stores the value into a pointer location        */
10383 /*-----------------------------------------------------------------*/
10384 static void
10385 genPointerSet (iCode * ic, iCode *pi)
10386 {
10387   operand *right, *result;
10388   sym_link *type, *etype;
10389   int p_type;
10390
10391   D (emitcode (";", "genPointerSet "););
10392
10393   right = IC_RIGHT (ic);
10394   result = IC_RESULT (ic);
10395
10396   /* depending on the type of pointer we need to
10397      move it to the correct pointer register */
10398   type = operandType (result);
10399   etype = getSpec (type);
10400   /* if left is of type of pointer then it is simple */
10401   if (IS_PTR (type) && !IS_FUNC (type->next))
10402     {
10403       p_type = DCL_TYPE (type);
10404     }
10405   else
10406     {
10407       /* we have to go by the storage class */
10408       p_type = PTR_TYPE (SPEC_OCLS (etype));
10409     }
10410   /* special case when cast remat */
10411   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10412       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10413           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10414           type = operandType (result);
10415           p_type = DCL_TYPE (type);
10416   }
10417
10418   /* now that we have the pointer type we assign
10419      the pointer values */
10420   switch (p_type)
10421     {
10422
10423     case POINTER:
10424     case IPOINTER:
10425       genNearPointerSet (right, result, ic, pi);
10426       break;
10427
10428     case PPOINTER:
10429       genPagedPointerSet (right, result, ic, pi);
10430       break;
10431
10432     case FPOINTER:
10433       genFarPointerSet (right, result, ic, pi);
10434       break;
10435
10436     case GPOINTER:
10437       genGenPointerSet (right, result, ic, pi);
10438       break;
10439
10440     default:
10441       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10442               "genPointerSet: illegal pointer type");
10443     }
10444
10445 }
10446
10447 /*-----------------------------------------------------------------*/
10448 /* genIfx - generate code for Ifx statement                        */
10449 /*-----------------------------------------------------------------*/
10450 static void
10451 genIfx (iCode * ic, iCode * popIc)
10452 {
10453   operand *cond = IC_COND (ic);
10454   int isbit = 0;
10455
10456   D (emitcode (";", "genIfx "););
10457
10458   aopOp (cond, ic, FALSE, FALSE);
10459
10460   /* get the value into acc */
10461   if (AOP_TYPE (cond) != AOP_CRY)
10462     {
10463         toBoolean (cond);
10464     }
10465   else
10466     {
10467         isbit = 1;
10468     }
10469     
10470   /* the result is now in the accumulator */
10471   freeAsmop (cond, NULL, ic, TRUE);
10472
10473   /* if there was something to be popped then do it */
10474   if (popIc)
10475     genIpop (popIc);
10476
10477   /* if the condition is  a bit variable */
10478   if (isbit && IS_ITEMP (cond) &&
10479       SPIL_LOC (cond))
10480     {
10481         genIfxJump (ic, SPIL_LOC (cond)->rname);
10482     }
10483   else if (isbit && !IS_ITEMP (cond))
10484     {
10485         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10486     }
10487   else
10488     {
10489         genIfxJump (ic, "a");
10490     }
10491
10492   ic->generated = 1;
10493 }
10494
10495 /*-----------------------------------------------------------------*/
10496 /* genAddrOf - generates code for address of                       */
10497 /*-----------------------------------------------------------------*/
10498 static void
10499 genAddrOf (iCode * ic)
10500 {
10501   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10502   int size, offset;
10503
10504   D (emitcode (";", "genAddrOf ");
10505     );
10506
10507   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10508
10509   /* if the operand is on the stack then we
10510      need to get the stack offset of this
10511      variable */
10512   if (sym->onStack) {
10513       
10514       /* if 10 bit stack */
10515       if (options.stack10bit) {
10516           char buff[10];
10517           tsprintf(buff, sizeof(buff), 
10518                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10519           /* if it has an offset then we need to compute it */
10520 /*        emitcode ("subb", "a,#!constbyte", */
10521 /*                  -((sym->stack < 0) ? */
10522 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10523 /*                    ((short) sym->stack)) & 0xff); */
10524 /*        emitcode ("mov","b,a"); */
10525 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10526 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10527 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10528           if (sym->stack) {
10529               emitcode ("mov", "a,_bpx");
10530               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10531                                              ((char) (sym->stack - _G.nRegsSaved)) :
10532                                              ((char) sym->stack )) & 0xff);
10533               emitcode ("mov", "b,a");
10534               emitcode ("mov", "a,_bpx+1");
10535               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10536                                               ((short) (sym->stack - _G.nRegsSaved)) :
10537                                               ((short) sym->stack )) >> 8) & 0xff);
10538               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10539               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10540               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10541           } else {
10542               /* we can just move _bp */
10543               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10544               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10545               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10546           }       
10547       } else {
10548           /* if it has an offset then we need to compute it */
10549           if (sym->stack) {
10550               emitcode ("mov", "a,_bp");
10551               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10552               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10553           } else {
10554               /* we can just move _bp */
10555               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10556           }
10557           /* fill the result with zero */
10558           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10559           
10560           
10561           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10562               fprintf (stderr,
10563                        "*** warning: pointer to stack var truncated.\n");
10564           }
10565
10566           offset = 1;
10567           while (size--) {
10568               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10569           }      
10570       }
10571       goto release;
10572   }
10573
10574   /* object not on stack then we need the name */
10575   size = AOP_SIZE (IC_RESULT (ic));
10576   offset = 0;
10577
10578   while (size--)
10579     {
10580       char s[SDCC_NAME_MAX];
10581       if (offset) {
10582           switch (offset) {
10583           case 1:
10584               tsprintf(s, sizeof(s), "!his",sym->rname);
10585               break;
10586           case 2:
10587               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10588               break;
10589           case 3:
10590               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10591               break;
10592           default: /* should not need this (just in case) */
10593               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10594                        sym->rname,
10595                        offset * 8);
10596           }
10597       } 
10598       else
10599       {
10600           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10601       }
10602         
10603       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10604     }
10605
10606 release:
10607   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10608
10609 }
10610
10611 /*-----------------------------------------------------------------*/
10612 /* genArrayInit - generates code for address of                       */
10613 /*-----------------------------------------------------------------*/
10614 static void
10615 genArrayInit (iCode * ic)
10616 {
10617     literalList *iLoop;
10618     int         ix, count;
10619     int         elementSize = 0, eIndex;
10620     unsigned    val, lastVal;
10621     sym_link    *type;
10622     operand     *left=IC_LEFT(ic);
10623     
10624     D (emitcode (";", "genArrayInit "););
10625
10626     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10627     
10628     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10629     {
10630         // Load immediate value into DPTR.
10631         emitcode("mov", "dptr, %s",
10632              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10633     }
10634     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10635     {
10636 #if 0
10637       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10638               "Unexpected operand to genArrayInit.\n");
10639       exit(1);
10640 #else
10641       // a regression because of SDCCcse.c:1.52
10642       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10643       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10644       if (options.model == MODEL_FLAT24)
10645         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10646 #endif
10647     }
10648     
10649     type = operandType(IC_LEFT(ic));
10650     
10651     if (type && type->next)
10652     {
10653         elementSize = getSize(type->next);
10654     }
10655     else
10656     {
10657         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10658                                 "can't determine element size in genArrayInit.\n");
10659         exit(1);
10660     }
10661     
10662     iLoop = IC_ARRAYILIST(ic);
10663     lastVal = 0xffff;
10664     
10665     while (iLoop)
10666     {
10667         bool firstpass = TRUE;
10668         
10669         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10670                  iLoop->count, (int)iLoop->literalValue, elementSize);
10671         
10672         ix = iLoop->count;
10673         
10674         while (ix)
10675         {
10676             symbol *tlbl = NULL;
10677             
10678             count = ix > 256 ? 256 : ix;
10679             
10680             if (count > 1)
10681             {
10682                 tlbl = newiTempLabel (NULL);
10683                 if (firstpass || (count & 0xff))
10684                 {
10685                     emitcode("mov", "b, #!constbyte", count & 0xff);
10686                 }
10687                 
10688                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10689             }
10690             
10691             firstpass = FALSE;
10692                 
10693             for (eIndex = 0; eIndex < elementSize; eIndex++)
10694             {
10695                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10696                 if (val != lastVal)
10697                 {
10698                     emitcode("mov", "a, #!constbyte", val);
10699                     lastVal = val;
10700                 }
10701                 
10702                 emitcode("movx", "@dptr, a");
10703                 emitcode("inc", "dptr");
10704             }
10705             
10706             if (count > 1)
10707             {
10708                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10709             }
10710             
10711             ix -= count;
10712         }
10713         
10714         iLoop = iLoop->next;
10715     }
10716     
10717     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10718 }
10719
10720 /*-----------------------------------------------------------------*/
10721 /* genFarFarAssign - assignment when both are in far space         */
10722 /*-----------------------------------------------------------------*/
10723 static void
10724 genFarFarAssign (operand * result, operand * right, iCode * ic)
10725 {
10726   int size = AOP_SIZE (right);
10727   int offset = 0;
10728   symbol *rSym = NULL;
10729
10730   if (size == 1)
10731   {
10732       /* quick & easy case. */
10733       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10734       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10735       freeAsmop (right, NULL, ic, FALSE);
10736       /* now assign DPTR to result */
10737       _G.accInUse++;
10738       aopOp(result, ic, FALSE, FALSE);
10739       _G.accInUse--;
10740       aopPut(AOP(result), "a", 0);
10741       freeAsmop(result, NULL, ic, FALSE);
10742       return;
10743   }
10744   
10745   /* See if we've got an underlying symbol to abuse. */
10746   if (IS_SYMOP(result) && OP_SYMBOL(result))
10747   {
10748       if (IS_TRUE_SYMOP(result))
10749       {
10750           rSym = OP_SYMBOL(result);
10751       }
10752       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10753       {
10754           rSym = OP_SYMBOL(result)->usl.spillLoc;
10755       }
10756   }
10757              
10758   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10759   {
10760       /* We can use the '390 auto-toggle feature to good effect here. */
10761       
10762       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10763       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10764       emitcode ("mov", "dptr,#%s", rSym->rname); 
10765       /* DP2 = result, DP1 = right, DP1 is current. */
10766       while (size)
10767       {
10768           emitcode("movx", "a,@dptr");
10769           emitcode("movx", "@dptr,a");
10770           if (--size)
10771           {
10772                emitcode("inc", "dptr");
10773                emitcode("inc", "dptr");
10774           }
10775       }
10776       emitcode("mov", "dps,#0");
10777       freeAsmop (right, NULL, ic, FALSE);
10778 #if 0
10779 some alternative code for processors without auto-toggle
10780 no time to test now, so later well put in...kpb
10781         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10782         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10783         emitcode ("mov", "dptr,#%s", rSym->rname); 
10784         /* DP2 = result, DP1 = right, DP1 is current. */
10785         while (size)
10786         {
10787           --size;
10788           emitcode("movx", "a,@dptr");
10789           if (size)
10790             emitcode("inc", "dptr");
10791           emitcode("inc", "dps");
10792           emitcode("movx", "@dptr,a");
10793           if (size)
10794             emitcode("inc", "dptr");
10795           emitcode("inc", "dps");
10796         }
10797         emitcode("mov", "dps,#0");
10798         freeAsmop (right, NULL, ic, FALSE);
10799 #endif
10800   }
10801   else
10802   {
10803       D (emitcode (";", "genFarFarAssign"););
10804       aopOp (result, ic, TRUE, TRUE);
10805
10806       _startLazyDPSEvaluation ();
10807       
10808       while (size--)
10809         {
10810           aopPut (AOP (result),
10811                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10812           offset++;
10813         }
10814       _endLazyDPSEvaluation ();
10815       freeAsmop (result, NULL, ic, FALSE);
10816       freeAsmop (right, NULL, ic, FALSE);
10817   }
10818 }
10819
10820 /*-----------------------------------------------------------------*/
10821 /* genAssign - generate code for assignment                        */
10822 /*-----------------------------------------------------------------*/
10823 static void
10824 genAssign (iCode * ic)
10825 {
10826   operand *result, *right;
10827   int size, offset;
10828   unsigned long lit = 0L;
10829
10830   D (emitcode (";", "genAssign ");
10831     );
10832
10833   result = IC_RESULT (ic);
10834   right = IC_RIGHT (ic);
10835
10836   /* if they are the same */
10837   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10838     return;
10839
10840   aopOp (right, ic, FALSE, FALSE);
10841
10842   emitcode (";", "genAssign: resultIsFar = %s",
10843             isOperandInFarSpace (result) ?
10844             "TRUE" : "FALSE");
10845
10846   /* special case both in far space */
10847   if ((AOP_TYPE (right) == AOP_DPTR ||
10848        AOP_TYPE (right) == AOP_DPTR2) &&
10849   /* IS_TRUE_SYMOP(result)       && */
10850       isOperandInFarSpace (result))
10851     {
10852       genFarFarAssign (result, right, ic);
10853       return;
10854     }
10855
10856   aopOp (result, ic, TRUE, FALSE);
10857
10858   /* if they are the same registers */
10859   if (sameRegs (AOP (right), AOP (result)))
10860     goto release;
10861
10862   /* if the result is a bit */
10863   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10864     {
10865       /* if the right size is a literal then
10866          we know what the value is */
10867       if (AOP_TYPE (right) == AOP_LIT)
10868         {
10869           if (((int) operandLitValue (right)))
10870             aopPut (AOP (result), one, 0);
10871           else
10872             aopPut (AOP (result), zero, 0);
10873           goto release;
10874         }
10875
10876       /* the right is also a bit variable */
10877       if (AOP_TYPE (right) == AOP_CRY)
10878         {
10879           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10880           aopPut (AOP (result), "c", 0);
10881           goto release;
10882         }
10883
10884       /* we need to or */
10885       toBoolean (right);
10886       aopPut (AOP (result), "a", 0);
10887       goto release;
10888     }
10889
10890   /* bit variables done */
10891   /* general case */
10892   size = AOP_SIZE (result);
10893   offset = 0;
10894   if (AOP_TYPE (right) == AOP_LIT)
10895     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10896
10897   if ((size > 1) &&
10898       (AOP_TYPE (result) != AOP_REG) &&
10899       (AOP_TYPE (right) == AOP_LIT) &&
10900       !IS_FLOAT (operandType (right)))
10901     {
10902       _startLazyDPSEvaluation ();
10903       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10904         {
10905           aopPut (AOP (result),
10906                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10907                   offset);
10908           offset++;
10909           size--;
10910         }
10911       /* And now fill the rest with zeros. */
10912       if (size)
10913         {
10914           emitcode ("clr", "a");
10915         }
10916       while (size--)
10917         {
10918           aopPut (AOP (result), "a", offset++);
10919         }
10920       _endLazyDPSEvaluation ();
10921     }
10922   else
10923     {
10924       _startLazyDPSEvaluation ();
10925       while (size--)
10926         {
10927           aopPut (AOP (result),
10928                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10929                   offset);
10930           offset++;
10931         }
10932       _endLazyDPSEvaluation ();
10933     }
10934
10935 release:
10936   freeAsmop (right, NULL, ic, FALSE);
10937   freeAsmop (result, NULL, ic, TRUE);
10938 }
10939
10940 /*-----------------------------------------------------------------*/
10941 /* genJumpTab - generates code for jump table                      */
10942 /*-----------------------------------------------------------------*/
10943 static void
10944 genJumpTab (iCode * ic)
10945 {
10946   symbol *jtab;
10947   char *l;
10948
10949   D (emitcode (";", "genJumpTab ");
10950     );
10951
10952   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10953   /* get the condition into accumulator */
10954   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10955   MOVA (l);
10956   /* multiply by four! */
10957   emitcode ("add", "a,acc");
10958   emitcode ("add", "a,acc");
10959   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10960
10961   jtab = newiTempLabel (NULL);
10962   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10963   emitcode ("jmp", "@a+dptr");
10964   emitcode ("", "!tlabeldef", jtab->key + 100);
10965   /* now generate the jump labels */
10966   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10967        jtab = setNextItem (IC_JTLABELS (ic)))
10968     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10969
10970 }
10971
10972 /*-----------------------------------------------------------------*/
10973 /* genCast - gen code for casting                                  */
10974 /*-----------------------------------------------------------------*/
10975 static void
10976 genCast (iCode * ic)
10977 {
10978   operand *result = IC_RESULT (ic);
10979   sym_link *ctype = operandType (IC_LEFT (ic));
10980   sym_link *rtype = operandType (IC_RIGHT (ic));
10981   operand *right = IC_RIGHT (ic);
10982   int size, offset;
10983
10984   D (emitcode (";", "genCast "););
10985
10986   /* if they are equivalent then do nothing */
10987   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10988     return;
10989
10990   aopOp (right, ic, FALSE, FALSE);
10991   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10992
10993   /* if the result is a bit */
10994   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10995   if (IS_BITVAR(OP_SYMBOL(result)->type))
10996     {
10997       /* if the right size is a literal then
10998          we know what the value is */
10999       if (AOP_TYPE (right) == AOP_LIT)
11000         {
11001           if (((int) operandLitValue (right)))
11002             aopPut (AOP (result), one, 0);
11003           else
11004             aopPut (AOP (result), zero, 0);
11005
11006           goto release;
11007         }
11008
11009       /* the right is also a bit variable */
11010       if (AOP_TYPE (right) == AOP_CRY)
11011         {
11012           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11013           aopPut (AOP (result), "c", 0);
11014           goto release;
11015         }
11016
11017       /* we need to or */
11018       toBoolean (right);
11019       aopPut (AOP (result), "a", 0);
11020       goto release;
11021     }
11022
11023   /* if they are the same size : or less */
11024   if (AOP_SIZE (result) <= AOP_SIZE (right))
11025     {
11026
11027       /* if they are in the same place */
11028       if (sameRegs (AOP (right), AOP (result)))
11029         goto release;
11030
11031       /* if they in different places then copy */
11032       size = AOP_SIZE (result);
11033       offset = 0;
11034       _startLazyDPSEvaluation ();
11035       while (size--)
11036         {
11037           aopPut (AOP (result),
11038                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11039                   offset);
11040           offset++;
11041         }
11042       _endLazyDPSEvaluation ();
11043       goto release;
11044     }
11045
11046
11047   /* if the result is of type pointer */
11048   if (IS_PTR (ctype))
11049     {
11050
11051       int p_type;
11052       sym_link *type = operandType (right);
11053
11054       /* pointer to generic pointer */
11055       if (IS_GENPTR (ctype))
11056         {
11057           if (IS_PTR (type))
11058             {
11059               p_type = DCL_TYPE (type);
11060             }
11061           else
11062             {
11063 #if OLD_CAST_BEHAVIOR
11064               /* KV: we are converting a non-pointer type to
11065                * a generic pointer. This (ifdef'd out) code
11066                * says that the resulting generic pointer
11067                * should have the same class as the storage
11068                * location of the non-pointer variable.
11069                *
11070                * For example, converting an int (which happens
11071                * to be stored in DATA space) to a pointer results
11072                * in a DATA generic pointer; if the original int
11073                * in XDATA space, so will be the resulting pointer.
11074                *
11075                * I don't like that behavior, and thus this change:
11076                * all such conversions will be forced to XDATA and
11077                * throw a warning. If you want some non-XDATA
11078                * type, or you want to suppress the warning, you
11079                * must go through an intermediate cast, like so:
11080                *
11081                * char _generic *gp = (char _xdata *)(intVar);
11082                */
11083               sym_link *etype = getSpec (type);
11084
11085               /* we have to go by the storage class */
11086               if (SPEC_OCLS (etype) != generic)
11087                 {
11088                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11089                 }
11090               else
11091 #endif
11092                 {
11093                   /* Converting unknown class (i.e. register variable)
11094                    * to generic pointer. This is not good, but
11095                    * we'll make a guess (and throw a warning).
11096                    */
11097                   p_type = FPOINTER;
11098                   werror (W_INT_TO_GEN_PTR_CAST);
11099                 }
11100             }
11101
11102           /* the first two bytes are known */
11103           size = GPTRSIZE - 1;
11104           offset = 0;
11105           _startLazyDPSEvaluation ();
11106           while (size--)
11107             {
11108               aopPut (AOP (result),
11109                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11110                       offset);
11111               offset++;
11112             }
11113           _endLazyDPSEvaluation ();
11114
11115           /* the last byte depending on type */
11116             {
11117                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11118                 char gpValStr[10];
11119             
11120                 if (gpVal == -1)
11121                 {
11122                     // pointerTypeToGPByte will have bitched.
11123                     exit(1);
11124                 }
11125             
11126                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11127                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11128             }
11129           goto release;
11130         }
11131
11132       /* just copy the pointers */
11133       size = AOP_SIZE (result);
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       goto release;
11145     }
11146
11147   /* so we now know that the size of destination is greater
11148      than the size of the source */
11149   /* we move to result for the size of source */
11150   size = AOP_SIZE (right);
11151   offset = 0;
11152   _startLazyDPSEvaluation ();
11153   while (size--)
11154     {
11155       aopPut (AOP (result),
11156               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11157               offset);
11158       offset++;
11159     }
11160   _endLazyDPSEvaluation ();
11161
11162   /* now depending on the sign of the source && destination */
11163   size = AOP_SIZE (result) - AOP_SIZE (right);
11164   /* if unsigned or not an integral type */
11165   /* also, if the source is a bit, we don't need to sign extend, because
11166    * it can't possibly have set the sign bit.
11167    */
11168   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11169     {
11170       while (size--)
11171         {
11172           aopPut (AOP (result), zero, offset++);
11173         }
11174     }
11175   else
11176     {
11177       /* we need to extend the sign :{ */
11178       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11179                         FALSE, FALSE, NULL));
11180       emitcode ("rlc", "a");
11181       emitcode ("subb", "a,acc");
11182       while (size--)
11183         aopPut (AOP (result), "a", offset++);
11184     }
11185
11186   /* we are done hurray !!!! */
11187
11188 release:
11189   freeAsmop (right, NULL, ic, TRUE);
11190   freeAsmop (result, NULL, ic, TRUE);
11191
11192 }
11193
11194 /*-----------------------------------------------------------------*/
11195 /* genDjnz - generate decrement & jump if not zero instrucion      */
11196 /*-----------------------------------------------------------------*/
11197 static int
11198 genDjnz (iCode * ic, iCode * ifx)
11199 {
11200   symbol *lbl, *lbl1;
11201   if (!ifx)
11202     return 0;
11203
11204   /* if the if condition has a false label
11205      then we cannot save */
11206   if (IC_FALSE (ifx))
11207     return 0;
11208
11209   /* if the minus is not of the form
11210      a = a - 1 */
11211   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11212       !IS_OP_LITERAL (IC_RIGHT (ic)))
11213     return 0;
11214
11215   if (operandLitValue (IC_RIGHT (ic)) != 1)
11216     return 0;
11217
11218   /* if the size of this greater than one then no
11219      saving */
11220   if (getSize (operandType (IC_RESULT (ic))) > 1)
11221     return 0;
11222
11223   /* otherwise we can save BIG */
11224   D(emitcode(";", "genDjnz"););
11225
11226   lbl = newiTempLabel (NULL);
11227   lbl1 = newiTempLabel (NULL);
11228
11229   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11230
11231   if (AOP_NEEDSACC(IC_RESULT(ic)))
11232   {
11233       /* If the result is accessed indirectly via
11234        * the accumulator, we must explicitly write
11235        * it back after the decrement.
11236        */
11237       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11238       
11239       if (strcmp(rByte, "a"))
11240       {
11241            /* Something is hopelessly wrong */
11242            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11243                    __FILE__, __LINE__);
11244            /* We can just give up; the generated code will be inefficient,
11245             * but what the hey.
11246             */
11247            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11248            return 0;
11249       }
11250       emitcode ("dec", "%s", rByte);
11251       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11252       emitcode ("jnz", "!tlabel", lbl->key + 100);
11253   }
11254   else if (IS_AOP_PREG (IC_RESULT (ic)))
11255     {
11256       emitcode ("dec", "%s",
11257                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11258       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11259       emitcode ("jnz", "!tlabel", lbl->key + 100);
11260     }
11261   else
11262     {
11263       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11264                 lbl->key + 100);
11265     }
11266   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11267   emitcode ("", "!tlabeldef", lbl->key + 100);
11268   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11269   emitcode ("", "!tlabeldef", lbl1->key + 100);
11270
11271   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11272   ifx->generated = 1;
11273   return 1;
11274 }
11275
11276 /*-----------------------------------------------------------------*/
11277 /* genReceive - generate code for a receive iCode                  */
11278 /*-----------------------------------------------------------------*/
11279 static void
11280 genReceive (iCode * ic)
11281 {
11282     int size = getSize (operandType (IC_RESULT (ic)));
11283     int offset = 0;
11284     int rb1off ;
11285     
11286     D (emitcode (";", "genReceive "););
11287
11288     if (ic->argreg == 1) 
11289     {
11290         /* first parameter */
11291         if (AOP_IS_STR(IC_RESULT(ic)))
11292         {
11293             /* Nothing to do: it's already in the proper place. */
11294             return;
11295         }
11296         else
11297         {
11298             bool useDp2;
11299             
11300             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11301                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11302                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11303             
11304             _G.accInUse++;
11305             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11306             _G.accInUse--; 
11307             
11308             /* Sanity checking... */
11309             if (AOP_USESDPTR(IC_RESULT(ic)))
11310             {
11311                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11312                         "genReceive got unexpected DPTR.");
11313             }
11314             assignResultValue (IC_RESULT (ic));
11315         }
11316     } 
11317     else 
11318     { 
11319         /* second receive onwards */
11320         /* this gets a little tricky since unused recevies will be
11321          eliminated, we have saved the reg in the type field . and
11322          we use that to figure out which register to use */
11323         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11324         rb1off = ic->argreg;
11325         while (size--) 
11326         {
11327             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11328         }
11329     }
11330     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11331 }
11332
11333 /*-----------------------------------------------------------------*/
11334 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11335 /*-----------------------------------------------------------------*/
11336 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11337 {
11338     operand *from , *to , *count;
11339     symbol *lbl;
11340     bitVect *rsave;
11341     int i;
11342
11343     /* we know it has to be 3 parameters */
11344     assert (nparms == 3);
11345     
11346     rsave = newBitVect(16);
11347     /* save DPTR if it needs to be saved */
11348     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11349             if (bitVectBitValue(ic->rMask,i))
11350                     rsave = bitVectSetBit(rsave,i);
11351     }
11352     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11353                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11354     savermask(rsave);
11355     
11356     to = parms[0];
11357     from = parms[1];
11358     count = parms[2];
11359
11360     aopOp (from, ic->next, FALSE, FALSE);
11361
11362     /* get from into DPTR1 */
11363     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11364     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11365     if (options.model == MODEL_FLAT24) {
11366         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11367     }
11368
11369     freeAsmop (from, NULL, ic, FALSE);
11370     aopOp (to, ic, FALSE, FALSE);
11371     /* get "to" into DPTR */
11372     /* if the operand is already in dptr
11373        then we do nothing else we move the value to dptr */
11374     if (AOP_TYPE (to) != AOP_STR) {
11375         /* if already in DPTR then we need to push */
11376         if (AOP_TYPE(to) == AOP_DPTR) {
11377             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11378             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11379             if (options.model == MODEL_FLAT24)
11380                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11381             emitcode ("pop", "dph");
11382             emitcode ("pop", "dpl");        
11383         } else {
11384             _startLazyDPSEvaluation ();
11385             /* if this is remateriazable */
11386             if (AOP_TYPE (to) == AOP_IMMD) {
11387                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11388             } else {                    /* we need to get it byte by byte */
11389                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11390                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11391                 if (options.model == MODEL_FLAT24) {
11392                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11393                 }
11394             }
11395             _endLazyDPSEvaluation ();
11396         }
11397     }
11398     freeAsmop (to, NULL, ic, FALSE);
11399     _G.dptrInUse = _G.dptr1InUse = 1;
11400     aopOp (count, ic->next->next, FALSE,FALSE);
11401     lbl =newiTempLabel(NULL);
11402
11403     /* now for the actual copy */
11404     if (AOP_TYPE(count) == AOP_LIT && 
11405         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11406         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11407         if (fromc) {
11408             emitcode ("lcall","__bi_memcpyc2x_s");
11409         } else {
11410             emitcode ("lcall","__bi_memcpyx2x_s");
11411         }
11412         freeAsmop (count, NULL, ic, FALSE);
11413     } else {
11414         symbol *lbl1 = newiTempLabel(NULL);
11415         
11416         emitcode (";"," Auto increment but no djnz");
11417         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11418         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11419         freeAsmop (count, NULL, ic, FALSE);
11420         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11421         emitcode ("","!tlabeldef",lbl->key+100);
11422         if (fromc) {
11423             emitcode ("clr","a");
11424             emitcode ("movc", "a,@a+dptr");
11425         } else 
11426             emitcode ("movx", "a,@dptr");
11427         emitcode ("movx", "@dptr,a");
11428         emitcode ("inc", "dptr");
11429         emitcode ("inc", "dptr");
11430         emitcode ("mov","a,b");
11431         emitcode ("orl","a,_ap");
11432         emitcode ("jz","!tlabel",lbl1->key+100);
11433         emitcode ("mov","a,_ap");
11434         emitcode ("add","a,#!constbyte",0xFF);
11435         emitcode ("mov","_ap,a");
11436         emitcode ("mov","a,b");
11437         emitcode ("addc","a,#!constbyte",0xFF);
11438         emitcode ("mov","b,a");
11439         emitcode ("sjmp","!tlabel",lbl->key+100);
11440         emitcode ("","!tlabeldef",lbl1->key+100);
11441     }
11442     emitcode ("mov", "dps,#0"); 
11443     _G.dptrInUse = _G.dptr1InUse = 0;
11444     unsavermask(rsave);
11445
11446 }
11447
11448 /*-----------------------------------------------------------------*/
11449 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11450 /*-----------------------------------------------------------------*/
11451 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11452 {
11453     operand *from , *to , *count;
11454     symbol *lbl,*lbl2;
11455     bitVect *rsave;
11456     int i;
11457
11458     /* we know it has to be 3 parameters */
11459     assert (nparms == 3);
11460     
11461     rsave = newBitVect(16);
11462     /* save DPTR if it needs to be saved */
11463     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11464             if (bitVectBitValue(ic->rMask,i))
11465                     rsave = bitVectSetBit(rsave,i);
11466     }
11467     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11468                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11469     savermask(rsave);
11470     
11471     to = parms[0];
11472     from = parms[1];
11473     count = parms[2];
11474
11475     aopOp (from, ic->next, FALSE, FALSE);
11476
11477     /* get from into DPTR1 */
11478     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11479     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11480     if (options.model == MODEL_FLAT24) {
11481         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11482     }
11483
11484     freeAsmop (from, NULL, ic, FALSE);
11485     aopOp (to, ic, FALSE, FALSE);
11486     /* get "to" into DPTR */
11487     /* if the operand is already in dptr
11488        then we do nothing else we move the value to dptr */
11489     if (AOP_TYPE (to) != AOP_STR) {
11490         /* if already in DPTR then we need to push */
11491         if (AOP_TYPE(to) == AOP_DPTR) {
11492             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11493             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11494             if (options.model == MODEL_FLAT24)
11495                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11496             emitcode ("pop", "dph");
11497             emitcode ("pop", "dpl");        
11498         } else {
11499             _startLazyDPSEvaluation ();
11500             /* if this is remateriazable */
11501             if (AOP_TYPE (to) == AOP_IMMD) {
11502                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11503             } else {                    /* we need to get it byte by byte */
11504                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11505                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11506                 if (options.model == MODEL_FLAT24) {
11507                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11508                 }
11509             }
11510             _endLazyDPSEvaluation ();
11511         }
11512     }
11513     freeAsmop (to, NULL, ic, FALSE);
11514     _G.dptrInUse = _G.dptr1InUse = 1;
11515     aopOp (count, ic->next->next, FALSE,FALSE);
11516     lbl =newiTempLabel(NULL);
11517     lbl2 =newiTempLabel(NULL);
11518
11519     /* now for the actual compare */
11520     if (AOP_TYPE(count) == AOP_LIT && 
11521         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11522         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11523         if (fromc)
11524             emitcode("lcall","__bi_memcmpc2x_s");
11525         else
11526             emitcode("lcall","__bi_memcmpx2x_s");
11527         freeAsmop (count, NULL, ic, FALSE);
11528         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11529         aopPut(AOP(IC_RESULT(ic)),"a",0);
11530         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11531     } else {
11532         symbol *lbl1 = newiTempLabel(NULL);
11533
11534         emitcode("push","ar0");         
11535         emitcode (";"," Auto increment but no djnz");
11536         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11537         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11538         freeAsmop (count, NULL, ic, FALSE);
11539         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11540         emitcode ("","!tlabeldef",lbl->key+100);
11541         if (fromc) {
11542             emitcode ("clr","a");
11543             emitcode ("movc", "a,@a+dptr");
11544         } else 
11545             emitcode ("movx", "a,@dptr");
11546         emitcode ("mov","r0,a");
11547         emitcode ("movx", "a,@dptr");
11548         emitcode ("clr","c");
11549         emitcode ("subb","a,r0");
11550         emitcode ("jnz","!tlabel",lbl2->key+100);
11551         emitcode ("inc", "dptr");
11552         emitcode ("inc", "dptr");
11553         emitcode ("mov","a,b");
11554         emitcode ("orl","a,_ap");
11555         emitcode ("jz","!tlabel",lbl1->key+100);
11556         emitcode ("mov","a,_ap");
11557         emitcode ("add","a,#!constbyte",0xFF);
11558         emitcode ("mov","_ap,a");
11559         emitcode ("mov","a,b");
11560         emitcode ("addc","a,#!constbyte",0xFF);
11561         emitcode ("mov","b,a");
11562         emitcode ("sjmp","!tlabel",lbl->key+100);
11563         emitcode ("","!tlabeldef",lbl1->key+100);
11564         emitcode ("clr","a");
11565         emitcode ("","!tlabeldef",lbl2->key+100);
11566         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11567         aopPut(AOP(IC_RESULT(ic)),"a",0);
11568         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11569         emitcode("pop","ar0");
11570         emitcode ("mov", "dps,#0");      
11571     }
11572     _G.dptrInUse = _G.dptr1InUse = 0;
11573     unsavermask(rsave);
11574
11575 }
11576
11577 /*-----------------------------------------------------------------*/
11578 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11579 /* port, first parameter output area second parameter pointer to   */
11580 /* port third parameter count                                      */
11581 /*-----------------------------------------------------------------*/
11582 static void genInp( iCode *ic, int nparms, operand **parms)
11583 {
11584     operand *from , *to , *count;
11585     symbol *lbl;
11586     bitVect *rsave;
11587     int i;
11588
11589     /* we know it has to be 3 parameters */
11590     assert (nparms == 3);
11591     
11592     rsave = newBitVect(16);
11593     /* save DPTR if it needs to be saved */
11594     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11595             if (bitVectBitValue(ic->rMask,i))
11596                     rsave = bitVectSetBit(rsave,i);
11597     }
11598     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11599                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11600     savermask(rsave);
11601     
11602     to = parms[0];
11603     from = parms[1];
11604     count = parms[2];
11605
11606     aopOp (from, ic->next, FALSE, FALSE);
11607
11608     /* get from into DPTR1 */
11609     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11610     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11611     if (options.model == MODEL_FLAT24) {
11612         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11613     }
11614
11615     freeAsmop (from, NULL, ic, FALSE);
11616     aopOp (to, ic, FALSE, FALSE);
11617     /* get "to" into DPTR */
11618     /* if the operand is already in dptr
11619        then we do nothing else we move the value to dptr */
11620     if (AOP_TYPE (to) != AOP_STR) {
11621         /* if already in DPTR then we need to push */
11622         if (AOP_TYPE(to) == AOP_DPTR) {
11623             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11624             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11625             if (options.model == MODEL_FLAT24)
11626                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11627             emitcode ("pop", "dph");
11628             emitcode ("pop", "dpl");        
11629         } else {
11630             _startLazyDPSEvaluation ();
11631             /* if this is remateriazable */
11632             if (AOP_TYPE (to) == AOP_IMMD) {
11633                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11634             } else {                    /* we need to get it byte by byte */
11635                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11636                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11637                 if (options.model == MODEL_FLAT24) {
11638                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11639                 }
11640             }
11641             _endLazyDPSEvaluation ();
11642         }
11643     }
11644     freeAsmop (to, NULL, ic, FALSE);
11645
11646     _G.dptrInUse = _G.dptr1InUse = 1;
11647     aopOp (count, ic->next->next, FALSE,FALSE);
11648     lbl =newiTempLabel(NULL);
11649
11650     /* now for the actual copy */
11651     if (AOP_TYPE(count) == AOP_LIT && 
11652         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11653         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11654         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11655         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11656         freeAsmop (count, NULL, ic, FALSE);
11657         emitcode ("","!tlabeldef",lbl->key+100);
11658         emitcode ("movx", "a,@dptr");   /* read data from port */
11659         emitcode ("dec","dps");         /* switch to DPTR */
11660         emitcode ("movx", "@dptr,a");   /* save into location */
11661         emitcode ("inc", "dptr");       /* point to next area */
11662         emitcode ("inc","dps");         /* switch to DPTR2 */
11663         emitcode ("djnz","b,!tlabel",lbl->key+100);
11664     } else {
11665         symbol *lbl1 = newiTempLabel(NULL);
11666         
11667         emitcode (";"," Auto increment but no djnz");
11668         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11669         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11670         freeAsmop (count, NULL, ic, FALSE);
11671         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11672         emitcode ("","!tlabeldef",lbl->key+100);
11673         emitcode ("movx", "a,@dptr");
11674         emitcode ("dec","dps");         /* switch to DPTR */
11675         emitcode ("movx", "@dptr,a");
11676         emitcode ("inc", "dptr");
11677         emitcode ("inc","dps");         /* switch to DPTR2 */
11678 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11679 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11680         emitcode ("mov","a,b");
11681         emitcode ("orl","a,_ap");
11682         emitcode ("jz","!tlabel",lbl1->key+100);
11683         emitcode ("mov","a,_ap");
11684         emitcode ("add","a,#!constbyte",0xFF);
11685         emitcode ("mov","_ap,a");
11686         emitcode ("mov","a,b");
11687         emitcode ("addc","a,#!constbyte",0xFF);
11688         emitcode ("mov","b,a");
11689         emitcode ("sjmp","!tlabel",lbl->key+100);
11690         emitcode ("","!tlabeldef",lbl1->key+100);
11691     }
11692     emitcode ("mov", "dps,#0"); 
11693     _G.dptrInUse = _G.dptr1InUse = 0;
11694     unsavermask(rsave);
11695
11696 }
11697
11698 /*-----------------------------------------------------------------*/
11699 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11700 /* port, first parameter output area second parameter pointer to   */
11701 /* port third parameter count                                      */
11702 /*-----------------------------------------------------------------*/
11703 static void genOutp( iCode *ic, int nparms, operand **parms)
11704 {
11705     operand *from , *to , *count;
11706     symbol *lbl;
11707     bitVect *rsave;
11708     int i;
11709
11710     /* we know it has to be 3 parameters */
11711     assert (nparms == 3);
11712     
11713     rsave = newBitVect(16);
11714     /* save DPTR if it needs to be saved */
11715     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11716             if (bitVectBitValue(ic->rMask,i))
11717                     rsave = bitVectSetBit(rsave,i);
11718     }
11719     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11720                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11721     savermask(rsave);
11722     
11723     to = parms[0];
11724     from = parms[1];
11725     count = parms[2];
11726
11727     aopOp (from, ic->next, FALSE, FALSE);
11728
11729     /* get from into DPTR1 */
11730     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11731     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11732     if (options.model == MODEL_FLAT24) {
11733         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11734     }
11735
11736     freeAsmop (from, NULL, ic, FALSE);
11737     aopOp (to, ic, FALSE, FALSE);
11738     /* get "to" into DPTR */
11739     /* if the operand is already in dptr
11740        then we do nothing else we move the value to dptr */
11741     if (AOP_TYPE (to) != AOP_STR) {
11742         /* if already in DPTR then we need to push */
11743         if (AOP_TYPE(to) == AOP_DPTR) {
11744             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11745             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11746             if (options.model == MODEL_FLAT24)
11747                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11748             emitcode ("pop", "dph");
11749             emitcode ("pop", "dpl");        
11750         } else {
11751             _startLazyDPSEvaluation ();
11752             /* if this is remateriazable */
11753             if (AOP_TYPE (to) == AOP_IMMD) {
11754                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11755             } else {                    /* we need to get it byte by byte */
11756                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11757                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11758                 if (options.model == MODEL_FLAT24) {
11759                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11760                 }
11761             }
11762             _endLazyDPSEvaluation ();
11763         }
11764     }
11765     freeAsmop (to, NULL, ic, FALSE);
11766
11767     _G.dptrInUse = _G.dptr1InUse = 1;
11768     aopOp (count, ic->next->next, FALSE,FALSE);
11769     lbl =newiTempLabel(NULL);
11770
11771     /* now for the actual copy */
11772     if (AOP_TYPE(count) == AOP_LIT && 
11773         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11774         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11775         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11776         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11777         emitcode ("","!tlabeldef",lbl->key+100);
11778         emitcode ("movx", "a,@dptr");   /* read data from port */
11779         emitcode ("inc","dps");         /* switch to DPTR2 */
11780         emitcode ("movx", "@dptr,a");   /* save into location */
11781         emitcode ("inc", "dptr");       /* point to next area */
11782         emitcode ("dec","dps");         /* switch to DPTR */
11783         emitcode ("djnz","b,!tlabel",lbl->key+100);
11784         freeAsmop (count, NULL, ic, FALSE);
11785     } else {
11786         symbol *lbl1 = newiTempLabel(NULL);
11787         
11788         emitcode (";"," Auto increment but no djnz");
11789         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11790         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11791         freeAsmop (count, NULL, ic, FALSE);
11792         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11793         emitcode ("","!tlabeldef",lbl->key+100);
11794         emitcode ("movx", "a,@dptr");
11795         emitcode ("inc", "dptr");
11796         emitcode ("inc","dps");         /* switch to DPTR2 */
11797         emitcode ("movx", "@dptr,a");
11798         emitcode ("dec","dps");         /* switch to DPTR */
11799         emitcode ("mov","a,b");
11800         emitcode ("orl","a,_ap");
11801         emitcode ("jz","!tlabel",lbl1->key+100);
11802         emitcode ("mov","a,_ap");
11803         emitcode ("add","a,#!constbyte",0xFF);
11804         emitcode ("mov","_ap,a");
11805         emitcode ("mov","a,b");
11806         emitcode ("addc","a,#!constbyte",0xFF);
11807         emitcode ("mov","b,a");
11808         emitcode ("sjmp","!tlabel",lbl->key+100);
11809         emitcode ("","!tlabeldef",lbl1->key+100);
11810     }
11811     emitcode ("mov", "dps,#0"); 
11812     _G.dptrInUse = _G.dptr1InUse = 0;
11813     unsavermask(rsave);
11814
11815 }
11816
11817 /*-----------------------------------------------------------------*/
11818 /* genSwapW - swap lower & high order bytes                        */
11819 /*-----------------------------------------------------------------*/
11820 static void genSwapW(iCode *ic, int nparms, operand **parms)
11821 {
11822     operand *dest;
11823     operand *src;
11824     assert (nparms==1);
11825
11826     src = parms[0];
11827     dest=IC_RESULT(ic);
11828
11829     assert(getSize(operandType(src))==2);
11830
11831     aopOp (src, ic, FALSE, FALSE);
11832     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11833     _G.accInUse++;
11834     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11835     _G.accInUse--;
11836     freeAsmop (src, NULL, ic, FALSE);
11837     
11838     aopOp (dest,ic, FALSE, FALSE);
11839     aopPut(AOP(dest),"b",0);
11840     aopPut(AOP(dest),"a",1);
11841     freeAsmop (dest, NULL, ic, FALSE);    
11842 }
11843
11844 /*-----------------------------------------------------------------*/
11845 /* genMemsetX - gencode for memSetX data                           */
11846 /*-----------------------------------------------------------------*/
11847 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11848 {
11849     operand *to , *val , *count;
11850     symbol *lbl;
11851     char *l;
11852     int i;
11853     bitVect *rsave;
11854
11855     /* we know it has to be 3 parameters */
11856     assert (nparms == 3);
11857     
11858     to = parms[0];
11859     val = parms[1];
11860     count = parms[2];
11861         
11862     /* save DPTR if it needs to be saved */
11863     rsave = newBitVect(16);
11864     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11865             if (bitVectBitValue(ic->rMask,i))
11866                     rsave = bitVectSetBit(rsave,i);
11867     }
11868     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11869                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11870     savermask(rsave);
11871
11872     aopOp (to, ic, FALSE, FALSE);
11873     /* get "to" into DPTR */
11874     /* if the operand is already in dptr
11875        then we do nothing else we move the value to dptr */
11876     if (AOP_TYPE (to) != AOP_STR) {
11877         /* if already in DPTR then we need to push */
11878         if (AOP_TYPE(to) == AOP_DPTR) {
11879             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11880             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11881             if (options.model == MODEL_FLAT24)
11882                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11883             emitcode ("pop", "dph");
11884             emitcode ("pop", "dpl");        
11885         } else {
11886             _startLazyDPSEvaluation ();
11887             /* if this is remateriazable */
11888             if (AOP_TYPE (to) == AOP_IMMD) {
11889                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11890             } else {                    /* we need to get it byte by byte */
11891                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11892                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11893                 if (options.model == MODEL_FLAT24) {
11894                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11895                 }
11896             }
11897             _endLazyDPSEvaluation ();
11898         }
11899     }
11900     freeAsmop (to, NULL, ic, FALSE);
11901
11902     aopOp (val, ic->next->next, FALSE,FALSE);
11903     aopOp (count, ic->next->next, FALSE,FALSE);    
11904     lbl =newiTempLabel(NULL);
11905     /* now for the actual copy */
11906     if (AOP_TYPE(count) == AOP_LIT && 
11907         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11908         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11909         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11910         MOVA(l);
11911         emitcode ("","!tlabeldef",lbl->key+100);
11912         emitcode ("movx", "@dptr,a");
11913         emitcode ("inc", "dptr");
11914         emitcode ("djnz","b,!tlabel",lbl->key+100);
11915     } else {
11916         symbol *lbl1 = newiTempLabel(NULL);
11917         
11918         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11919         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11920         emitcode ("","!tlabeldef",lbl->key+100);
11921         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11922         emitcode ("movx", "@dptr,a");
11923         emitcode ("inc", "dptr");
11924         emitcode ("mov","a,b");
11925         emitcode ("orl","a,_ap");
11926         emitcode ("jz","!tlabel",lbl1->key+100);
11927         emitcode ("mov","a,_ap");
11928         emitcode ("add","a,#!constbyte",0xFF);
11929         emitcode ("mov","_ap,a");
11930         emitcode ("mov","a,b");
11931         emitcode ("addc","a,#!constbyte",0xFF);
11932         emitcode ("mov","b,a");
11933         emitcode ("sjmp","!tlabel",lbl->key+100);
11934         emitcode ("","!tlabeldef",lbl1->key+100);
11935     }
11936     freeAsmop (count, NULL, ic, FALSE);
11937     unsavermask(rsave);
11938 }
11939
11940 /*-----------------------------------------------------------------*/
11941 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11942 /*-----------------------------------------------------------------*/
11943 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11944 {
11945         bitVect *rsave ;
11946         operand *pnum, *result;
11947         int i;
11948     
11949         assert (nparms==1);
11950         /* save registers that need to be saved */
11951         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11952                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11953     
11954         pnum = parms[0]; 
11955         aopOp (pnum, ic, FALSE, FALSE);
11956         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11957         freeAsmop (pnum, NULL, ic, FALSE);
11958         emitcode ("lcall","NatLib_LoadPrimitive");
11959         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11960         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11961             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11962                 for (i = (size-1) ; i >= 0 ; i-- ) {
11963                         emitcode ("push","a%s",javaRet[i]);
11964                 }
11965                 for (i=0; i < size ; i++ ) {
11966                         emitcode ("pop","a%s",
11967                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11968                 }
11969         } else {
11970                 for (i = 0 ; i < size ; i++ ) {
11971                         aopPut(AOP(result),javaRet[i],i);
11972                 }
11973         }    
11974         freeAsmop (result, NULL, ic, FALSE);
11975         unsavermask(rsave);
11976 }
11977
11978 /*-----------------------------------------------------------------*/
11979 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11980 /*-----------------------------------------------------------------*/
11981 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11982 {
11983         bitVect *rsave ;
11984         operand *pnum, *result;
11985         int size = 3;
11986         int i;
11987     
11988         assert (nparms==1);
11989         /* save registers that need to be saved */
11990         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11991                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11992     
11993         pnum = parms[0]; 
11994         aopOp (pnum, ic, FALSE, FALSE);
11995         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11996         freeAsmop (pnum, NULL, ic, FALSE);
11997         emitcode ("lcall","NatLib_LoadPointer");
11998         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11999         if (AOP_TYPE(result)!=AOP_STR) {
12000                 for (i = 0 ; i < size ; i++ ) {
12001                         aopPut(AOP(result),fReturn[i],i);
12002                 }
12003         }    
12004         freeAsmop (result, NULL, ic, FALSE);
12005         unsavermask(rsave);
12006 }
12007
12008 /*-----------------------------------------------------------------*/
12009 /* genNatLibInstallStateBlock -                                    */
12010 /*-----------------------------------------------------------------*/
12011 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12012                                        operand **parms, const char *name)
12013 {
12014         bitVect *rsave ;
12015         operand *psb, *handle;
12016         assert (nparms==2);
12017
12018         /* save registers that need to be saved */
12019         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12020                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12021         psb = parms[0];
12022         handle = parms[1];
12023
12024         /* put pointer to state block into DPTR1 */
12025         aopOp (psb, ic, FALSE, FALSE);
12026         if (AOP_TYPE (psb) == AOP_IMMD) {
12027                 emitcode ("mov","dps,#1");
12028                 emitcode ("mov", "dptr,%s",
12029                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12030                 emitcode ("mov","dps,#0");
12031         } else {
12032                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12033                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12034                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12035         }
12036         freeAsmop (psb, NULL, ic, FALSE);
12037
12038         /* put libraryID into DPTR */
12039         emitcode ("mov","dptr,#LibraryID");
12040
12041         /* put handle into r3:r2 */
12042         aopOp (handle, ic, FALSE, FALSE);
12043         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12044                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12045                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12046                 emitcode ("pop","ar3");
12047                 emitcode ("pop","ar2");
12048         } else {        
12049                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12050                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12051         }
12052         freeAsmop (psb, NULL, ic, FALSE);
12053
12054         /* make the call */
12055         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12056
12057         /* put return value into place*/
12058         _G.accInUse++;
12059         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12060         _G.accInUse--;
12061         aopPut(AOP(IC_RESULT(ic)),"a",0);
12062         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12063         unsavermask(rsave);
12064 }
12065
12066 /*-----------------------------------------------------------------*/
12067 /* genNatLibRemoveStateBlock -                                     */
12068 /*-----------------------------------------------------------------*/
12069 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12070 {
12071         bitVect *rsave ;
12072
12073         assert(nparms==0);
12074
12075         /* save registers that need to be saved */
12076         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12077                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12078
12079         /* put libraryID into DPTR */
12080         emitcode ("mov","dptr,#LibraryID");
12081         /* make the call */
12082         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12083         unsavermask(rsave);
12084 }
12085
12086 /*-----------------------------------------------------------------*/
12087 /* genNatLibGetStateBlock -                                        */
12088 /*-----------------------------------------------------------------*/
12089 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12090                                    operand **parms,const char *name)
12091 {
12092         bitVect *rsave ;
12093         symbol *lbl = newiTempLabel(NULL);
12094         
12095         assert(nparms==0);
12096         /* save registers that need to be saved */
12097         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12098                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12099
12100         /* put libraryID into DPTR */
12101         emitcode ("mov","dptr,#LibraryID");
12102         /* make the call */
12103         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12104         emitcode ("jnz","!tlabel",lbl->key+100);
12105
12106         /* put return value into place */
12107         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12108         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12109                 emitcode ("push","ar3");
12110                 emitcode ("push","ar2");
12111                 emitcode ("pop","%s",
12112                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12113                 emitcode ("pop","%s",
12114                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12115         } else {
12116                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12117                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12118         }
12119         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12120         emitcode ("","!tlabeldef",lbl->key+100);
12121         unsavermask(rsave);
12122 }
12123
12124 /*-----------------------------------------------------------------*/
12125 /* genMMMalloc -                                                   */
12126 /*-----------------------------------------------------------------*/
12127 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12128                          int size, const char *name)
12129 {
12130         bitVect *rsave ;
12131         operand *bsize;
12132         symbol *rsym;
12133         symbol *lbl = newiTempLabel(NULL);
12134
12135         assert (nparms == 1);
12136         /* save registers that need to be saved */
12137         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12138                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12139         
12140         bsize=parms[0];
12141         aopOp (bsize,ic,FALSE,FALSE);
12142
12143         /* put the size in R4-R2 */
12144         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12145                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12146                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12147                 if (size==3) {
12148                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12149                         emitcode("pop","ar4");
12150                 }
12151                 emitcode("pop","ar3");
12152                 emitcode("pop","ar2");          
12153         } else {
12154                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12155                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12156                 if (size==3) {
12157                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12158                 }
12159         }
12160         freeAsmop (bsize, NULL, ic, FALSE);
12161
12162         /* make the call */
12163         emitcode ("lcall","MM_%s",name);
12164         emitcode ("jz","!tlabel",lbl->key+100);
12165         emitcode ("mov","r2,#!constbyte",0xff);
12166         emitcode ("mov","r3,#!constbyte",0xff);
12167         emitcode ("","!tlabeldef",lbl->key+100);
12168         /* we don't care about the pointer : we just save the handle */
12169         rsym = OP_SYMBOL(IC_RESULT(ic));
12170         if (rsym->liveFrom != rsym->liveTo) {
12171                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12172                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12173                         emitcode ("push","ar3");
12174                         emitcode ("push","ar2");
12175                         emitcode ("pop","%s",
12176                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12177                         emitcode ("pop","%s",
12178                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12179                 } else {
12180                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12181                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12182                 }
12183                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12184         }
12185         unsavermask(rsave);
12186 }
12187
12188 /*-----------------------------------------------------------------*/
12189 /* genMMDeref -                                                    */
12190 /*-----------------------------------------------------------------*/
12191 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12192 {
12193         bitVect *rsave ;
12194         operand *handle;
12195
12196         assert (nparms == 1);
12197         /* save registers that need to be saved */
12198         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12199                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12200         
12201         handle=parms[0];
12202         aopOp (handle,ic,FALSE,FALSE);
12203
12204         /* put the size in R4-R2 */
12205         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12206                 emitcode("push","%s",
12207                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12208                 emitcode("push","%s",
12209                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12210                 emitcode("pop","ar3");
12211                 emitcode("pop","ar2");          
12212         } else {
12213                 emitcode ("mov","r2,%s",
12214                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12215                 emitcode ("mov","r3,%s",
12216                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12217         }
12218         freeAsmop (handle, NULL, ic, FALSE);
12219
12220         /* make the call */
12221         emitcode ("lcall","MM_Deref");
12222         
12223         {
12224                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12225                 if (rsym->liveFrom != rsym->liveTo) {                   
12226                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12227                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12228                             _startLazyDPSEvaluation ();
12229                             
12230                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12231                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12232                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12233
12234                             _endLazyDPSEvaluation ();
12235                             
12236                         }
12237                 }
12238         }
12239         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12240         unsavermask(rsave);
12241 }
12242
12243 /*-----------------------------------------------------------------*/
12244 /* genMMUnrestrictedPersist -                                      */
12245 /*-----------------------------------------------------------------*/
12246 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12247 {
12248         bitVect *rsave ;
12249         operand *handle;
12250
12251         assert (nparms == 1);
12252         /* save registers that need to be saved */
12253         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12254                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12255         
12256         handle=parms[0];
12257         aopOp (handle,ic,FALSE,FALSE);
12258
12259         /* put the size in R3-R2 */
12260         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12261                 emitcode("push","%s",
12262                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12263                 emitcode("push","%s",
12264                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12265                 emitcode("pop","ar3");
12266                 emitcode("pop","ar2");          
12267         } else {
12268                 emitcode ("mov","r2,%s",
12269                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12270                 emitcode ("mov","r3,%s",
12271                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12272         }
12273         freeAsmop (handle, NULL, ic, FALSE);
12274
12275         /* make the call */
12276         emitcode ("lcall","MM_UnrestrictedPersist");
12277
12278         {
12279                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12280                 if (rsym->liveFrom != rsym->liveTo) {   
12281                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12282                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12283                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12284                 }
12285         }
12286         unsavermask(rsave);
12287 }
12288
12289 /*-----------------------------------------------------------------*/
12290 /* genSystemExecJavaProcess -                                      */
12291 /*-----------------------------------------------------------------*/
12292 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12293 {
12294         bitVect *rsave ;
12295         operand *handle, *pp;
12296
12297         assert (nparms==2);
12298         /* save registers that need to be saved */
12299         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12300                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12301         
12302         pp = parms[0];
12303         handle = parms[1];
12304         
12305         /* put the handle in R3-R2 */
12306         aopOp (handle,ic,FALSE,FALSE);
12307         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12308                 emitcode("push","%s",
12309                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12310                 emitcode("push","%s",
12311                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12312                 emitcode("pop","ar3");
12313                 emitcode("pop","ar2");          
12314         } else {
12315                 emitcode ("mov","r2,%s",
12316                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12317                 emitcode ("mov","r3,%s",
12318                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12319         }
12320         freeAsmop (handle, NULL, ic, FALSE);
12321         
12322         /* put pointer in DPTR */
12323         aopOp (pp,ic,FALSE,FALSE);
12324         if (AOP_TYPE(pp) == AOP_IMMD) {
12325                 emitcode ("mov", "dptr,%s",
12326                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12327         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12328                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12329                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12330                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12331         }
12332         freeAsmop (handle, NULL, ic, FALSE);
12333
12334         /* make the call */
12335         emitcode ("lcall","System_ExecJavaProcess");
12336         
12337         /* put result in place */
12338         {
12339                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12340                 if (rsym->liveFrom != rsym->liveTo) {   
12341                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12342                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12343                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12344                 }
12345         }
12346         
12347         unsavermask(rsave);
12348 }
12349
12350 /*-----------------------------------------------------------------*/
12351 /* genSystemRTCRegisters -                                         */
12352 /*-----------------------------------------------------------------*/
12353 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12354                                   char *name)
12355 {
12356         bitVect *rsave ;
12357         operand *pp;
12358
12359         assert (nparms==1);
12360         /* save registers that need to be saved */
12361         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12362                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12363         
12364         pp=parms[0];
12365         /* put pointer in DPTR */
12366         aopOp (pp,ic,FALSE,FALSE);
12367         if (AOP_TYPE (pp) == AOP_IMMD) {
12368                 emitcode ("mov","dps,#1");
12369                 emitcode ("mov", "dptr,%s", 
12370                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12371                 emitcode ("mov","dps,#0");
12372         } else {
12373                 emitcode ("mov","dpl1,%s",
12374                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12375                 emitcode ("mov","dph1,%s",
12376                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12377                 emitcode ("mov","dpx1,%s",
12378                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12379         }
12380         freeAsmop (pp, NULL, ic, FALSE);
12381
12382         /* make the call */
12383         emitcode ("lcall","System_%sRTCRegisters",name);
12384
12385         unsavermask(rsave);
12386 }
12387
12388 /*-----------------------------------------------------------------*/
12389 /* genSystemThreadSleep -                                          */
12390 /*-----------------------------------------------------------------*/
12391 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12392 {
12393         bitVect *rsave ;
12394         operand *to, *s;
12395
12396         assert (nparms==1);
12397         /* save registers that need to be saved */
12398         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12399                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12400
12401         to = parms[0];
12402         aopOp(to,ic,FALSE,FALSE);
12403         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12404             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12405                 emitcode ("push","%s",
12406                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12407                 emitcode ("push","%s",
12408                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12409                 emitcode ("push","%s",
12410                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12411                 emitcode ("push","%s",
12412                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12413                 emitcode ("pop","ar3");
12414                 emitcode ("pop","ar2");
12415                 emitcode ("pop","ar1");
12416                 emitcode ("pop","ar0");
12417         } else {
12418                 emitcode ("mov","r0,%s",
12419                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12420                 emitcode ("mov","r1,%s",
12421                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12422                 emitcode ("mov","r2,%s",
12423                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12424                 emitcode ("mov","r3,%s",
12425                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12426         }
12427         freeAsmop (to, NULL, ic, FALSE);
12428
12429         /* suspend in acc */
12430         s = parms[1];
12431         aopOp(s,ic,FALSE,FALSE);
12432         emitcode ("mov","a,%s",
12433                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12434         freeAsmop (s, NULL, ic, FALSE);
12435
12436         /* make the call */
12437         emitcode ("lcall","System_%s",name);
12438
12439         unsavermask(rsave);
12440 }
12441
12442 /*-----------------------------------------------------------------*/
12443 /* genSystemThreadResume -                                         */
12444 /*-----------------------------------------------------------------*/
12445 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12446 {
12447         bitVect *rsave ;
12448         operand *tid,*pid;
12449
12450         assert (nparms==2);
12451         /* save registers that need to be saved */
12452         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12453                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12454         
12455         tid = parms[0];
12456         pid = parms[1];
12457         
12458         /* PID in R0 */
12459         aopOp(pid,ic,FALSE,FALSE);
12460         emitcode ("mov","r0,%s",
12461                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12462         freeAsmop (pid, NULL, ic, FALSE);
12463         
12464         /* tid into ACC */
12465         aopOp(tid,ic,FALSE,FALSE);
12466         emitcode ("mov","a,%s",
12467                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12468         freeAsmop (tid, NULL, ic, FALSE);
12469         
12470         emitcode ("lcall","System_ThreadResume");
12471
12472         /* put result into place */
12473         {
12474                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12475                 if (rsym->liveFrom != rsym->liveTo) {   
12476                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12477                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12478                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12479                 }
12480         }
12481         unsavermask(rsave);
12482 }
12483
12484 /*-----------------------------------------------------------------*/
12485 /* genSystemProcessResume -                                        */
12486 /*-----------------------------------------------------------------*/
12487 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12488 {
12489         bitVect *rsave ;
12490         operand *pid;
12491
12492         assert (nparms==1);
12493         /* save registers that need to be saved */
12494         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12495                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12496         
12497         pid = parms[0];
12498         
12499         /* pid into ACC */
12500         aopOp(pid,ic,FALSE,FALSE);
12501         emitcode ("mov","a,%s",
12502                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12503         freeAsmop (pid, NULL, ic, FALSE);
12504         
12505         emitcode ("lcall","System_ProcessResume");
12506
12507         unsavermask(rsave);
12508 }
12509
12510 /*-----------------------------------------------------------------*/
12511 /* genSystem -                                                     */
12512 /*-----------------------------------------------------------------*/
12513 static void genSystem (iCode *ic,int nparms,char *name)
12514 {
12515         assert(nparms == 0);
12516
12517         emitcode ("lcall","System_%s",name);
12518 }
12519
12520 /*-----------------------------------------------------------------*/
12521 /* genSystemPoll -                                                  */
12522 /*-----------------------------------------------------------------*/
12523 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12524 {
12525         bitVect *rsave ;
12526         operand *fp;
12527
12528         assert (nparms==1);
12529         /* save registers that need to be saved */
12530         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12531                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12532
12533         fp = parms[0];
12534         aopOp (fp,ic,FALSE,FALSE);
12535         if (AOP_TYPE (fp) == AOP_IMMD) {
12536                 emitcode ("mov", "dptr,%s", 
12537                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12538         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12539                 emitcode ("mov","dpl,%s",
12540                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12541                 emitcode ("mov","dph,%s",
12542                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12543                 emitcode ("mov","dpx,%s",
12544                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12545         }
12546         freeAsmop (fp, NULL, ic, FALSE);
12547
12548         emitcode ("lcall","System_%sPoll",name);
12549
12550         /* put result into place */
12551         {
12552                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12553                 if (rsym->liveFrom != rsym->liveTo) {   
12554                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12555                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12556                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12557                 }
12558         }
12559         unsavermask(rsave);
12560 }
12561
12562 /*-----------------------------------------------------------------*/
12563 /* genSystemGetCurrentID -                                         */
12564 /*-----------------------------------------------------------------*/
12565 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12566 {
12567         assert (nparms==0);
12568
12569         emitcode ("lcall","System_GetCurrent%sId",name);
12570         /* put result into place */
12571         {
12572                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12573                 if (rsym->liveFrom != rsym->liveTo) {   
12574                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12575                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12576                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12577                 }
12578         }
12579 }
12580
12581 /*-----------------------------------------------------------------*/
12582 /* genBuiltIn - calls the appropriate function to  generating code */
12583 /* for a built in function                                         */
12584 /*-----------------------------------------------------------------*/
12585 static void genBuiltIn (iCode *ic)
12586 {
12587         operand *bi_parms[MAX_BUILTIN_ARGS];
12588         int nbi_parms;
12589         iCode *bi_iCode;
12590         symbol *bif;
12591
12592         /* get all the arguments for a built in function */
12593         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12594
12595         /* which function is it */
12596         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12597         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12598                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12599         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12600                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12601         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12602                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12603         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12604                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12605         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12606                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12607         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12608                 genInp(bi_iCode,nbi_parms,bi_parms);
12609         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12610                 genOutp(bi_iCode,nbi_parms,bi_parms);
12611         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12612                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12613                 /* JavaNative builtIns */               
12614         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12615                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12616         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12617                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12618         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12619                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12620         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12621                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12622         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12623                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12624         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12625                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12626         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12627                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12628         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12629                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12630         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12631                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12632         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12633                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12634         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12635                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12636         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12637                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12638         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12639                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12640         } else if (strcmp(bif->name,"MM_Free")==0) {
12641                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12642         } else if (strcmp(bif->name,"MM_Deref")==0) {
12643                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12644         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12645                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12646         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12647                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12648         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12649                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12650         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12651                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12652         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12653                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12654         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12655                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12656         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12657                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12658         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12659                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12660         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12661                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12662         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12663                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12664         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12665                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12666         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12667                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12668         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12669                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12670         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12671                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12672         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12673                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12674         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12675                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12676         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12677                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12678         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12679                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12680         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12681                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12682         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12683                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12684         } else {
12685                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12686                 return ;
12687         }
12688         return ;    
12689 }
12690
12691 /*-----------------------------------------------------------------*/
12692 /* gen390Code - generate code for Dallas 390 based controllers     */
12693 /*-----------------------------------------------------------------*/
12694 void
12695 gen390Code (iCode * lic)
12696 {
12697   iCode *ic;
12698   int cln = 0;
12699
12700   lineHead = lineCurr = NULL;
12701   dptrn[1][0] = "dpl1";
12702   dptrn[1][1] = "dph1";
12703   dptrn[1][2] = "dpx1";
12704   
12705   if (options.model == MODEL_FLAT24) {
12706     fReturnSizeDS390 = 5;
12707     fReturn = fReturn24;
12708   } else {
12709     fReturnSizeDS390 = 4;
12710     fReturn = fReturn16;
12711     options.stack10bit=0;
12712   }
12713 #if 1
12714   /* print the allocation information */
12715   if (allocInfo)
12716     printAllocInfo (currFunc, codeOutFile);
12717 #endif
12718   /* if debug information required */
12719   if (options.debug && currFunc)
12720     {
12721       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12722       _G.debugLine = 1;
12723       if (IS_STATIC (currFunc->etype))
12724         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12725       else
12726         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12727       _G.debugLine = 0;
12728     }
12729   /* stack pointer name */
12730   if (options.useXstack)
12731     spname = "_spx";
12732   else
12733     spname = "sp";
12734
12735
12736   for (ic = lic; ic; ic = ic->next)
12737     {
12738
12739       if (ic->lineno && cln != ic->lineno)
12740         {
12741           if (options.debug)
12742             {
12743               _G.debugLine = 1;
12744               emitcode ("", "C$%s$%d$%d$%d ==.",
12745                         FileBaseName (ic->filename), ic->lineno,
12746                         ic->level, ic->block);
12747               _G.debugLine = 0;
12748             }
12749           if (!options.noCcodeInAsm) {
12750             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12751                       printCLine(ic->filename, ic->lineno));
12752           }
12753           cln = ic->lineno;
12754         }
12755       if (options.iCodeInAsm) {
12756         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12757       }
12758       /* if the result is marked as
12759          spilt and rematerializable or code for
12760          this has already been generated then
12761          do nothing */
12762       if (resultRemat (ic) || ic->generated)
12763         continue;
12764
12765       /* depending on the operation */
12766       switch (ic->op)
12767         {
12768         case '!':
12769           genNot (ic);
12770           break;
12771
12772         case '~':
12773           genCpl (ic);
12774           break;
12775
12776         case UNARYMINUS:
12777           genUminus (ic);
12778           break;
12779
12780         case IPUSH:
12781           genIpush (ic);
12782           break;
12783
12784         case IPOP:
12785           /* IPOP happens only when trying to restore a
12786              spilt live range, if there is an ifx statement
12787              following this pop then the if statement might
12788              be using some of the registers being popped which
12789              would destory the contents of the register so
12790              we need to check for this condition and handle it */
12791           if (ic->next &&
12792               ic->next->op == IFX &&
12793               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12794             genIfx (ic->next, ic);
12795           else
12796             genIpop (ic);
12797           break;
12798
12799         case CALL:
12800           genCall (ic);
12801           break;
12802
12803         case PCALL:
12804           genPcall (ic);
12805           break;
12806
12807         case FUNCTION:
12808           genFunction (ic);
12809           break;
12810
12811         case ENDFUNCTION:
12812           genEndFunction (ic);
12813           break;
12814
12815         case RETURN:
12816           genRet (ic);
12817           break;
12818
12819         case LABEL:
12820           genLabel (ic);
12821           break;
12822
12823         case GOTO:
12824           genGoto (ic);
12825           break;
12826
12827         case '+':
12828           genPlus (ic);
12829           break;
12830
12831         case '-':
12832           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12833             genMinus (ic);
12834           break;
12835
12836         case '*':
12837           genMult (ic);
12838           break;
12839
12840         case '/':
12841           genDiv (ic);
12842           break;
12843
12844         case '%':
12845           genMod (ic);
12846           break;
12847
12848         case '>':
12849           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12850           break;
12851
12852         case '<':
12853           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12854           break;
12855
12856         case LE_OP:
12857         case GE_OP:
12858         case NE_OP:
12859
12860           /* note these two are xlated by algebraic equivalence
12861              during parsing SDCC.y */
12862           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12863                   "got '>=' or '<=' shouldn't have come here");
12864           break;
12865
12866         case EQ_OP:
12867           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12868           break;
12869
12870         case AND_OP:
12871           genAndOp (ic);
12872           break;
12873
12874         case OR_OP:
12875           genOrOp (ic);
12876           break;
12877
12878         case '^':
12879           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12880           break;
12881
12882         case '|':
12883           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12884           break;
12885
12886         case BITWISEAND:
12887           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12888           break;
12889
12890         case INLINEASM:
12891           genInline (ic);
12892           break;
12893
12894         case RRC:
12895           genRRC (ic);
12896           break;
12897
12898         case RLC:
12899           genRLC (ic);
12900           break;
12901
12902         case GETHBIT:
12903           genGetHbit (ic);
12904           break;
12905
12906         case LEFT_OP:
12907           genLeftShift (ic);
12908           break;
12909
12910         case RIGHT_OP:
12911           genRightShift (ic);
12912           break;
12913
12914         case GET_VALUE_AT_ADDRESS:
12915           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12916           break;
12917
12918         case '=':
12919           if (POINTER_SET (ic))
12920             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12921           else
12922             genAssign (ic);
12923           break;
12924
12925         case IFX:
12926           genIfx (ic, NULL);
12927           break;
12928
12929         case ADDRESS_OF:
12930           genAddrOf (ic);
12931           break;
12932
12933         case JUMPTABLE:
12934           genJumpTab (ic);
12935           break;
12936
12937         case CAST:
12938           genCast (ic);
12939           break;
12940
12941         case RECEIVE:
12942           genReceive (ic);
12943           break;
12944
12945         case SEND:
12946           if (ic->builtinSEND) genBuiltIn(ic);
12947           else addSet (&_G.sendSet, ic);
12948           break;
12949
12950         case ARRAYINIT:
12951             genArrayInit(ic);
12952             break;
12953             
12954         default:
12955           ic = ic;
12956         }
12957     }
12958
12959
12960   /* now we are ready to call the
12961      peep hole optimizer */
12962   if (!options.nopeep)
12963     peepHole (&lineHead);
12964
12965   /* now do the actual printing */
12966   printLine (lineHead, codeOutFile);
12967   return;
12968 }