1cf40126b348e97bf7c6490a1f18184af97ec885
[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) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
113 #define MOVA(x) { char *_mova_tmp = strdup(x); \
114                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
115                  { \
116                     emitcode("mov","a,%s",_mova_tmp); \
117                  } \
118                  free(_mova_tmp); \
119                 }
120 #define CLRC    emitcode("clr","c")
121 #define SETC    emitcode("setb","c")
122
123 // A scratch register which will be used to hold
124 // result bytes from operands in far space via DPTR2.
125 #define DP2_RESULT_REG  "_ap"
126
127 static lineNode *lineHead = NULL;
128 static lineNode *lineCurr = NULL;
129
130 static unsigned char SLMask[] =
131 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
132  0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char SRMask[] =
134 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
135  0x07, 0x03, 0x01, 0x00};
136
137 #define LSB     0
138 #define MSB16   1
139 #define MSB24   2
140 #define MSB32   3
141 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
142                                 symbol *lbl = newiTempLabel(NULL);              \
143                                 emitcode ("setb","F1");                         \
144                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
145                                 emitcode ("clr","F1");                          \
146                                 emitcode ("","!tlabeldef",lbl->key+100);        \
147                         }}
148 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
149                                 symbol *lbl = newiTempLabel(NULL);              \
150                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
151                                 emitcode ("setb","EA");                         \
152                                 emitcode ("","!tlabeldef",lbl->key+100);        \
153                         }}
154
155
156 /*-----------------------------------------------------------------*/
157 /* emitcode - writes the code into a file : for now it is simple    */
158 /*-----------------------------------------------------------------*/
159 static void
160 emitcode (char *inst, char *fmt,...)
161 {
162     va_list ap;
163     char lb[INITIAL_INLINEASM];
164     char *lbp = lb;
165     
166     va_start (ap, fmt);
167     
168     if (inst && *inst)
169     {
170         if (fmt && *fmt)
171         {
172             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
173         }
174         else
175         {
176             SNPRINTF (lb, sizeof(lb), "%s", inst);
177         }
178         
179         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
180                    fmt, ap);
181     }
182     else
183     {
184         tvsprintf (lb, sizeof(lb), fmt, ap);
185     }
186     
187
188     while (isspace (*lbp))
189     {
190         lbp++;
191     }
192
193     if (lbp && *lbp)
194     {
195         lineCurr = (lineCurr ?
196                     connectLine (lineCurr, newLineNode (lb)) :
197                     (lineHead = newLineNode (lb)));
198     }
199     
200     lineCurr->isInline = _G.inLine;
201     lineCurr->isDebug = _G.debugLine;
202     va_end (ap);
203 }
204
205 /*-----------------------------------------------------------------*/
206 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
207 /*-----------------------------------------------------------------*/
208 static regs *
209 getFreePtr (iCode * ic, asmop ** aopp, bool result)
210 {
211   bool r0iu = FALSE, r1iu = FALSE;
212   bool r0ou = FALSE, r1ou = FALSE;
213
214   /* the logic: if r0 & r1 used in the instruction
215      then we are in trouble otherwise */
216
217   /* first check if r0 & r1 are used by this
218      instruction, in which case we are in trouble */
219   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
220   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
221   if (r0iu && r1iu) {
222       goto endOfWorld;
223     }
224
225   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
226   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
227
228   /* if no usage of r0 then return it */
229   if (!r0iu && !r0ou)
230     {
231       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
232       (*aopp)->type = AOP_R0;
233
234       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
235     }
236
237   /* if no usage of r1 then return it */
238   if (!r1iu && !r1ou)
239     {
240       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241       (*aopp)->type = AOP_R1;
242
243       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
244     }
245
246   /* now we know they both have usage */
247   /* if r0 not used in this instruction */
248   if (!r0iu)
249     {
250       /* push it if not already pushed */
251       if (!_G.r0Pushed)
252         {
253           emitcode ("push", "%s",
254                     ds390_regWithIdx (R0_IDX)->dname);
255           _G.r0Pushed++;
256         }
257
258       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
259       (*aopp)->type = AOP_R0;
260
261       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
262     }
263
264   /* if r1 not used then */
265
266   if (!r1iu)
267     {
268       /* push it if not already pushed */
269       if (!_G.r1Pushed)
270         {
271           emitcode ("push", "%s",
272                     ds390_regWithIdx (R1_IDX)->dname);
273           _G.r1Pushed++;
274         }
275
276       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
277       (*aopp)->type = AOP_R1;
278       return ds390_regWithIdx (R1_IDX);
279     }
280
281 endOfWorld:
282   /* I said end of world but not quite end of world yet */
283   /* if this is a result then we can push it on the stack */
284   if (result)
285     {
286       (*aopp)->type = AOP_STK;
287       return NULL;
288     }
289
290   /* other wise this is true end of the world */
291   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
292           "getFreePtr should never reach here");
293   exit (1);
294 }
295
296 /*-----------------------------------------------------------------*/
297 /* newAsmop - creates a new asmOp                                  */
298 /*-----------------------------------------------------------------*/
299 static asmop *
300 newAsmop (short type)
301 {
302   asmop *aop;
303
304   aop = Safe_calloc (1, sizeof (asmop));
305   aop->type = type;
306   return aop;
307 }
308
309 static int _currentDPS;         /* Current processor DPS. */
310 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
311 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
312
313 /*-----------------------------------------------------------------*/
314 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
315 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
316 /* alternate DPTR (DPL1/DPH1/DPX1).          */
317 /*-----------------------------------------------------------------*/
318 static void
319 genSetDPTR (int n)
320 {
321
322   /* If we are doing lazy evaluation, simply note the desired
323    * change, but don't emit any code yet.
324    */
325   if (_lazyDPS)
326     {
327       _desiredDPS = n;
328       return;
329     }
330
331   if (!n)
332     {
333       emitcode ("mov", "dps,#0");
334     }
335   else
336     {
337       TR_DPTR("#1");
338       emitcode ("mov", "dps,#1");
339     }
340 }
341
342 /*-----------------------------------------------------------------*/
343 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
344 /*                   */
345 /* Any code that operates on DPTR (NB: not on the individual     */
346 /* components, like DPH) *must* call _flushLazyDPS() before using  */
347 /* DPTR within a lazy DPS evaluation block.        */
348 /*                   */
349 /* Note that aopPut and aopGet already contain the proper calls to */
350 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
351 /* DPS evaluation block.             */
352 /*                   */
353 /* Also, _flushLazyDPS must be called before any flow control      */
354 /* operations that could potentially branch out of the block.    */
355 /*                         */
356 /* Lazy DPS evaluation is simply an optimization (though an      */
357 /* important one), so if in doubt, leave it out.       */
358 /*-----------------------------------------------------------------*/
359 static void
360 _startLazyDPSEvaluation (void)
361 {
362   _currentDPS = 0;
363   _desiredDPS = 0;
364 #ifdef BETTER_LITERAL_SHIFT  
365   _lazyDPS++;
366 #else
367   _lazyDPS = 1;
368 #endif  
369 }
370
371 /*-----------------------------------------------------------------*/
372 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
373 /* desired one. Call before using DPTR within a lazy DPS evaluation */
374 /* block.                */
375 /*-----------------------------------------------------------------*/
376 static void
377 _flushLazyDPS (void)
378 {
379   if (!_lazyDPS)
380     {
381       /* nothing to do. */
382       return;
383     }
384
385   if (_desiredDPS != _currentDPS)
386     {
387       if (_desiredDPS)
388         {
389           emitcode ("inc", "dps");
390         }
391       else
392         {
393           emitcode ("dec", "dps");
394         }
395       _currentDPS = _desiredDPS;
396     }
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
401 /*                   */
402 /* Forces us back to the safe state (standard DPTR selected).    */
403 /*-----------------------------------------------------------------*/
404 static void
405 _endLazyDPSEvaluation (void)
406 {
407 #ifdef BETTER_LITERAL_SHIFT  
408   _lazyDPS--;
409 #else
410   _lazyDPS = 0;
411 #endif    
412   if (!_lazyDPS)
413   {
414     if (_currentDPS)
415     {
416       genSetDPTR (0);
417       _flushLazyDPS ();
418     }
419     _currentDPS = 0;
420     _desiredDPS = 0;
421   }
422 }
423
424
425
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type               */
428 /*-----------------------------------------------------------------*/
429 static int
430 pointerCode (sym_link * etype)
431 {
432
433   return PTR_TYPE (SPEC_OCLS (etype));
434
435 }
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *
441 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
442 {
443   asmop *aop;
444   memmap *space = SPEC_OCLS (sym->etype);
445
446   /* if already has one */
447   if (sym->aop)
448     return sym->aop;
449
450   /* assign depending on the storage class */
451   /* if it is on the stack or indirectly addressable */
452   /* space we need to assign either r0 or r1 to it   */
453   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
454     {
455       sym->aop = aop = newAsmop (0);
456       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
457       aop->size = getSize (sym->type);
458
459       /* now assign the address of the variable to
460          the pointer register */
461       if (aop->type != AOP_STK)
462         {
463
464           if (sym->onStack)
465             {
466               if (_G.accInUse)
467                 emitcode ("push", "acc");
468
469               if (_G.bInUse)
470                 emitcode ("push", "b");
471
472               emitcode ("mov", "a,_bp");
473               emitcode ("add", "a,#!constbyte",
474                         ((sym->stack < 0) ?
475                          ((char) (sym->stack - _G.nRegsSaved)) :
476                          ((char) sym->stack)) & 0xff);
477               emitcode ("mov", "%s,a",
478                         aop->aopu.aop_ptr->name);
479
480               if (_G.bInUse)
481                 emitcode ("pop", "b");
482
483               if (_G.accInUse)
484                 emitcode ("pop", "acc");
485             }
486           else
487             emitcode ("mov", "%s,#%s",
488                       aop->aopu.aop_ptr->name,
489                       sym->rname);
490           aop->paged = space->paged;
491         }
492       else
493         aop->aopu.aop_stk = sym->stack;
494       return aop;
495     }
496
497   if (sym->onStack && options.stack10bit)
498     {
499         short stack_val = -((sym->stack < 0) ?
500                             ((short) (sym->stack - _G.nRegsSaved)) :
501                             ((short) sym->stack)) ;
502         if (useDP2 && _G.dptr1InUse) {
503             emitcode ("push","dpl1");
504             emitcode ("push","dph1");
505             emitcode ("push","dpx1");
506         } else if (_G.dptrInUse ) {
507             emitcode ("push","dpl");
508             emitcode ("push","dph");
509             emitcode ("push","dpx");
510         }
511       /* It's on the 10 bit stack, which is located in
512        * far data space.
513        */           
514         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
515             if (useDP2) {
516                 if (options.model == MODEL_FLAT24)
517                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
518                 TR_DPTR("#2");
519                 emitcode ("mov", "dph1,_bpx+1");
520                 emitcode ("mov", "dpl1,_bpx");
521                 emitcode ("mov","dps,#1");
522             } else {
523                 if (options.model == MODEL_FLAT24)
524                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
525                 emitcode ("mov", "dph,_bpx+1");
526                 emitcode ("mov", "dpl,_bpx");
527             }
528             stack_val = -stack_val;
529             while (stack_val--) {
530                 emitcode ("inc","dptr");
531             }
532             if (useDP2) {
533                 emitcode("mov","dps,#0");
534             }
535         }  else {
536             if (_G.accInUse)
537                 emitcode ("push", "acc");
538             
539             if (_G.bInUse)
540                 emitcode ("push", "b");
541         
542             emitcode ("mov", "a,_bpx");
543             emitcode ("clr","c");
544             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
545             emitcode ("mov","b,a");
546             emitcode ("mov","a,_bpx+1");
547             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
548             if (useDP2) {
549                 if (options.model == MODEL_FLAT24)
550                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
551                 TR_DPTR("#2");
552                 emitcode ("mov", "dph1,a");
553                 emitcode ("mov", "dpl1,b");
554             } else {
555                 if (options.model == MODEL_FLAT24)
556                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
557                 emitcode ("mov", "dph,a");
558                 emitcode ("mov", "dpl,b");
559             }
560             
561             if (_G.bInUse)
562                 emitcode ("pop", "b");
563             
564             if (_G.accInUse)
565                 emitcode ("pop", "acc");
566         }
567         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
568         aop->size = getSize (sym->type);
569         return aop;
570     }
571
572   /* if in bit space */
573   if (IN_BITSPACE (space))
574     {
575       sym->aop = aop = newAsmop (AOP_CRY);
576       aop->aopu.aop_dir = sym->rname;
577       aop->size = getSize (sym->type);
578       return aop;
579     }
580   /* if it is in direct space */
581   if (IN_DIRSPACE (space))
582     {
583       sym->aop = aop = newAsmop (AOP_DIR);
584       aop->aopu.aop_dir = sym->rname;
585       aop->size = getSize (sym->type);
586       return aop;
587     }
588
589   /* special case for a function */
590   if (IS_FUNC (sym->type))
591     {
592       sym->aop = aop = newAsmop (AOP_IMMD);
593       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
594       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
595       aop->size = FPTRSIZE;
596       return aop;
597     }
598   
599   /* only remaining is far space */
600   /* in which case DPTR gets the address */
601   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
602   if (useDP2)
603     {
604       genSetDPTR (1);
605       _flushLazyDPS ();
606       emitcode ("mov", "dptr,#%s", sym->rname);
607       genSetDPTR (0);
608     }
609   else
610     {
611       emitcode ("mov", "dptr,#%s", sym->rname);
612     }
613   aop->size = getSize (sym->type);
614
615   /* if it is in code space */
616   if (IN_CODESPACE (space))
617     aop->code = 1;
618
619   return aop;
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* aopForRemat - rematerialzes an object                           */
624 /*-----------------------------------------------------------------*/
625 static asmop *
626 aopForRemat (symbol * sym)
627 {
628   iCode *ic = sym->rematiCode;
629   asmop *aop = newAsmop (AOP_IMMD);
630   int ptr_type =0;
631   int val = 0;
632
633   for (;;)
634     {
635       if (ic->op == '+')
636         val += (int) operandLitValue (IC_RIGHT (ic));
637       else if (ic->op == '-')
638         val -= (int) operandLitValue (IC_RIGHT (ic));
639       else if (IS_CAST_ICODE(ic)) {
640               sym_link *from_type = operandType(IC_RIGHT(ic));
641               aop->aopu.aop_immd.from_cast_remat = 1;
642               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
643               ptr_type = DCL_TYPE(from_type);
644               if (ptr_type == IPOINTER) {
645                 // bug #481053
646                 ptr_type = POINTER;
647               }
648               continue ;
649       } else break;
650       
651       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
652     }
653
654   if (val)
655     sprintf (buffer, "(%s %c 0x%04x)",
656              OP_SYMBOL (IC_LEFT (ic))->rname,
657              val >= 0 ? '+' : '-',
658              abs (val) & 0xffff);
659   else {
660       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
661           sprintf(buffer,"0x%x",(int) operandLitValue (IC_RIGHT (ic)));
662       else
663           strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
664   }
665
666   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
667   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
668   /* set immd2 field if required */
669   if (aop->aopu.aop_immd.from_cast_remat) 
670   {
671       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
672       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);  
673   }
674
675   return aop;
676 }
677
678 /*-----------------------------------------------------------------*/
679 /* aopHasRegs - returns true if aop has regs between from-to       */
680 /*-----------------------------------------------------------------*/
681 static int aopHasRegs(asmop *aop, int from, int to)
682 {
683     int size =0;
684
685     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
686
687     for (; size < aop->size ; size++) {
688         int reg;
689         for (reg = from ; reg <= to ; reg++)
690             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
691     }
692     return 0;
693 }
694
695 /*-----------------------------------------------------------------*/
696 /* regsInCommon - two operands have some registers in common       */
697 /*-----------------------------------------------------------------*/
698 static bool
699 regsInCommon (operand * op1, operand * op2)
700 {
701   symbol *sym1, *sym2;
702   int i;
703
704   /* if they have registers in common */
705   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
706     return FALSE;
707
708   sym1 = OP_SYMBOL (op1);
709   sym2 = OP_SYMBOL (op2);
710
711   if (sym1->nRegs == 0 || sym2->nRegs == 0)
712     return FALSE;
713
714   for (i = 0; i < sym1->nRegs; i++)
715     {
716       int j;
717       if (!sym1->regs[i])
718         continue;
719
720       for (j = 0; j < sym2->nRegs; j++)
721         {
722           if (!sym2->regs[j])
723             continue;
724
725           if (sym2->regs[j] == sym1->regs[i])
726             return TRUE;
727         }
728     }
729
730   return FALSE;
731 }
732
733 /*-----------------------------------------------------------------*/
734 /* operandsEqu - equivalent                                        */
735 /*-----------------------------------------------------------------*/
736 static bool
737 operandsEqu (operand * op1, operand * op2)
738 {
739   symbol *sym1, *sym2;
740
741   /* if they not symbols */
742   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
743     return FALSE;
744
745   sym1 = OP_SYMBOL (op1);
746   sym2 = OP_SYMBOL (op2);
747
748   /* if both are itemps & one is spilt
749      and the other is not then false */
750   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
751       sym1->isspilt != sym2->isspilt)
752     return FALSE;
753
754   /* if they are the same */
755   if (sym1 == sym2)
756     return TRUE;
757
758   if (strcmp (sym1->rname, sym2->rname) == 0)
759     return TRUE;
760
761
762   /* if left is a tmp & right is not */
763   if (IS_ITEMP (op1) &&
764       !IS_ITEMP (op2) &&
765       sym1->isspilt &&
766       (sym1->usl.spillLoc == sym2))
767     return TRUE;
768
769   if (IS_ITEMP (op2) &&
770       !IS_ITEMP (op1) &&
771       sym2->isspilt &&
772       sym1->level > 0 &&
773       (sym2->usl.spillLoc == sym1))
774     return TRUE;
775
776   return FALSE;
777 }
778
779 /*-----------------------------------------------------------------*/
780 /* sameRegs - two asmops have the same registers                   */
781 /*-----------------------------------------------------------------*/
782 static bool
783 sameRegs (asmop * aop1, asmop * aop2)
784 {
785   int i;
786
787   if (aop1 == aop2)
788     {
789       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
790         {
791           return FALSE;
792         }
793       return TRUE;
794     }
795
796   if (aop1->type != AOP_REG ||
797       aop2->type != AOP_REG)
798     return FALSE;
799
800   if (aop1->size != aop2->size)
801     return FALSE;
802
803   for (i = 0; i < aop1->size; i++)
804     if (aop1->aopu.aop_reg[i] !=
805         aop2->aopu.aop_reg[i])
806       return FALSE;
807
808   return TRUE;
809 }
810
811 /*-----------------------------------------------------------------*/
812 /* aopOp - allocates an asmop for an operand  :                    */
813 /*-----------------------------------------------------------------*/
814 static void
815 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
816 {
817   asmop *aop;
818   symbol *sym;
819   int i;
820
821   if (!op)
822     return;
823
824   /* if this a literal */
825   if (IS_OP_LITERAL (op))
826     {
827       op->aop = aop = newAsmop (AOP_LIT);
828       aop->aopu.aop_lit = op->operand.valOperand;
829       aop->size = getSize (operandType (op));
830       return;
831     }
832
833   /* if already has a asmop then continue */
834   if (op->aop)
835     return;
836
837   /* if the underlying symbol has a aop */
838   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
839     {
840       op->aop = OP_SYMBOL (op)->aop;
841       return;
842     }
843
844   /* if this is a true symbol */
845   if (IS_TRUE_SYMOP (op))
846     {
847       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
848       return;
849     }
850
851   /* this is a temporary : this has
852      only four choices :
853      a) register
854      b) spillocation
855      c) rematerialize
856      d) conditional
857      e) can be a return use only */
858
859   sym = OP_SYMBOL (op);
860
861
862   /* if the type is a conditional */
863   if (sym->regType == REG_CND)
864     {
865       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
866       aop->size = 0;
867       return;
868     }
869
870   /* if it is spilt then two situations
871      a) is rematerialize
872      b) has a spill location */
873   if (sym->isspilt || sym->nRegs == 0)
874     {
875
876       /* rematerialize it NOW */
877       if (sym->remat)
878         {
879           sym->aop = op->aop = aop =
880             aopForRemat (sym);
881           aop->size = getSize (sym->type);
882           return;
883         }
884
885       if (sym->accuse)
886         {
887           int i;
888           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
889           aop->size = getSize (sym->type);
890           for (i = 0; i < 2; i++)
891             aop->aopu.aop_str[i] = accUse[i];
892           return;
893         }
894
895       if (sym->ruonly)
896         {
897           int i;
898
899           if (useDP2)
900             {
901               /* a AOP_STR uses DPTR, but DPTR is already in use;
902                * we're just hosed.
903                */
904                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
905             }
906
907           aop = op->aop = sym->aop = newAsmop (AOP_STR);
908           aop->size = getSize (sym->type);
909           for (i = 0; i < (int) fReturnSizeDS390; i++)
910             aop->aopu.aop_str[i] = fReturn[i];
911           return;
912         }
913       
914       if (sym->dptr) { /* has been allocated to a DPTRn */
915           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
916           aop->size = getSize (sym->type);
917           aop->aopu.dptr = sym->dptr;
918           return ;
919       }
920       /* else spill location  */
921       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
922           /* force a new aop if sizes differ */
923           sym->usl.spillLoc->aop = NULL;
924       }
925       sym->aop = op->aop = aop =
926         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
927       aop->size = getSize (sym->type);
928       return;
929     }
930
931   /* must be in a register */
932   sym->aop = op->aop = aop = newAsmop (AOP_REG);
933   aop->size = sym->nRegs;
934   for (i = 0; i < sym->nRegs; i++)
935     aop->aopu.aop_reg[i] = sym->regs[i];
936 }
937
938 /*-----------------------------------------------------------------*/
939 /* freeAsmop - free up the asmop given to an operand               */
940 /*----------------------------------------------------------------*/
941 static void
942 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
943 {
944   asmop *aop;
945
946   if (!op)
947     aop = aaop;
948   else
949     aop = op->aop;
950
951   if (!aop)
952     return;
953
954   if (aop->freed)
955     goto dealloc;
956
957   aop->freed = 1;
958
959   /* depending on the asmop type only three cases need work AOP_RO
960      , AOP_R1 && AOP_STK */
961   switch (aop->type)
962     {
963     case AOP_R0:
964       if (_G.r0Pushed)
965         {
966           if (pop)
967             {
968               emitcode ("pop", "ar0");
969               _G.r0Pushed--;
970             }
971         }
972       bitVectUnSetBit (ic->rUsed, R0_IDX);
973       break;
974
975     case AOP_R1:
976       if (_G.r1Pushed)
977         {
978           if (pop)
979             {
980               emitcode ("pop", "ar1");
981               _G.r1Pushed--;
982             }
983         }
984       bitVectUnSetBit (ic->rUsed, R1_IDX);
985       break;
986
987     case AOP_STK:
988       {
989         int sz = aop->size;
990         int stk = aop->aopu.aop_stk + aop->size;
991         bitVectUnSetBit (ic->rUsed, R0_IDX);
992         bitVectUnSetBit (ic->rUsed, R1_IDX);
993
994         getFreePtr (ic, &aop, FALSE);
995
996         if (options.stack10bit)
997           {
998             /* I'm not sure what to do here yet... */
999             /* #STUB */
1000             fprintf (stderr,
1001                      "*** Warning: probably generating bad code for "
1002                      "10 bit stack mode.\n");
1003           }
1004
1005         if (stk)
1006           {
1007             emitcode ("mov", "a,_bp");
1008             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1009             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1010           }
1011         else
1012           {
1013             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1014           }
1015
1016         while (sz--)
1017           {
1018             emitcode ("pop", "acc");
1019             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1020             if (!sz)
1021               break;
1022             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1023           }
1024         op->aop = aop;
1025         freeAsmop (op, NULL, ic, TRUE);
1026         if (_G.r0Pushed)
1027           {
1028             emitcode ("pop", "ar0");
1029             _G.r0Pushed--;
1030           }
1031
1032         if (_G.r1Pushed)
1033           {
1034             emitcode ("pop", "ar1");
1035             _G.r1Pushed--;
1036           }
1037       }
1038     case AOP_DPTR2:
1039         if (_G.dptr1InUse) {
1040             emitcode ("pop","dpx1");
1041             emitcode ("pop","dph1");
1042             emitcode ("pop","dpl1");
1043         }
1044         break;
1045     case AOP_DPTR:
1046         if (_G.dptrInUse) {
1047             emitcode ("pop","dpx");
1048             emitcode ("pop","dph");
1049             emitcode ("pop","dpl");
1050         }
1051         break;
1052     }
1053 dealloc:
1054   /* all other cases just dealloc */
1055   if (op)
1056     {
1057       op->aop = NULL;
1058       if (IS_SYMOP (op))
1059         {
1060           OP_SYMBOL (op)->aop = NULL;
1061           /* if the symbol has a spill */
1062           if (SPIL_LOC (op))
1063             SPIL_LOC (op)->aop = NULL;
1064         }
1065     }
1066 }
1067
1068 /*------------------------------------------------------------------*/
1069 /* aopGet - for fetching value of the aop                           */
1070 /*                    */
1071 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1072 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1073 /* just less efficient.               */
1074 /*------------------------------------------------------------------*/
1075
1076 static char *
1077 aopGet (asmop * aop,
1078         int offset,
1079         bool bit16,
1080         bool dname,
1081         bool canClobberACC)
1082 {
1083   //char *s = buffer;
1084   //char *rs;
1085
1086   /* offset is greater than
1087      size then zero */
1088   if (offset > (aop->size - 1) &&
1089       aop->type != AOP_LIT)
1090     return zero;
1091
1092   /* depending on type */
1093   switch (aop->type)
1094     {
1095
1096     case AOP_R0:
1097     case AOP_R1:
1098       /* if we need to increment it */
1099       while (offset > aop->coff)
1100         {
1101           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1102           aop->coff++;
1103         }
1104
1105       while (offset < aop->coff)
1106         {
1107           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1108           aop->coff--;
1109         }
1110
1111       aop->coff = offset;
1112       if (aop->paged)
1113         {
1114           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1115           return (dname ? "acc" : "a");
1116         }
1117       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1118       return Safe_strdup(buffer);       
1119
1120     case AOP_DPTRn:
1121         assert(offset <= 3);
1122         return dptrn[aop->aopu.dptr][offset];
1123
1124     case AOP_DPTR:
1125     case AOP_DPTR2:
1126
1127       if (aop->type == AOP_DPTR2)
1128         {
1129           genSetDPTR (1);
1130           if (!canClobberACC)
1131             {
1132                     TR_AP("#1");
1133                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1134             }
1135         }
1136
1137       _flushLazyDPS ();
1138
1139       while (offset > aop->coff)
1140         {
1141           emitcode ("inc", "dptr");
1142           aop->coff++;
1143         }
1144
1145       while (offset < aop->coff)
1146         {
1147           emitcode ("lcall", "__decdptr");
1148           aop->coff--;
1149         }
1150
1151       aop->coff = offset;
1152       if (aop->code)
1153         {
1154           emitcode ("clr", "a");
1155           emitcode ("movc", "a,@a+dptr");
1156         }
1157       else
1158         {
1159           emitcode ("movx", "a,@dptr");
1160         }
1161
1162       if (aop->type == AOP_DPTR2)
1163         {
1164           genSetDPTR (0);
1165           if (!canClobberACC)
1166             {
1167        TR_AP("#2");
1168               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1169               return DP2_RESULT_REG;
1170             }
1171         }
1172       return (dname ? "acc" : "a");
1173
1174     case AOP_IMMD:
1175       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1176       {
1177           SNPRINTF(buffer, sizeof(buffer), 
1178                    "%s",aop->aopu.aop_immd.aop_immd2);
1179       } 
1180       else if (bit16)
1181       {
1182          SNPRINTF(buffer, sizeof(buffer), 
1183                   "#%s", aop->aopu.aop_immd.aop_immd1);
1184       }
1185       else if (offset) 
1186       {
1187           switch (offset) {
1188           case 1:
1189               tsprintf(buffer, sizeof(buffer),
1190                        "#!his",aop->aopu.aop_immd.aop_immd1);
1191               break;
1192           case 2:
1193               tsprintf(buffer, sizeof(buffer), 
1194                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1195               break;
1196           case 3:
1197               tsprintf(buffer, sizeof(buffer),
1198                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1199               break;
1200           default: /* should not need this (just in case) */
1201               SNPRINTF (buffer, sizeof(buffer), 
1202                         "#(%s >> %d)",
1203                        aop->aopu.aop_immd.aop_immd1,
1204                        offset * 8);
1205           }
1206       }
1207       else
1208       {
1209         SNPRINTF (buffer, sizeof(buffer), 
1210                   "#%s", aop->aopu.aop_immd.aop_immd1);
1211       }
1212       return Safe_strdup(buffer);       
1213
1214     case AOP_DIR:
1215       if (offset)
1216       {
1217         SNPRINTF (buffer, sizeof(buffer),
1218                   "(%s + %d)",
1219                  aop->aopu.aop_dir,
1220                  offset);
1221       }
1222       else
1223       {
1224         SNPRINTF(buffer, sizeof(buffer), 
1225                  "%s", aop->aopu.aop_dir);
1226       }
1227
1228       return Safe_strdup(buffer);
1229
1230     case AOP_REG:
1231       if (dname)
1232         return aop->aopu.aop_reg[offset]->dname;
1233       else
1234         return aop->aopu.aop_reg[offset]->name;
1235
1236     case AOP_CRY:
1237       emitcode ("clr", "a");
1238       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1239       emitcode ("rlc", "a");
1240       return (dname ? "acc" : "a");
1241
1242     case AOP_ACC:
1243       if (!offset && dname)
1244         return "acc";
1245       return aop->aopu.aop_str[offset];
1246
1247     case AOP_LIT:
1248       return aopLiteral (aop->aopu.aop_lit, offset);
1249
1250     case AOP_STR:
1251       aop->coff = offset;
1252       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1253           dname)
1254         return "acc";
1255
1256       return aop->aopu.aop_str[offset];
1257
1258     }
1259
1260   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1261           "aopget got unsupported aop->type");
1262   exit (1);
1263 }
1264 /*-----------------------------------------------------------------*/
1265 /* aopPut - puts a string for a aop                                */
1266 /*-----------------------------------------------------------------*/
1267 static void
1268 aopPut (asmop * aop, char *s, int offset)
1269 {
1270   char *d = buffer;
1271
1272   if (aop->size && offset > (aop->size - 1))
1273     {
1274       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1275               "aopPut got offset > aop->size");
1276       exit (1);
1277     }
1278
1279   /* will assign value to value */
1280   /* depending on where it is ofcourse */
1281   switch (aop->type)
1282     {
1283     case AOP_DIR:
1284       if (offset)
1285         sprintf (d, "(%s + %d)",
1286                  aop->aopu.aop_dir, offset);
1287       else
1288         sprintf (d, "%s", aop->aopu.aop_dir);
1289
1290       if (strcmp (d, s))
1291         emitcode ("mov", "%s,%s", d, s);
1292
1293       break;
1294
1295     case AOP_REG:
1296       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1297           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1298         {
1299           if (*s == '@' ||
1300               strcmp (s, "r0") == 0 ||
1301               strcmp (s, "r1") == 0 ||
1302               strcmp (s, "r2") == 0 ||
1303               strcmp (s, "r3") == 0 ||
1304               strcmp (s, "r4") == 0 ||
1305               strcmp (s, "r5") == 0 ||
1306               strcmp (s, "r6") == 0 ||
1307               strcmp (s, "r7") == 0)
1308             emitcode ("mov", "%s,%s",
1309                       aop->aopu.aop_reg[offset]->dname, s);
1310           else
1311             emitcode ("mov", "%s,%s",
1312                       aop->aopu.aop_reg[offset]->name, s);
1313         }
1314       break;
1315
1316     case AOP_DPTRn:
1317         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1318         break;
1319
1320     case AOP_DPTR:
1321     case AOP_DPTR2:
1322
1323       if (aop->type == AOP_DPTR2)
1324         {
1325           genSetDPTR (1);
1326         }
1327       _flushLazyDPS ();
1328
1329       if (aop->code)
1330         {
1331           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1332                   "aopPut writting to code space");
1333           exit (1);
1334         }
1335
1336       while (offset > aop->coff)
1337         {
1338           aop->coff++;
1339           emitcode ("inc", "dptr");
1340         }
1341
1342       while (offset < aop->coff)
1343         {
1344           aop->coff--;
1345           emitcode ("lcall", "__decdptr");
1346         }
1347
1348       aop->coff = offset;
1349
1350       /* if not in accumulater */
1351       MOVA (s);
1352
1353       emitcode ("movx", "@dptr,a");
1354
1355       if (aop->type == AOP_DPTR2)
1356         {
1357           genSetDPTR (0);
1358         }
1359       break;
1360
1361     case AOP_R0:
1362     case AOP_R1:
1363       while (offset > aop->coff)
1364         {
1365           aop->coff++;
1366           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1367         }
1368       while (offset < aop->coff)
1369         {
1370           aop->coff--;
1371           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1372         }
1373       aop->coff = offset;
1374
1375       if (aop->paged)
1376         {
1377           MOVA (s);
1378           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1379
1380         }
1381       else if (*s == '@')
1382         {
1383           MOVA (s);
1384           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1385         }
1386       else if (strcmp (s, "r0") == 0 ||
1387                strcmp (s, "r1") == 0 ||
1388                strcmp (s, "r2") == 0 ||
1389                strcmp (s, "r3") == 0 ||
1390                strcmp (s, "r4") == 0 ||
1391                strcmp (s, "r5") == 0 ||
1392                strcmp (s, "r6") == 0 ||
1393                strcmp (s, "r7") == 0)
1394         {
1395           char buffer[10];
1396           sprintf (buffer, "a%s", s);
1397           emitcode ("mov", "@%s,%s",
1398                     aop->aopu.aop_ptr->name, buffer);
1399         }
1400       else
1401         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1402
1403       break;
1404
1405     case AOP_STK:
1406       if (strcmp (s, "a") == 0)
1407         emitcode ("push", "acc");
1408       else
1409         if (*s=='@') {
1410           MOVA(s);
1411           emitcode ("push", "acc");
1412         } else {
1413           emitcode ("push", s);
1414         }
1415
1416       break;
1417
1418     case AOP_CRY:
1419       /* if bit variable */
1420       if (!aop->aopu.aop_dir)
1421         {
1422           emitcode ("clr", "a");
1423           emitcode ("rlc", "a");
1424         }
1425       else
1426         {
1427           if (s == zero)
1428             emitcode ("clr", "%s", aop->aopu.aop_dir);
1429           else if (s == one)
1430             emitcode ("setb", "%s", aop->aopu.aop_dir);
1431           else if (!strcmp (s, "c"))
1432             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1433           else
1434             {
1435               if (strcmp (s, "a"))
1436                 {
1437                   MOVA (s);
1438                 }
1439               {
1440                 /* set C, if a >= 1 */
1441                 emitcode ("add", "a,#!constbyte",0xff);
1442                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1443               }
1444             }
1445         }
1446       break;
1447
1448     case AOP_STR:
1449       aop->coff = offset;
1450       if (strcmp (aop->aopu.aop_str[offset], s))
1451         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1452       break;
1453
1454     case AOP_ACC:
1455       aop->coff = offset;
1456       if (!offset && (strcmp (s, "acc") == 0))
1457         break;
1458
1459       if (strcmp (aop->aopu.aop_str[offset], s))
1460         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1461       break;
1462
1463     default:
1464       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1465               "aopPut got unsupported aop->type");
1466       exit (1);
1467     }
1468
1469 }
1470
1471
1472 /*--------------------------------------------------------------------*/
1473 /* reAdjustPreg - points a register back to where it should (coff==0) */
1474 /*--------------------------------------------------------------------*/
1475 static void
1476 reAdjustPreg (asmop * aop)
1477 {
1478   if ((aop->coff==0) || (aop->size <= 1)) {
1479     return;
1480   }
1481
1482   switch (aop->type)
1483     {
1484     case AOP_R0:
1485     case AOP_R1:
1486       while (aop->coff--)
1487         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1488       break;
1489     case AOP_DPTR:
1490     case AOP_DPTR2:
1491       if (aop->type == AOP_DPTR2)
1492         {
1493           genSetDPTR (1);
1494           _flushLazyDPS ();
1495         }
1496       while (aop->coff--)
1497         {
1498           emitcode ("lcall", "__decdptr");
1499         }
1500
1501       if (aop->type == AOP_DPTR2)
1502         {
1503           genSetDPTR (0);
1504         }
1505       break;
1506
1507     }
1508   aop->coff=0;
1509 }
1510
1511 #define AOP(op) op->aop
1512 #define AOP_TYPE(op) AOP(op)->type
1513 #define AOP_SIZE(op) AOP(op)->size
1514 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1515                        AOP_TYPE(x) == AOP_R0))
1516
1517 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1518                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1519                          AOP(x)->paged))
1520
1521 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1522                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1523                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1524 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1525 #define AOP_USESDPTR(x) (AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_STR)
1526
1527 /* Workaround for DS80C390 bug: div ab may return bogus results
1528  * if A is accessed in instruction immediately before the div.
1529  *
1530  * Will be fixed in B4 rev of processor, Dallas claims.
1531  */
1532
1533 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1534     if (!AOP_NEEDSACC(RIGHT))         \
1535     {               \
1536       /* We can load A first, then B, since     \
1537        * B (the RIGHT operand) won't clobber A,   \
1538        * thus avoiding touching A right before the div. \
1539        */             \
1540       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1541       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1542       MOVA(L);            \
1543       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1544     }               \
1545     else              \
1546     {               \
1547       /* Just stuff in a nop after loading A. */    \
1548       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1549       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1550       MOVA(L);            \
1551       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1552     }
1553
1554 /*-----------------------------------------------------------------*/
1555 /* genNotFloat - generates not for float operations              */
1556 /*-----------------------------------------------------------------*/
1557 static void
1558 genNotFloat (operand * op, operand * res)
1559 {
1560   int size, offset;
1561   char *l;
1562   symbol *tlbl;
1563
1564   D (emitcode (";", "genNotFloat ");
1565     );
1566
1567   /* we will put 127 in the first byte of
1568      the result */
1569   aopPut (AOP (res), "#127", 0);
1570   size = AOP_SIZE (op) - 1;
1571   offset = 1;
1572
1573   _startLazyDPSEvaluation ();
1574   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1575   MOVA (l);
1576
1577   while (size--)
1578     {
1579       emitcode ("orl", "a,%s",
1580                 aopGet (op->aop,
1581                         offset++, FALSE, FALSE, FALSE));
1582     }
1583   _endLazyDPSEvaluation ();
1584
1585   tlbl = newiTempLabel (NULL);
1586   aopPut (res->aop, one, 1);
1587   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1588   aopPut (res->aop, zero, 1);
1589   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1590
1591   size = res->aop->size - 2;
1592   offset = 2;
1593   /* put zeros in the rest */
1594   while (size--)
1595     aopPut (res->aop, zero, offset++);
1596 }
1597
1598 /*-----------------------------------------------------------------*/
1599 /* opIsGptr: returns non-zero if the passed operand is       */
1600 /* a generic pointer type.             */
1601 /*-----------------------------------------------------------------*/
1602 static int
1603 opIsGptr (operand * op)
1604 {
1605   sym_link *type = operandType (op);
1606
1607   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1608     {
1609       return 1;
1610     }
1611   return 0;
1612 }
1613
1614 /*-----------------------------------------------------------------*/
1615 /* getDataSize - get the operand data size                         */
1616 /*-----------------------------------------------------------------*/
1617 static int
1618 getDataSize (operand * op)
1619 {
1620   int size;
1621   size = AOP_SIZE (op);
1622   if (size == GPTRSIZE)
1623     {
1624       sym_link *type = operandType (op);
1625       if (IS_GENPTR (type))
1626         {
1627           /* generic pointer; arithmetic operations
1628            * should ignore the high byte (pointer type).
1629            */
1630           size--;
1631         }
1632     }
1633   return size;
1634 }
1635
1636 /*-----------------------------------------------------------------*/
1637 /* outAcc - output Acc                                             */
1638 /*-----------------------------------------------------------------*/
1639 static void
1640 outAcc (operand * result)
1641 {
1642   int size, offset;
1643   size = getDataSize (result);
1644   if (size)
1645     {
1646       aopPut (AOP (result), "a", 0);
1647       size--;
1648       offset = 1;
1649       /* unsigned or positive */
1650       while (size--)
1651         {
1652           aopPut (AOP (result), zero, offset++);
1653         }
1654     }
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* outBitC - output a bit C                                        */
1659 /*-----------------------------------------------------------------*/
1660 static void
1661 outBitC (operand * result)
1662 {
1663   /* if the result is bit */
1664   if (AOP_TYPE (result) == AOP_CRY)
1665     {
1666       aopPut (AOP (result), "c", 0);
1667     }
1668   else
1669     {
1670       emitcode ("clr", "a");
1671       emitcode ("rlc", "a");
1672       outAcc (result);
1673     }
1674 }
1675
1676 /*-----------------------------------------------------------------*/
1677 /* toBoolean - emit code for orl a,operator(sizeop)                */
1678 /*-----------------------------------------------------------------*/
1679 static void
1680 toBoolean (operand * oper)
1681 {
1682   int   size = AOP_SIZE (oper) - 1;
1683   int   offset = 1;
1684   bool usedB = FALSE;
1685
1686   /* The generic part of a generic pointer should
1687    * not participate in it's truth value.
1688    *
1689    * i.e. 0x10000000 is zero.
1690    */
1691   if (opIsGptr (oper))
1692     {
1693       D (emitcode (";", "toBoolean: generic ptr special case.");
1694         );
1695       size--;
1696     }
1697
1698   _startLazyDPSEvaluation ();
1699   if (AOP_NEEDSACC (oper) && size)
1700     {
1701       usedB = TRUE;
1702       emitcode ("push", "b");
1703       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1704     }
1705   else
1706     {
1707       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1708     }
1709   while (size--)
1710     {
1711       if (usedB)
1712         {
1713           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1714         }
1715       else
1716         {
1717           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1718         }
1719     }
1720   _endLazyDPSEvaluation ();
1721
1722   if (usedB)
1723     {
1724       emitcode ("mov", "a,b");
1725       emitcode ("pop", "b");
1726     }
1727 }
1728
1729
1730 /*-----------------------------------------------------------------*/
1731 /* genNot - generate code for ! operation                          */
1732 /*-----------------------------------------------------------------*/
1733 static void
1734 genNot (iCode * ic)
1735 {
1736   symbol *tlbl;
1737   sym_link *optype = operandType (IC_LEFT (ic));
1738
1739   D (emitcode (";", "genNot ");
1740     );
1741
1742   /* assign asmOps to operand & result */
1743   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1744   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1745
1746   /* if in bit space then a special case */
1747   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1748     {
1749       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1750       emitcode ("cpl", "c");
1751       outBitC (IC_RESULT (ic));
1752       goto release;
1753     }
1754
1755   /* if type float then do float */
1756   if (IS_FLOAT (optype))
1757     {
1758       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1759       goto release;
1760     }
1761
1762   toBoolean (IC_LEFT (ic));
1763
1764   tlbl = newiTempLabel (NULL);
1765   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1766   emitcode ("", "!tlabeldef", tlbl->key + 100);
1767   outBitC (IC_RESULT (ic));
1768
1769 release:
1770   /* release the aops */
1771   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1772   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1773 }
1774
1775
1776 /*-----------------------------------------------------------------*/
1777 /* genCpl - generate code for complement                           */
1778 /*-----------------------------------------------------------------*/
1779 static void
1780 genCpl (iCode * ic)
1781 {
1782   int offset = 0;
1783   int size;
1784   symbol *tlbl;
1785
1786   D (emitcode (";", "genCpl ");
1787     );
1788
1789
1790   /* assign asmOps to operand & result */
1791   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1792   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1793
1794   /* special case if in bit space */
1795   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1796     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1797       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1798       emitcode ("cpl", "c");
1799       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1800       goto release;
1801     }
1802     tlbl=newiTempLabel(NULL);
1803     emitcode ("cjne", "%s,#0x01,%05d$", 
1804               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1805     emitcode ("", "%05d$:", tlbl->key+100);
1806     outBitC (IC_RESULT(ic));
1807     goto release;
1808   }
1809
1810   size = AOP_SIZE (IC_RESULT (ic));
1811   _startLazyDPSEvaluation ();
1812   while (size--)
1813     {
1814       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1815       MOVA (l);
1816       emitcode ("cpl", "a");
1817       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1818     }
1819   _endLazyDPSEvaluation ();
1820
1821
1822 release:
1823   /* release the aops */
1824   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1825   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1826 }
1827
1828 /*-----------------------------------------------------------------*/
1829 /* genUminusFloat - unary minus for floating points                */
1830 /*-----------------------------------------------------------------*/
1831 static void
1832 genUminusFloat (operand * op, operand * result)
1833 {
1834   int size, offset = 0;
1835   char *l;
1836   /* for this we just need to flip the
1837      first it then copy the rest in place */
1838   D (emitcode (";", "genUminusFloat");
1839     );
1840
1841   _startLazyDPSEvaluation ();
1842   size = AOP_SIZE (op) - 1;
1843   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1844   MOVA (l);
1845
1846   emitcode ("cpl", "acc.7");
1847   aopPut (AOP (result), "a", 3);
1848
1849   while (size--)
1850     {
1851       aopPut (AOP (result),
1852               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1853               offset);
1854       offset++;
1855     }
1856   _endLazyDPSEvaluation ();
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* genUminus - unary minus code generation                         */
1861 /*-----------------------------------------------------------------*/
1862 static void
1863 genUminus (iCode * ic)
1864 {
1865   int offset, size;
1866   sym_link *optype, *rtype;
1867
1868   D (emitcode (";", "genUminus ");
1869     );
1870
1871
1872   /* assign asmops */
1873   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1874   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1875
1876   /* if both in bit space then special
1877      case */
1878   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1879       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1880     {
1881
1882       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1883       emitcode ("cpl", "c");
1884       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1885       goto release;
1886     }
1887
1888   optype = operandType (IC_LEFT (ic));
1889   rtype = operandType (IC_RESULT (ic));
1890
1891   /* if float then do float stuff */
1892   if (IS_FLOAT (optype))
1893     {
1894       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1895       goto release;
1896     }
1897
1898   /* otherwise subtract from zero */
1899   size = AOP_SIZE (IC_LEFT (ic));
1900   offset = 0;
1901   _startLazyDPSEvaluation ();
1902   while (size--)
1903     {
1904       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1905       if (!strcmp (l, "a"))
1906         {
1907           if (offset == 0)
1908             SETC;
1909           emitcode ("cpl", "a");
1910           emitcode ("addc", "a,#0");
1911         }
1912       else
1913         {
1914           if (offset == 0)
1915             CLRC;
1916           emitcode ("clr", "a");
1917           emitcode ("subb", "a,%s", l);
1918         }
1919       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1920     }
1921   _endLazyDPSEvaluation ();
1922
1923   /* if any remaining bytes in the result */
1924   /* we just need to propagate the sign   */
1925   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1926     {
1927       emitcode ("rlc", "a");
1928       emitcode ("subb", "a,acc");
1929       while (size--)
1930         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1931     }
1932
1933 release:
1934   /* release the aops */
1935   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1936   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* savermask - saves registers in the mask                         */
1941 /*-----------------------------------------------------------------*/
1942 static void savermask(bitVect *rs_mask)
1943 {
1944     int i;
1945     if (options.useXstack) {
1946         if (bitVectBitValue (rs_mask, R0_IDX))
1947             emitcode ("mov", "b,r0");
1948         emitcode ("mov", "r0,%s", spname);
1949         for (i = 0; i < ds390_nRegs; i++) {
1950             if (bitVectBitValue (rs_mask, i)) {
1951                 if (i == R0_IDX)
1952                     emitcode ("mov", "a,b");
1953                 else
1954                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1955                 emitcode ("movx", "@r0,a");
1956                 emitcode ("inc", "r0");
1957             }
1958         }
1959         emitcode ("mov", "%s,r0", spname);
1960         if (bitVectBitValue (rs_mask, R0_IDX))
1961             emitcode ("mov", "r0,b");
1962     } else {
1963         for (i = 0; i < ds390_nRegs; i++) {
1964             if (bitVectBitValue (rs_mask, i))
1965                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1966         }
1967     }
1968 }
1969
1970 /*-----------------------------------------------------------------*/
1971 /* saveRegisters - will look for a call and save the registers     */
1972 /*-----------------------------------------------------------------*/
1973 static void
1974 saveRegisters (iCode * lic)
1975 {
1976   iCode *ic;
1977   bitVect *rsave;
1978
1979   /* look for call */
1980   for (ic = lic; ic; ic = ic->next)
1981     if (ic->op == CALL || ic->op == PCALL)
1982       break;
1983
1984   if (!ic)
1985     {
1986       fprintf (stderr, "found parameter push with no function call\n");
1987       return;
1988     }
1989
1990   /* if the registers have been saved already then
1991      do nothing */
1992   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1993
1994   /* special case if DPTR alive across a function call then must save it 
1995      even though callee saves */
1996   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1997       int i =0;
1998       rsave = newBitVect(ic->rMask->size);
1999       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2000           if (bitVectBitValue(ic->rMask,i))
2001               rsave = bitVectSetBit(rsave,i);
2002       }
2003       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2004   } else {
2005     /* safe the registers in use at this time but skip the
2006        ones for the result */
2007     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2008                            ds390_rUmaskForOp (IC_RESULT(ic)));
2009   }
2010   ic->regsSaved = 1;
2011   savermask(rsave);
2012 }
2013
2014 /*-----------------------------------------------------------------*/
2015 /* usavermask - restore registers with mask                        */
2016 /*-----------------------------------------------------------------*/
2017 static void unsavermask(bitVect *rs_mask)
2018 {
2019     int i;
2020     if (options.useXstack) {
2021         emitcode ("mov", "r0,%s", spname);
2022         for (i = ds390_nRegs; i >= 0; i--) {
2023             if (bitVectBitValue (rs_mask, i)) {
2024                 emitcode ("dec", "r0");
2025                 emitcode ("movx", "a,@r0");
2026                 if (i == R0_IDX)
2027                     emitcode ("mov", "b,a");
2028                 else
2029                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2030             }       
2031         }
2032         emitcode ("mov", "%s,r0", spname);
2033         if (bitVectBitValue (rs_mask, R0_IDX))
2034             emitcode ("mov", "r0,b");
2035     } else {
2036         for (i = ds390_nRegs; i >= 0; i--) {
2037             if (bitVectBitValue (rs_mask, i))
2038                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2039         }
2040     }
2041 }
2042
2043 /*-----------------------------------------------------------------*/
2044 /* unsaveRegisters - pop the pushed registers                      */
2045 /*-----------------------------------------------------------------*/
2046 static void
2047 unsaveRegisters (iCode * ic)
2048 {
2049   bitVect *rsave;
2050
2051   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2052       int i =0;
2053       rsave = newBitVect(ic->rMask->size);
2054       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2055           if (bitVectBitValue(ic->rMask,i))
2056               rsave = bitVectSetBit(rsave,i);
2057       }
2058       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2059   } else {
2060     /* restore the registers in use at this time but skip the
2061        ones for the result */
2062     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2063                            ds390_rUmaskForOp (IC_RESULT(ic)));
2064   }
2065   unsavermask(rsave);
2066 }
2067
2068
2069 /*-----------------------------------------------------------------*/
2070 /* pushSide -                */
2071 /*-----------------------------------------------------------------*/
2072 static void
2073 pushSide (operand * oper, int size)
2074 {
2075   int offset = 0;
2076   _startLazyDPSEvaluation ();
2077   while (size--)
2078     {
2079       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2080       if (AOP_TYPE (oper) != AOP_REG &&
2081           AOP_TYPE (oper) != AOP_DIR &&
2082           strcmp (l, "a"))
2083         {
2084           emitcode ("mov", "a,%s", l);
2085           emitcode ("push", "acc");
2086         }
2087       else
2088         emitcode ("push", "%s", l);
2089     }
2090   _endLazyDPSEvaluation ();
2091 }
2092
2093 /*-----------------------------------------------------------------*/
2094 /* assignResultValue -               */
2095 /*-----------------------------------------------------------------*/
2096 static void
2097 assignResultValue (operand * oper)
2098 {
2099   int offset = 0;
2100   int size = AOP_SIZE (oper);
2101
2102   _startLazyDPSEvaluation ();
2103   while (size--)
2104     {
2105       aopPut (AOP (oper), fReturn[offset], offset);
2106       offset++;
2107     }
2108   _endLazyDPSEvaluation ();
2109 }
2110
2111
2112 /*-----------------------------------------------------------------*/
2113 /* genXpush - pushes onto the external stack                       */
2114 /*-----------------------------------------------------------------*/
2115 static void
2116 genXpush (iCode * ic)
2117 {
2118   asmop *aop = newAsmop (0);
2119   regs *r;
2120   int size, offset = 0;
2121
2122   D (emitcode (";", "genXpush ");
2123     );
2124
2125   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2126   r = getFreePtr (ic, &aop, FALSE);
2127
2128
2129   emitcode ("mov", "%s,_spx", r->name);
2130
2131   size = AOP_SIZE (IC_LEFT (ic));
2132   _startLazyDPSEvaluation ();
2133   while (size--)
2134     {
2135
2136       char *l = aopGet (AOP (IC_LEFT (ic)),
2137                         offset++, FALSE, FALSE, TRUE);
2138       MOVA (l);
2139       emitcode ("movx", "@%s,a", r->name);
2140       emitcode ("inc", "%s", r->name);
2141
2142     }
2143   _endLazyDPSEvaluation ();
2144
2145
2146   emitcode ("mov", "_spx,%s", r->name);
2147
2148   freeAsmop (NULL, aop, ic, TRUE);
2149   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* genIpush - genrate code for pushing this gets a little complex  */
2154 /*-----------------------------------------------------------------*/
2155 static void
2156 genIpush (iCode * ic)
2157 {
2158   int size, offset = 0;
2159   char *l;
2160
2161   D (emitcode (";", "genIpush ");
2162     );
2163
2164   /* if this is not a parm push : ie. it is spill push
2165      and spill push is always done on the local stack */
2166   if (!ic->parmPush)
2167     {
2168
2169       /* and the item is spilt then do nothing */
2170       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2171         return;
2172
2173       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2174       size = AOP_SIZE (IC_LEFT (ic));
2175       /* push it on the stack */
2176       _startLazyDPSEvaluation ();
2177       while (size--)
2178         {
2179           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2180           if (*l == '#')
2181             {
2182               MOVA (l);
2183               l = "acc";
2184             }
2185           emitcode ("push", "%s", l);
2186         }
2187       _endLazyDPSEvaluation ();
2188       return;
2189     }
2190
2191   /* this is a paramter push: in this case we call
2192      the routine to find the call and save those
2193      registers that need to be saved */
2194   saveRegisters (ic);
2195
2196   /* if use external stack then call the external
2197      stack pushing routine */
2198   if (options.useXstack)
2199     {
2200       genXpush (ic);
2201       return;
2202     }
2203
2204   /* then do the push */
2205   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2206
2207   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2208   size = AOP_SIZE (IC_LEFT (ic));
2209
2210   _startLazyDPSEvaluation ();
2211   while (size--)
2212     {
2213       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2214       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2215           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2216           strcmp (l, "a"))
2217         {
2218           emitcode ("mov", "a,%s", l);
2219           emitcode ("push", "acc");
2220         }
2221       else
2222         emitcode ("push", "%s", l);
2223     }
2224   _endLazyDPSEvaluation ();
2225
2226   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2227 }
2228
2229 /*-----------------------------------------------------------------*/
2230 /* genIpop - recover the registers: can happen only for spilling   */
2231 /*-----------------------------------------------------------------*/
2232 static void
2233 genIpop (iCode * ic)
2234 {
2235   int size, offset;
2236
2237   D (emitcode (";", "genIpop ");
2238     );
2239
2240
2241   /* if the temp was not pushed then */
2242   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2243     return;
2244
2245   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2246   size = AOP_SIZE (IC_LEFT (ic));
2247   offset = (size - 1);
2248   _startLazyDPSEvaluation ();
2249   while (size--)
2250     {
2251       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2252                                      FALSE, TRUE, TRUE));
2253     }
2254   _endLazyDPSEvaluation ();
2255
2256   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2257 }
2258
2259 /*-----------------------------------------------------------------*/
2260 /* unsaveRBank - restores the resgister bank from stack            */
2261 /*-----------------------------------------------------------------*/
2262 static void
2263 unsaveRBank (int bank, iCode * ic, bool popPsw)
2264 {
2265   int i;
2266   asmop *aop = NULL;
2267   regs *r = NULL;
2268
2269   if (options.useXstack)
2270   {
2271       if (!ic)
2272       {
2273           /* Assume r0 is available for use. */
2274           r = ds390_regWithIdx (R0_IDX);;          
2275       } 
2276       else
2277       {
2278           aop = newAsmop (0);
2279           r = getFreePtr (ic, &aop, FALSE);
2280       }
2281       emitcode ("mov", "%s,_spx", r->name);      
2282   }
2283   
2284   if (popPsw)
2285     {
2286       if (options.useXstack)
2287       {
2288           emitcode ("movx", "a,@%s", r->name);
2289           emitcode ("mov", "psw,a");
2290           emitcode ("dec", "%s", r->name);
2291         }
2292       else
2293       {
2294         emitcode ("pop", "psw");
2295       }
2296     }
2297
2298   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2299     {
2300       if (options.useXstack)
2301         {
2302           emitcode ("movx", "a,@%s", r->name);
2303           emitcode ("mov", "(%s+%d),a",
2304                     regs390[i].base, 8 * bank + regs390[i].offset);
2305           emitcode ("dec", "%s", r->name);
2306
2307         }
2308       else
2309         emitcode ("pop", "(%s+%d)",
2310                   regs390[i].base, 8 * bank + regs390[i].offset);
2311     }
2312
2313   if (options.useXstack)
2314     {
2315       emitcode ("mov", "_spx,%s", r->name);
2316     }
2317     
2318   if (aop)
2319   {
2320       freeAsmop (NULL, aop, ic, TRUE);  
2321   }    
2322 }
2323
2324 /*-----------------------------------------------------------------*/
2325 /* saveRBank - saves an entire register bank on the stack          */
2326 /*-----------------------------------------------------------------*/
2327 static void
2328 saveRBank (int bank, iCode * ic, bool pushPsw)
2329 {
2330   int i;
2331   asmop *aop = NULL;
2332   regs *r = NULL;
2333
2334   if (options.useXstack)
2335     {
2336         if (!ic)
2337         {
2338           /* Assume r0 is available for use. */
2339                   r = ds390_regWithIdx (R0_IDX);;
2340         }
2341         else
2342         {
2343           aop = newAsmop (0);
2344           r = getFreePtr (ic, &aop, FALSE);
2345         }
2346         emitcode ("mov", "%s,_spx", r->name);    
2347     }
2348
2349   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2350     {
2351       if (options.useXstack)
2352         {
2353           emitcode ("inc", "%s", r->name);
2354           emitcode ("mov", "a,(%s+%d)",
2355                     regs390[i].base, 8 * bank + regs390[i].offset);
2356           emitcode ("movx", "@%s,a", r->name);
2357         }
2358       else
2359         emitcode ("push", "(%s+%d)",
2360                   regs390[i].base, 8 * bank + regs390[i].offset);
2361     }
2362
2363   if (pushPsw)
2364     {
2365       if (options.useXstack)
2366         {
2367           emitcode ("mov", "a,psw");
2368           emitcode ("movx", "@%s,a", r->name);
2369           emitcode ("inc", "%s", r->name);
2370           emitcode ("mov", "_spx,%s", r->name);
2371         }
2372       else
2373       {
2374         emitcode ("push", "psw");
2375       }
2376
2377       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2378     }
2379   
2380   if (aop)
2381   {
2382        freeAsmop (NULL, aop, ic, TRUE);
2383   }    
2384     
2385   if (ic)
2386   {  
2387       ic->bankSaved = 1;
2388   }
2389 }
2390
2391 /*-----------------------------------------------------------------*/
2392 /* genSend - gen code for SEND                                     */
2393 /*-----------------------------------------------------------------*/
2394 static void genSend(set *sendSet)
2395 {
2396     iCode *sic;
2397     int sendCount = 0 ;
2398     static int rb1_count = 0;
2399
2400     for (sic = setFirstItem (sendSet); sic;
2401          sic = setNextItem (sendSet)) {     
2402         int size, offset = 0;
2403         
2404         size=getSize(operandType(IC_LEFT(sic)));
2405         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2406         if (sendCount == 0) { /* first parameter */
2407             // we know that dpl(hxb) is the result, so
2408             rb1_count = 0 ;
2409             _startLazyDPSEvaluation ();
2410             if (size>1) {
2411                 aopOp (IC_LEFT (sic), sic, FALSE, 
2412                        (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2413             } else {
2414                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2415             }
2416             while (size--) {
2417                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2418                                   FALSE, FALSE, TRUE);
2419                 if (strcmp (l, fReturn[offset])) {
2420                     emitcode ("mov", "%s,%s",
2421                               fReturn[offset],
2422                               l);
2423                 }
2424                 offset++;
2425             }
2426             _endLazyDPSEvaluation ();
2427             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2428             rb1_count =0;
2429         } else { /* if more parameter in registers */
2430             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2431             while (size--) {
2432                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2433                                                                 FALSE, FALSE, TRUE));
2434             }
2435             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2436         }
2437         sendCount++;
2438     }
2439 }
2440
2441 /*-----------------------------------------------------------------*/
2442 /* genCall - generates a call statement                            */
2443 /*-----------------------------------------------------------------*/
2444 static void
2445 genCall (iCode * ic)
2446 {
2447   sym_link *dtype;
2448   bool restoreBank = FALSE;
2449   bool swapBanks = FALSE;
2450
2451   D (emitcode (";", "genCall "););
2452
2453   /* if we are calling a not _naked function that is not using
2454      the same register bank then we need to save the
2455      destination registers on the stack */
2456   dtype = operandType (IC_LEFT (ic));
2457   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2458       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2459       IFFUNC_ISISR (currFunc->type))
2460   {
2461       if (!ic->bankSaved) 
2462       {
2463            /* This is unexpected; the bank should have been saved in
2464             * genFunction.
2465             */
2466            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2467            restoreBank = TRUE;
2468       }
2469       swapBanks = TRUE;
2470   }
2471   
2472     /* if caller saves & we have not saved then */
2473     if (!ic->regsSaved)
2474       saveRegisters (ic);
2475   
2476   /* if send set is not empty the assign */
2477   /* We've saved all the registers we care about;
2478   * therefore, we may clobber any register not used
2479   * in the calling convention (i.e. anything not in
2480   * fReturn.
2481   */
2482   if (_G.sendSet)
2483     {
2484         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2485             genSend(reverseSet(_G.sendSet));
2486         } else {
2487             genSend(_G.sendSet);
2488         }
2489       _G.sendSet = NULL;
2490     }  
2491     
2492   if (swapBanks)
2493   {
2494         emitcode ("mov", "psw,#!constbyte", 
2495            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2496   }
2497
2498   /* make the call */
2499   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2500                             OP_SYMBOL (IC_LEFT (ic))->rname :
2501                             OP_SYMBOL (IC_LEFT (ic))->name));
2502
2503   if (swapBanks)
2504   {
2505        emitcode ("mov", "psw,#!constbyte", 
2506           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2507   }
2508
2509   /* if we need assign a result value */
2510   if ((IS_ITEMP (IC_RESULT (ic)) &&
2511        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2512         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2513         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2514       IS_TRUE_SYMOP (IC_RESULT (ic)))
2515     {
2516       if (isOperandInFarSpace (IC_RESULT (ic))
2517           && getSize (operandType (IC_RESULT (ic))) <= 2)
2518         {
2519           int size = getSize (operandType (IC_RESULT (ic)));
2520
2521           /* Special case for 1 or 2 byte return in far space. */
2522           MOVA (fReturn[0]);
2523           if (size > 1)
2524             {
2525               emitcode ("mov", "b,%s", fReturn[1]);
2526             }
2527
2528           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2529           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2530
2531           if (size > 1)
2532             {
2533               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2534             }
2535           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2536         }
2537       else
2538         {
2539           _G.accInUse++;
2540           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2541           _G.accInUse--;
2542
2543           assignResultValue (IC_RESULT (ic));
2544
2545           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2546         }
2547     }
2548
2549   /* adjust the stack for parameters if
2550      required */
2551   if (ic->parmBytes) {
2552       int i;
2553       if (options.stack10bit) {
2554           if (ic->parmBytes <= 10) {
2555               emitcode(";","stack adjustment for parms");
2556               for (i=0; i < ic->parmBytes ; i++) {
2557                   emitcode("pop","acc");
2558               }
2559           } else {            
2560               PROTECT_SP;
2561               emitcode ("clr","c");
2562               emitcode ("mov","a,sp");
2563               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2564               emitcode ("mov","sp,a");
2565               emitcode ("mov","a,esp");
2566               emitcode ("anl","a,#3");
2567               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2568               emitcode ("mov","esp,a");   
2569               UNPROTECT_SP;
2570           }
2571       } else {
2572           if (ic->parmBytes > 3) {
2573               emitcode ("mov", "a,%s", spname);
2574               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2575               emitcode ("mov", "%s,a", spname);
2576           } else
2577               for (i = 0; i < ic->parmBytes; i++)
2578                   emitcode ("dec", "%s", spname);
2579       }
2580   }
2581
2582   /* if we hade saved some registers then unsave them */
2583   if (ic->regsSaved)
2584     unsaveRegisters (ic);
2585
2586   /* if register bank was saved then pop them */
2587   if (restoreBank)
2588     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* genPcall - generates a call by pointer statement                */
2593 /*-----------------------------------------------------------------*/
2594 static void
2595 genPcall (iCode * ic)
2596 {
2597   sym_link *dtype;
2598   symbol *rlbl = newiTempLabel (NULL);
2599   bool restoreBank=FALSE;
2600
2601   D (emitcode (";", "genPcall ");
2602     );
2603
2604
2605   /* if caller saves & we have not saved then */
2606   if (!ic->regsSaved)
2607     saveRegisters (ic);
2608
2609   /* if we are calling a function that is not using
2610      the same register bank then we need to save the
2611      destination registers on the stack */
2612   dtype = operandType (IC_LEFT (ic));
2613   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2614       IFFUNC_ISISR (currFunc->type) &&
2615       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2616     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2617     restoreBank=TRUE;
2618   }
2619
2620   /* push the return address on to the stack */
2621   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2622   emitcode ("push", "acc");
2623   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2624   emitcode ("push", "acc");
2625
2626   if (options.model == MODEL_FLAT24)
2627     {
2628       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2629       emitcode ("push", "acc");
2630     }
2631
2632   /* now push the calling address */
2633   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2634
2635   pushSide (IC_LEFT (ic), FPTRSIZE);
2636
2637   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2638
2639   /* if send set is not empty the assign */
2640   if (_G.sendSet)
2641     {
2642         genSend(reverseSet(_G.sendSet));
2643         _G.sendSet = NULL;
2644     }
2645
2646   emitcode ("ret", "");
2647   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2648
2649
2650   /* if we need assign a result value */
2651   if ((IS_ITEMP (IC_RESULT (ic)) &&
2652        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2653         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2654       IS_TRUE_SYMOP (IC_RESULT (ic)))
2655     {
2656
2657       _G.accInUse++;
2658       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2659       _G.accInUse--;
2660
2661       assignResultValue (IC_RESULT (ic));
2662
2663       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2664     }
2665
2666   /* adjust the stack for parameters if
2667      required */
2668   if (ic->parmBytes)
2669     {
2670       int i;
2671       if (options.stack10bit) {
2672           if (ic->parmBytes <= 10) {
2673               emitcode(";","stack adjustment for parms");
2674               for (i=0; i < ic->parmBytes ; i++) {
2675                   emitcode("pop","acc");
2676               }
2677           } else {            
2678               PROTECT_SP;
2679               emitcode ("clr","c");
2680               emitcode ("mov","a,sp");
2681               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2682               emitcode ("mov","sp,a");
2683               emitcode ("mov","a,esp");
2684               emitcode ("anl","a,#3");
2685               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2686               emitcode ("mov","esp,a");   
2687               UNPROTECT_SP;
2688           }
2689       } else {
2690           if (ic->parmBytes > 3) {
2691               emitcode ("mov", "a,%s", spname);
2692               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2693               emitcode ("mov", "%s,a", spname);
2694           }
2695           else
2696               for (i = 0; i < ic->parmBytes; i++)
2697                   emitcode ("dec", "%s", spname);
2698           
2699       }
2700     }
2701   /* if register bank was saved then unsave them */
2702   if (restoreBank)
2703     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2704   
2705   /* if we hade saved some registers then
2706      unsave them */
2707   if (ic->regsSaved)
2708     unsaveRegisters (ic);
2709
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* resultRemat - result  is rematerializable                       */
2714 /*-----------------------------------------------------------------*/
2715 static int
2716 resultRemat (iCode * ic)
2717 {
2718   if (SKIP_IC (ic) || ic->op == IFX)
2719     return 0;
2720
2721   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2722     {
2723       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2724       if (sym->remat && !POINTER_SET (ic))
2725         return 1;
2726     }
2727
2728   return 0;
2729 }
2730
2731 #if defined(__BORLANDC__) || defined(_MSC_VER)
2732 #define STRCASECMP stricmp
2733 #else
2734 #define STRCASECMP strcasecmp
2735 #endif
2736
2737 /*-----------------------------------------------------------------*/
2738 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2739 /*-----------------------------------------------------------------*/
2740 static bool
2741 inExcludeList (char *s)
2742 {
2743   int i = 0;
2744
2745   if (options.excludeRegs[i] &&
2746       STRCASECMP (options.excludeRegs[i], "none") == 0)
2747     return FALSE;
2748
2749   for (i = 0; options.excludeRegs[i]; i++)
2750     {
2751       if (options.excludeRegs[i] &&
2752           STRCASECMP (s, options.excludeRegs[i]) == 0)
2753         return TRUE;
2754     }
2755   return FALSE;
2756 }
2757
2758 /*-----------------------------------------------------------------*/
2759 /* genFunction - generated code for function entry                 */
2760 /*-----------------------------------------------------------------*/
2761 static void
2762 genFunction (iCode * ic)
2763 {
2764   symbol *sym;
2765   sym_link *ftype;
2766   bool   switchedPSW = FALSE;
2767
2768   D (emitcode (";", "genFunction "););
2769
2770   _G.nRegsSaved = 0;
2771   /* create the function header */
2772   emitcode (";", "-----------------------------------------");
2773   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2774   emitcode (";", "-----------------------------------------");
2775
2776   emitcode ("", "%s:", sym->rname);
2777   ftype = operandType (IC_LEFT (ic));
2778
2779   if (IFFUNC_ISNAKED(ftype))
2780   {
2781       emitcode(";", "naked function: no prologue.");
2782       return;
2783   }
2784   
2785   if (options.stack_probe) 
2786       emitcode ("lcall","__stack_probe");
2787   /* if critical function then turn interrupts off */
2788   if (IFFUNC_ISCRITICAL (ftype))
2789     emitcode ("clr", "ea");
2790
2791   /* here we need to generate the equates for the
2792      register bank if required */
2793   if (FUNC_REGBANK (ftype) != rbank)
2794     {
2795       int i;
2796
2797       rbank = FUNC_REGBANK (ftype);
2798       for (i = 0; i < ds390_nRegs; i++)
2799         {
2800           if (regs390[i].print) {
2801               if (strcmp (regs390[i].base, "0") == 0)
2802                   emitcode ("", "%s !equ !constbyte",
2803                             regs390[i].dname,
2804                             8 * rbank + regs390[i].offset);
2805               else
2806                   emitcode ("", "%s !equ %s + !constbyte",
2807                             regs390[i].dname,
2808                             regs390[i].base,
2809                             8 * rbank + regs390[i].offset);
2810           }
2811         }
2812     }
2813
2814   /* if this is an interrupt service routine then
2815      save acc, b, dpl, dph  */
2816   if (IFFUNC_ISISR (sym->type))
2817       { /* is ISR */
2818       if (!inExcludeList ("acc"))
2819         emitcode ("push", "acc");
2820       if (!inExcludeList ("b"))
2821         emitcode ("push", "b");
2822       if (!inExcludeList ("dpl"))
2823         emitcode ("push", "dpl");
2824       if (!inExcludeList ("dph"))
2825         emitcode ("push", "dph");
2826       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2827         {
2828           emitcode ("push", "dpx");
2829           /* Make sure we're using standard DPTR */
2830           emitcode ("push", "dps");
2831           emitcode ("mov", "dps,#0");
2832           if (options.stack10bit)
2833             {
2834               /* This ISR could conceivably use DPTR2. Better save it. */
2835               emitcode ("push", "dpl1");
2836               emitcode ("push", "dph1");
2837               emitcode ("push", "dpx1");
2838               emitcode ("push",  DP2_RESULT_REG);
2839             }
2840         }
2841       /* if this isr has no bank i.e. is going to
2842          run with bank 0 , then we need to save more
2843          registers :-) */
2844       if (!FUNC_REGBANK (sym->type))
2845         {
2846             int i;
2847
2848           /* if this function does not call any other
2849              function then we can be economical and
2850              save only those registers that are used */
2851           if (!IFFUNC_HASFCALL(sym->type))
2852             {
2853
2854               /* if any registers used */
2855               if (sym->regsUsed)
2856                 {
2857                   /* save the registers used */
2858                   for (i = 0; i < sym->regsUsed->size; i++)
2859                     {
2860                       if (bitVectBitValue (sym->regsUsed, i) ||
2861                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2862                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2863                     }
2864                 }
2865
2866             }
2867           else
2868             {
2869               /* this function has  a function call cannot
2870                  determines register usage so we will have to push the
2871                  entire bank */
2872               saveRBank (0, ic, FALSE);
2873               if (options.parms_in_bank1) {
2874                   for (i=0; i < 8 ; i++ ) {
2875                       emitcode ("push","%s",rb1regs[i]);
2876                   }
2877               }
2878             }
2879         }
2880         else
2881         {
2882             /* This ISR uses a non-zero bank.
2883              *
2884              * We assume that the bank is available for our
2885              * exclusive use.
2886              *
2887              * However, if this ISR calls a function which uses some
2888              * other bank, we must save that bank entirely.
2889              */
2890             unsigned long banksToSave = 0;
2891             
2892             if (IFFUNC_HASFCALL(sym->type))
2893             {
2894
2895 #define MAX_REGISTER_BANKS 4
2896
2897                 iCode *i;
2898                 int ix;
2899
2900                 for (i = ic; i; i = i->next)
2901                 {
2902                     if (i->op == ENDFUNCTION)
2903                     {
2904                         /* we got to the end OK. */
2905                         break;
2906                     }
2907                     
2908                     if (i->op == CALL)
2909                     {
2910                         sym_link *dtype;
2911                         
2912                         dtype = operandType (IC_LEFT(i));
2913                         if (dtype 
2914                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2915                         {
2916                              /* Mark this bank for saving. */
2917                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2918                              {
2919                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2920                              }
2921                              else
2922                              {
2923                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2924                              }
2925                              
2926                              /* And note that we don't need to do it in 
2927                               * genCall.
2928                               */
2929                              i->bankSaved = 1;
2930                         }
2931                     }
2932                     if (i->op == PCALL)
2933                     {
2934                         /* This is a mess; we have no idea what
2935                          * register bank the called function might
2936                          * use.
2937                          *
2938                          * The only thing I can think of to do is
2939                          * throw a warning and hope.
2940                          */
2941                         werror(W_FUNCPTR_IN_USING_ISR);   
2942                     }
2943                 }
2944
2945                 if (banksToSave && options.useXstack)
2946                 {
2947                     /* Since we aren't passing it an ic, 
2948                      * saveRBank will assume r0 is available to abuse.
2949                      *
2950                      * So switch to our (trashable) bank now, so
2951                      * the caller's R0 isn't trashed.
2952                      */
2953                     emitcode ("push", "psw");
2954                     emitcode ("mov", "psw,#!constbyte", 
2955                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2956                     switchedPSW = TRUE;
2957                 }
2958                 
2959                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2960                 {
2961                      if (banksToSave & (1 << ix))
2962                      {
2963                          saveRBank(ix, NULL, FALSE);
2964                      }
2965                 }
2966             }
2967             // jwk: this needs a closer look
2968             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2969         }
2970     }
2971   else
2972     {
2973       /* if callee-save to be used for this function
2974          then save the registers being used in this function */
2975       if (IFFUNC_CALLEESAVES(sym->type))
2976         {
2977           int i;
2978
2979           /* if any registers used */
2980           if (sym->regsUsed)
2981             {
2982               /* save the registers used */
2983               for (i = 0; i < sym->regsUsed->size; i++)
2984                 {
2985                   if (bitVectBitValue (sym->regsUsed, i) ||
2986                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987                     {
2988                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2989                       _G.nRegsSaved++;
2990                     }
2991                 }
2992             }
2993         }
2994     }
2995
2996   /* set the register bank to the desired value */
2997   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2998    && !switchedPSW)
2999     {
3000       emitcode ("push", "psw");
3001       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3002     }
3003
3004   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3005        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3006       if (options.stack10bit) {
3007           emitcode ("push","_bpx");
3008           emitcode ("push","_bpx+1");
3009           emitcode ("mov","_bpx,%s",spname);
3010           emitcode ("mov","_bpx+1,esp");
3011           emitcode ("anl","_bpx+1,#3");
3012       } else {
3013           if (options.useXstack) {
3014               emitcode ("mov", "r0,%s", spname);
3015               emitcode ("mov", "a,_bp");
3016               emitcode ("movx", "@r0,a");
3017               emitcode ("inc", "%s", spname);
3018           } else {
3019               /* set up the stack */
3020               emitcode ("push", "_bp"); /* save the callers stack  */
3021           }
3022           emitcode ("mov", "_bp,%s", spname);
3023       }
3024   }
3025
3026   /* adjust the stack for the function */
3027   if (sym->stack) {
3028       int i = sym->stack;
3029       if (options.stack10bit) {
3030           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3031           assert (sym->recvSize <= 4);
3032           if (sym->stack <= 8) {
3033               while (i--) emitcode ("push","acc");
3034           } else {
3035               PROTECT_SP;
3036               emitcode ("mov","a,sp");
3037               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3038               emitcode ("mov","sp,a");
3039               emitcode ("mov","a,esp");
3040               emitcode ("anl","a,#3");
3041               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3042               emitcode ("mov","esp,a");
3043               UNPROTECT_SP;
3044           }
3045       } else {
3046           if (i > 256)
3047               werror (W_STACK_OVERFLOW, sym->name);
3048           
3049           if (i > 3 && sym->recvSize < 4) {
3050               
3051               emitcode ("mov", "a,sp");
3052               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3053               emitcode ("mov", "sp,a");
3054               
3055           } else
3056               while (i--)
3057                   emitcode ("inc", "sp");
3058       }
3059   }
3060
3061   if (sym->xstack)
3062     {
3063
3064       emitcode ("mov", "a,_spx");
3065       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3066       emitcode ("mov", "_spx,a");
3067     }
3068
3069 }
3070
3071 /*-----------------------------------------------------------------*/
3072 /* genEndFunction - generates epilogue for functions               */
3073 /*-----------------------------------------------------------------*/
3074 static void
3075 genEndFunction (iCode * ic)
3076 {
3077   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3078
3079   D (emitcode (";", "genEndFunction "););
3080
3081   if (IFFUNC_ISNAKED(sym->type))
3082   {
3083       emitcode(";", "naked function: no epilogue.");
3084       return;
3085   }
3086
3087   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3088        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3089
3090       if (options.stack10bit) {
3091           PROTECT_SP;     
3092           emitcode ("mov", "sp,_bpx", spname);
3093           emitcode ("mov", "esp,_bpx+1", spname);
3094           UNPROTECT_SP;
3095       } else {
3096           emitcode ("mov", "%s,_bp", spname);
3097       }
3098   }
3099
3100   /* if use external stack but some variables were
3101      added to the local stack then decrement the
3102      local stack */
3103   if (options.useXstack && sym->stack) {
3104       emitcode ("mov", "a,sp");
3105       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3106       emitcode ("mov", "sp,a");
3107   }
3108
3109
3110   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3111        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3112
3113       if (options.useXstack) {
3114           emitcode ("mov", "r0,%s", spname);
3115           emitcode ("movx", "a,@r0");
3116           emitcode ("mov", "_bp,a");
3117           emitcode ("dec", "%s", spname);
3118       } else {
3119           if (options.stack10bit) {
3120               emitcode ("pop", "_bpx+1");
3121               emitcode ("pop", "_bpx");
3122           } else {
3123               emitcode ("pop", "_bp");
3124           }
3125       }
3126   }
3127
3128   /* restore the register bank  */
3129   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3130   {
3131     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3132      || !options.useXstack)
3133     {
3134         /* Special case of ISR using non-zero bank with useXstack
3135          * is handled below.
3136          */
3137         emitcode ("pop", "psw");
3138     }
3139   } 
3140
3141   if (IFFUNC_ISISR (sym->type))
3142       { /* is ISR */  
3143
3144       /* now we need to restore the registers */
3145       /* if this isr has no bank i.e. is going to
3146          run with bank 0 , then we need to save more
3147          registers :-) */
3148       if (!FUNC_REGBANK (sym->type))
3149         {
3150             int i;
3151           /* if this function does not call any other
3152              function then we can be economical and
3153              save only those registers that are used */
3154           if (!IFFUNC_HASFCALL(sym->type))
3155             {
3156
3157               /* if any registers used */
3158               if (sym->regsUsed)
3159                 {
3160                   /* save the registers used */
3161                   for (i = sym->regsUsed->size; i >= 0; i--)
3162                     {
3163                       if (bitVectBitValue (sym->regsUsed, i) ||
3164                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3165                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3166                     }
3167                 }
3168
3169             }
3170           else
3171             {
3172               /* this function has  a function call cannot
3173                  determines register usage so we will have to pop the
3174                  entire bank */
3175               if (options.parms_in_bank1) {
3176                   for (i = 7 ; i >= 0 ; i-- ) {
3177                       emitcode ("pop","%s",rb1regs[i]);
3178                   }
3179               }
3180               unsaveRBank (0, ic, FALSE);
3181             }
3182         }
3183         else
3184         {
3185             /* This ISR uses a non-zero bank.
3186              *
3187              * Restore any register banks saved by genFunction
3188              * in reverse order.
3189              */
3190           // jwk: this needs a closer look
3191             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3192             int ix;
3193           
3194             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3195             {
3196                 if (savedBanks & (1 << ix))
3197                 {
3198                     unsaveRBank(ix, NULL, FALSE);
3199                 }
3200             }
3201             
3202             if (options.useXstack)
3203             {
3204                 /* Restore bank AFTER calling unsaveRBank,
3205                  * since it can trash r0.
3206                  */
3207                 emitcode ("pop", "psw");
3208             }
3209         }
3210
3211       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3212         {
3213           if (options.stack10bit)
3214             {
3215               emitcode ("pop", DP2_RESULT_REG);
3216               emitcode ("pop", "dpx1");
3217               emitcode ("pop", "dph1");
3218               emitcode ("pop", "dpl1");
3219             }
3220           emitcode ("pop", "dps");
3221           emitcode ("pop", "dpx");
3222         }
3223       if (!inExcludeList ("dph"))
3224         emitcode ("pop", "dph");
3225       if (!inExcludeList ("dpl"))
3226         emitcode ("pop", "dpl");
3227       if (!inExcludeList ("b"))
3228         emitcode ("pop", "b");
3229       if (!inExcludeList ("acc"))
3230         emitcode ("pop", "acc");
3231
3232       if (IFFUNC_ISCRITICAL (sym->type))
3233         emitcode ("setb", "ea");
3234
3235       /* if debug then send end of function */
3236       if (options.debug && currFunc) {
3237           _G.debugLine = 1;
3238           emitcode ("", "C$%s$%d$%d$%d ==.",
3239                     FileBaseName (ic->filename), currFunc->lastLine,
3240                     ic->level, ic->block);
3241           if (IS_STATIC (currFunc->etype))
3242             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3243           else
3244             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3245           _G.debugLine = 0;
3246         }
3247
3248       emitcode ("reti", "");
3249     }
3250   else
3251     {
3252       if (IFFUNC_ISCRITICAL (sym->type))
3253         emitcode ("setb", "ea");
3254
3255       if (IFFUNC_CALLEESAVES(sym->type))
3256         {
3257           int i;
3258
3259           /* if any registers used */
3260           if (sym->regsUsed)
3261             {
3262               /* save the registers used */
3263               for (i = sym->regsUsed->size; i >= 0; i--)
3264                 {
3265                   if (bitVectBitValue (sym->regsUsed, i) ||
3266                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3267                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3268                 }
3269             }
3270
3271         }
3272
3273       /* if debug then send end of function */
3274       if (options.debug && currFunc)
3275         {
3276           _G.debugLine = 1;
3277           emitcode ("", "C$%s$%d$%d$%d ==.",
3278                     FileBaseName (ic->filename), currFunc->lastLine,
3279                     ic->level, ic->block);
3280           if (IS_STATIC (currFunc->etype))
3281             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3282           else
3283             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3284           _G.debugLine = 0;
3285         }
3286
3287       emitcode ("ret", "");
3288     }
3289
3290 }
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genJavaNativeRet - generate code for return JavaNative          */
3294 /*-----------------------------------------------------------------*/
3295 static void genJavaNativeRet(iCode *ic)
3296 {
3297     int i, size;
3298
3299     aopOp (IC_LEFT (ic), ic, FALSE, 
3300            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3301     size = AOP_SIZE (IC_LEFT (ic));
3302
3303     assert (size <= 4);
3304
3305     /* it is assigned to GPR0-R3 then push them */
3306     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3307         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3308         for (i = 0 ; i < size ; i++ ) {
3309             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3310         }
3311         for (i = (size-1) ; i >= 0 ; i--) {
3312             emitcode ("pop","a%s",javaRet[i]);
3313         }
3314     } else {
3315         for (i = 0 ; i < size ; i++) 
3316             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3317     }
3318     for (i = size ; i < 4 ; i++ )
3319             emitcode ("mov","%s,#0",javaRet[i]);
3320     return;
3321 }
3322
3323 /*-----------------------------------------------------------------*/
3324 /* genRet - generate code for return statement                     */
3325 /*-----------------------------------------------------------------*/
3326 static void
3327 genRet (iCode * ic)
3328 {
3329   int size, offset = 0, pushed = 0;
3330
3331   D (emitcode (";", "genRet ");
3332     );
3333
3334   /* if we have no return value then
3335      just generate the "ret" */
3336   if (!IC_LEFT (ic))
3337     goto jumpret;
3338
3339   /* if this is a JavaNative function then return 
3340      value in different register */
3341   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3342       genJavaNativeRet(ic);
3343       goto jumpret;
3344   }
3345   /* we have something to return then
3346      move the return value into place */
3347   aopOp (IC_LEFT (ic), ic, FALSE, 
3348          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3349   size = AOP_SIZE (IC_LEFT (ic));
3350
3351   _startLazyDPSEvaluation ();
3352   while (size--)
3353     {
3354       char *l;
3355       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3356         {
3357           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3358                       FALSE, TRUE, FALSE);
3359           emitcode ("push", "%s", l);
3360           pushed++;
3361         }
3362       else
3363         {
3364           /* Since A is the last element of fReturn,
3365            * is is OK to clobber it in the aopGet.
3366            */
3367           l = aopGet (AOP (IC_LEFT (ic)), offset,
3368                       FALSE, FALSE, TRUE);
3369           if (strcmp (fReturn[offset], l))
3370             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3371         }
3372     }
3373   _endLazyDPSEvaluation ();
3374
3375   if (pushed)
3376     {
3377       while (pushed)
3378         {
3379           pushed--;
3380           if (strcmp (fReturn[pushed], "a"))
3381             emitcode ("pop", fReturn[pushed]);
3382           else
3383             emitcode ("pop", "acc");
3384         }
3385     }
3386   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3387
3388 jumpret:
3389   /* generate a jump to the return label
3390      if the next is not the return statement */
3391   if (!(ic->next && ic->next->op == LABEL &&
3392         IC_LABEL (ic->next) == returnLabel))
3393
3394     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3395
3396 }
3397
3398 /*-----------------------------------------------------------------*/
3399 /* genLabel - generates a label                                    */
3400 /*-----------------------------------------------------------------*/
3401 static void
3402 genLabel (iCode * ic)
3403 {
3404   /* special case never generate */
3405   if (IC_LABEL (ic) == entryLabel)
3406     return;
3407
3408   D (emitcode (";", "genLabel ");
3409     );
3410
3411   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3412 }
3413
3414 /*-----------------------------------------------------------------*/
3415 /* genGoto - generates a ljmp                                      */
3416 /*-----------------------------------------------------------------*/
3417 static void
3418 genGoto (iCode * ic)
3419 {
3420   D (emitcode (";", "genGoto ");
3421     );
3422   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* findLabelBackwards: walks back through the iCode chain looking  */
3427 /* for the given label. Returns number of iCode instructions     */
3428 /* between that label and given ic.          */
3429 /* Returns zero if label not found.          */
3430 /*-----------------------------------------------------------------*/
3431 static int
3432 findLabelBackwards (iCode * ic, int key)
3433 {
3434   int count = 0;
3435
3436   while (ic->prev)
3437     {
3438       ic = ic->prev;
3439       count++;
3440
3441       /* If we have any pushes or pops, we cannot predict the distance.
3442          I don't like this at all, this should be dealt with in the 
3443          back-end */
3444       if (ic->op == IPUSH || ic->op == IPOP) {
3445         return 0;
3446       }
3447
3448       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3449         {
3450           /* printf("findLabelBackwards = %d\n", count); */
3451           return count;
3452         }
3453     }
3454
3455   return 0;
3456 }
3457
3458 /*-----------------------------------------------------------------*/
3459 /* genPlusIncr :- does addition with increment if possible         */
3460 /*-----------------------------------------------------------------*/
3461 static bool
3462 genPlusIncr (iCode * ic)
3463 {
3464   unsigned int icount;
3465   unsigned int size = getDataSize (IC_RESULT (ic));
3466
3467   /* will try to generate an increment */
3468   /* if the right side is not a literal
3469      we cannot */
3470   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3471     return FALSE;
3472
3473   /* if the literal value of the right hand side
3474      is greater than 4 then it is not worth it */
3475   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3476     return FALSE;
3477
3478   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3479       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3480       while (icount--) {
3481           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3482       }
3483       return TRUE;
3484   }
3485   /* if increment 16 bits in register */
3486   if (
3487        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3488        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3489        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3490        (size > 1) &&
3491        (icount == 1))
3492     {
3493       symbol *tlbl;
3494       int emitTlbl;
3495       int labelRange;
3496
3497       /* If the next instruction is a goto and the goto target
3498        * is <= 5 instructions previous to this, we can generate
3499        * jumps straight to that target.
3500        */
3501       if (ic->next && ic->next->op == GOTO
3502           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3503           && labelRange <= 5)
3504         {
3505           emitcode (";", "tail increment optimized (range %d)", labelRange);
3506           tlbl = IC_LABEL (ic->next);
3507           emitTlbl = 0;
3508         }
3509       else
3510         {
3511           tlbl = newiTempLabel (NULL);
3512           emitTlbl = 1;
3513         }
3514       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3515       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3516           IS_AOP_PREG (IC_RESULT (ic)))
3517         emitcode ("cjne", "%s,#0,!tlabel"
3518                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3519                   ,tlbl->key + 100);
3520       else
3521         {
3522           emitcode ("clr", "a");
3523           emitcode ("cjne", "a,%s,!tlabel"
3524                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3525                     ,tlbl->key + 100);
3526         }
3527
3528       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3529       if (size > 2)
3530         {
3531           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3532               IS_AOP_PREG (IC_RESULT (ic)))
3533             emitcode ("cjne", "%s,#0,!tlabel"
3534                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3535                       ,tlbl->key + 100);
3536           else
3537             emitcode ("cjne", "a,%s,!tlabel"
3538                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3539                       ,tlbl->key + 100);
3540
3541           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3542         }
3543       if (size > 3)
3544         {
3545           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3546               IS_AOP_PREG (IC_RESULT (ic)))
3547             emitcode ("cjne", "%s,#0,!tlabel"
3548                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3549                       ,tlbl->key + 100);
3550           else
3551             {
3552               emitcode ("cjne", "a,%s,!tlabel"
3553                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3554                         ,tlbl->key + 100);
3555             }
3556           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3557         }
3558
3559       if (emitTlbl)
3560         {
3561           emitcode ("", "!tlabeldef", tlbl->key + 100);
3562         }
3563       return TRUE;
3564     }
3565
3566   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3567       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3568       options.model == MODEL_FLAT24 ) {
3569
3570       switch (size) {
3571       case 3:
3572           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3573       case 2:
3574           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3575       case 1:
3576           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3577           break;
3578       }
3579       while (icount--) emitcode ("inc","dptr");      
3580       return TRUE;
3581   }
3582
3583   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3584       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3585       icount <= 5 ) {
3586       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3587       while (icount--) emitcode ("inc","dptr");
3588       emitcode ("mov","dps,#0");
3589       return TRUE;
3590   }
3591
3592   /* if the sizes are greater than 1 then we cannot */
3593   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3594       AOP_SIZE (IC_LEFT (ic)) > 1)
3595     return FALSE;
3596
3597   /* we can if the aops of the left & result match or
3598      if they are in registers and the registers are the
3599      same */
3600   if (
3601        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3602        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3603        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3604     {
3605
3606       if (icount > 3)
3607         {
3608           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3609           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3610           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3611         }
3612       else
3613         {
3614
3615           _startLazyDPSEvaluation ();
3616           while (icount--)
3617             {
3618               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3619             }
3620           _endLazyDPSEvaluation ();
3621         }
3622
3623       return TRUE;
3624     }
3625
3626   return FALSE;
3627 }
3628
3629 /*-----------------------------------------------------------------*/
3630 /* outBitAcc - output a bit in acc                                 */
3631 /*-----------------------------------------------------------------*/
3632 static void
3633 outBitAcc (operand * result)
3634 {
3635   symbol *tlbl = newiTempLabel (NULL);
3636   /* if the result is a bit */
3637   if (AOP_TYPE (result) == AOP_CRY)
3638     {
3639       aopPut (AOP (result), "a", 0);
3640     }
3641   else
3642     {
3643       emitcode ("jz", "!tlabel", tlbl->key + 100);
3644       emitcode ("mov", "a,%s", one);
3645       emitcode ("", "!tlabeldef", tlbl->key + 100);
3646       outAcc (result);
3647     }
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genPlusBits - generates code for addition of two bits           */
3652 /*-----------------------------------------------------------------*/
3653 static void
3654 genPlusBits (iCode * ic)
3655 {
3656   D (emitcode (";", "genPlusBits ");
3657     );
3658   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3659     {
3660       symbol *lbl = newiTempLabel (NULL);
3661       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3662       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3663       emitcode ("cpl", "c");
3664       emitcode ("", "!tlabeldef", (lbl->key + 100));
3665       outBitC (IC_RESULT (ic));
3666     }
3667   else
3668     {
3669       emitcode ("clr", "a");
3670       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3671       emitcode ("rlc", "a");
3672       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3673       emitcode ("addc", "a,#0");
3674       outAcc (IC_RESULT (ic));
3675     }
3676 }
3677
3678 static void
3679 adjustArithmeticResult (iCode * ic)
3680 {
3681   if (opIsGptr (IC_RESULT (ic)) &&
3682       opIsGptr (IC_LEFT (ic)) &&
3683       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3684     {
3685       aopPut (AOP (IC_RESULT (ic)),
3686               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3687               GPTRSIZE - 1);
3688     }
3689
3690   if (opIsGptr (IC_RESULT (ic)) &&
3691       opIsGptr (IC_RIGHT (ic)) &&
3692       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3693     {
3694       aopPut (AOP (IC_RESULT (ic)),
3695             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3696               GPTRSIZE - 1);
3697     }
3698
3699   if (opIsGptr (IC_RESULT (ic)) &&
3700       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3701       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3702       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3703       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3704     {
3705       char buffer[5];
3706       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3707       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3708     }
3709 }
3710
3711 #ifdef KEVIN_SCREWED_UP
3712 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3713 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3714 // will be set TRUE. The caller must then handle the case specially, noting
3715 // that the IC_RESULT operand is not aopOp'd.
3716 #define AOP_OP_3_NOFATAL(ic, rc) \
3717     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3718     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3719                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3720     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3721         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3722     { \
3723        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3724        rc = TRUE; \
3725     }  \
3726     else \
3727     { \
3728        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3729                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3730        rc = FALSE; \
3731        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3732            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3733        { \
3734             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3735             fprintf(stderr,                                  \
3736                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3737        } \
3738     }
3739
3740 // aopOp the left & right operands of an ic.
3741 #define AOP_OP_2(ic) \
3742     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3743     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3744
3745 #else // Kevin didn't screw up...
3746
3747 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
3748
3749 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3750 // generates the result if possible. If result is generated, returns TRUE; otherwise
3751 // returns false and caller must deal with fact that result isn't aopOp'd.
3752 bool aopOp3(iCode * ic)
3753 {
3754     bool dp1InUse, dp2InUse;
3755     
3756     // First, generate the right opcode. DPTR may be used if neither left nor result are
3757     // of type AOP_STR.
3758     
3759 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3760 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3761 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3762 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3763 //      );
3764     
3765     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3766     
3767     // Now, the left opcode. This can use DPTR if the right didn't AND the result is not
3768     // AOP_STR (however, if the result is the same operand as the left, then DPTR may be used).
3769     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)) ||
3770                                   (AOP_IS_STR(IC_RESULT(ic)) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))));
3771     
3772     // We've op'd the left. So, if left & result are the same operand, we know aopOp
3773     // will succeed, and we can just do it & bail.
3774     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
3775     {
3776 //      D(emitcode(";", "aopOp3: left & result equal"););
3777         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3778         return TRUE;
3779     }
3780     
3781     // Note which dptrs are currently in use.
3782     dp1InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) ||
3783                 AOP_IS_STR(IC_RIGHT(ic)) || AOP_IS_STR(IC_LEFT(ic));
3784     dp2InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2);
3785     
3786     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot generate it.
3787     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3788     {
3789         return FALSE;
3790     }
3791     
3792     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3793     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3794     {
3795         return FALSE;
3796     }
3797
3798     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3799
3800     // SOme sanity checking...
3801     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 &&
3802         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2)
3803     {
3804         fprintf(stderr,
3805                 "Ack: got unexpected DP2! (%s:%d %s:%d)\n",
3806                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3807     }
3808         
3809     return TRUE;
3810 }
3811
3812 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3813 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3814 // will be set TRUE. The caller must then handle the case specially, noting
3815 // that the IC_RESULT operand is not aopOp'd.
3816 // 
3817 #define AOP_OP_3_NOFATAL(ic, rc) \
3818             do { rc = !aopOp3(ic); } while (0)
3819
3820 // aopOp the left & right operands of an ic.
3821 #define AOP_OP_2(ic) \
3822     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3823     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3824
3825 #endif
3826
3827 // convienience macro.
3828 #define AOP_SET_LOCALS(ic) \
3829     left = IC_LEFT(ic); \
3830     right = IC_RIGHT(ic); \
3831     result = IC_RESULT(ic);
3832
3833
3834 // Given an integer value of pushedSize bytes on the stack,
3835 // adjust it to be resultSize bytes, either by discarding
3836 // the most significant bytes or by zero-padding.
3837 //
3838 // On exit from this macro, pushedSize will have been adjusted to
3839 // equal resultSize, and ACC may be trashed.
3840 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3841       /* If the pushed data is bigger than the result,          \
3842        * simply discard unused bytes. Icky, but works.          \
3843        */                                                       \
3844       while (pushedSize > resultSize)                           \
3845       {                                                         \
3846           D (emitcode (";", "discarding unused result byte."););\
3847           emitcode ("pop", "acc");                              \
3848           pushedSize--;                                         \
3849       }                                                         \
3850       if (pushedSize < resultSize)                              \
3851       {                                                         \
3852           emitcode ("clr", "a");                                \
3853           /* Conversly, we haven't pushed enough here.          \
3854            * just zero-pad, and all is well.                    \
3855            */                                                   \
3856           while (pushedSize < resultSize)                       \
3857           {                                                     \
3858               emitcode("push", "acc");                          \
3859               pushedSize++;                                     \
3860           }                                                     \
3861       }                                                         \
3862       assert(pushedSize == resultSize);
3863
3864 /*-----------------------------------------------------------------*/
3865 /* genPlus - generates code for addition                           */
3866 /*-----------------------------------------------------------------*/
3867 static void
3868 genPlus (iCode * ic)
3869 {
3870   int size, offset = 0;
3871   bool pushResult = FALSE;
3872   int rSize;
3873
3874   D (emitcode (";", "genPlus "););
3875
3876   /* special cases :- */
3877   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3878       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3879       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3880       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3881       if (size <= 9) {
3882           while (size--) emitcode ("inc","dptr");
3883       } else {
3884           emitcode ("mov","a,dpl");
3885           emitcode ("add","a,#!constbyte",size & 0xff);
3886           emitcode ("mov","dpl,a");
3887           emitcode ("mov","a,dph");
3888           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3889           emitcode ("mov","dph,a");
3890           emitcode ("mov","a,dpx");
3891           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3892           emitcode ("mov","dpx,a");
3893       }
3894       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3895       return ;
3896   }
3897   if ( IS_SYMOP(IC_LEFT(ic)) && 
3898        OP_SYMBOL(IC_LEFT(ic))->remat &&
3899        isOperandInFarSpace(IC_RIGHT(ic))) {
3900       operand *op = IC_RIGHT(ic);
3901       IC_RIGHT(ic) = IC_LEFT(ic);
3902       IC_LEFT(ic) = op;
3903   }
3904                 
3905   AOP_OP_3_NOFATAL (ic, pushResult);
3906   if (pushResult)
3907     {
3908       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3909     }
3910
3911   if (!pushResult)
3912     {
3913       /* if literal, literal on the right or
3914          if left requires ACC or right is already
3915          in ACC */
3916       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3917        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3918           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3919         {
3920           operand *t = IC_RIGHT (ic);
3921           IC_RIGHT (ic) = IC_LEFT (ic);
3922           IC_LEFT (ic) = t;
3923           emitcode (";", "Swapped plus args.");
3924         }
3925
3926       /* if both left & right are in bit
3927          space */
3928       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3929           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3930         {
3931           genPlusBits (ic);
3932           goto release;
3933         }
3934
3935       /* if left in bit space & right literal */
3936       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3937           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3938         {
3939           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3940           /* if result in bit space */
3941           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3942             {
3943               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3944                 emitcode ("cpl", "c");
3945               outBitC (IC_RESULT (ic));
3946             }
3947           else
3948             {
3949               size = getDataSize (IC_RESULT (ic));
3950               _startLazyDPSEvaluation ();
3951               while (size--)
3952                 {
3953                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3954                   emitcode ("addc", "a,#0");
3955                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3956                 }
3957               _endLazyDPSEvaluation ();
3958             }
3959           goto release;
3960         }
3961
3962       /* if I can do an increment instead
3963          of add then GOOD for ME */
3964       if (genPlusIncr (ic) == TRUE)
3965         {
3966           emitcode (";", "did genPlusIncr");
3967           goto release;
3968         }
3969
3970     }
3971   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3972
3973   _startLazyDPSEvaluation ();
3974   while (size--)
3975     {
3976       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3977         {
3978           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3979           if (offset == 0)
3980             emitcode ("add", "a,%s",
3981                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3982           else
3983             emitcode ("addc", "a,%s",
3984                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3985         }
3986       else
3987         {
3988           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3989           {
3990               /* right is going to use ACC or we would have taken the
3991                * above branch.
3992                */
3993               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3994        TR_AP("#3");
3995               D(emitcode(";", "+ AOP_ACC special case."););
3996               emitcode("xch", "a, %s", DP2_RESULT_REG);
3997           }
3998           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3999           if (offset == 0)
4000           {
4001             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4002             {
4003          TR_AP("#4");
4004                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4005             }
4006             else
4007             {
4008                 emitcode ("add", "a,%s",
4009                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
4010             }
4011           }
4012           else
4013           {
4014             emitcode ("addc", "a,%s",
4015                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
4016           }
4017         }
4018       if (!pushResult)
4019         {
4020           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4021         }
4022       else
4023         {
4024           emitcode ("push", "acc");
4025         }
4026       offset++;
4027     }
4028   _endLazyDPSEvaluation ();
4029
4030   if (pushResult)
4031     {
4032       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4033
4034       size = getDataSize (IC_LEFT (ic));
4035       rSize = getDataSize (IC_RESULT (ic));
4036
4037       ADJUST_PUSHED_RESULT(size, rSize);
4038
4039       _startLazyDPSEvaluation ();
4040       while (size--)
4041         {
4042           emitcode ("pop", "acc");
4043           aopPut (AOP (IC_RESULT (ic)), "a", size);
4044         }
4045       _endLazyDPSEvaluation ();
4046     }
4047
4048   adjustArithmeticResult (ic);
4049
4050 release:
4051   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4052   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4053   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4054 }
4055
4056 /*-----------------------------------------------------------------*/
4057 /* genMinusDec :- does subtraction with deccrement if possible     */
4058 /*-----------------------------------------------------------------*/
4059 static bool
4060 genMinusDec (iCode * ic)
4061 {
4062   unsigned int icount;
4063   unsigned int size = getDataSize (IC_RESULT (ic));
4064
4065   /* will try to generate an increment */
4066   /* if the right side is not a literal
4067      we cannot */
4068   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4069     return FALSE;
4070
4071   /* if the literal value of the right hand side
4072      is greater than 4 then it is not worth it */
4073   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4074     return FALSE;
4075
4076   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4077       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4078       while (icount--) {
4079           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
4080       }
4081       return TRUE;
4082   }
4083   /* if decrement 16 bits in register */
4084   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4085       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4086       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4087       (size > 1) &&
4088       (icount == 1))
4089     {
4090       symbol *tlbl;
4091       int emitTlbl;
4092       int labelRange;
4093
4094       /* If the next instruction is a goto and the goto target
4095          * is <= 5 instructions previous to this, we can generate
4096          * jumps straight to that target.
4097        */
4098       if (ic->next && ic->next->op == GOTO
4099           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4100           && labelRange <= 5)
4101         {
4102           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4103           tlbl = IC_LABEL (ic->next);
4104           emitTlbl = 0;
4105         }
4106       else
4107         {
4108           tlbl = newiTempLabel (NULL);
4109           emitTlbl = 1;
4110         }
4111
4112       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4113       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4114           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4115           IS_AOP_PREG (IC_RESULT (ic)))
4116         emitcode ("cjne", "%s,#!constbyte,!tlabel"
4117                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4118                   ,tlbl->key + 100);
4119       else
4120         {
4121           emitcode ("mov", "a,#!constbyte",0xff);
4122           emitcode ("cjne", "a,%s,!tlabel"
4123                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4124                     ,tlbl->key + 100);
4125         }
4126       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4127       if (size > 2)
4128         {
4129           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4130               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4131               IS_AOP_PREG (IC_RESULT (ic)))
4132             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4133                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4134                       ,tlbl->key + 100);
4135           else
4136             {
4137               emitcode ("cjne", "a,%s,!tlabel"
4138                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4139                         ,tlbl->key + 100);
4140             }
4141           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4142         }
4143       if (size > 3)
4144         {
4145           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4146               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4147               IS_AOP_PREG (IC_RESULT (ic)))
4148             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4149                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4150                       ,tlbl->key + 100);
4151           else
4152             {
4153               emitcode ("cjne", "a,%s,!tlabel"
4154                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4155                         ,tlbl->key + 100);
4156             }
4157           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4158         }
4159       if (emitTlbl)
4160         {
4161           emitcode ("", "!tlabeldef", tlbl->key + 100);
4162         }
4163       return TRUE;
4164     }
4165
4166   /* if the sizes are greater than 1 then we cannot */
4167   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4168       AOP_SIZE (IC_LEFT (ic)) > 1)
4169     return FALSE;
4170
4171   /* we can if the aops of the left & result match or
4172      if they are in registers and the registers are the
4173      same */
4174   if (
4175        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4176        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4177        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4178     {
4179
4180       _startLazyDPSEvaluation ();
4181       while (icount--)
4182         {
4183           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4184         }
4185       _endLazyDPSEvaluation ();
4186
4187       return TRUE;
4188     }
4189
4190   return FALSE;
4191 }
4192
4193 /*-----------------------------------------------------------------*/
4194 /* addSign - complete with sign                                    */
4195 /*-----------------------------------------------------------------*/
4196 static void
4197 addSign (operand * result, int offset, int sign)
4198 {
4199   int size = (getDataSize (result) - offset);
4200   if (size > 0)
4201     {
4202       _startLazyDPSEvaluation();
4203       if (sign)
4204         {
4205           emitcode ("rlc", "a");
4206           emitcode ("subb", "a,acc");
4207           while (size--)
4208           {
4209             aopPut (AOP (result), "a", offset++);
4210           }
4211         }
4212       else
4213       {
4214         while (size--)
4215         {
4216           aopPut (AOP (result), zero, offset++);
4217         }
4218       }
4219       _endLazyDPSEvaluation();
4220     }
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusBits - generates code for subtraction  of two bits      */
4225 /*-----------------------------------------------------------------*/
4226 static void
4227 genMinusBits (iCode * ic)
4228 {
4229   symbol *lbl = newiTempLabel (NULL);
4230
4231   D (emitcode (";", "genMinusBits "););
4232
4233   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4234     {
4235       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4236       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4237       emitcode ("cpl", "c");
4238       emitcode ("", "!tlabeldef", (lbl->key + 100));
4239       outBitC (IC_RESULT (ic));
4240     }
4241   else
4242     {
4243       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4244       emitcode ("subb", "a,acc");
4245       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4246       emitcode ("inc", "a");
4247       emitcode ("", "!tlabeldef", (lbl->key + 100));
4248       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4249       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4250     }
4251 }
4252
4253 /*-----------------------------------------------------------------*/
4254 /* genMinus - generates code for subtraction                       */
4255 /*-----------------------------------------------------------------*/
4256 static void
4257 genMinus (iCode * ic)
4258 {
4259   int size, offset = 0;
4260   int rSize;
4261   unsigned long lit = 0L;
4262   bool pushResult = FALSE;
4263
4264   D (emitcode (";", "genMinus "););
4265
4266   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4267   aopOp (IC_RIGHT (ic), ic, FALSE, 
4268          (AOP_INDPTRn(IC_LEFT(ic)) ? FALSE : (AOP_USESDPTR(IC_LEFT(ic)) ? TRUE : FALSE)));
4269   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4270       ((AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)
4271        || OP_SYMBOL(IC_RESULT(ic))->ruonly))
4272     {
4273       pushResult = TRUE;
4274     }
4275   else
4276     {
4277       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4278
4279       /* special cases :- */
4280       /* if both left & right are in bit space */
4281       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4282           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4283         {
4284           genMinusBits (ic);
4285           goto release;
4286         }
4287
4288       /* if I can do an decrement instead
4289          of subtract then GOOD for ME */
4290       if (genMinusDec (ic) == TRUE)
4291         goto release;
4292
4293     }
4294
4295   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4296
4297   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4298     {
4299       CLRC;
4300     }
4301   else
4302     {
4303       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4304       lit = -(long) lit;
4305     }
4306
4307
4308   /* if literal, add a,#-lit, else normal subb */
4309   _startLazyDPSEvaluation ();
4310   while (size--) {
4311       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4312       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4313           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4314               emitcode ("mov","b,a");
4315               MOVA(aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4316               emitcode ("xch","a,b");
4317               emitcode ("subb","a,b");
4318           } else {
4319               emitcode ("subb", "a,%s",
4320                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4321           }
4322       } else {
4323           /* first add without previous c */
4324           if (!offset) {
4325               if (!size && lit==-1) {
4326                   emitcode ("dec", "a");
4327               } else {
4328                   emitcode ("add", "a,#!constbyte",
4329                             (unsigned int) (lit & 0x0FFL));
4330               }
4331           } else {
4332               emitcode ("addc", "a,#!constbyte",
4333                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4334           }
4335       }
4336       
4337       if (pushResult) {
4338           emitcode ("push", "acc");
4339       } else {
4340           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4341       }
4342       offset++;
4343   }
4344   _endLazyDPSEvaluation ();
4345   
4346   if (pushResult)
4347     {
4348       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4349
4350       size = getDataSize (IC_LEFT (ic));
4351       rSize = getDataSize (IC_RESULT (ic));
4352
4353       ADJUST_PUSHED_RESULT(size, rSize);
4354
4355       _startLazyDPSEvaluation ();
4356       while (size--)
4357         {
4358           emitcode ("pop", "acc");
4359           aopPut (AOP (IC_RESULT (ic)), "a", size);
4360         }
4361       _endLazyDPSEvaluation ();
4362     }
4363
4364   adjustArithmeticResult (ic);
4365
4366 release:
4367   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4369   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4370 }
4371
4372
4373 /*-----------------------------------------------------------------*/
4374 /* genMultbits :- multiplication of bits                           */
4375 /*-----------------------------------------------------------------*/
4376 static void
4377 genMultbits (operand * left,
4378              operand * right,
4379              operand * result,
4380              iCode   * ic)
4381 {
4382   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4384   aopOp(result, ic, TRUE, FALSE);
4385   outBitC (result);
4386 }
4387
4388
4389 /*-----------------------------------------------------------------*/
4390 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4391 /*-----------------------------------------------------------------*/
4392 static void
4393 genMultOneByte (operand * left,
4394                 operand * right,
4395                 operand * result,
4396                 iCode   * ic)
4397 {
4398   sym_link *opetype = operandType (result);
4399   symbol *lbl;
4400
4401
4402   /* (if two literals: the value is computed before) */
4403   /* if one literal, literal on the right */
4404   if (AOP_TYPE (left) == AOP_LIT)
4405     {
4406       operand *t = right;
4407       right = left;
4408       left = t;
4409       emitcode (";", "swapped left and right");
4410     }
4411
4412   if (SPEC_USIGN(opetype)
4413       // ignore the sign of left and right, what else can we do?
4414       || (SPEC_USIGN(operandType(left)) && 
4415           SPEC_USIGN(operandType(right)))) {
4416     // just an unsigned 8*8=8/16 multiply
4417     //emitcode (";","unsigned");
4418     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4419     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4420     emitcode ("mul", "ab");
4421    
4422     _G.accInUse++; _G.bInUse++;
4423     aopOp(result, ic, TRUE, FALSE);
4424       
4425       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4426       {
4427           // this should never happen
4428           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4429                    AOP_SIZE(result), __FILE__, lineno);
4430           exit (1);
4431       }      
4432       
4433     aopPut (AOP (result), "a", 0);
4434     _G.accInUse--; _G.bInUse--;
4435     if (AOP_SIZE(result)==2) 
4436     {
4437       aopPut (AOP (result), "b", 1);
4438     }
4439     return;
4440   }
4441
4442   // we have to do a signed multiply
4443
4444   emitcode (";", "signed");
4445   emitcode ("clr", "F0"); // reset sign flag
4446   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4447
4448   lbl=newiTempLabel(NULL);
4449   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4450   // left side is negative, 8-bit two's complement, this fails for -128
4451   emitcode ("setb", "F0"); // set sign flag
4452   emitcode ("cpl", "a");
4453   emitcode ("inc", "a");
4454
4455   emitcode ("", "!tlabeldef", lbl->key+100);
4456
4457   /* if literal */
4458   if (AOP_TYPE(right)==AOP_LIT) {
4459     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4460     /* AND literal negative */
4461     if ((int) val < 0) {
4462       emitcode ("cpl", "F0"); // complement sign flag
4463       emitcode ("mov", "b,#!constbyte", -val);
4464     } else {
4465       emitcode ("mov", "b,#!constbyte", val);
4466     }
4467   } else {
4468     lbl=newiTempLabel(NULL);
4469     emitcode ("mov", "b,a");
4470     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4471     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4472     // right side is negative, 8-bit two's complement
4473     emitcode ("cpl", "F0"); // complement sign flag
4474     emitcode ("cpl", "a");
4475     emitcode ("inc", "a");
4476     emitcode ("", "!tlabeldef", lbl->key+100);
4477   }
4478   emitcode ("mul", "ab");
4479     
4480   _G.accInUse++;_G.bInUse++;
4481   aopOp(result, ic, TRUE, FALSE);
4482     
4483   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4484   {
4485     // this should never happen
4486       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4487                AOP_SIZE(result), __FILE__, lineno);
4488       exit (1);
4489   }    
4490     
4491   lbl=newiTempLabel(NULL);
4492   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4493   // only ONE op was negative, we have to do a 8/16-bit two's complement
4494   emitcode ("cpl", "a"); // lsb
4495   if (AOP_SIZE(result)==1) {
4496     emitcode ("inc", "a");
4497   } else {
4498     emitcode ("add", "a,#1");
4499     emitcode ("xch", "a,b");
4500     emitcode ("cpl", "a"); // msb
4501     emitcode ("addc", "a,#0");
4502     emitcode ("xch", "a,b");
4503   }
4504
4505   emitcode ("", "!tlabeldef", lbl->key+100);
4506   aopPut (AOP (result), "a", 0);
4507   _G.accInUse--;_G.bInUse--;
4508   if (AOP_SIZE(result)==2) {
4509     aopPut (AOP (result), "b", 1);
4510   }
4511 }
4512
4513 /*-----------------------------------------------------------------*/
4514 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4515 /*-----------------------------------------------------------------*/
4516 static void genMultTwoByte (operand *left, operand *right, 
4517                             operand *result, iCode *ic)
4518 {
4519         sym_link *retype = getSpec(operandType(right));
4520         sym_link *letype = getSpec(operandType(left));
4521         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4522         symbol *lbl;
4523
4524         if (AOP_TYPE (left) == AOP_LIT) {
4525                 operand *t = right;
4526                 right = left;
4527                 left = t;
4528         }
4529         /* save EA bit in F1 */
4530         lbl = newiTempLabel(NULL);
4531         emitcode ("setb","F1");
4532         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4533         emitcode ("clr","F1");
4534         emitcode("","!tlabeldef",lbl->key+100);
4535
4536         /* load up MB with right */
4537         if (!umult) {
4538                 emitcode("clr","F0");
4539                 if (AOP_TYPE(right) == AOP_LIT) {
4540                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4541                         if (val < 0) {
4542                                 emitcode("setb","F0");
4543                                 val = -val;
4544                         }
4545                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4546                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4547                 } else {
4548                         lbl = newiTempLabel(NULL);
4549                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4550                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4551                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4552                         emitcode ("xch", "a,b");
4553                         emitcode ("cpl","a");
4554                         emitcode ("add", "a,#1");
4555                         emitcode ("xch", "a,b");
4556                         emitcode ("cpl", "a"); // msb
4557                         emitcode ("addc", "a,#0");
4558                         emitcode ("setb","F0");
4559                         emitcode ("","!tlabeldef",lbl->key+100);
4560                         emitcode ("mov","mb,b");
4561                         emitcode ("mov","mb,a");
4562                 }
4563         } else {
4564                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4565                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4566         }
4567         /* load up MA with left */
4568         if (!umult) {
4569                 lbl = newiTempLabel(NULL);
4570                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4571                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4572                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4573                 emitcode ("xch", "a,b");
4574                 emitcode ("cpl","a");
4575                 emitcode ("add", "a,#1");
4576                 emitcode ("xch", "a,b");
4577                 emitcode ("cpl", "a"); // msb
4578                 emitcode ("addc","a,#0");
4579                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4580                 emitcode ("setb","F0");
4581                 emitcode ("","!tlabeldef",lbl->key+100);
4582                 emitcode ("mov","ma,b");
4583                 emitcode ("mov","ma,a");
4584         } else {
4585                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4586                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4587         }
4588         /* wait for multiplication to finish */
4589         lbl = newiTempLabel(NULL);
4590         emitcode("","!tlabeldef", lbl->key+100);
4591         emitcode("mov","a,mcnt1");
4592         emitcode("anl","a,#!constbyte",0x80);
4593         emitcode("jnz","!tlabel",lbl->key+100);
4594         
4595         freeAsmop (left, NULL, ic, TRUE);
4596         freeAsmop (right, NULL, ic,TRUE);
4597         aopOp(result, ic, TRUE, FALSE);
4598
4599         /* if unsigned then simple */   
4600         if (umult) {
4601                 emitcode ("mov","a,ma");
4602                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4603                 emitcode ("mov","a,ma");
4604                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4605                 aopPut(AOP(result),"ma",1);
4606                 aopPut(AOP(result),"ma",0);
4607         } else {
4608                 emitcode("push","ma");
4609                 emitcode("push","ma");
4610                 emitcode("push","ma");
4611                 MOVA("ma");
4612                 /* negate result if needed */
4613                 lbl = newiTempLabel(NULL);      
4614                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4615                 emitcode("cpl","a");
4616                 emitcode("add","a,#1");
4617                 emitcode("","!tlabeldef", lbl->key+100);
4618                 if (AOP_TYPE(result) == AOP_ACC)
4619                 {
4620                     D(emitcode(";", "ACC special case."););
4621                     /* We know result is the only live aop, and 
4622                      * it's obviously not a DPTR2, so AP is available.
4623                      */
4624                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4625                 }
4626                 else
4627                 {
4628                     aopPut(AOP(result),"a",0);
4629                 }
4630             
4631                 emitcode("pop","acc");
4632                 lbl = newiTempLabel(NULL);      
4633                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4634                 emitcode("cpl","a");
4635                 emitcode("addc","a,#0");
4636                 emitcode("","!tlabeldef", lbl->key+100);
4637                 aopPut(AOP(result),"a",1);
4638                 emitcode("pop","acc");
4639                 if (AOP_SIZE(result) >= 3) {
4640                         lbl = newiTempLabel(NULL);      
4641                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4642                         emitcode("cpl","a");
4643                         emitcode("addc","a,#0");                        
4644                         emitcode("","!tlabeldef", lbl->key+100);
4645                         aopPut(AOP(result),"a",2);
4646                 }
4647                 emitcode("pop","acc");
4648                 if (AOP_SIZE(result) >= 4) {
4649                         lbl = newiTempLabel(NULL);      
4650                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4651                         emitcode("cpl","a");
4652                         emitcode("addc","a,#0");                        
4653                         emitcode("","!tlabeldef", lbl->key+100);
4654                         aopPut(AOP(result),"a",3);
4655                 }
4656                 if (AOP_TYPE(result) == AOP_ACC)
4657                 {
4658                     /* We stashed the result away above. */
4659                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4660                 }           
4661                 
4662         }
4663         freeAsmop (result, NULL, ic, TRUE);
4664
4665         /* restore EA bit in F1 */
4666         lbl = newiTempLabel(NULL);
4667         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4668         emitcode ("setb","EA");
4669         emitcode("","!tlabeldef",lbl->key+100);
4670         return ;
4671 }
4672
4673 /*-----------------------------------------------------------------*/
4674 /* genMult - generates code for multiplication                     */
4675 /*-----------------------------------------------------------------*/
4676 static void
4677 genMult (iCode * ic)
4678 {
4679   operand *left = IC_LEFT (ic);
4680   operand *right = IC_RIGHT (ic);
4681   operand *result = IC_RESULT (ic);
4682
4683   D (emitcode (";", "genMult "););
4684
4685   /* assign the amsops */
4686   AOP_OP_2 (ic);
4687
4688   /* special cases first */
4689   /* both are bits */
4690   if (AOP_TYPE (left) == AOP_CRY &&
4691       AOP_TYPE (right) == AOP_CRY)
4692     {
4693       genMultbits (left, right, result, ic);
4694       goto release;
4695     }
4696
4697   /* if both are of size == 1 */
4698   if (AOP_SIZE (left) == 1 &&
4699       AOP_SIZE (right) == 1)
4700     {
4701       genMultOneByte (left, right, result, ic);
4702       goto release;
4703     }
4704
4705   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4706           /* use the ds390 ARITHMETIC accel UNIT */
4707           genMultTwoByte (left, right, result, ic);
4708           return ;
4709   }
4710   /* should have been converted to function call */
4711   assert (0);
4712
4713 release:
4714   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4715   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4716   freeAsmop (result, NULL, ic, TRUE);
4717 }
4718
4719 /*-----------------------------------------------------------------*/
4720 /* genDivbits :- division of bits                                  */
4721 /*-----------------------------------------------------------------*/
4722 static void
4723 genDivbits (operand * left,
4724             operand * right,
4725             operand * result,
4726             iCode   * ic)
4727 {
4728
4729   char *l;
4730
4731   /* the result must be bit */
4732   LOAD_AB_FOR_DIV (left, right, l);
4733   emitcode ("div", "ab");
4734   emitcode ("rrc", "a");
4735   aopOp(result, ic, TRUE, FALSE);
4736     
4737   aopPut (AOP (result), "c", 0);
4738 }
4739
4740 /*-----------------------------------------------------------------*/
4741 /* genDivOneByte : 8 bit division                                  */
4742 /*-----------------------------------------------------------------*/
4743 static void
4744 genDivOneByte (operand * left,
4745                operand * right,
4746                operand * result,
4747                iCode   * ic)
4748 {
4749   sym_link *opetype = operandType (result);
4750   char *l;
4751   symbol *lbl;
4752   int size, offset;
4753
4754   offset = 1;
4755   /* signed or unsigned */
4756   if (SPEC_USIGN (opetype))
4757     {
4758         /* unsigned is easy */
4759         LOAD_AB_FOR_DIV (left, right, l);
4760         emitcode ("div", "ab");
4761
4762         _G.accInUse++;
4763         aopOp(result, ic, TRUE, FALSE);
4764         aopPut (AOP (result), "a", 0);
4765         _G.accInUse--;
4766
4767         size = AOP_SIZE (result) - 1;
4768         
4769         while (size--)
4770         {
4771             aopPut (AOP (result), zero, offset++);
4772         }
4773       return;
4774     }
4775
4776   /* signed is a little bit more difficult */
4777
4778   /* save the signs of the operands */
4779   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4780   MOVA (l);
4781   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4782   emitcode ("push", "acc");     /* save it on the stack */
4783
4784   /* now sign adjust for both left & right */
4785   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4786   MOVA (l);
4787   lbl = newiTempLabel (NULL);
4788   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4789   emitcode ("cpl", "a");
4790   emitcode ("inc", "a");
4791   emitcode ("", "!tlabeldef", (lbl->key + 100));
4792   emitcode ("mov", "b,a");
4793
4794   /* sign adjust left side */
4795   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4796   MOVA (l);
4797
4798   lbl = newiTempLabel (NULL);
4799   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4800   emitcode ("cpl", "a");
4801   emitcode ("inc", "a");
4802   emitcode ("", "!tlabeldef", (lbl->key + 100));
4803
4804   /* now the division */
4805   emitcode ("nop", "; workaround for DS80C390 div bug.");
4806   emitcode ("div", "ab");
4807   /* we are interested in the lower order
4808      only */
4809   emitcode ("mov", "b,a");
4810   lbl = newiTempLabel (NULL);
4811   emitcode ("pop", "acc");
4812   /* if there was an over flow we don't
4813      adjust the sign of the result */
4814   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4815   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4816   CLRC;
4817   emitcode ("clr", "a");
4818   emitcode ("subb", "a,b");
4819   emitcode ("mov", "b,a");
4820   emitcode ("", "!tlabeldef", (lbl->key + 100));
4821
4822   /* now we are done */
4823   _G.accInUse++;     _G.bInUse++;
4824     aopOp(result, ic, TRUE, FALSE);
4825     
4826     aopPut (AOP (result), "b", 0);
4827     
4828     size = AOP_SIZE (result) - 1;
4829     
4830     if (size > 0)
4831     {
4832       emitcode ("mov", "c,b.7");
4833       emitcode ("subb", "a,acc");
4834     }
4835     while (size--)
4836     {
4837         aopPut (AOP (result), "a", offset++);
4838     }
4839     _G.accInUse--;     _G.bInUse--;
4840
4841 }
4842
4843 /*-----------------------------------------------------------------*/
4844 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4845 /*-----------------------------------------------------------------*/
4846 static void genDivTwoByte (operand *left, operand *right, 
4847                             operand *result, iCode *ic)
4848 {
4849         sym_link *retype = getSpec(operandType(right));
4850         sym_link *letype = getSpec(operandType(left));
4851         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4852         symbol *lbl;
4853
4854         /* save EA bit in F1 */
4855         lbl = newiTempLabel(NULL);
4856         emitcode ("setb","F1");
4857         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4858         emitcode ("clr","F1");
4859         emitcode("","!tlabeldef",lbl->key+100);
4860
4861         /* load up MA with left */
4862         if (!umult) {
4863                 emitcode("clr","F0");
4864                 lbl = newiTempLabel(NULL);
4865                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4866                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4867                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4868                 emitcode ("xch", "a,b");
4869                 emitcode ("cpl","a");
4870                 emitcode ("add", "a,#1");
4871                 emitcode ("xch", "a,b");
4872                 emitcode ("cpl", "a"); // msb
4873                 emitcode ("addc","a,#0");
4874                 emitcode ("setb","F0");
4875                 emitcode ("","!tlabeldef",lbl->key+100);
4876                 emitcode ("mov","ma,b");
4877                 emitcode ("mov","ma,a");
4878         } else {
4879                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4880                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4881         }
4882
4883         /* load up MB with right */
4884         if (!umult) {
4885                 if (AOP_TYPE(right) == AOP_LIT) {
4886                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4887                         if (val < 0) {
4888                                 lbl = newiTempLabel(NULL);
4889                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4890                                 emitcode("setb","F0");
4891                                 emitcode ("","!tlabeldef",lbl->key+100);
4892                                 val = -val;
4893                         } 
4894                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4895                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4896                 } else {
4897                         lbl = newiTempLabel(NULL);
4898                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4899                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4900                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4901                         emitcode ("xch", "a,b");
4902                         emitcode ("cpl","a");
4903                         emitcode ("add", "a,#1");
4904                         emitcode ("xch", "a,b");
4905                         emitcode ("cpl", "a"); // msb
4906                         emitcode ("addc", "a,#0");
4907                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4908                         emitcode ("setb","F0");
4909                         emitcode ("","!tlabeldef",lbl->key+100);
4910                         emitcode ("mov","mb,b");
4911                         emitcode ("mov","mb,a");
4912                 }
4913         } else {
4914                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4915                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4916         }
4917
4918         /* wait for multiplication to finish */
4919         lbl = newiTempLabel(NULL);
4920         emitcode("","!tlabeldef", lbl->key+100);
4921         emitcode("mov","a,mcnt1");
4922         emitcode("anl","a,#!constbyte",0x80);
4923         emitcode("jnz","!tlabel",lbl->key+100);
4924         
4925         freeAsmop (left, NULL, ic, TRUE);
4926         freeAsmop (right, NULL, ic,TRUE);
4927         aopOp(result, ic, TRUE, FALSE);
4928
4929         /* if unsigned then simple */   
4930         if (umult) {
4931                 aopPut(AOP(result),"ma",1);
4932                 aopPut(AOP(result),"ma",0);
4933         } else {
4934                 emitcode("push","ma");
4935                 MOVA("ma");
4936                 /* negate result if needed */
4937                 lbl = newiTempLabel(NULL);      
4938                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4939                 emitcode("cpl","a");
4940                 emitcode("add","a,#1");
4941                 emitcode("","!tlabeldef", lbl->key+100);
4942                 aopPut(AOP(result),"a",0);
4943                 emitcode("pop","acc");
4944                 lbl = newiTempLabel(NULL);      
4945                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4946                 emitcode("cpl","a");
4947                 emitcode("addc","a,#0");
4948                 emitcode("","!tlabeldef", lbl->key+100);
4949                 aopPut(AOP(result),"a",1);
4950         }
4951         freeAsmop (result, NULL, ic, TRUE);
4952         /* restore EA bit in F1 */
4953         lbl = newiTempLabel(NULL);
4954         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4955         emitcode ("setb","EA");
4956         emitcode("","!tlabeldef",lbl->key+100);
4957         return ;
4958 }
4959
4960 /*-----------------------------------------------------------------*/
4961 /* genDiv - generates code for division                            */
4962 /*-----------------------------------------------------------------*/
4963 static void
4964 genDiv (iCode * ic)
4965 {
4966   operand *left = IC_LEFT (ic);
4967   operand *right = IC_RIGHT (ic);
4968   operand *result = IC_RESULT (ic);
4969
4970   D (emitcode (";", "genDiv "););
4971
4972   /* assign the amsops */
4973   AOP_OP_2 (ic);
4974
4975   /* special cases first */
4976   /* both are bits */
4977   if (AOP_TYPE (left) == AOP_CRY &&
4978       AOP_TYPE (right) == AOP_CRY)
4979     {
4980       genDivbits (left, right, result, ic);
4981       goto release;
4982     }
4983
4984   /* if both are of size == 1 */
4985   if (AOP_SIZE (left) == 1 &&
4986       AOP_SIZE (right) == 1)
4987     {
4988       genDivOneByte (left, right, result, ic);
4989       goto release;
4990     }
4991
4992   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4993           /* use the ds390 ARITHMETIC accel UNIT */
4994           genDivTwoByte (left, right, result, ic);
4995           return ;
4996   }
4997   /* should have been converted to function call */
4998   assert (0);
4999 release:
5000   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5001   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5002   freeAsmop (result, NULL, ic, TRUE);
5003 }
5004
5005 /*-----------------------------------------------------------------*/
5006 /* genModbits :- modulus of bits                                   */
5007 /*-----------------------------------------------------------------*/
5008 static void
5009 genModbits (operand * left,
5010             operand * right,
5011             operand * result,
5012             iCode   * ic)
5013 {
5014
5015   char *l;
5016
5017   /* the result must be bit */
5018   LOAD_AB_FOR_DIV (left, right, l);
5019   emitcode ("div", "ab");
5020   emitcode ("mov", "a,b");
5021   emitcode ("rrc", "a");
5022   aopOp(result, ic, TRUE, FALSE);
5023   aopPut (AOP (result), "c", 0);
5024 }
5025
5026 /*-----------------------------------------------------------------*/
5027 /* genModOneByte : 8 bit modulus                                   */
5028 /*-----------------------------------------------------------------*/
5029 static void
5030 genModOneByte (operand * left,
5031                operand * right,
5032                operand * result,
5033                iCode   * ic)
5034 {
5035   sym_link *opetype = operandType (result);
5036   char *l;
5037   symbol *lbl;
5038
5039   /* signed or unsigned */
5040   if (SPEC_USIGN (opetype))
5041     {
5042       /* unsigned is easy */
5043       LOAD_AB_FOR_DIV (left, right, l);
5044       emitcode ("div", "ab");
5045       aopOp(result, ic, TRUE, FALSE);   
5046       aopPut (AOP (result), "b", 0);
5047       return;
5048     }
5049
5050   /* signed is a little bit more difficult */
5051
5052   /* save the signs of the operands */
5053   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5054   MOVA (l);
5055
5056   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5057   emitcode ("push", "acc");     /* save it on the stack */
5058
5059   /* now sign adjust for both left & right */
5060   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
5061   MOVA (l);
5062
5063   lbl = newiTempLabel (NULL);
5064   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5065   emitcode ("cpl", "a");
5066   emitcode ("inc", "a");
5067   emitcode ("", "!tlabeldef", (lbl->key + 100));
5068   emitcode ("mov", "b,a");
5069
5070   /* sign adjust left side */
5071   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5072   MOVA (l);
5073
5074   lbl = newiTempLabel (NULL);
5075   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5076   emitcode ("cpl", "a");
5077   emitcode ("inc", "a");
5078   emitcode ("", "!tlabeldef", (lbl->key + 100));
5079
5080   /* now the multiplication */
5081   emitcode ("nop", "; workaround for DS80C390 div bug.");
5082   emitcode ("div", "ab");
5083   /* we are interested in the lower order
5084      only */
5085   lbl = newiTempLabel (NULL);
5086   emitcode ("pop", "acc");
5087   /* if there was an over flow we don't
5088      adjust the sign of the result */
5089   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5090   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5091   CLRC;
5092   emitcode ("clr", "a");
5093   emitcode ("subb", "a,b");
5094   emitcode ("mov", "b,a");
5095   emitcode ("", "!tlabeldef", (lbl->key + 100));
5096   
5097   _G.bInUse++;
5098   /* now we are done */
5099   aopOp(result, ic, TRUE, FALSE);    
5100   aopPut (AOP (result), "b", 0);
5101   _G.bInUse--;
5102
5103 }
5104
5105 /*-----------------------------------------------------------------*/
5106 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5107 /*-----------------------------------------------------------------*/
5108 static void genModTwoByte (operand *left, operand *right, 
5109                             operand *result, iCode *ic)
5110 {
5111         sym_link *retype = getSpec(operandType(right));
5112         sym_link *letype = getSpec(operandType(left));
5113         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5114         symbol *lbl;
5115
5116         /* load up MA with left */
5117         /* save EA bit in F1 */
5118         lbl = newiTempLabel(NULL);
5119         emitcode ("setb","F1");
5120         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5121         emitcode ("clr","F1");
5122         emitcode("","!tlabeldef",lbl->key+100);
5123
5124         if (!umult) {
5125                 lbl = newiTempLabel(NULL);
5126                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5127                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5128                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5129                 emitcode ("xch", "a,b");
5130                 emitcode ("cpl","a");
5131                 emitcode ("add", "a,#1");
5132                 emitcode ("xch", "a,b");
5133                 emitcode ("cpl", "a"); // msb
5134                 emitcode ("addc","a,#0");
5135                 emitcode ("","!tlabeldef",lbl->key+100);
5136                 emitcode ("mov","ma,b");
5137                 emitcode ("mov","ma,a");
5138         } else {
5139                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5140                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5141         }
5142
5143         /* load up MB with right */
5144         if (!umult) {
5145                 if (AOP_TYPE(right) == AOP_LIT) {
5146                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5147                         if (val < 0) {
5148                                 val = -val;
5149                         } 
5150                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5151                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5152                 } else {
5153                         lbl = newiTempLabel(NULL);
5154                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5155                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5156                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5157                         emitcode ("xch", "a,b");
5158                         emitcode ("cpl","a");
5159                         emitcode ("add", "a,#1");
5160                         emitcode ("xch", "a,b");
5161                         emitcode ("cpl", "a"); // msb
5162                         emitcode ("addc", "a,#0");
5163                         emitcode ("","!tlabeldef",lbl->key+100);
5164                         emitcode ("mov","mb,b");
5165                         emitcode ("mov","mb,a");
5166                 }
5167         } else {
5168                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5169                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5170         }
5171
5172         /* wait for multiplication to finish */
5173         lbl = newiTempLabel(NULL);
5174         emitcode("","!tlabeldef", lbl->key+100);
5175         emitcode("mov","a,mcnt1");
5176         emitcode("anl","a,#!constbyte",0x80);
5177         emitcode("jnz","!tlabel",lbl->key+100);
5178         
5179         freeAsmop (left, NULL, ic, TRUE);
5180         freeAsmop (right, NULL, ic,TRUE);
5181         aopOp(result, ic, TRUE, FALSE);
5182
5183         aopPut(AOP(result),"mb",1);
5184         aopPut(AOP(result),"mb",0);
5185         freeAsmop (result, NULL, ic, TRUE);
5186
5187         /* restore EA bit in F1 */
5188         lbl = newiTempLabel(NULL);
5189         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5190         emitcode ("setb","EA");
5191         emitcode("","!tlabeldef",lbl->key+100);
5192         return ;
5193 }
5194
5195 /*-----------------------------------------------------------------*/
5196 /* genMod - generates code for division                            */
5197 /*-----------------------------------------------------------------*/
5198 static void
5199 genMod (iCode * ic)
5200 {
5201   operand *left = IC_LEFT (ic);
5202   operand *right = IC_RIGHT (ic);
5203   operand *result = IC_RESULT (ic);
5204
5205   D (emitcode (";", "genMod "); );
5206
5207   /* assign the amsops */
5208   AOP_OP_2 (ic);
5209
5210   /* special cases first */
5211   /* both are bits */
5212   if (AOP_TYPE (left) == AOP_CRY &&
5213       AOP_TYPE (right) == AOP_CRY)
5214     {
5215       genModbits (left, right, result, ic);
5216       goto release;
5217     }
5218
5219   /* if both are of size == 1 */
5220   if (AOP_SIZE (left) == 1 &&
5221       AOP_SIZE (right) == 1)
5222     {
5223       genModOneByte (left, right, result, ic);
5224       goto release;
5225     }
5226
5227   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5228           /* use the ds390 ARITHMETIC accel UNIT */
5229           genModTwoByte (left, right, result, ic);
5230           return ;
5231   }
5232
5233   /* should have been converted to function call */
5234   assert (0);
5235
5236 release:
5237   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5238   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5239   freeAsmop (result, NULL, ic, TRUE);
5240 }
5241
5242 /*-----------------------------------------------------------------*/
5243 /* genIfxJump :- will create a jump depending on the ifx           */
5244 /*-----------------------------------------------------------------*/
5245 static void
5246 genIfxJump (iCode * ic, char *jval)
5247 {
5248   symbol *jlbl;
5249   symbol *tlbl = newiTempLabel (NULL);
5250   char *inst;
5251
5252   D (emitcode (";", "genIfxJump ");
5253     );
5254
5255   /* if true label then we jump if condition
5256      supplied is true */
5257   if (IC_TRUE (ic))
5258     {
5259       jlbl = IC_TRUE (ic);
5260       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5261                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5262     }
5263   else
5264     {
5265       /* false label is present */
5266       jlbl = IC_FALSE (ic);
5267       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5268                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5269     }
5270   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5271     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5272   else
5273     emitcode (inst, "!tlabel", tlbl->key + 100);
5274   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5275   emitcode ("", "!tlabeldef", tlbl->key + 100);
5276
5277   /* mark the icode as generated */
5278   ic->generated = 1;
5279 }
5280
5281 /*-----------------------------------------------------------------*/
5282 /* genCmp :- greater or less than comparison                       */
5283 /*-----------------------------------------------------------------*/
5284 static void
5285 genCmp (operand * left, operand * right,
5286         iCode * ic, iCode * ifx, int sign)
5287 {
5288   int size, offset = 0;
5289   unsigned long lit = 0L;
5290   operand *result;
5291
5292   D (emitcode (";", "genCmp");
5293     );
5294
5295   result = IC_RESULT (ic);
5296
5297   /* if left & right are bit variables */
5298   if (AOP_TYPE (left) == AOP_CRY &&
5299       AOP_TYPE (right) == AOP_CRY)
5300     {
5301       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5302       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5303     }
5304   else
5305     {
5306       /* subtract right from left if at the
5307          end the carry flag is set then we know that
5308          left is greater than right */
5309       size = max (AOP_SIZE (left), AOP_SIZE (right));
5310
5311       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5312       if ((size == 1) && !sign &&
5313           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5314         {
5315           symbol *lbl = newiTempLabel (NULL);
5316           emitcode ("cjne", "%s,%s,!tlabel",
5317                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5318                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5319                     lbl->key + 100);
5320           emitcode ("", "!tlabeldef", lbl->key + 100);
5321         }
5322       else
5323         {
5324           if (AOP_TYPE (right) == AOP_LIT)
5325             {
5326               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5327               /* optimize if(x < 0) or if(x >= 0) */
5328               if (lit == 0L)
5329                 {
5330                   if (!sign)
5331                     {
5332                       CLRC;
5333                     }
5334                   else
5335                     {
5336                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5337
5338                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340
5341                       aopOp (result, ic, FALSE, FALSE);
5342
5343                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5344                         {
5345                           freeAsmop (result, NULL, ic, TRUE);
5346                           genIfxJump (ifx, "acc.7");
5347                           return;
5348                         }
5349                       else
5350                         {
5351                           emitcode ("rlc", "a");
5352                         }
5353                       goto release_freedLR;
5354                     }
5355                   goto release;
5356                 }
5357             }
5358           CLRC;
5359           while (size--)
5360             {
5361               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5362               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5363               //emitcode (";", "genCmp #2");
5364               if (sign && (size == 0))
5365                 {
5366                     //emitcode (";", "genCmp #3");
5367                   emitcode ("xrl", "a,#!constbyte",0x80);
5368                   if (AOP_TYPE (right) == AOP_LIT)
5369                     {
5370                       unsigned long lit = (unsigned long)
5371                       floatFromVal (AOP (right)->aopu.aop_lit);
5372                       //emitcode (";", "genCmp #3.1");
5373                       emitcode ("subb", "a,#!constbyte",
5374                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5375                     }
5376                   else
5377                     {
5378                       //emitcode (";", "genCmp #3.2");
5379                       if (AOP_NEEDSACC (right))
5380                         {
5381                           emitcode ("push", "acc");
5382                         }
5383                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5384                                                        FALSE, FALSE, FALSE));
5385                       emitcode ("xrl", "b,#!constbyte",0x80);
5386                       if (AOP_NEEDSACC (right))
5387                         {
5388                           emitcode ("pop", "acc");
5389                         }
5390                       emitcode ("subb", "a,b");
5391                     }
5392                 }
5393               else
5394                 {
5395                   const char *s;
5396
5397                   //emitcode (";", "genCmp #4");
5398                   if (AOP_NEEDSACC (right))
5399                     {
5400                       /* Yuck!! */
5401                       //emitcode (";", "genCmp #4.1");
5402                       emitcode ("xch", "a, b");
5403                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5404                       emitcode ("xch", "a, b");
5405                       s = "b";
5406                     }
5407                   else
5408                     {
5409                       //emitcode (";", "genCmp #4.2");
5410                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5411                     }
5412
5413                   emitcode ("subb", "a,%s", s);
5414                 }
5415             }
5416         }
5417     }
5418
5419 release:
5420 /* Don't need the left & right operands any more; do need the result. */
5421   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423
5424   aopOp (result, ic, FALSE, FALSE);
5425
5426 release_freedLR:
5427
5428   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5429     {
5430       outBitC (result);
5431     }
5432   else
5433     {
5434       /* if the result is used in the next
5435          ifx conditional branch then generate
5436          code a little differently */
5437       if (ifx)
5438         {
5439           genIfxJump (ifx, "c");
5440         }
5441       else
5442         {
5443           outBitC (result);
5444         }
5445       /* leave the result in acc */
5446     }
5447   freeAsmop (result, NULL, ic, TRUE);
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genCmpGt :- greater than comparison                             */
5452 /*-----------------------------------------------------------------*/
5453 static void
5454 genCmpGt (iCode * ic, iCode * ifx)
5455 {
5456   operand *left, *right;
5457   sym_link *letype, *retype;
5458   int sign;
5459
5460   D (emitcode (";", "genCmpGt ");
5461     );
5462
5463   left = IC_LEFT (ic);
5464   right = IC_RIGHT (ic);
5465
5466   letype = getSpec (operandType (left));
5467   retype = getSpec (operandType (right));
5468   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5469
5470   /* assign the left & right amsops */
5471   AOP_OP_2 (ic);
5472
5473   genCmp (right, left, ic, ifx, sign);
5474 }
5475
5476 /*-----------------------------------------------------------------*/
5477 /* genCmpLt - less than comparisons                                */
5478 /*-----------------------------------------------------------------*/
5479 static void
5480 genCmpLt (iCode * ic, iCode * ifx)
5481 {
5482   operand *left, *right;
5483   sym_link *letype, *retype;
5484   int sign;
5485
5486   D (emitcode (";", "genCmpLt "););
5487
5488   left = IC_LEFT (ic);
5489   right = IC_RIGHT (ic);
5490
5491   letype = getSpec (operandType (left));
5492   retype = getSpec (operandType (right));
5493   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5494
5495   /* assign the left & right amsops */
5496   AOP_OP_2 (ic);
5497
5498   genCmp (left, right, ic, ifx, sign);
5499 }
5500
5501 /*-----------------------------------------------------------------*/
5502 /* gencjneshort - compare and jump if not equal                    */
5503 /*-----------------------------------------------------------------*/
5504 static void
5505 gencjneshort (operand * left, operand * right, symbol * lbl)
5506 {
5507   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5508   int offset = 0;
5509   unsigned long lit = 0L;
5510
5511   D (emitcode (";", "gencjneshort");
5512     );
5513
5514   /* if the left side is a literal or
5515      if the right is in a pointer register and left
5516      is not */
5517   if ((AOP_TYPE (left) == AOP_LIT) ||
5518       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5519     {
5520       operand *t = right;
5521       right = left;
5522       left = t;
5523     }
5524
5525   if (AOP_TYPE (right) == AOP_LIT)
5526     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5527
5528   if (opIsGptr (left) || opIsGptr (right))
5529     {
5530       /* We are comparing a generic pointer to something.
5531        * Exclude the generic type byte from the comparison.
5532        */
5533       size--;
5534       D (emitcode (";", "cjneshort: generic ptr special case.");
5535         )
5536     }
5537
5538
5539   /* if the right side is a literal then anything goes */
5540   if (AOP_TYPE (right) == AOP_LIT &&
5541       AOP_TYPE (left) != AOP_DIR)
5542     {
5543       while (size--)
5544         {
5545           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5546           MOVA (l);
5547           emitcode ("cjne", "a,%s,!tlabel",
5548                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5549                     lbl->key + 100);
5550           offset++;
5551         }
5552     }
5553
5554   /* if the right side is in a register or in direct space or
5555      if the left is a pointer register & right is not */
5556   else if (AOP_TYPE (right) == AOP_REG ||
5557            AOP_TYPE (right) == AOP_DIR ||
5558            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5559            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5560     {
5561       while (size--)
5562         {
5563           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5564           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5565               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5566             emitcode ("jnz", "!tlabel", lbl->key + 100);
5567           else
5568             emitcode ("cjne", "a,%s,!tlabel",
5569                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5570                       lbl->key + 100);
5571           offset++;
5572         }
5573     }
5574   else
5575     {
5576       /* right is a pointer reg need both a & b */
5577       while (size--)
5578         {
5579           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5580           if (strcmp (l, "b"))
5581             emitcode ("mov", "b,%s", l);
5582           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5583           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5584           offset++;
5585         }
5586     }
5587 }
5588
5589 /*-----------------------------------------------------------------*/
5590 /* gencjne - compare and jump if not equal                         */
5591 /*-----------------------------------------------------------------*/
5592 static void
5593 gencjne (operand * left, operand * right, symbol * lbl)
5594 {
5595   symbol *tlbl = newiTempLabel (NULL);
5596
5597   D (emitcode (";", "gencjne");
5598     );
5599
5600   gencjneshort (left, right, lbl);
5601
5602   emitcode ("mov", "a,%s", one);
5603   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5604   emitcode ("", "!tlabeldef", lbl->key + 100);
5605   emitcode ("clr", "a");
5606   emitcode ("", "!tlabeldef", tlbl->key + 100);
5607 }
5608
5609 /*-----------------------------------------------------------------*/
5610 /* genCmpEq - generates code for equal to                          */
5611 /*-----------------------------------------------------------------*/
5612 static void
5613 genCmpEq (iCode * ic, iCode * ifx)
5614 {
5615   operand *left, *right, *result;
5616
5617   D (emitcode (";", "genCmpEq ");
5618     );
5619
5620   AOP_OP_2 (ic);
5621   AOP_SET_LOCALS (ic);
5622
5623   /* if literal, literal on the right or
5624      if the right is in a pointer register and left
5625      is not */
5626   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5627       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5628     {
5629       operand *t = IC_RIGHT (ic);
5630       IC_RIGHT (ic) = IC_LEFT (ic);
5631       IC_LEFT (ic) = t;
5632     }
5633
5634   if (ifx &&                    /* !AOP_SIZE(result) */
5635       OP_SYMBOL (result) &&
5636       OP_SYMBOL (result)->regType == REG_CND)
5637     {
5638       symbol *tlbl;
5639       /* if they are both bit variables */
5640       if (AOP_TYPE (left) == AOP_CRY &&
5641           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5642         {
5643           if (AOP_TYPE (right) == AOP_LIT)
5644             {
5645               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5646               if (lit == 0L)
5647                 {
5648                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5649                   emitcode ("cpl", "c");
5650                 }
5651               else if (lit == 1L)
5652                 {
5653                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5654                 }
5655               else
5656                 {
5657                   emitcode ("clr", "c");
5658                 }
5659               /* AOP_TYPE(right) == AOP_CRY */
5660             }
5661           else
5662             {
5663               symbol *lbl = newiTempLabel (NULL);
5664               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5665               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5666               emitcode ("cpl", "c");
5667               emitcode ("", "!tlabeldef", (lbl->key + 100));
5668             }
5669           /* if true label then we jump if condition
5670              supplied is true */
5671           tlbl = newiTempLabel (NULL);
5672           if (IC_TRUE (ifx))
5673             {
5674               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5675               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5676             }
5677           else
5678             {
5679               emitcode ("jc", "!tlabel", tlbl->key + 100);
5680               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5681             }
5682           emitcode ("", "!tlabeldef", tlbl->key + 100);
5683         }
5684       else
5685         {
5686           tlbl = newiTempLabel (NULL);
5687           gencjneshort (left, right, tlbl);
5688           if (IC_TRUE (ifx))
5689             {
5690               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5691               emitcode ("", "!tlabeldef", tlbl->key + 100);
5692             }
5693           else
5694             {
5695               symbol *lbl = newiTempLabel (NULL);
5696               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5697               emitcode ("", "!tlabeldef", tlbl->key + 100);
5698               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5699               emitcode ("", "!tlabeldef", lbl->key + 100);
5700             }
5701         }
5702       /* mark the icode as generated */
5703       ifx->generated = 1;
5704
5705       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5706       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5707       return;
5708     }
5709
5710   /* if they are both bit variables */
5711   if (AOP_TYPE (left) == AOP_CRY &&
5712       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5713     {
5714       if (AOP_TYPE (right) == AOP_LIT)
5715         {
5716           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5717           if (lit == 0L)
5718             {
5719               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5720               emitcode ("cpl", "c");
5721             }
5722           else if (lit == 1L)
5723             {
5724               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5725             }
5726           else
5727             {
5728               emitcode ("clr", "c");
5729             }
5730           /* AOP_TYPE(right) == AOP_CRY */
5731         }
5732       else
5733         {
5734           symbol *lbl = newiTempLabel (NULL);
5735           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5736           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5737           emitcode ("cpl", "c");
5738           emitcode ("", "!tlabeldef", (lbl->key + 100));
5739         }
5740
5741       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5742       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5743
5744       aopOp (result, ic, TRUE, FALSE);
5745
5746       /* c = 1 if egal */
5747       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5748         {
5749           outBitC (result);
5750           goto release;
5751         }
5752       if (ifx)
5753         {
5754           genIfxJump (ifx, "c");
5755           goto release;
5756         }
5757       /* if the result is used in an arithmetic operation
5758          then put the result in place */
5759       outBitC (result);
5760     }
5761   else
5762     {
5763       gencjne (left, right, newiTempLabel (NULL));
5764
5765       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5767
5768       aopOp (result, ic, TRUE, FALSE);
5769
5770       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5771         {
5772           aopPut (AOP (result), "a", 0);
5773           goto release;
5774         }
5775       if (ifx)
5776         {
5777           genIfxJump (ifx, "a");
5778           goto release;
5779         }
5780       /* if the result is used in an arithmetic operation
5781          then put the result in place */
5782       if (AOP_TYPE (result) != AOP_CRY)
5783         outAcc (result);
5784       /* leave the result in acc */
5785     }
5786
5787 release:
5788   freeAsmop (result, NULL, ic, TRUE);
5789 }
5790
5791 /*-----------------------------------------------------------------*/
5792 /* ifxForOp - returns the icode containing the ifx for operand     */
5793 /*-----------------------------------------------------------------*/
5794 static iCode *
5795 ifxForOp (operand * op, iCode * ic)
5796 {
5797   /* if true symbol then needs to be assigned */
5798   if (IS_TRUE_SYMOP (op))
5799     return NULL;
5800
5801   /* if this has register type condition and
5802      the next instruction is ifx with the same operand
5803      and live to of the operand is upto the ifx only then */
5804   if (ic->next &&
5805       ic->next->op == IFX &&
5806       IC_COND (ic->next)->key == op->key &&
5807       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5808     return ic->next;
5809
5810   return NULL;
5811 }
5812 /*-----------------------------------------------------------------*/
5813 /* hasInc - operand is incremented before any other use            */
5814 /*-----------------------------------------------------------------*/
5815 static iCode *
5816 hasInc (operand *op, iCode *ic, int osize)
5817 {
5818   sym_link *type = operandType(op);
5819   sym_link *retype = getSpec (type);
5820   iCode *lic = ic->next;
5821   int isize ;
5822   
5823   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5824   if (!IS_SYMOP(op)) return NULL;
5825
5826   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5827   if (IS_AGGREGATE(type->next)) return NULL;
5828   if (osize != (isize = getSize(type->next))) return NULL;
5829
5830   while (lic) {
5831       /* if operand of the form op = op + <sizeof *op> */
5832       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5833           isOperandEqual(IC_RESULT(lic),op) && 
5834           isOperandLiteral(IC_RIGHT(lic)) &&
5835           operandLitValue(IC_RIGHT(lic)) == isize) {
5836           return lic;
5837       }
5838       /* if the operand used or deffed */
5839       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5840           return NULL;
5841       }
5842       /* if GOTO or IFX */
5843       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5844       lic = lic->next;
5845   }
5846   return NULL;
5847 }
5848
5849 /*-----------------------------------------------------------------*/
5850 /* genAndOp - for && operation                                     */
5851 /*-----------------------------------------------------------------*/
5852 static void
5853 genAndOp (iCode * ic)
5854 {
5855   operand *left, *right, *result;
5856   symbol *tlbl;
5857
5858   D (emitcode (";", "genAndOp "););
5859
5860   /* note here that && operations that are in an
5861      if statement are taken away by backPatchLabels
5862      only those used in arthmetic operations remain */
5863   AOP_OP_2 (ic);
5864   AOP_SET_LOCALS (ic);
5865
5866   /* if both are bit variables */
5867   if (AOP_TYPE (left) == AOP_CRY &&
5868       AOP_TYPE (right) == AOP_CRY)
5869     {
5870       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5871       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5872       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5873       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874   
5875       aopOp (result,ic,FALSE, FALSE);
5876       outBitC (result);
5877     }
5878   else
5879     {
5880       tlbl = newiTempLabel (NULL);
5881       toBoolean (left);
5882       emitcode ("jz", "!tlabel", tlbl->key + 100);
5883       toBoolean (right);
5884       emitcode ("", "!tlabeldef", tlbl->key + 100);
5885       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5887   
5888       aopOp (result,ic,FALSE, FALSE);
5889       outBitAcc (result);
5890     }
5891     freeAsmop (result, NULL, ic, TRUE);
5892 }
5893
5894
5895 /*-----------------------------------------------------------------*/
5896 /* genOrOp - for || operation                                      */
5897 /*-----------------------------------------------------------------*/
5898 static void
5899 genOrOp (iCode * ic)
5900 {
5901   operand *left, *right, *result;
5902   symbol *tlbl;
5903
5904   D (emitcode (";", "genOrOp "););
5905
5906   /* note here that || operations that are in an
5907      if statement are taken away by backPatchLabels
5908      only those used in arthmetic operations remain */
5909   AOP_OP_2 (ic);
5910   AOP_SET_LOCALS (ic);
5911
5912   /* if both are bit variables */
5913   if (AOP_TYPE (left) == AOP_CRY &&
5914       AOP_TYPE (right) == AOP_CRY)
5915     {
5916       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5917       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5918       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5919       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5920   
5921       aopOp (result,ic,FALSE, FALSE);
5922       
5923       outBitC (result);
5924     }
5925   else
5926     {
5927       tlbl = newiTempLabel (NULL);
5928       toBoolean (left);
5929       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5930       toBoolean (right);
5931       emitcode ("", "!tlabeldef", tlbl->key + 100);
5932       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5933       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934   
5935       aopOp (result,ic,FALSE, FALSE);
5936       
5937       outBitAcc (result);
5938     }
5939
5940   freeAsmop (result, NULL, ic, TRUE);
5941 }
5942
5943 /*-----------------------------------------------------------------*/
5944 /* isLiteralBit - test if lit == 2^n                               */
5945 /*-----------------------------------------------------------------*/
5946 static int
5947 isLiteralBit (unsigned long lit)
5948 {
5949   unsigned long pw[32] =
5950   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5951    0x100L, 0x200L, 0x400L, 0x800L,
5952    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5953    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5954    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5955    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5956    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5957   int idx;
5958
5959   for (idx = 0; idx < 32; idx++)
5960     if (lit == pw[idx])
5961       return idx + 1;
5962   return 0;
5963 }
5964
5965 /*-----------------------------------------------------------------*/
5966 /* continueIfTrue -                                                */
5967 /*-----------------------------------------------------------------*/
5968 static void
5969 continueIfTrue (iCode * ic)
5970 {
5971   if (IC_TRUE (ic))
5972     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5973   ic->generated = 1;
5974 }
5975
5976 /*-----------------------------------------------------------------*/
5977 /* jmpIfTrue -                                                     */
5978 /*-----------------------------------------------------------------*/
5979 static void
5980 jumpIfTrue (iCode * ic)
5981 {
5982   if (!IC_TRUE (ic))
5983     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5984   ic->generated = 1;
5985 }
5986
5987 /*-----------------------------------------------------------------*/
5988 /* jmpTrueOrFalse -                                                */
5989 /*-----------------------------------------------------------------*/
5990 static void
5991 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5992 {
5993   // ugly but optimized by peephole
5994   if (IC_TRUE (ic))
5995     {
5996       symbol *nlbl = newiTempLabel (NULL);
5997       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5998       emitcode ("", "!tlabeldef", tlbl->key + 100);
5999       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6000       emitcode ("", "!tlabeldef", nlbl->key + 100);
6001     }
6002   else
6003     {
6004       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6005       emitcode ("", "!tlabeldef", tlbl->key + 100);
6006     }
6007   ic->generated = 1;
6008 }
6009
6010 // Generate code to perform a bit-wise logic operation
6011 // on two operands in far space (assumed to already have been 
6012 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6013 // in far space. This requires pushing the result on the stack
6014 // then popping it into the result.
6015 static void
6016 genFarFarLogicOp(iCode *ic, char *logicOp)
6017 {
6018       int size, resultSize, compSize;
6019       int offset = 0;
6020       
6021       TR_AP("#5");
6022       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6023       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6024                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6025       
6026       _startLazyDPSEvaluation();
6027       for (size = compSize; (size--); offset++)
6028       {
6029           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
6030           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6031           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
6032           
6033           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6034           emitcode ("push", "acc");
6035       }
6036       _endLazyDPSEvaluation();
6037      
6038       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6039       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6040       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6041      
6042       resultSize = AOP_SIZE(IC_RESULT(ic));
6043
6044       ADJUST_PUSHED_RESULT(compSize, resultSize);
6045
6046       _startLazyDPSEvaluation();
6047       while (compSize--)
6048       {
6049           emitcode ("pop", "acc");
6050           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6051       }
6052       _endLazyDPSEvaluation();
6053       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6054 }
6055
6056
6057 /*-----------------------------------------------------------------*/
6058 /* genAnd  - code for and                                          */
6059 /*-----------------------------------------------------------------*/
6060 static void
6061 genAnd (iCode * ic, iCode * ifx)
6062 {
6063   operand *left, *right, *result;
6064   int size, offset = 0;
6065   unsigned long lit = 0L;
6066   int bytelit = 0;
6067   char buffer[10];
6068   bool pushResult;
6069
6070   D (emitcode (";", "genAnd "););
6071
6072   AOP_OP_3_NOFATAL (ic, pushResult);
6073   AOP_SET_LOCALS (ic);
6074
6075   if (pushResult)
6076   {
6077       genFarFarLogicOp(ic, "anl");
6078       return;
6079   }  
6080
6081 #ifdef DEBUG_TYPE
6082   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6083             AOP_TYPE (result),
6084             AOP_TYPE (left), AOP_TYPE (right));
6085   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6086             AOP_SIZE (result),
6087             AOP_SIZE (left), AOP_SIZE (right));
6088 #endif
6089
6090   /* if left is a literal & right is not then exchange them */
6091   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6092 #ifdef LOGIC_OPS_BROKEN      
6093     ||  AOP_NEEDSACC (left)
6094 #endif
6095     )
6096     {
6097       operand *tmp = right;
6098       right = left;
6099       left = tmp;
6100     }
6101
6102   /* if result = right then exchange them */
6103   if (sameRegs (AOP (result), AOP (right)))
6104     {
6105       operand *tmp = right;
6106       right = left;
6107       left = tmp;
6108     }
6109
6110   /* if right is bit then exchange them */
6111   if (AOP_TYPE (right) == AOP_CRY &&
6112       AOP_TYPE (left) != AOP_CRY)
6113     {
6114       operand *tmp = right;
6115       right = left;
6116       left = tmp;
6117     }
6118   if (AOP_TYPE (right) == AOP_LIT)
6119     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6120
6121   size = AOP_SIZE (result);
6122
6123   // if(bit & yy)
6124   // result = bit & yy;
6125   if (AOP_TYPE (left) == AOP_CRY)
6126     {
6127       // c = bit & literal;
6128       if (AOP_TYPE (right) == AOP_LIT)
6129         {
6130           if (lit & 1)
6131             {
6132               if (size && sameRegs (AOP (result), AOP (left)))
6133                 // no change
6134                 goto release;
6135               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6136             }
6137           else
6138             {
6139               // bit(result) = 0;
6140               if (size && (AOP_TYPE (result) == AOP_CRY))
6141                 {
6142                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6143                   goto release;
6144                 }
6145               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6146                 {
6147                   jumpIfTrue (ifx);
6148                   goto release;
6149                 }
6150               emitcode ("clr", "c");
6151             }
6152         }
6153       else
6154         {
6155           if (AOP_TYPE (right) == AOP_CRY)
6156             {
6157               // c = bit & bit;
6158               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6159               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6160             }
6161           else
6162             {
6163               // c = bit & val;
6164               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6165               // c = lsb
6166               emitcode ("rrc", "a");
6167               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6168             }
6169         }
6170       // bit = c
6171       // val = c
6172       if (size)
6173         outBitC (result);
6174       // if(bit & ...)
6175       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6176         genIfxJump (ifx, "c");
6177       goto release;
6178     }
6179
6180   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6181   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6182   if ((AOP_TYPE (right) == AOP_LIT) &&
6183       (AOP_TYPE (result) == AOP_CRY) &&
6184       (AOP_TYPE (left) != AOP_CRY))
6185     {
6186       int posbit = isLiteralBit (lit);
6187       /* left &  2^n */
6188       if (posbit)
6189         {
6190           posbit--;
6191           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6192           // bit = left & 2^n
6193           if (size)
6194             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6195           // if(left &  2^n)
6196           else
6197             {
6198               if (ifx)
6199                 {
6200                   sprintf (buffer, "acc.%d", posbit & 0x07);
6201                   genIfxJump (ifx, buffer);
6202                 }
6203               else 
6204                   {
6205                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6206                   }
6207               goto release;
6208             }
6209         }
6210       else
6211         {
6212           symbol *tlbl = newiTempLabel (NULL);
6213           int sizel = AOP_SIZE (left);
6214           if (size)
6215             emitcode ("setb", "c");
6216           while (sizel--)
6217             {
6218               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6219                 {
6220                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6221                   // byte ==  2^n ?
6222                   if ((posbit = isLiteralBit (bytelit)) != 0)
6223                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6224                   else
6225                     {
6226                       if (bytelit != 0x0FFL)
6227                         emitcode ("anl", "a,%s",
6228                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6229                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6230                     }
6231                 }
6232               offset++;
6233             }
6234           // bit = left & literal
6235           if (size)
6236             {
6237               emitcode ("clr", "c");
6238               emitcode ("", "!tlabeldef", tlbl->key + 100);
6239             }
6240           // if(left & literal)
6241           else
6242             {
6243               if (ifx)
6244                 jmpTrueOrFalse (ifx, tlbl);
6245               goto release;
6246             }
6247         }
6248       outBitC (result);
6249       goto release;
6250     }
6251
6252   /* if left is same as result */
6253   if (sameRegs (AOP (result), AOP (left)))
6254     {
6255       for (; size--; offset++)
6256         {
6257           if (AOP_TYPE (right) == AOP_LIT)
6258             {
6259               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6260                 continue;
6261               else if (bytelit == 0)
6262                 aopPut (AOP (result), zero, offset);
6263               else if (IS_AOP_PREG (result))
6264                 {
6265                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6266                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6267                   aopPut (AOP (result), "a", offset);
6268                 }
6269               else
6270                 emitcode ("anl", "%s,%s",
6271                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6272                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6273             }
6274           else
6275             {
6276               if (AOP_TYPE (left) == AOP_ACC)
6277                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6278               else
6279                 {
6280                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6281                   if (IS_AOP_PREG (result))
6282                     {
6283                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6284                       aopPut (AOP (result), "a", offset);
6285
6286                     }
6287                   else
6288                     emitcode ("anl", "%s,a",
6289                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6290                 }
6291             }
6292         }
6293     }
6294   else
6295     {
6296       // left & result in different registers
6297       if (AOP_TYPE (result) == AOP_CRY)
6298         {
6299           // result = bit
6300           // if(size), result in bit
6301           // if(!size && ifx), conditional oper: if(left & right)
6302           symbol *tlbl = newiTempLabel (NULL);
6303           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6304           if (size)
6305             emitcode ("setb", "c");
6306           while (sizer--)
6307             {
6308               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6309                 emitcode ("anl", "a,%s",
6310                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6311               } else {
6312                 if (AOP_TYPE(left)==AOP_ACC) {
6313                   emitcode("mov", "b,a");
6314                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6315                   emitcode("anl", "a,b");
6316                 }else {
6317                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6318                   emitcode ("anl", "a,%s",
6319                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6320                 }
6321               }
6322               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6323               offset++;
6324             }
6325           if (size)
6326             {
6327               CLRC;
6328               emitcode ("", "!tlabeldef", tlbl->key + 100);
6329               outBitC (result);
6330             }
6331           else if (ifx)
6332             jmpTrueOrFalse (ifx, tlbl);
6333         }
6334       else
6335         {
6336           for (; (size--); offset++)
6337             {
6338               // normal case
6339               // result = left & right
6340               if (AOP_TYPE (right) == AOP_LIT)
6341                 {
6342                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6343                     {
6344                       aopPut (AOP (result),
6345                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6346                               offset);
6347                       continue;
6348                     }
6349                   else if (bytelit == 0)
6350                     {
6351                       aopPut (AOP (result), zero, offset);
6352                       continue;
6353                     }
6354                   D (emitcode (";", "better literal AND."););
6355                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6356                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6357                                                     FALSE, FALSE, FALSE));
6358
6359                 }
6360               else
6361                 {
6362                   // faster than result <- left, anl result,right
6363                   // and better if result is SFR
6364                   if (AOP_TYPE (left) == AOP_ACC)
6365                     {
6366                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6367                                                        FALSE, FALSE, FALSE));
6368                     }
6369                   else
6370                     {
6371                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6372                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6373                       {
6374                           emitcode("mov", "b,a");
6375                           rOp = "b";
6376                       }
6377                         
6378                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6379                       emitcode ("anl", "a,%s", rOp);
6380                     }                   
6381                 }
6382               aopPut (AOP (result), "a", offset);
6383             }
6384         }
6385     }
6386
6387 release:
6388   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6389   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6390   freeAsmop (result, NULL, ic, TRUE);
6391 }
6392
6393
6394 /*-----------------------------------------------------------------*/
6395 /* genOr  - code for or                                            */
6396 /*-----------------------------------------------------------------*/
6397 static void
6398 genOr (iCode * ic, iCode * ifx)
6399 {
6400   operand *left, *right, *result;
6401   int size, offset = 0;
6402   unsigned long lit = 0L;
6403   bool     pushResult;
6404
6405   D (emitcode (";", "genOr "););
6406
6407   AOP_OP_3_NOFATAL (ic, pushResult);
6408   AOP_SET_LOCALS (ic);
6409
6410   if (pushResult)
6411   {
6412       genFarFarLogicOp(ic, "orl");
6413       return;
6414   }
6415
6416
6417 #ifdef DEBUG_TYPE
6418   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6419             AOP_TYPE (result),
6420             AOP_TYPE (left), AOP_TYPE (right));
6421   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6422             AOP_SIZE (result),
6423             AOP_SIZE (left), AOP_SIZE (right));
6424 #endif
6425
6426   /* if left is a literal & right is not then exchange them */
6427   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6428 #ifdef LOGIC_OPS_BROKEN
6429    || AOP_NEEDSACC (left) // I think this is a net loss now.
6430 #endif      
6431       )
6432     {
6433       operand *tmp = right;
6434       right = left;
6435       left = tmp;
6436     }
6437
6438   /* if result = right then exchange them */
6439   if (sameRegs (AOP (result), AOP (right)))
6440     {
6441       operand *tmp = right;
6442       right = left;
6443       left = tmp;
6444     }
6445
6446   /* if right is bit then exchange them */
6447   if (AOP_TYPE (right) == AOP_CRY &&
6448       AOP_TYPE (left) != AOP_CRY)
6449     {
6450       operand *tmp = right;
6451       right = left;
6452       left = tmp;
6453     }
6454   if (AOP_TYPE (right) == AOP_LIT)
6455     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6456
6457   size = AOP_SIZE (result);
6458
6459   // if(bit | yy)
6460   // xx = bit | yy;
6461   if (AOP_TYPE (left) == AOP_CRY)
6462     {
6463       if (AOP_TYPE (right) == AOP_LIT)
6464         {
6465           // c = bit & literal;
6466           if (lit)
6467             {
6468               // lit != 0 => result = 1
6469               if (AOP_TYPE (result) == AOP_CRY)
6470                 {
6471                   if (size)
6472                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6473                   else if (ifx)
6474                     continueIfTrue (ifx);
6475                   goto release;
6476                 }
6477               emitcode ("setb", "c");
6478             }
6479           else
6480             {
6481               // lit == 0 => result = left
6482               if (size && sameRegs (AOP (result), AOP (left)))
6483                 goto release;
6484               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6485             }
6486         }
6487       else
6488         {
6489           if (AOP_TYPE (right) == AOP_CRY)
6490             {
6491               // c = bit | bit;
6492               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6493               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6494             }
6495           else
6496             {
6497               // c = bit | val;
6498               symbol *tlbl = newiTempLabel (NULL);
6499               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6500                 emitcode ("setb", "c");
6501               emitcode ("jb", "%s,!tlabel",
6502                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6503               toBoolean (right);
6504               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6505               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6506                 {
6507                   jmpTrueOrFalse (ifx, tlbl);
6508                   goto release;
6509                 }
6510               else
6511                 {
6512                   CLRC;
6513                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6514                 }
6515             }
6516         }
6517       // bit = c
6518       // val = c
6519       if (size)
6520         outBitC (result);
6521       // if(bit | ...)
6522       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6523         genIfxJump (ifx, "c");
6524       goto release;
6525     }
6526
6527   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6528   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6529   if ((AOP_TYPE (right) == AOP_LIT) &&
6530       (AOP_TYPE (result) == AOP_CRY) &&
6531       (AOP_TYPE (left) != AOP_CRY))
6532     {
6533       if (lit)
6534         {
6535           // result = 1
6536           if (size)
6537             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6538           else
6539             continueIfTrue (ifx);
6540           goto release;
6541         }
6542       else
6543         {
6544           // lit = 0, result = boolean(left)
6545           if (size)
6546             emitcode ("setb", "c");
6547           toBoolean (right);
6548           if (size)
6549             {
6550               symbol *tlbl = newiTempLabel (NULL);
6551               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6552               CLRC;
6553               emitcode ("", "!tlabeldef", tlbl->key + 100);
6554             }
6555           else
6556             {
6557               genIfxJump (ifx, "a");
6558               goto release;
6559             }
6560         }
6561       outBitC (result);
6562       goto release;
6563     }
6564
6565   /* if left is same as result */
6566   if (sameRegs (AOP (result), AOP (left)))
6567     {
6568       for (; size--; offset++)
6569         {
6570           if (AOP_TYPE (right) == AOP_LIT)
6571             {
6572               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6573                 {
6574                   continue;
6575                 }
6576               else
6577                 {
6578                   if (IS_AOP_PREG (left))
6579                     {
6580                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6581                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6582                       aopPut (AOP (result), "a", offset);
6583                     }
6584                   else
6585                     {
6586                       emitcode ("orl", "%s,%s",
6587                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6588                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6589                     }
6590                 }
6591             }
6592           else
6593             {
6594               if (AOP_TYPE (left) == AOP_ACC)
6595                 {
6596                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6597                 }
6598               else
6599                 {
6600                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6601                   if (IS_AOP_PREG (left))
6602                     {
6603                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6604                       aopPut (AOP (result), "a", offset);
6605                     }
6606                   else
6607                     {
6608                       emitcode ("orl", "%s,a",
6609                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6610                     }
6611                 }
6612             }
6613         }
6614     }
6615   else
6616     {
6617       // left & result in different registers
6618       if (AOP_TYPE (result) == AOP_CRY)
6619         {
6620           // result = bit
6621           // if(size), result in bit
6622           // if(!size && ifx), conditional oper: if(left | right)
6623           symbol *tlbl = newiTempLabel (NULL);
6624           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6625           if (size)
6626             emitcode ("setb", "c");
6627           while (sizer--)
6628             {
6629               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6630                 emitcode ("orl", "a,%s",
6631                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6632               } else {
6633                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6634                 emitcode ("orl", "a,%s",
6635                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6636               }
6637               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6638               offset++;
6639             }
6640           if (size)
6641             {
6642               CLRC;
6643               emitcode ("", "!tlabeldef", tlbl->key + 100);
6644               outBitC (result);
6645             }
6646           else if (ifx)
6647             jmpTrueOrFalse (ifx, tlbl);
6648         }
6649       else
6650         {
6651             _startLazyDPSEvaluation();
6652           for (; (size--); offset++)
6653             {
6654               // normal case
6655               // result = left & right
6656               if (AOP_TYPE (right) == AOP_LIT)
6657                 {
6658                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6659                     {
6660                       aopPut (AOP (result),
6661                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6662                               offset);
6663                       continue;
6664                     }
6665                   D (emitcode (";", "better literal OR."););
6666                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6667                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6668                                                     FALSE, FALSE, FALSE));
6669
6670                 }
6671               else
6672                 {
6673                   // faster than result <- left, anl result,right
6674                   // and better if result is SFR
6675                   if (AOP_TYPE (left) == AOP_ACC)
6676                     {
6677                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6678                                                        FALSE, FALSE, FALSE));
6679                     }
6680                   else
6681                     {
6682                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6683                         
6684                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6685                       {
6686                           emitcode("mov", "b,a");
6687                           rOp = "b";
6688                       }
6689                         
6690                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6691                       emitcode ("orl", "a,%s", rOp);
6692                     }
6693                 }
6694               aopPut (AOP (result), "a", offset);
6695             }
6696             _endLazyDPSEvaluation();
6697         }
6698     }
6699
6700 release:
6701   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6702   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6703   freeAsmop (result, NULL, ic, TRUE);
6704 }
6705
6706 /*-----------------------------------------------------------------*/
6707 /* genXor - code for xclusive or                                   */
6708 /*-----------------------------------------------------------------*/
6709 static void
6710 genXor (iCode * ic, iCode * ifx)
6711 {
6712   operand *left, *right, *result;
6713   int size, offset = 0;
6714   unsigned long lit = 0L;
6715   bool pushResult;
6716
6717   D (emitcode (";", "genXor "););
6718
6719   AOP_OP_3_NOFATAL (ic, pushResult);
6720   AOP_SET_LOCALS (ic);
6721
6722   if (pushResult)
6723   {
6724       genFarFarLogicOp(ic, "xrl");
6725       return;
6726   }  
6727
6728 #ifdef DEBUG_TYPE
6729   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6730             AOP_TYPE (result),
6731             AOP_TYPE (left), AOP_TYPE (right));
6732   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6733             AOP_SIZE (result),
6734             AOP_SIZE (left), AOP_SIZE (right));
6735 #endif
6736
6737   /* if left is a literal & right is not ||
6738      if left needs acc & right does not */
6739   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6740 #ifdef LOGIC_OPS_BROKEN      
6741       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6742 #endif
6743      )
6744     {
6745       operand *tmp = right;
6746       right = left;
6747       left = tmp;
6748     }
6749
6750   /* if result = right then exchange them */
6751   if (sameRegs (AOP (result), AOP (right)))
6752     {
6753       operand *tmp = right;
6754       right = left;
6755       left = tmp;
6756     }
6757
6758   /* if right is bit then exchange them */
6759   if (AOP_TYPE (right) == AOP_CRY &&
6760       AOP_TYPE (left) != AOP_CRY)
6761     {
6762       operand *tmp = right;
6763       right = left;
6764       left = tmp;
6765     }
6766   if (AOP_TYPE (right) == AOP_LIT)
6767     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6768
6769   size = AOP_SIZE (result);
6770
6771   // if(bit ^ yy)
6772   // xx = bit ^ yy;
6773   if (AOP_TYPE (left) == AOP_CRY)
6774     {
6775       if (AOP_TYPE (right) == AOP_LIT)
6776         {
6777           // c = bit & literal;
6778           if (lit >> 1)
6779             {
6780               // lit>>1  != 0 => result = 1
6781               if (AOP_TYPE (result) == AOP_CRY)
6782                 {
6783                   if (size)
6784                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6785                   else if (ifx)
6786                     continueIfTrue (ifx);
6787                   goto release;
6788                 }
6789               emitcode ("setb", "c");
6790             }
6791           else
6792             {
6793               // lit == (0 or 1)
6794               if (lit == 0)
6795                 {
6796                   // lit == 0, result = left
6797                   if (size && sameRegs (AOP (result), AOP (left)))
6798                     goto release;
6799                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6800                 }
6801               else
6802                 {
6803                   // lit == 1, result = not(left)
6804                   if (size && sameRegs (AOP (result), AOP (left)))
6805                     {
6806                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6807                       goto release;
6808                     }
6809                   else
6810                     {
6811                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6812                       emitcode ("cpl", "c");
6813                     }
6814                 }
6815             }
6816
6817         }
6818       else
6819         {
6820           // right != literal
6821           symbol *tlbl = newiTempLabel (NULL);
6822           if (AOP_TYPE (right) == AOP_CRY)
6823             {
6824               // c = bit ^ bit;
6825               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6826             }
6827           else
6828             {
6829               int sizer = AOP_SIZE (right);
6830               // c = bit ^ val
6831               // if val>>1 != 0, result = 1
6832               emitcode ("setb", "c");
6833               while (sizer)
6834                 {
6835                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6836                   if (sizer == 1)
6837                     // test the msb of the lsb
6838                     emitcode ("anl", "a,#!constbyte",0xfe);
6839                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6840                   sizer--;
6841                 }
6842               // val = (0,1)
6843               emitcode ("rrc", "a");
6844             }
6845           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6846           emitcode ("cpl", "c");
6847           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6848         }
6849       // bit = c
6850       // val = c
6851       if (size)
6852         outBitC (result);
6853       // if(bit | ...)
6854       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6855         genIfxJump (ifx, "c");
6856       goto release;
6857     }
6858
6859   if (sameRegs (AOP (result), AOP (left)))
6860     {
6861       /* if left is same as result */
6862       for (; size--; offset++)
6863         {
6864           if (AOP_TYPE (right) == AOP_LIT)
6865             {
6866               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6867                 continue;
6868               else if (IS_AOP_PREG (left))
6869                 {
6870                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6871                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6872                   aopPut (AOP (result), "a", offset);
6873                 }
6874               else
6875                 emitcode ("xrl", "%s,%s",
6876                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6877                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6878             }
6879           else
6880             {
6881               if (AOP_TYPE (left) == AOP_ACC)
6882                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6883               else
6884                 {
6885                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6886                   if (IS_AOP_PREG (left))
6887                     {
6888                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6889                       aopPut (AOP (result), "a", offset);
6890                     }
6891                   else
6892                     emitcode ("xrl", "%s,a",
6893                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6894                 }
6895             }
6896         }
6897     }
6898   else
6899     {
6900       // left & result in different registers
6901       if (AOP_TYPE (result) == AOP_CRY)
6902         {
6903           // result = bit
6904           // if(size), result in bit
6905           // if(!size && ifx), conditional oper: if(left ^ right)
6906           symbol *tlbl = newiTempLabel (NULL);
6907           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6908                   
6909           if (size)
6910             emitcode ("setb", "c");
6911           while (sizer--)
6912             {
6913               if ((AOP_TYPE (right) == AOP_LIT) &&
6914                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6915                 {
6916                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6917                 }
6918               else
6919                 {
6920                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6921                     emitcode ("xrl", "a,%s",
6922                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6923                   } else {
6924                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6925                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6926                       {
6927                           emitcode("mov", "b,a");
6928                           rOp = "b";
6929                       }
6930                         
6931                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6932                       emitcode ("xrl", "a,%s", rOp);                  
6933                   }
6934                 }
6935               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6936               offset++;
6937             }
6938           if (size)
6939             {
6940               CLRC;
6941               emitcode ("", "!tlabeldef", tlbl->key + 100);
6942               outBitC (result);
6943             }
6944           else if (ifx)
6945             jmpTrueOrFalse (ifx, tlbl);
6946         }
6947       else
6948         {
6949         for (; (size--); offset++)
6950           {
6951             // normal case
6952             // result = left & right
6953             if (AOP_TYPE (right) == AOP_LIT)
6954               {
6955                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6956                   {
6957                     aopPut (AOP (result),
6958                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6959                             offset);
6960                     continue;
6961                   }
6962                 D (emitcode (";", "better literal XOR."););
6963                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6964                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6965                                                   FALSE, FALSE, FALSE));
6966               }
6967             else
6968               {
6969                 // faster than result <- left, anl result,right
6970                 // and better if result is SFR
6971                 if (AOP_TYPE (left) == AOP_ACC)
6972                   {
6973                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6974                                                      FALSE, FALSE, FALSE));
6975                   }
6976                 else
6977                   {
6978                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6979                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6980                       {
6981                           emitcode("mov", "b,a");
6982                           rOp = "b";
6983                       }
6984                         
6985                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6986                       emitcode ("xrl", "a,%s", rOp);
6987                   }
6988               }
6989             aopPut (AOP (result), "a", offset);
6990           }
6991         }
6992         
6993     }
6994
6995 release:
6996   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6998   freeAsmop (result, NULL, ic, TRUE);
6999 }
7000
7001 /*-----------------------------------------------------------------*/
7002 /* genInline - write the inline code out                           */
7003 /*-----------------------------------------------------------------*/
7004 static void
7005 genInline (iCode * ic)
7006 {
7007   char *buffer, *bp, *bp1;
7008
7009   D (emitcode (";", "genInline ");
7010     );
7011
7012   _G.inLine += (!options.asmpeep);
7013
7014   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7015   strcpy (buffer, IC_INLINE (ic));
7016
7017   /* emit each line as a code */
7018   while (*bp)
7019     {
7020       if (*bp == '\n')
7021         {
7022           *bp++ = '\0';
7023           emitcode (bp1, "");
7024           bp1 = bp;
7025         }
7026       else
7027         {
7028           if (*bp == ':')
7029             {
7030               bp++;
7031               *bp = '\0';
7032               bp++;
7033               emitcode (bp1, "");
7034               bp1 = bp;
7035             }
7036           else
7037             bp++;
7038         }
7039     }
7040   if (bp1 != bp)
7041     emitcode (bp1, "");
7042   /*     emitcode("",buffer); */
7043   _G.inLine -= (!options.asmpeep);
7044 }
7045
7046 /*-----------------------------------------------------------------*/
7047 /* genRRC - rotate right with carry                                */
7048 /*-----------------------------------------------------------------*/
7049 static void
7050 genRRC (iCode * ic)
7051 {
7052   operand *left, *result;
7053   int size, offset = 0;
7054   char *l;
7055
7056   D (emitcode (";", "genRRC ");
7057     );
7058
7059   /* rotate right with carry */
7060   left = IC_LEFT (ic);
7061   result = IC_RESULT (ic);
7062   aopOp (left, ic, FALSE, FALSE);
7063   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7064
7065   /* move it to the result */
7066   size = AOP_SIZE (result);
7067   offset = size - 1;
7068   CLRC;
7069
7070   _startLazyDPSEvaluation ();
7071   while (size--)
7072     {
7073       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7074       MOVA (l);
7075       emitcode ("rrc", "a");
7076       if (AOP_SIZE (result) > 1)
7077         aopPut (AOP (result), "a", offset--);
7078     }
7079   _endLazyDPSEvaluation ();
7080
7081   /* now we need to put the carry into the
7082      highest order byte of the result */
7083   if (AOP_SIZE (result) > 1)
7084     {
7085       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
7086       MOVA (l);
7087     }
7088   emitcode ("mov", "acc.7,c");
7089   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7090   freeAsmop (left, NULL, ic, TRUE);
7091   freeAsmop (result, NULL, ic, TRUE);
7092 }
7093
7094 /*-----------------------------------------------------------------*/
7095 /* genRLC - generate code for rotate left with carry               */
7096 /*-----------------------------------------------------------------*/
7097 static void
7098 genRLC (iCode * ic)
7099 {
7100   operand *left, *result;
7101   int size, offset = 0;
7102   char *l;
7103
7104   D (emitcode (";", "genRLC ");
7105     );
7106
7107   /* rotate right with carry */
7108   left = IC_LEFT (ic);
7109   result = IC_RESULT (ic);
7110   aopOp (left, ic, FALSE, FALSE);
7111   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7112
7113   /* move it to the result */
7114   size = AOP_SIZE (result);
7115   offset = 0;
7116   if (size--)
7117     {
7118       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7119       MOVA (l);
7120       emitcode ("add", "a,acc");
7121       if (AOP_SIZE (result) > 1)
7122         {
7123           aopPut (AOP (result), "a", offset++);
7124         }
7125
7126       _startLazyDPSEvaluation ();
7127       while (size--)
7128         {
7129           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7130           MOVA (l);
7131           emitcode ("rlc", "a");
7132           if (AOP_SIZE (result) > 1)
7133             aopPut (AOP (result), "a", offset++);
7134         }
7135       _endLazyDPSEvaluation ();
7136     }
7137   /* now we need to put the carry into the
7138      highest order byte of the result */
7139   if (AOP_SIZE (result) > 1)
7140     {
7141       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7142       MOVA (l);
7143     }
7144   emitcode ("mov", "acc.0,c");
7145   aopPut (AOP (result), "a", 0);
7146   freeAsmop (left, NULL, ic, TRUE);
7147   freeAsmop (result, NULL, ic, TRUE);
7148 }
7149
7150 /*-----------------------------------------------------------------*/
7151 /* genGetHbit - generates code get highest order bit               */
7152 /*-----------------------------------------------------------------*/
7153 static void
7154 genGetHbit (iCode * ic)
7155 {
7156   operand *left, *result;
7157   left = IC_LEFT (ic);
7158   result = IC_RESULT (ic);
7159   aopOp (left, ic, FALSE, FALSE);
7160   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7161
7162   D (emitcode (";", "genGetHbit ");
7163     );
7164
7165   /* get the highest order byte into a */
7166   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7167   if (AOP_TYPE (result) == AOP_CRY)
7168     {
7169       emitcode ("rlc", "a");
7170       outBitC (result);
7171     }
7172   else
7173     {
7174       emitcode ("rl", "a");
7175       emitcode ("anl", "a,#1");
7176       outAcc (result);
7177     }
7178
7179
7180   freeAsmop (left, NULL, ic, TRUE);
7181   freeAsmop (result, NULL, ic, TRUE);
7182 }
7183
7184 /*-----------------------------------------------------------------*/
7185 /* AccRol - rotate left accumulator by known count                 */
7186 /*-----------------------------------------------------------------*/
7187 static void
7188 AccRol (int shCount)
7189 {
7190   shCount &= 0x0007;            // shCount : 0..7
7191
7192   switch (shCount)
7193     {
7194     case 0:
7195       break;
7196     case 1:
7197       emitcode ("rl", "a");
7198       break;
7199     case 2:
7200       emitcode ("rl", "a");
7201       emitcode ("rl", "a");
7202       break;
7203     case 3:
7204       emitcode ("swap", "a");
7205       emitcode ("rr", "a");
7206       break;
7207     case 4:
7208       emitcode ("swap", "a");
7209       break;
7210     case 5:
7211       emitcode ("swap", "a");
7212       emitcode ("rl", "a");
7213       break;
7214     case 6:
7215       emitcode ("rr", "a");
7216       emitcode ("rr", "a");
7217       break;
7218     case 7:
7219       emitcode ("rr", "a");
7220       break;
7221     }
7222 }
7223
7224 /*-----------------------------------------------------------------*/
7225 /* AccLsh - left shift accumulator by known count                  */
7226 /*-----------------------------------------------------------------*/
7227 static void
7228 AccLsh (int shCount)
7229 {
7230   if (shCount != 0)
7231     {
7232       if (shCount == 1)
7233         emitcode ("add", "a,acc");
7234       else if (shCount == 2)
7235         {
7236           emitcode ("add", "a,acc");
7237           emitcode ("add", "a,acc");
7238         }
7239       else
7240         {
7241           /* rotate left accumulator */
7242           AccRol (shCount);
7243           /* and kill the lower order bits */
7244           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7245         }
7246     }
7247 }
7248
7249 /*-----------------------------------------------------------------*/
7250 /* AccRsh - right shift accumulator by known count                 */
7251 /*-----------------------------------------------------------------*/
7252 static void
7253 AccRsh (int shCount)
7254 {
7255   if (shCount != 0)
7256     {
7257       if (shCount == 1)
7258         {
7259           CLRC;
7260           emitcode ("rrc", "a");
7261         }
7262       else
7263         {
7264           /* rotate right accumulator */
7265           AccRol (8 - shCount);
7266           /* and kill the higher order bits */
7267           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7268         }
7269     }
7270 }
7271
7272 #ifdef BETTER_LITERAL_SHIFT
7273 /*-----------------------------------------------------------------*/
7274 /* AccSRsh - signed right shift accumulator by known count                 */
7275 /*-----------------------------------------------------------------*/
7276 static void
7277 AccSRsh (int shCount)
7278 {
7279   symbol *tlbl;
7280   if (shCount != 0)
7281     {
7282       if (shCount == 1)
7283         {
7284           emitcode ("mov", "c,acc.7");
7285           emitcode ("rrc", "a");
7286         }
7287       else if (shCount == 2)
7288         {
7289           emitcode ("mov", "c,acc.7");
7290           emitcode ("rrc", "a");
7291           emitcode ("mov", "c,acc.7");
7292           emitcode ("rrc", "a");
7293         }
7294       else
7295         {
7296           tlbl = newiTempLabel (NULL);
7297           /* rotate right accumulator */
7298           AccRol (8 - shCount);
7299           /* and kill the higher order bits */
7300           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7301           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7302           emitcode ("orl", "a,#!constbyte",
7303                     (unsigned char) ~SRMask[shCount]);
7304           emitcode ("", "!tlabeldef", tlbl->key + 100);
7305         }
7306     }
7307 }
7308 #endif
7309
7310 #ifdef BETTER_LITERAL_SHIFT
7311 /*-----------------------------------------------------------------*/
7312 /* shiftR1Left2Result - shift right one byte from left to result   */
7313 /*-----------------------------------------------------------------*/
7314 static void
7315 shiftR1Left2Result (operand * left, int offl,
7316                     operand * result, int offr,
7317                     int shCount, int sign)
7318 {
7319   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7320   /* shift right accumulator */
7321   if (sign)
7322     AccSRsh (shCount);
7323   else
7324     AccRsh (shCount);
7325   aopPut (AOP (result), "a", offr);
7326 }
7327 #endif
7328
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* shiftL1Left2Result - shift left one byte from left to result    */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 shiftL1Left2Result (operand * left, int offl,
7335                     operand * result, int offr, int shCount)
7336 {
7337   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7338   /* shift left accumulator */
7339   AccLsh (shCount);
7340   aopPut (AOP (result), "a", offr);
7341 }
7342 #endif
7343
7344 #ifdef BETTER_LITERAL_SHIFT
7345 /*-----------------------------------------------------------------*/
7346 /* movLeft2Result - move byte from left to result                  */
7347 /*-----------------------------------------------------------------*/
7348 static void
7349 movLeft2Result (operand * left, int offl,
7350                 operand * result, int offr, int sign)
7351 {
7352   char *l;
7353   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7354   {
7355       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7356
7357       if (*l == '@' && (IS_AOP_PREG (result)))
7358       {
7359           emitcode ("mov", "a,%s", l);
7360           aopPut (AOP (result), "a", offr);
7361       }
7362       else
7363       {
7364           if (!sign)
7365           {
7366             aopPut (AOP (result), l, offr);
7367           }
7368           else
7369             {
7370               /* MSB sign in acc.7 ! */
7371               if (getDataSize (left) == offl + 1)
7372                 {
7373                   emitcode ("mov", "a,%s", l);
7374                   aopPut (AOP (result), "a", offr);
7375                 }
7376             }
7377       }
7378   }
7379 }
7380 #endif
7381
7382 #ifdef BETTER_LITERAL_SHIFT
7383 /*-----------------------------------------------------------------*/
7384 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7385 /*-----------------------------------------------------------------*/
7386 static void
7387 AccAXRrl1 (char *x)
7388 {
7389   emitcode ("rrc", "a");
7390   emitcode ("xch", "a,%s", x);
7391   emitcode ("rrc", "a");
7392   emitcode ("xch", "a,%s", x);
7393 }
7394 #endif
7395
7396 #ifdef BETTER_LITERAL_SHIFT
7397 //REMOVE ME!!!
7398 /*-----------------------------------------------------------------*/
7399 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7400 /*-----------------------------------------------------------------*/
7401 static void
7402 AccAXLrl1 (char *x)
7403 {
7404   emitcode ("xch", "a,%s", x);
7405   emitcode ("rlc", "a");
7406   emitcode ("xch", "a,%s", x);
7407   emitcode ("rlc", "a");
7408 }
7409 #endif
7410
7411 #ifdef BETTER_LITERAL_SHIFT
7412 /*-----------------------------------------------------------------*/
7413 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7414 /*-----------------------------------------------------------------*/
7415 static void
7416 AccAXLsh1 (char *x)
7417 {
7418   emitcode ("xch", "a,%s", x);
7419   emitcode ("add", "a,acc");
7420   emitcode ("xch", "a,%s", x);
7421   emitcode ("rlc", "a");
7422 }
7423 #endif
7424
7425 #ifdef BETTER_LITERAL_SHIFT
7426 /*-----------------------------------------------------------------*/
7427 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7428 /*-----------------------------------------------------------------*/
7429 static void
7430 AccAXLsh (char *x, int shCount)
7431 {
7432   switch (shCount)
7433     {
7434     case 0:
7435       break;
7436     case 1:
7437       AccAXLsh1 (x);
7438       break;
7439     case 2:
7440       AccAXLsh1 (x);
7441       AccAXLsh1 (x);
7442       break;
7443     case 3:
7444     case 4:
7445     case 5:                     // AAAAABBB:CCCCCDDD
7446
7447       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7448
7449       emitcode ("anl", "a,#!constbyte",
7450                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7451
7452       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7453
7454       AccRol (shCount);         // DDDCCCCC:BBB00000
7455
7456       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7457
7458       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7459
7460       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7461
7462       emitcode ("anl", "a,#!constbyte",
7463                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7464
7465       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7466
7467       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7468
7469       break;
7470     case 6:                     // AAAAAABB:CCCCCCDD
7471       emitcode ("anl", "a,#!constbyte",
7472                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7473       emitcode ("mov", "c,acc.0");      // c = B
7474       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7475 #if 0
7476       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7477       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7478 #else
7479       emitcode("rrc","a"); 
7480       emitcode("xch","a,%s", x); 
7481       emitcode("rrc","a"); 
7482       emitcode("mov","c,acc.0"); //<< get correct bit 
7483       emitcode("xch","a,%s", x); 
7484
7485       emitcode("rrc","a"); 
7486       emitcode("xch","a,%s", x); 
7487       emitcode("rrc","a"); 
7488       emitcode("xch","a,%s", x); 
7489 #endif
7490       break;
7491     case 7:                     // a:x <<= 7
7492
7493       emitcode ("anl", "a,#!constbyte",
7494                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7495
7496       emitcode ("mov", "c,acc.0");      // c = B
7497
7498       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7499
7500       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7501
7502       break;
7503     default:
7504       break;
7505     }
7506 }
7507 #endif
7508
7509 #ifdef BETTER_LITERAL_SHIFT
7510 //REMOVE ME!!!
7511 /*-----------------------------------------------------------------*/
7512 /* AccAXRsh - right shift a:x known count (0..7)                   */
7513 /*-----------------------------------------------------------------*/
7514 static void
7515 AccAXRsh (char *x, int shCount)
7516 {
7517   switch (shCount)
7518     {
7519     case 0:
7520       break;
7521     case 1:
7522       CLRC;
7523       AccAXRrl1 (x);            // 0->a:x
7524
7525       break;
7526     case 2:
7527       CLRC;
7528       AccAXRrl1 (x);            // 0->a:x
7529
7530       CLRC;
7531       AccAXRrl1 (x);            // 0->a:x
7532
7533       break;
7534     case 3:
7535     case 4:
7536     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7537
7538       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7539
7540       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7541
7542       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7543
7544       emitcode ("anl", "a,#!constbyte",
7545                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7546
7547       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7548
7549       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7550
7551       emitcode ("anl", "a,#!constbyte",
7552                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7553
7554       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7555
7556       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7557
7558       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7559
7560       break;
7561     case 6:                     // AABBBBBB:CCDDDDDD
7562
7563       emitcode ("mov", "c,acc.7");
7564       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7565
7566       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7567
7568       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7569
7570       emitcode ("anl", "a,#!constbyte",
7571                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7572
7573       break;
7574     case 7:                     // ABBBBBBB:CDDDDDDD
7575
7576       emitcode ("mov", "c,acc.7");      // c = A
7577
7578       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7579
7580       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7581
7582       emitcode ("anl", "a,#!constbyte",
7583                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7584
7585       break;
7586     default:
7587       break;
7588     }
7589 }
7590 #endif
7591
7592 #ifdef BETTER_LITERAL_SHIFT
7593 /*-----------------------------------------------------------------*/
7594 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7595 /*-----------------------------------------------------------------*/
7596 static void
7597 AccAXRshS (char *x, int shCount)
7598 {
7599   symbol *tlbl;
7600   switch (shCount)
7601     {
7602     case 0:
7603       break;
7604     case 1:
7605       emitcode ("mov", "c,acc.7");
7606       AccAXRrl1 (x);            // s->a:x
7607
7608       break;
7609     case 2:
7610       emitcode ("mov", "c,acc.7");
7611       AccAXRrl1 (x);            // s->a:x
7612
7613       emitcode ("mov", "c,acc.7");
7614       AccAXRrl1 (x);            // s->a:x
7615
7616       break;
7617     case 3:
7618     case 4:
7619     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7620
7621       tlbl = newiTempLabel (NULL);
7622       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7623
7624       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7625
7626       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7627
7628       emitcode ("anl", "a,#!constbyte",
7629                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7630
7631       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7632
7633       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7634
7635       emitcode ("anl", "a,#!constbyte",
7636                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7637
7638       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7639
7640       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7641
7642       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7643
7644       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7645       emitcode ("orl", "a,#!constbyte",
7646                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7647
7648       emitcode ("", "!tlabeldef", tlbl->key + 100);
7649       break;                    // SSSSAAAA:BBBCCCCC
7650
7651     case 6:                     // AABBBBBB:CCDDDDDD
7652
7653       tlbl = newiTempLabel (NULL);
7654       emitcode ("mov", "c,acc.7");
7655       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7656
7657       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7658
7659       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7660
7661       emitcode ("anl", "a,#!constbyte",
7662                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7663
7664       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7665       emitcode ("orl", "a,#!constbyte",
7666                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7667
7668       emitcode ("", "!tlabeldef", tlbl->key + 100);
7669       break;
7670     case 7:                     // ABBBBBBB:CDDDDDDD
7671
7672       tlbl = newiTempLabel (NULL);
7673       emitcode ("mov", "c,acc.7");      // c = A
7674
7675       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7676
7677       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7678
7679       emitcode ("anl", "a,#!constbyte",
7680                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7681
7682       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7683       emitcode ("orl", "a,#!constbyte",
7684                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7685
7686       emitcode ("", "!tlabeldef", tlbl->key + 100);
7687       break;
7688     default:
7689       break;
7690     }
7691 }
7692 #endif
7693
7694 #ifdef BETTER_LITERAL_SHIFT
7695 static void
7696 _loadLeftIntoAx(char    **lsb, 
7697                 operand *left, 
7698                 operand *result,
7699                 int     offl,
7700                 int     offr)
7701 {
7702   // Get the initial value from left into a pair of registers.
7703   // MSB must be in A, LSB can be any register.
7704   //
7705   // If the result is held in registers, it is an optimization
7706   // if the LSB can be held in the register which will hold the,
7707   // result LSB since this saves us from having to copy it into
7708   // the result following AccAXLsh.
7709   //
7710   // If the result is addressed indirectly, this is not a gain.
7711   if (AOP_NEEDSACC(result))
7712   {
7713        char *leftByte;
7714        
7715        _startLazyDPSEvaluation();
7716       if (AOP_TYPE(left) == AOP_DPTR2)
7717        {
7718            // Get MSB in A.
7719            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7720            // get LSB in DP2_RESULT_REG.
7721            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7722            assert(!strcmp(leftByte, DP2_RESULT_REG));
7723        }
7724        else
7725        {
7726            // get LSB into DP2_RESULT_REG
7727            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7728            if (strcmp(leftByte, DP2_RESULT_REG))
7729            {
7730                TR_AP("#7");
7731                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7732            }
7733            // And MSB in A.
7734            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7735            assert(strcmp(leftByte, DP2_RESULT_REG));
7736            MOVA(leftByte);
7737        }
7738        _endLazyDPSEvaluation();
7739        *lsb = DP2_RESULT_REG;
7740   }
7741   else
7742   {
7743       if (sameRegs (AOP (result), AOP (left)) &&
7744         ((offl + MSB16) == offr))
7745       {
7746           /* don't crash result[offr] */
7747           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7748           emitcode ("xch", "a,%s", 
7749                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7750       }
7751       else
7752       {
7753           movLeft2Result (left, offl, result, offr, 0);
7754           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7755       }
7756       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7757       assert(strcmp(*lsb,"a"));      
7758   }
7759 }
7760
7761 static void
7762 _storeAxResults(char    *lsb,
7763                 operand *result,
7764                 int     offr)
7765 {
7766   _startLazyDPSEvaluation();
7767   if (AOP_NEEDSACC(result))
7768   {
7769       /* We have to explicitly update the result LSB.
7770        */
7771       emitcode("xch","a,%s", lsb);
7772       aopPut(AOP(result), "a", offr);
7773       emitcode("mov","a,%s", lsb);
7774   }
7775   if (getDataSize (result) > 1)
7776   {
7777       aopPut (AOP (result), "a", offr + MSB16);
7778   }
7779   _endLazyDPSEvaluation();
7780 }
7781
7782 /*-----------------------------------------------------------------*/
7783 /* shiftL2Left2Result - shift left two bytes from left to result   */
7784 /*-----------------------------------------------------------------*/
7785 static void
7786 shiftL2Left2Result (operand * left, int offl,
7787                     operand * result, int offr, int shCount)
7788 {
7789   char *lsb;
7790
7791   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7792   
7793   AccAXLsh (lsb, shCount);
7794   
7795   _storeAxResults(lsb, result, offr);
7796 }
7797 #endif
7798
7799 #ifdef BETTER_LITERAL_SHIFT
7800 /*-----------------------------------------------------------------*/
7801 /* shiftR2Left2Result - shift right two bytes from left to result  */
7802 /*-----------------------------------------------------------------*/
7803 static void
7804 shiftR2Left2Result (operand * left, int offl,
7805                     operand * result, int offr,
7806                     int shCount, int sign)
7807 {
7808   char *lsb;
7809   
7810   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7811   
7812   /* a:x >> shCount (x = lsb(result)) */
7813   if (sign)
7814   {
7815      AccAXRshS(lsb, shCount);
7816   }
7817   else
7818   {
7819     AccAXRsh(lsb, shCount);
7820   }
7821   
7822   _storeAxResults(lsb, result, offr);
7823 }
7824 #endif
7825
7826 #if 0
7827 //REMOVE ME!!!
7828 /*-----------------------------------------------------------------*/
7829 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7830 /*-----------------------------------------------------------------*/
7831 static void
7832 shiftLLeftOrResult (operand * left, int offl,
7833                     operand * result, int offr, int shCount)
7834 {
7835   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7836   /* shift left accumulator */
7837   AccLsh (shCount);
7838   /* or with result */
7839   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7840   /* back to result */
7841   aopPut (AOP (result), "a", offr);
7842 }
7843 #endif
7844
7845 #if 0
7846 //REMOVE ME!!!
7847 /*-----------------------------------------------------------------*/
7848 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7849 /*-----------------------------------------------------------------*/
7850 static void
7851 shiftRLeftOrResult (operand * left, int offl,
7852                     operand * result, int offr, int shCount)
7853 {
7854   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7855   /* shift right accumulator */
7856   AccRsh (shCount);
7857   /* or with result */
7858   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7859   /* back to result */
7860   aopPut (AOP (result), "a", offr);
7861 }
7862 #endif
7863
7864 #ifdef BETTER_LITERAL_SHIFT
7865 /*-----------------------------------------------------------------*/
7866 /* genlshOne - left shift a one byte quantity by known count       */
7867 /*-----------------------------------------------------------------*/
7868 static void
7869 genlshOne (operand * result, operand * left, int shCount)
7870 {
7871   D (emitcode (";", "genlshOne "););
7872   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7873 }
7874 #endif
7875
7876 #ifdef BETTER_LITERAL_SHIFT
7877 /*-----------------------------------------------------------------*/
7878 /* genlshTwo - left shift two bytes by known amount != 0           */
7879 /*-----------------------------------------------------------------*/
7880 static void
7881 genlshTwo (operand * result, operand * left, int shCount)
7882 {
7883   int size;
7884
7885   D (emitcode (";", "genlshTwo "););
7886
7887   size = getDataSize (result);
7888
7889   /* if shCount >= 8 */
7890   if (shCount >= 8)
7891   {
7892       shCount -= 8;
7893
7894       _startLazyDPSEvaluation();
7895
7896       if (size > 1)
7897         {
7898           if (shCount)
7899           {
7900             _endLazyDPSEvaluation();
7901             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7902             aopPut (AOP (result), zero, LSB);       
7903           }
7904           else
7905           {
7906             movLeft2Result (left, LSB, result, MSB16, 0);
7907             aopPut (AOP (result), zero, LSB);
7908             _endLazyDPSEvaluation();
7909           }
7910         }
7911         else
7912         {
7913           aopPut (AOP (result), zero, LSB);
7914           _endLazyDPSEvaluation();
7915         }
7916   }
7917
7918   /*  1 <= shCount <= 7 */
7919   else
7920     {
7921       if (size == 1)
7922       {
7923         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7924       }
7925       else
7926       {
7927         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7928       }
7929     }
7930 }
7931 #endif
7932
7933 #if 0
7934 //REMOVE ME!!!
7935 /*-----------------------------------------------------------------*/
7936 /* shiftLLong - shift left one long from left to result            */
7937 /* offl = LSB or MSB16                                             */
7938 /*-----------------------------------------------------------------*/
7939 static void
7940 shiftLLong (operand * left, operand * result, int offr)
7941 {
7942   char *l;
7943   int size = AOP_SIZE (result);
7944
7945   if (size >= LSB + offr)
7946     {
7947       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7948       MOVA (l);
7949       emitcode ("add", "a,acc");
7950       if (sameRegs (AOP (left), AOP (result)) &&
7951           size >= MSB16 + offr && offr != LSB)
7952         emitcode ("xch", "a,%s",
7953                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7954       else
7955         aopPut (AOP (result), "a", LSB + offr);
7956     }
7957
7958   if (size >= MSB16 + offr)
7959     {
7960       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7961         {
7962           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7963           MOVA (l);
7964         }
7965       emitcode ("rlc", "a");
7966       if (sameRegs (AOP (left), AOP (result)) &&
7967           size >= MSB24 + offr && offr != LSB)
7968         emitcode ("xch", "a,%s",
7969                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7970       else
7971         aopPut (AOP (result), "a", MSB16 + offr);
7972     }
7973
7974   if (size >= MSB24 + offr)
7975     {
7976       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7977         {
7978           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7979           MOVA (l);
7980         }
7981       emitcode ("rlc", "a");
7982       if (sameRegs (AOP (left), AOP (result)) &&
7983           size >= MSB32 + offr && offr != LSB)
7984         emitcode ("xch", "a,%s",
7985                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7986       else
7987         aopPut (AOP (result), "a", MSB24 + offr);
7988     }
7989
7990   if (size > MSB32 + offr)
7991     {
7992       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7993         {
7994           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7995           MOVA (l);
7996         }
7997       emitcode ("rlc", "a");
7998       aopPut (AOP (result), "a", MSB32 + offr);
7999     }
8000   if (offr != LSB)
8001     aopPut (AOP (result), zero, LSB);
8002 }
8003 #endif
8004
8005 #if 0
8006 //REMOVE ME!!!
8007 /*-----------------------------------------------------------------*/
8008 /* genlshFour - shift four byte by a known amount != 0             */
8009 /*-----------------------------------------------------------------*/
8010 static void
8011 genlshFour (operand * result, operand * left, int shCount)
8012 {
8013   int size;
8014
8015   D (emitcode (";", "genlshFour ");
8016     );
8017
8018   size = AOP_SIZE (result);
8019
8020   /* if shifting more that 3 bytes */
8021   if (shCount >= 24)
8022     {
8023       shCount -= 24;
8024       if (shCount)
8025         /* lowest order of left goes to the highest
8026            order of the destination */
8027         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8028       else
8029         movLeft2Result (left, LSB, result, MSB32, 0);
8030       aopPut (AOP (result), zero, LSB);
8031       aopPut (AOP (result), zero, MSB16);
8032       aopPut (AOP (result), zero, MSB24);
8033       return;
8034     }
8035
8036   /* more than two bytes */
8037   else if (shCount >= 16)
8038     {
8039       /* lower order two bytes goes to higher order two bytes */
8040       shCount -= 16;
8041       /* if some more remaining */
8042       if (shCount)
8043         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8044       else
8045         {
8046           movLeft2Result (left, MSB16, result, MSB32, 0);
8047           movLeft2Result (left, LSB, result, MSB24, 0);
8048         }
8049       aopPut (AOP (result), zero, MSB16);
8050       aopPut (AOP (result), zero, LSB);
8051       return;
8052     }
8053
8054   /* if more than 1 byte */
8055   else if (shCount >= 8)
8056     {
8057       /* lower order three bytes goes to higher order  three bytes */
8058       shCount -= 8;
8059       if (size == 2)
8060         {
8061           if (shCount)
8062             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8063           else
8064             movLeft2Result (left, LSB, result, MSB16, 0);
8065         }
8066       else
8067         {                       /* size = 4 */
8068           if (shCount == 0)
8069             {
8070               movLeft2Result (left, MSB24, result, MSB32, 0);
8071               movLeft2Result (left, MSB16, result, MSB24, 0);
8072               movLeft2Result (left, LSB, result, MSB16, 0);
8073               aopPut (AOP (result), zero, LSB);
8074             }
8075           else if (shCount == 1)
8076             shiftLLong (left, result, MSB16);
8077           else
8078             {
8079               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8080               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8081               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8082               aopPut (AOP (result), zero, LSB);
8083             }
8084         }
8085     }
8086
8087   /* 1 <= shCount <= 7 */
8088   else if (shCount <= 2)
8089     {
8090       shiftLLong (left, result, LSB);
8091       if (shCount == 2)
8092         shiftLLong (result, result, LSB);
8093     }
8094   /* 3 <= shCount <= 7, optimize */
8095   else
8096     {
8097       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8098       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8099       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8100     }
8101 }
8102 #endif
8103
8104 #ifdef BETTER_LITERAL_SHIFT
8105 /*-----------------------------------------------------------------*/
8106 /* genLeftShiftLiteral - left shifting by known count              */
8107 /*-----------------------------------------------------------------*/
8108 static bool
8109 genLeftShiftLiteral (operand * left,
8110                      operand * right,
8111                      operand * result,
8112                      iCode * ic)
8113 {
8114   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8115   int size;
8116
8117   size = getSize (operandType (result));
8118
8119   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8120
8121   /* We only handle certain easy cases so far. */
8122   if ((shCount != 0)
8123    && (shCount < (size * 8))
8124    && (size != 1)
8125    && (size != 2))
8126   {
8127       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8128       return FALSE;
8129   }
8130
8131   freeAsmop (right, NULL, ic, TRUE);
8132
8133   aopOp(left, ic, FALSE, FALSE);
8134   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8135
8136 #if 0 // debug spew
8137   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8138   {
8139         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8140         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8141         {
8142            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8143         }
8144   }
8145   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8146   {
8147         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8148         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8149         {
8150            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8151         }       
8152   }  
8153 #endif
8154   
8155 #if VIEW_SIZE
8156   emitcode ("; shift left ", "result %d, left %d", size,
8157             AOP_SIZE (left));
8158 #endif
8159
8160   /* I suppose that the left size >= result size */
8161   if (shCount == 0)
8162   {
8163         _startLazyDPSEvaluation();
8164         while (size--)
8165         {
8166           movLeft2Result (left, size, result, size, 0);
8167         }
8168         _endLazyDPSEvaluation();
8169   }
8170   else if (shCount >= (size * 8))
8171   {
8172     _startLazyDPSEvaluation();
8173     while (size--)
8174     {
8175       aopPut (AOP (result), zero, size);
8176     }
8177     _endLazyDPSEvaluation();
8178   }
8179   else
8180   {
8181       switch (size)
8182         {
8183         case 1:
8184           genlshOne (result, left, shCount);
8185           break;
8186
8187         case 2:
8188           genlshTwo (result, left, shCount);
8189           break;
8190 #if 0
8191         case 4:
8192           genlshFour (result, left, shCount);
8193           break;
8194 #endif
8195         default:
8196           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8197           break;
8198         }
8199     }
8200   freeAsmop (left, NULL, ic, TRUE);
8201   freeAsmop (result, NULL, ic, TRUE);
8202   return TRUE;
8203 }
8204 #endif
8205
8206 /*-----------------------------------------------------------------*/
8207 /* genLeftShift - generates code for left shifting                 */
8208 /*-----------------------------------------------------------------*/
8209 static void
8210 genLeftShift (iCode * ic)
8211 {
8212   operand *left, *right, *result;
8213   int size, offset;
8214   char *l;
8215   symbol *tlbl, *tlbl1;
8216
8217   D (emitcode (";", "genLeftShift "););
8218
8219   right = IC_RIGHT (ic);
8220   left = IC_LEFT (ic);
8221   result = IC_RESULT (ic);
8222
8223   aopOp (right, ic, FALSE, FALSE);
8224
8225
8226 #ifdef BETTER_LITERAL_SHIFT
8227   /* if the shift count is known then do it
8228      as efficiently as possible */
8229   if (AOP_TYPE (right) == AOP_LIT)
8230     {
8231       if (genLeftShiftLiteral (left, right, result, ic))
8232       {
8233         return;
8234       }
8235     }
8236 #endif
8237
8238   /* shift count is unknown then we have to form
8239      a loop get the loop count in B : Note: we take
8240      only the lower order byte since shifting
8241      more that 32 bits make no sense anyway, ( the
8242      largest size of an object can be only 32 bits ) */
8243
8244   if (AOP_TYPE (right) == AOP_LIT)
8245   {
8246       /* Really should be handled by genLeftShiftLiteral,
8247        * but since I'm too lazy to fix that today, at least we can make
8248        * some small improvement.
8249        */
8250        emitcode("mov", "b,#!constbyte",
8251                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8252   }
8253   else
8254   {
8255         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8256         emitcode ("inc", "b");
8257   }
8258   freeAsmop (right, NULL, ic, TRUE);
8259   aopOp (left, ic, FALSE, FALSE);
8260   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8261
8262   /* now move the left to the result if they are not the
8263      same */
8264   if (!sameRegs (AOP (left), AOP (result)) &&
8265       AOP_SIZE (result) > 1)
8266     {
8267
8268       size = AOP_SIZE (result);
8269       offset = 0;
8270       _startLazyDPSEvaluation ();
8271       while (size--)
8272         {
8273           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8274           if (*l == '@' && (IS_AOP_PREG (result)))
8275             {
8276
8277               emitcode ("mov", "a,%s", l);
8278               aopPut (AOP (result), "a", offset);
8279             }
8280           else
8281             aopPut (AOP (result), l, offset);
8282           offset++;
8283         }
8284       _endLazyDPSEvaluation ();
8285     }
8286
8287   tlbl = newiTempLabel (NULL);
8288   size = AOP_SIZE (result);
8289   offset = 0;
8290   tlbl1 = newiTempLabel (NULL);
8291
8292   /* if it is only one byte then */
8293   if (size == 1)
8294     {
8295       symbol *tlbl1 = newiTempLabel (NULL);
8296
8297       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8298       MOVA (l);
8299       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8300       emitcode ("", "!tlabeldef", tlbl->key + 100);
8301       emitcode ("add", "a,acc");
8302       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8303       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8304       aopPut (AOP (result), "a", 0);
8305       goto release;
8306     }
8307
8308   reAdjustPreg (AOP (result));
8309
8310   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8311   emitcode ("", "!tlabeldef", tlbl->key + 100);
8312   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8313   MOVA (l);
8314   emitcode ("add", "a,acc");
8315   aopPut (AOP (result), "a", offset++);
8316   _startLazyDPSEvaluation ();
8317   while (--size)
8318     {
8319       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8320       MOVA (l);
8321       emitcode ("rlc", "a");
8322       aopPut (AOP (result), "a", offset++);
8323     }
8324   _endLazyDPSEvaluation ();
8325   reAdjustPreg (AOP (result));
8326
8327   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8328   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8329 release:
8330   freeAsmop (left, NULL, ic, TRUE);
8331   freeAsmop (result, NULL, ic, TRUE);
8332 }
8333
8334 #ifdef BETTER_LITERAL_SHIFT
8335 /*-----------------------------------------------------------------*/
8336 /* genrshOne - right shift a one byte quantity by known count      */
8337 /*-----------------------------------------------------------------*/
8338 static void
8339 genrshOne (operand * result, operand * left,
8340            int shCount, int sign)
8341 {
8342   D (emitcode (";", "genrshOne"););
8343   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8344 }
8345 #endif
8346
8347 #ifdef BETTER_LITERAL_SHIFT
8348 /*-----------------------------------------------------------------*/
8349 /* genrshTwo - right shift two bytes by known amount != 0          */
8350 /*-----------------------------------------------------------------*/
8351 static void
8352 genrshTwo (operand * result, operand * left,
8353            int shCount, int sign)
8354 {
8355   D (emitcode (";", "genrshTwo"););
8356
8357   /* if shCount >= 8 */
8358   if (shCount >= 8)
8359     {
8360       shCount -= 8;
8361       _startLazyDPSEvaluation();
8362       if (shCount)
8363       {
8364         shiftR1Left2Result (left, MSB16, result, LSB,
8365                             shCount, sign);
8366       }                     
8367       else
8368       {
8369         movLeft2Result (left, MSB16, result, LSB, sign);
8370       }
8371       addSign (result, MSB16, sign);
8372       _endLazyDPSEvaluation();
8373     }
8374
8375   /*  1 <= shCount <= 7 */
8376   else
8377   {
8378     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8379   }
8380 }
8381 #endif
8382
8383 #if 0
8384 //REMOVE ME!!!
8385 /*-----------------------------------------------------------------*/
8386 /* shiftRLong - shift right one long from left to result           */
8387 /* offl = LSB or MSB16                                             */
8388 /*-----------------------------------------------------------------*/
8389 static void
8390 shiftRLong (operand * left, int offl,
8391             operand * result, int sign)
8392 {
8393   int isSameRegs=sameRegs(AOP(left),AOP(result));
8394
8395   if (isSameRegs && offl>1) {
8396     // we are in big trouble, but this shouldn't happen
8397     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8398   }
8399
8400   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8401   
8402   if (offl==MSB16) {
8403     // shift is > 8
8404     if (sign) {
8405       emitcode ("rlc", "a");
8406       emitcode ("subb", "a,acc");
8407       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8408     } else {
8409       aopPut (AOP(result), zero, MSB32);
8410     }
8411   }
8412
8413   if (!sign) {
8414     emitcode ("clr", "c");
8415   } else {
8416     emitcode ("mov", "c,acc.7");
8417   }
8418
8419   emitcode ("rrc", "a");
8420
8421   if (isSameRegs && offl==MSB16) {
8422     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8423   } else {
8424     aopPut (AOP (result), "a", MSB32);
8425     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8426   }
8427
8428   emitcode ("rrc", "a");
8429   if (isSameRegs && offl==1) {
8430     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8431   } else {
8432     aopPut (AOP (result), "a", MSB24);
8433     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8434   }
8435   emitcode ("rrc", "a");
8436   aopPut (AOP (result), "a", MSB16 - offl);
8437
8438   if (offl == LSB)
8439     {
8440       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8441       emitcode ("rrc", "a");
8442       aopPut (AOP (result), "a", LSB);
8443     }
8444 }
8445 #endif
8446
8447 #if 0
8448 //REMOVE ME!!!
8449 /*-----------------------------------------------------------------*/
8450 /* genrshFour - shift four byte by a known amount != 0             */
8451 /*-----------------------------------------------------------------*/
8452 static void
8453 genrshFour (operand * result, operand * left,
8454             int shCount, int sign)
8455 {
8456   D (emitcode (";", "genrshFour");
8457     );
8458
8459   /* if shifting more that 3 bytes */
8460   if (shCount >= 24)
8461     {
8462       shCount -= 24;
8463       if (shCount)
8464         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8465       else
8466         movLeft2Result (left, MSB32, result, LSB, sign);
8467       addSign (result, MSB16, sign);
8468     }
8469   else if (shCount >= 16)
8470     {
8471       shCount -= 16;
8472       if (shCount)
8473         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8474       else
8475         {
8476           movLeft2Result (left, MSB24, result, LSB, 0);
8477           movLeft2Result (left, MSB32, result, MSB16, sign);
8478         }
8479       addSign (result, MSB24, sign);
8480     }
8481   else if (shCount >= 8)
8482     {
8483       shCount -= 8;
8484       if (shCount == 1)
8485         shiftRLong (left, MSB16, result, sign);
8486       else if (shCount == 0)
8487         {
8488           movLeft2Result (left, MSB16, result, LSB, 0);
8489           movLeft2Result (left, MSB24, result, MSB16, 0);
8490           movLeft2Result (left, MSB32, result, MSB24, sign);
8491           addSign (result, MSB32, sign);
8492         }
8493       else
8494         {
8495           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8496           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8497           /* the last shift is signed */
8498           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8499           addSign (result, MSB32, sign);
8500         }
8501     }
8502   else
8503     {                           /* 1 <= shCount <= 7 */
8504       if (shCount <= 2)
8505         {
8506           shiftRLong (left, LSB, result, sign);
8507           if (shCount == 2)
8508             shiftRLong (result, LSB, result, sign);
8509         }
8510       else
8511         {
8512           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8513           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8514           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8515         }
8516     }
8517 }
8518 #endif
8519
8520 #ifdef BETTER_LITERAL_SHIFT
8521 /*-----------------------------------------------------------------*/
8522 /* genRightShiftLiteral - right shifting by known count            */
8523 /*-----------------------------------------------------------------*/
8524 static bool
8525 genRightShiftLiteral (operand * left,
8526                       operand * right,
8527                       operand * result,
8528                       iCode * ic,
8529                       int sign)
8530 {
8531   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8532   int size;
8533
8534   size = getSize (operandType (result));
8535
8536   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8537
8538   /* We only handle certain easy cases so far. */
8539   if ((shCount != 0)
8540    && (shCount < (size * 8))
8541    && (size != 1)
8542    && (size != 2))
8543   {
8544       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8545       return FALSE;
8546   }
8547
8548   freeAsmop (right, NULL, ic, TRUE);
8549
8550   aopOp (left, ic, FALSE, FALSE);
8551   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8552
8553 #if VIEW_SIZE
8554   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8555             AOP_SIZE (left));
8556 #endif
8557
8558   /* test the LEFT size !!! */
8559
8560   /* I suppose that the left size >= result size */
8561   if (shCount == 0)
8562   {
8563       size = getDataSize (result);
8564       _startLazyDPSEvaluation();
8565       while (size--)
8566       {
8567         movLeft2Result (left, size, result, size, 0);
8568       }
8569       _endLazyDPSEvaluation();
8570   }
8571   else if (shCount >= (size * 8))
8572     {
8573       if (sign)
8574       {
8575         /* get sign in acc.7 */
8576         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8577       }
8578       addSign (result, LSB, sign);
8579     }
8580   else
8581     {
8582       switch (size)
8583         {
8584         case 1:
8585           genrshOne (result, left, shCount, sign);
8586           break;
8587
8588         case 2:
8589           genrshTwo (result, left, shCount, sign);
8590           break;
8591 #if 0
8592         case 4:
8593           genrshFour (result, left, shCount, sign);
8594           break;
8595 #endif    
8596         default:
8597           break;
8598         }
8599     }
8600   freeAsmop (left, NULL, ic, TRUE);
8601   freeAsmop (result, NULL, ic, TRUE);
8602   
8603   return TRUE;
8604 }
8605 #endif
8606
8607 /*-----------------------------------------------------------------*/
8608 /* genSignedRightShift - right shift of signed number              */
8609 /*-----------------------------------------------------------------*/
8610 static void
8611 genSignedRightShift (iCode * ic)
8612 {
8613   operand *right, *left, *result;
8614   int size, offset;
8615   char *l;
8616   symbol *tlbl, *tlbl1;
8617
8618   D (emitcode (";", "genSignedRightShift "););
8619
8620   /* we do it the hard way put the shift count in b
8621      and loop thru preserving the sign */
8622
8623   right = IC_RIGHT (ic);
8624   left = IC_LEFT (ic);
8625   result = IC_RESULT (ic);
8626
8627   aopOp (right, ic, FALSE, FALSE);
8628
8629 #ifdef BETTER_LITERAL_SHIFT
8630   if (AOP_TYPE (right) == AOP_LIT)
8631     {
8632       if (genRightShiftLiteral (left, right, result, ic, 1))
8633       {
8634         return;
8635       }
8636     }
8637 #endif
8638   /* shift count is unknown then we have to form
8639      a loop get the loop count in B : Note: we take
8640      only the lower order byte since shifting
8641      more that 32 bits make no sense anyway, ( the
8642      largest size of an object can be only 32 bits ) */
8643
8644   if (AOP_TYPE (right) == AOP_LIT)
8645   {
8646       /* Really should be handled by genRightShiftLiteral,
8647        * but since I'm too lazy to fix that today, at least we can make
8648        * some small improvement.
8649        */
8650        emitcode("mov", "b,#!constbyte",
8651                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8652   }
8653   else
8654   {
8655         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8656         emitcode ("inc", "b");
8657   }
8658   freeAsmop (right, NULL, ic, TRUE);
8659   aopOp (left, ic, FALSE, FALSE);
8660   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8661
8662   /* now move the left to the result if they are not the
8663      same */
8664   if (!sameRegs (AOP (left), AOP (result)) &&
8665       AOP_SIZE (result) > 1)
8666     {
8667
8668       size = AOP_SIZE (result);
8669       offset = 0;
8670       _startLazyDPSEvaluation ();
8671       while (size--)
8672         {
8673           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8674           if (*l == '@' && IS_AOP_PREG (result))
8675             {
8676
8677               emitcode ("mov", "a,%s", l);
8678               aopPut (AOP (result), "a", offset);
8679             }
8680           else
8681             aopPut (AOP (result), l, offset);
8682           offset++;
8683         }
8684       _endLazyDPSEvaluation ();
8685     }
8686
8687   /* mov the highest order bit to OVR */
8688   tlbl = newiTempLabel (NULL);
8689   tlbl1 = newiTempLabel (NULL);
8690
8691   size = AOP_SIZE (result);
8692   offset = size - 1;
8693   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8694   emitcode ("rlc", "a");
8695   emitcode ("mov", "ov,c");
8696   /* if it is only one byte then */
8697   if (size == 1)
8698     {
8699       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8700       MOVA (l);
8701       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8702       emitcode ("", "!tlabeldef", tlbl->key + 100);
8703       emitcode ("mov", "c,ov");
8704       emitcode ("rrc", "a");
8705       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8706       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8707       aopPut (AOP (result), "a", 0);
8708       goto release;
8709     }
8710
8711   reAdjustPreg (AOP (result));
8712   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8713   emitcode ("", "!tlabeldef", tlbl->key + 100);
8714   emitcode ("mov", "c,ov");
8715   _startLazyDPSEvaluation ();
8716   while (size--)
8717     {
8718       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8719       MOVA (l);
8720       emitcode ("rrc", "a");
8721       aopPut (AOP (result), "a", offset--);
8722     }
8723   _endLazyDPSEvaluation ();
8724   reAdjustPreg (AOP (result));
8725   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8726   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8727
8728 release:
8729   freeAsmop (left, NULL, ic, TRUE);
8730   freeAsmop (result, NULL, ic, TRUE);
8731 }
8732
8733 /*-----------------------------------------------------------------*/
8734 /* genRightShift - generate code for right shifting                */
8735 /*-----------------------------------------------------------------*/
8736 static void
8737 genRightShift (iCode * ic)
8738 {
8739   operand *right, *left, *result;
8740   sym_link *retype;
8741   int size, offset;
8742   char *l;
8743   symbol *tlbl, *tlbl1;
8744
8745   D (emitcode (";", "genRightShift "););
8746
8747   /* if signed then we do it the hard way preserve the
8748      sign bit moving it inwards */
8749   retype = getSpec (operandType (IC_RESULT (ic)));
8750
8751   if (!SPEC_USIGN (retype))
8752     {
8753       genSignedRightShift (ic);
8754       return;
8755     }
8756
8757   /* signed & unsigned types are treated the same : i.e. the
8758      signed is NOT propagated inwards : quoting from the
8759      ANSI - standard : "for E1 >> E2, is equivalent to division
8760      by 2**E2 if unsigned or if it has a non-negative value,
8761      otherwise the result is implementation defined ", MY definition
8762      is that the sign does not get propagated */
8763
8764   right = IC_RIGHT (ic);
8765   left = IC_LEFT (ic);
8766   result = IC_RESULT (ic);
8767
8768   aopOp (right, ic, FALSE, FALSE);
8769
8770 #ifdef BETTER_LITERAL_SHIFT
8771   /* if the shift count is known then do it
8772      as efficiently as possible */
8773   if (AOP_TYPE (right) == AOP_LIT)
8774     {
8775       if (genRightShiftLiteral (left, right, result, ic, 0))
8776       {
8777         return;
8778       }
8779     }
8780 #endif
8781
8782   /* shift count is unknown then we have to form
8783      a loop get the loop count in B : Note: we take
8784      only the lower order byte since shifting
8785      more that 32 bits make no sense anyway, ( the
8786      largest size of an object can be only 32 bits ) */
8787   
8788   if (AOP_TYPE (right) == AOP_LIT)
8789   {
8790       /* Really should be handled by genRightShiftLiteral,
8791        * but since I'm too lazy to fix that today, at least we can make
8792        * some small improvement.
8793        */
8794        emitcode("mov", "b,#!constbyte",
8795                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8796   }
8797   else
8798   {
8799         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8800         emitcode ("inc", "b");
8801   }
8802   freeAsmop (right, NULL, ic, TRUE);
8803   aopOp (left, ic, FALSE, FALSE);
8804   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8805
8806   /* now move the left to the result if they are not the
8807      same */
8808   if (!sameRegs (AOP (left), AOP (result)) &&
8809       AOP_SIZE (result) > 1)
8810     {
8811
8812       size = AOP_SIZE (result);
8813       offset = 0;
8814       _startLazyDPSEvaluation ();
8815       while (size--)
8816         {
8817           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8818           if (*l == '@' && IS_AOP_PREG (result))
8819             {
8820
8821               emitcode ("mov", "a,%s", l);
8822               aopPut (AOP (result), "a", offset);
8823             }
8824           else
8825             aopPut (AOP (result), l, offset);
8826           offset++;
8827         }
8828       _endLazyDPSEvaluation ();
8829     }
8830
8831   tlbl = newiTempLabel (NULL);
8832   tlbl1 = newiTempLabel (NULL);
8833   size = AOP_SIZE (result);
8834   offset = size - 1;
8835
8836   /* if it is only one byte then */
8837   if (size == 1)
8838     {
8839       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8840       MOVA (l);
8841       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8842       emitcode ("", "!tlabeldef", tlbl->key + 100);
8843       CLRC;
8844       emitcode ("rrc", "a");
8845       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8846       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8847       aopPut (AOP (result), "a", 0);
8848       goto release;
8849     }
8850
8851   reAdjustPreg (AOP (result));
8852   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8853   emitcode ("", "!tlabeldef", tlbl->key + 100);
8854   CLRC;
8855   _startLazyDPSEvaluation ();
8856   while (size--)
8857     {
8858       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8859       MOVA (l);
8860       emitcode ("rrc", "a");
8861       aopPut (AOP (result), "a", offset--);
8862     }
8863   _endLazyDPSEvaluation ();
8864   reAdjustPreg (AOP (result));
8865
8866   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8867   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8868
8869 release:
8870   freeAsmop (left, NULL, ic, TRUE);
8871   freeAsmop (result, NULL, ic, TRUE);
8872 }
8873
8874 /*-----------------------------------------------------------------*/
8875 /* genUnpackBits - generates code for unpacking bits               */
8876 /*-----------------------------------------------------------------*/
8877 static void
8878 genUnpackBits (operand * result, char *rname, int ptype)
8879 {
8880   int shCnt;
8881   int rlen = 0;
8882   sym_link *etype;
8883   int offset = 0;
8884
8885   D (emitcode (";", "genUnpackBits ");
8886     );
8887
8888   etype = getSpec (operandType (result));
8889
8890   /* read the first byte  */
8891   switch (ptype)
8892     {
8893
8894     case POINTER:
8895     case IPOINTER:
8896       emitcode ("mov", "a,@%s", rname);
8897       break;
8898
8899     case PPOINTER:
8900       emitcode ("movx", "a,@%s", rname);
8901       break;
8902
8903     case FPOINTER:
8904       emitcode ("movx", "a,@dptr");
8905       break;
8906
8907     case CPOINTER:
8908       emitcode ("clr", "a");
8909       emitcode ("movc", "a,@a+dptr");
8910       break;
8911
8912     case GPOINTER:
8913       emitcode ("lcall", "__gptrget");
8914       break;
8915     }
8916
8917   /* if we have bitdisplacement then it fits   */
8918   /* into this byte completely or if length is */
8919   /* less than a byte                          */
8920   if ((shCnt = SPEC_BSTR (etype)) ||
8921       (SPEC_BLEN (etype) <= 8))
8922     {
8923
8924       /* shift right acc */
8925       AccRsh (shCnt);
8926
8927       emitcode ("anl", "a,#!constbyte",
8928                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8929       aopPut (AOP (result), "a", offset);
8930       return;
8931     }
8932
8933   /* bit field did not fit in a byte  */
8934   rlen = SPEC_BLEN (etype) - 8;
8935   aopPut (AOP (result), "a", offset++);
8936
8937   while (1)
8938     {
8939
8940       switch (ptype)
8941         {
8942         case POINTER:
8943         case IPOINTER:
8944           emitcode ("inc", "%s", rname);
8945           emitcode ("mov", "a,@%s", rname);
8946           break;
8947
8948         case PPOINTER:
8949           emitcode ("inc", "%s", rname);
8950           emitcode ("movx", "a,@%s", rname);
8951           break;
8952
8953         case FPOINTER:
8954           emitcode ("inc", "dptr");
8955           emitcode ("movx", "a,@dptr");
8956           break;
8957
8958         case CPOINTER:
8959           emitcode ("clr", "a");
8960           emitcode ("inc", "dptr");
8961           emitcode ("movc", "a,@a+dptr");
8962           break;
8963
8964         case GPOINTER:
8965           emitcode ("inc", "dptr");
8966           emitcode ("lcall", "__gptrget");
8967           break;
8968         }
8969
8970       rlen -= 8;
8971       /* if we are done */
8972       if (rlen < 8)
8973         break;
8974
8975       aopPut (AOP (result), "a", offset++);
8976
8977     }
8978
8979   if (rlen)
8980     {
8981       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8982       aopPut (AOP (result), "a", offset);
8983     }
8984
8985   return;
8986 }
8987
8988
8989 /*-----------------------------------------------------------------*/
8990 /* genDataPointerGet - generates code when ptr offset is known     */
8991 /*-----------------------------------------------------------------*/
8992 static void
8993 genDataPointerGet (operand * left,
8994                    operand * result,
8995                    iCode * ic)
8996 {
8997   char *l;
8998   char buffer[256];
8999   int size, offset = 0;
9000   aopOp (result, ic, TRUE, FALSE);
9001
9002   /* get the string representation of the name */
9003   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
9004   size = AOP_SIZE (result);
9005   _startLazyDPSEvaluation ();
9006   while (size--)
9007     {
9008       if (offset)
9009         sprintf (buffer, "(%s + %d)", l + 1, offset);
9010       else
9011         sprintf (buffer, "%s", l + 1);
9012       aopPut (AOP (result), buffer, offset++);
9013     }
9014   _endLazyDPSEvaluation ();
9015
9016   freeAsmop (left, NULL, ic, TRUE);
9017   freeAsmop (result, NULL, ic, TRUE);
9018 }
9019
9020 /*-----------------------------------------------------------------*/
9021 /* genNearPointerGet - emitcode for near pointer fetch             */
9022 /*-----------------------------------------------------------------*/
9023 static void
9024 genNearPointerGet (operand * left,
9025                    operand * result,
9026                    iCode * ic,
9027                    iCode *pi)
9028 {
9029   asmop *aop = NULL;
9030   regs *preg = NULL;
9031   char *rname;
9032   sym_link *rtype, *retype, *letype;
9033   sym_link *ltype = operandType (left);
9034   char buffer[80];
9035
9036   rtype = operandType (result);
9037   retype = getSpec (rtype);
9038   letype = getSpec (ltype);
9039
9040   aopOp (left, ic, FALSE, FALSE);
9041
9042   /* if left is rematerialisable and
9043      result is not bit variable type and
9044      the left is pointer to data space i.e
9045      lower 128 bytes of space */
9046   if (AOP_TYPE (left) == AOP_IMMD &&
9047       !IS_BITVAR (retype) &&
9048       !IS_BITVAR (letype) &&
9049       DCL_TYPE (ltype) == POINTER)
9050     {
9051       genDataPointerGet (left, result, ic);
9052       return;
9053     }
9054
9055   /* if the value is already in a pointer register
9056      then don't need anything more */
9057   if (!AOP_INPREG (AOP (left)))
9058     {
9059       /* otherwise get a free pointer register */
9060       aop = newAsmop (0);
9061       preg = getFreePtr (ic, &aop, FALSE);
9062       emitcode ("mov", "%s,%s",
9063                 preg->name,
9064                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9065       rname = preg->name;
9066     }
9067   else
9068     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9069
9070   freeAsmop (left, NULL, ic, TRUE);
9071   aopOp (result, ic, FALSE, FALSE);
9072
9073   /* if bitfield then unpack the bits */
9074   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9075     genUnpackBits (result, rname, POINTER);
9076   else
9077     {
9078       /* we have can just get the values */
9079       int size = AOP_SIZE (result);
9080       int offset = 0;
9081
9082       while (size--)
9083         {
9084           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9085             {
9086
9087               emitcode ("mov", "a,@%s", rname);
9088               aopPut (AOP (result), "a", offset);
9089             }
9090           else
9091             {
9092               sprintf (buffer, "@%s", rname);
9093               aopPut (AOP (result), buffer, offset);
9094             }
9095           offset++;
9096           if (size || pi)
9097             emitcode ("inc", "%s", rname);
9098         }
9099     }
9100
9101   /* now some housekeeping stuff */
9102   if (aop)
9103     {
9104       /* we had to allocate for this iCode */
9105       if (pi) { /* post increment present */
9106         aopPut(AOP ( left ),rname,0);
9107       }
9108       freeAsmop (NULL, aop, ic, TRUE);
9109     }
9110   else
9111     {
9112       /* we did not allocate which means left
9113          already in a pointer register, then
9114          if size > 0 && this could be used again
9115          we have to point it back to where it
9116          belongs */
9117       if (AOP_SIZE (result) > 1 &&
9118           !OP_SYMBOL (left)->remat &&
9119           (OP_SYMBOL (left)->liveTo > ic->seq ||
9120            ic->depth) &&
9121           !pi)
9122         {
9123           int size = AOP_SIZE (result) - 1;
9124           while (size--)
9125             emitcode ("dec", "%s", rname);
9126         }
9127     }
9128
9129   /* done */
9130   freeAsmop (result, NULL, ic, TRUE);
9131   if (pi) pi->generated = 1;
9132 }
9133
9134 /*-----------------------------------------------------------------*/
9135 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9136 /*-----------------------------------------------------------------*/
9137 static void
9138 genPagedPointerGet (operand * left,
9139                     operand * result,
9140                     iCode * ic,
9141                     iCode * pi)
9142 {
9143   asmop *aop = NULL;
9144   regs *preg = NULL;
9145   char *rname;
9146   sym_link *rtype, *retype, *letype;
9147
9148   rtype = operandType (result);
9149   retype = getSpec (rtype);
9150   letype = getSpec (operandType (left));
9151   aopOp (left, ic, FALSE, FALSE);
9152
9153   /* if the value is already in a pointer register
9154      then don't need anything more */
9155   if (!AOP_INPREG (AOP (left)))
9156     {
9157       /* otherwise get a free pointer register */
9158       aop = newAsmop (0);
9159       preg = getFreePtr (ic, &aop, FALSE);
9160       emitcode ("mov", "%s,%s",
9161                 preg->name,
9162                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9163       rname = preg->name;
9164     }
9165   else
9166     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9167
9168   freeAsmop (left, NULL, ic, TRUE);
9169   aopOp (result, ic, FALSE, FALSE);
9170
9171   /* if bitfield then unpack the bits */
9172   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9173     genUnpackBits (result, rname, PPOINTER);
9174   else
9175     {
9176       /* we have can just get the values */
9177       int size = AOP_SIZE (result);
9178       int offset = 0;
9179
9180       while (size--)
9181         {
9182
9183           emitcode ("movx", "a,@%s", rname);
9184           aopPut (AOP (result), "a", offset);
9185
9186           offset++;
9187
9188           if (size || pi)
9189             emitcode ("inc", "%s", rname);
9190         }
9191     }
9192
9193   /* now some housekeeping stuff */
9194   if (aop)
9195     {
9196       /* we had to allocate for this iCode */
9197       if (pi) aopPut ( AOP (left), rname, 0);
9198       freeAsmop (NULL, aop, ic, TRUE);
9199     }
9200   else
9201     {
9202       /* we did not allocate which means left
9203          already in a pointer register, then
9204          if size > 0 && this could be used again
9205          we have to point it back to where it
9206          belongs */
9207       if (AOP_SIZE (result) > 1 &&
9208           !OP_SYMBOL (left)->remat &&
9209           (OP_SYMBOL (left)->liveTo > ic->seq ||
9210            ic->depth) &&
9211           !pi)
9212         {
9213           int size = AOP_SIZE (result) - 1;
9214           while (size--)
9215             emitcode ("dec", "%s", rname);
9216         }
9217     }
9218
9219   /* done */
9220   freeAsmop (result, NULL, ic, TRUE);
9221   if (pi) pi->generated = 1;
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genFarPointerGet - gget value from far space                    */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genFarPointerGet (operand * left,
9229                   operand * result, iCode * ic, iCode *pi)
9230 {
9231     int size, offset, dopi=1;
9232   sym_link *retype = getSpec (operandType (result));
9233   sym_link *letype = getSpec (operandType (left));
9234   D (emitcode (";", "genFarPointerGet");
9235     );
9236
9237   aopOp (left, ic, FALSE, FALSE);
9238
9239   /* if the operand is already in dptr
9240      then we do nothing else we move the value to dptr */
9241   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9242     {
9243       /* if this is remateriazable */
9244       if (AOP_TYPE (left) == AOP_IMMD)
9245         {
9246           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9247         }
9248       else
9249         {
9250           /* we need to get it byte by byte */
9251           _startLazyDPSEvaluation ();
9252           if (AOP_TYPE (left) != AOP_DPTR)
9253             {
9254               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9255               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9256               if (options.model == MODEL_FLAT24)
9257                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9258             }
9259           else
9260             {
9261               /* We need to generate a load to DPTR indirect through DPTR. */
9262               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9263                 );
9264               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9265               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9266               if (options.model == MODEL_FLAT24)
9267                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9268               emitcode ("pop", "dph");
9269               emitcode ("pop", "dpl");
9270               dopi =0;
9271             }
9272           _endLazyDPSEvaluation ();
9273         }
9274     }
9275   /* so dptr know contains the address */
9276   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9277
9278   /* if bit then unpack */
9279   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9280       if (AOP_INDPTRn(left)) {
9281           genSetDPTR(AOP(left)->aopu.dptr);
9282       }
9283       genUnpackBits (result, "dptr", FPOINTER);
9284       if (AOP_INDPTRn(left)) {
9285           genSetDPTR(0);
9286       }
9287   } else
9288     {
9289       size = AOP_SIZE (result);
9290       offset = 0;
9291
9292       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9293           while (size--) {
9294               genSetDPTR(AOP(left)->aopu.dptr);
9295               emitcode ("movx", "a,@dptr");
9296               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9297                   emitcode ("inc", "dptr");
9298               genSetDPTR (0);
9299               aopPut (AOP (result), "a", offset++);
9300           }
9301       } else {
9302           _startLazyDPSEvaluation ();
9303           while (size--) {
9304               if (AOP_INDPTRn(left)) {
9305                   genSetDPTR(AOP(left)->aopu.dptr);
9306               } else {
9307                   genSetDPTR (0);
9308               }
9309               _flushLazyDPS ();
9310               
9311               emitcode ("movx", "a,@dptr");
9312               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9313                   emitcode ("inc", "dptr");
9314               
9315               aopPut (AOP (result), "a", offset++);
9316           }
9317           _endLazyDPSEvaluation ();
9318       }
9319     }
9320   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9321       if (!AOP_INDPTRn(left)) {
9322           aopPut ( AOP (left), "dpl", 0);
9323           aopPut ( AOP (left), "dph", 1);
9324           if (options.model == MODEL_FLAT24)
9325               aopPut ( AOP (left), "dpx", 2);
9326       }
9327     pi->generated = 1;
9328   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9329              AOP_SIZE(result) > 1 &&
9330              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9331       
9332       size = AOP_SIZE (result) - 1;
9333       if (AOP_INDPTRn(left)) {
9334           genSetDPTR(AOP(left)->aopu.dptr);
9335       }
9336       while (size--) emitcode ("lcall","__decdptr");
9337       if (AOP_INDPTRn(left)) {
9338           genSetDPTR(0);
9339       }
9340   }
9341
9342   freeAsmop (left, NULL, ic, TRUE);
9343   freeAsmop (result, NULL, ic, TRUE);
9344 }
9345
9346 /*-----------------------------------------------------------------*/
9347 /* genCodePointerGet - get value from code space                  */
9348 /*-----------------------------------------------------------------*/
9349 static void
9350 genCodePointerGet (operand * left,
9351                     operand * result, iCode * ic, iCode *pi)
9352 {
9353   int size, offset, dopi=1;
9354   sym_link *retype = getSpec (operandType (result));
9355
9356   aopOp (left, ic, FALSE, FALSE);
9357
9358   /* if the operand is already in dptr
9359      then we do nothing else we move the value to dptr */
9360   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9361     {
9362       /* if this is remateriazable */
9363       if (AOP_TYPE (left) == AOP_IMMD)
9364         {
9365           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9366         }
9367       else
9368         {                       /* we need to get it byte by byte */
9369           _startLazyDPSEvaluation ();
9370           if (AOP_TYPE (left) != AOP_DPTR)
9371             {
9372               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9373               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9374               if (options.model == MODEL_FLAT24)
9375                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9376             }
9377           else
9378             {
9379               /* We need to generate a load to DPTR indirect through DPTR. */
9380               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9381                 );
9382               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9383               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9384               if (options.model == MODEL_FLAT24)
9385                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9386               emitcode ("pop", "dph");
9387               emitcode ("pop", "dpl");
9388               dopi=0;
9389             }
9390           _endLazyDPSEvaluation ();
9391         }
9392     }
9393   /* so dptr know contains the address */
9394   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9395
9396   /* if bit then unpack */
9397   if (IS_BITVAR (retype)) {
9398       if (AOP_INDPTRn(left)) {
9399           genSetDPTR(AOP(left)->aopu.dptr);
9400       }
9401       genUnpackBits (result, "dptr", CPOINTER);
9402       if (AOP_INDPTRn(left)) {
9403           genSetDPTR(0);
9404       }
9405   } else
9406     {
9407       size = AOP_SIZE (result);
9408       offset = 0;
9409       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9410           while (size--) {
9411               genSetDPTR(AOP(left)->aopu.dptr);
9412               emitcode ("clr", "a");
9413               emitcode ("movc", "a,@a+dptr");
9414               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9415                   emitcode ("inc", "dptr");
9416               genSetDPTR (0);
9417               aopPut (AOP (result), "a", offset++);
9418           }
9419       } else {
9420           _startLazyDPSEvaluation ();
9421           while (size--)
9422               {
9423                   if (AOP_INDPTRn(left)) {
9424                       genSetDPTR(AOP(left)->aopu.dptr);
9425                   } else {
9426                       genSetDPTR (0);
9427                   }
9428                   _flushLazyDPS ();
9429                   
9430                   emitcode ("clr", "a");
9431                   emitcode ("movc", "a,@a+dptr");
9432                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9433                       emitcode ("inc", "dptr");
9434                   aopPut (AOP (result), "a", offset++);
9435               }
9436           _endLazyDPSEvaluation ();
9437       }
9438     }
9439   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9440       if (!AOP_INDPTRn(left)) {
9441           aopPut ( AOP (left), "dpl", 0);
9442           aopPut ( AOP (left), "dph", 1);
9443           if (options.model == MODEL_FLAT24)
9444               aopPut ( AOP (left), "dpx", 2);
9445       }
9446       pi->generated = 1;
9447   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9448              AOP_SIZE(result) > 1 &&
9449              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9450       
9451       size = AOP_SIZE (result) - 1;
9452       if (AOP_INDPTRn(left)) {
9453           genSetDPTR(AOP(left)->aopu.dptr);
9454       }
9455       while (size--) emitcode ("lcall","__decdptr");
9456       if (AOP_INDPTRn(left)) {
9457           genSetDPTR(0);
9458       }
9459   }
9460   
9461   freeAsmop (left, NULL, ic, TRUE);
9462   freeAsmop (result, NULL, ic, TRUE);
9463 }
9464
9465 /*-----------------------------------------------------------------*/
9466 /* genGenPointerGet - gget value from generic pointer space        */
9467 /*-----------------------------------------------------------------*/
9468 static void
9469 genGenPointerGet (operand * left,
9470                   operand * result, iCode * ic, iCode * pi)
9471 {
9472   int size, offset;
9473   sym_link *retype = getSpec (operandType (result));
9474   sym_link *letype = getSpec (operandType (left));
9475
9476   D (emitcode (";", "genGenPointerGet "); );
9477
9478   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9479
9480   /* if the operand is already in dptr
9481      then we do nothing else we move the value to dptr */
9482   if (AOP_TYPE (left) != AOP_STR)
9483     {
9484       /* if this is remateriazable */
9485       if (AOP_TYPE (left) == AOP_IMMD)
9486         {
9487           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9488           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9489                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9490           else
9491                   emitcode ("mov", "b,#%d", pointerCode (retype));
9492         }
9493       else
9494         {                       /* we need to get it byte by byte */
9495           _startLazyDPSEvaluation ();
9496 #if 0   // I see no point at all to this code.
9497         // So I yanked it. Kill at some future date if no bugs rear their heads.
9498           if (AOP(left)->type==AOP_DPTR2) {
9499             char *l;
9500             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9501             genSetDPTR(0);
9502             _flushLazyDPS();
9503             emitcode ("mov", "dpl,%s", l);
9504             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9505             genSetDPTR(0);
9506             _flushLazyDPS();
9507             emitcode ("mov", "dph,%s", l);
9508             if (options.model == MODEL_FLAT24) {
9509               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9510               genSetDPTR(0);
9511               _flushLazyDPS();
9512               emitcode ("mov", "dpx,%s", l);
9513               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9514             } else {
9515               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9516             }
9517           } 
9518           else 
9519 #endif          
9520           {
9521             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9522             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9523             if (options.model == MODEL_FLAT24) {
9524               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9525               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9526             } else {
9527               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9528             }
9529           }
9530           _endLazyDPSEvaluation ();
9531         }
9532     }
9533
9534   /* so dptr-b now contains the address */
9535   _G.bInUse++;
9536   aopOp (result, ic, FALSE, TRUE);
9537   _G.bInUse--;
9538
9539   /* if bit then unpack */
9540   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9541   {
9542     genUnpackBits (result, "dptr", GPOINTER);
9543   }
9544   else
9545     {
9546         size = AOP_SIZE (result);
9547         offset = 0;
9548
9549         while (size--)
9550         {
9551             if (size)
9552             {
9553                 // Get two bytes at a time, results in _AP & A.
9554                 // dptr will be incremented ONCE by __gptrgetWord.
9555                 //
9556                 // Note: any change here must be coordinated
9557                 // with the implementation of __gptrgetWord
9558                 // in device/lib/_gptrget.c
9559                 emitcode ("lcall", "__gptrgetWord");
9560                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9561                 aopPut (AOP (result), "a", offset++);
9562                 size--;
9563             }
9564             else
9565             {
9566                 // Only one byte to get.
9567                 emitcode ("lcall", "__gptrget");
9568                 aopPut (AOP (result), "a", offset++);
9569             }
9570             
9571             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9572             {
9573                 emitcode ("inc", "dptr");
9574             }
9575         }
9576     }
9577
9578   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9579     aopPut ( AOP (left), "dpl", 0);
9580     aopPut ( AOP (left), "dph", 1);
9581     if (options.model == MODEL_FLAT24) {
9582         aopPut ( AOP (left), "dpx", 2);
9583         aopPut ( AOP (left), "b", 3);   
9584     } else  aopPut ( AOP (left), "b", 2);       
9585     pi->generated = 1;
9586   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9587              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9588       
9589       size = AOP_SIZE (result) - 1;
9590       while (size--) emitcode ("lcall","__decdptr");
9591   }
9592
9593   freeAsmop (left, NULL, ic, TRUE);
9594   freeAsmop (result, NULL, ic, TRUE);
9595 }
9596
9597 /*-----------------------------------------------------------------*/
9598 /* genPointerGet - generate code for pointer get                   */
9599 /*-----------------------------------------------------------------*/
9600 static void
9601 genPointerGet (iCode * ic, iCode *pi)
9602 {
9603   operand *left, *result;
9604   sym_link *type, *etype;
9605   int p_type;
9606
9607   D (emitcode (";", "genPointerGet ");
9608     );
9609
9610   left = IC_LEFT (ic);
9611   result = IC_RESULT (ic);
9612
9613   /* depending on the type of pointer we need to
9614      move it to the correct pointer register */
9615   type = operandType (left);
9616   etype = getSpec (type);
9617   /* if left is of type of pointer then it is simple */
9618   if (IS_PTR (type) && !IS_FUNC (type->next))
9619     p_type = DCL_TYPE (type);
9620   else
9621     {
9622       /* we have to go by the storage class */
9623       p_type = PTR_TYPE (SPEC_OCLS (etype));
9624     }
9625   /* special case when cast remat */
9626   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9627       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9628           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9629           type = operandType (left);
9630           p_type = DCL_TYPE (type);
9631   }
9632   /* now that we have the pointer type we assign
9633      the pointer values */
9634   switch (p_type)
9635     {
9636
9637     case POINTER:
9638     case IPOINTER:
9639       genNearPointerGet (left, result, ic, pi);
9640       break;
9641
9642     case PPOINTER:
9643       genPagedPointerGet (left, result, ic, pi);
9644       break;
9645
9646     case FPOINTER:
9647       genFarPointerGet (left, result, ic, pi);
9648       break;
9649
9650     case CPOINTER:
9651       genCodePointerGet (left, result, ic, pi);
9652       break;
9653
9654     case GPOINTER:
9655       genGenPointerGet (left, result, ic, pi);
9656       break;
9657     }
9658
9659 }
9660
9661 /*-----------------------------------------------------------------*/
9662 /* genPackBits - generates code for packed bit storage             */
9663 /*-----------------------------------------------------------------*/
9664 static void
9665 genPackBits (sym_link * etype,
9666              operand * right,
9667              char *rname, int p_type)
9668 {
9669   int shCount = 0;
9670   int offset = 0;
9671   int rLen = 0;
9672   int blen, bstr;
9673   char *l;
9674
9675   blen = SPEC_BLEN (etype);
9676   bstr = SPEC_BSTR (etype);
9677
9678   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9679   MOVA (l);
9680
9681   /* if the bit lenth is less than or    */
9682   /* it exactly fits a byte then         */
9683   if (SPEC_BLEN (etype) <= 8)
9684     {
9685       shCount = SPEC_BSTR (etype);
9686
9687       /* shift left acc */
9688       AccLsh (shCount);
9689
9690       if (SPEC_BLEN (etype) < 8)
9691         {                       /* if smaller than a byte */
9692
9693
9694           switch (p_type)
9695             {
9696             case POINTER:
9697               emitcode ("mov", "b,a");
9698               emitcode ("mov", "a,@%s", rname);
9699               break;
9700
9701             case FPOINTER:
9702               emitcode ("mov", "b,a");
9703               emitcode ("movx", "a,@dptr");
9704               break;
9705
9706             case GPOINTER:
9707               emitcode ("push", "b");
9708               emitcode ("push", "acc");
9709               emitcode ("lcall", "__gptrget");
9710               emitcode ("pop", "b");
9711               break;
9712             }
9713
9714           emitcode ("anl", "a,#!constbyte", (unsigned char)
9715                     ((unsigned char) (0xFF << (blen + bstr)) |
9716                      (unsigned char) (0xFF >> (8 - bstr))));
9717           emitcode ("orl", "a,b");
9718           if (p_type == GPOINTER)
9719             emitcode ("pop", "b");
9720         }
9721     }
9722
9723   switch (p_type)
9724     {
9725     case POINTER:
9726       emitcode ("mov", "@%s,a", rname);
9727       break;
9728
9729     case FPOINTER:
9730       emitcode ("movx", "@dptr,a");
9731       break;
9732
9733     case GPOINTER:
9734       emitcode ("lcall", "__gptrput");
9735       break;
9736     }
9737
9738   /* if we r done */
9739   if (SPEC_BLEN (etype) <= 8)
9740     return;
9741
9742   emitcode ("inc", "%s", rname);
9743   rLen = SPEC_BLEN (etype);
9744
9745   /* now generate for lengths greater than one byte */
9746   while (1)
9747     {
9748
9749       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9750
9751       rLen -= 8;
9752       if (rLen < 8)
9753         break;
9754
9755       switch (p_type)
9756         {
9757         case POINTER:
9758           if (*l == '@')
9759             {
9760               MOVA (l);
9761               emitcode ("mov", "@%s,a", rname);
9762             }
9763           else
9764             emitcode ("mov", "@%s,%s", rname, l);
9765           break;
9766
9767         case FPOINTER:
9768           MOVA (l);
9769           emitcode ("movx", "@dptr,a");
9770           break;
9771
9772         case GPOINTER:
9773           MOVA (l);
9774           emitcode ("lcall", "__gptrput");
9775           break;
9776         }
9777       emitcode ("inc", "%s", rname);
9778     }
9779
9780   MOVA (l);
9781
9782   /* last last was not complete */
9783   if (rLen)
9784     {
9785       /* save the byte & read byte */
9786       switch (p_type)
9787         {
9788         case POINTER:
9789           emitcode ("mov", "b,a");
9790           emitcode ("mov", "a,@%s", rname);
9791           break;
9792
9793         case FPOINTER:
9794           emitcode ("mov", "b,a");
9795           emitcode ("movx", "a,@dptr");
9796           break;
9797
9798         case GPOINTER:
9799           emitcode ("push", "b");
9800           emitcode ("push", "acc");
9801           emitcode ("lcall", "__gptrget");
9802           emitcode ("pop", "b");
9803           break;
9804         }
9805
9806       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9807       emitcode ("orl", "a,b");
9808     }
9809
9810   if (p_type == GPOINTER)
9811     emitcode ("pop", "b");
9812
9813   switch (p_type)
9814     {
9815
9816     case POINTER:
9817       emitcode ("mov", "@%s,a", rname);
9818       break;
9819
9820     case FPOINTER:
9821       emitcode ("movx", "@dptr,a");
9822       break;
9823
9824     case GPOINTER:
9825       emitcode ("lcall", "__gptrput");
9826       break;
9827     }
9828 }
9829 /*-----------------------------------------------------------------*/
9830 /* genDataPointerSet - remat pointer to data space                 */
9831 /*-----------------------------------------------------------------*/
9832 static void
9833 genDataPointerSet (operand * right,
9834                    operand * result,
9835                    iCode * ic)
9836 {
9837   int size, offset = 0;
9838   char *l, buffer[256];
9839
9840   aopOp (right, ic, FALSE, FALSE);
9841
9842   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9843   size = AOP_SIZE (right);
9844   while (size--)
9845     {
9846       if (offset)
9847         sprintf (buffer, "(%s + %d)", l + 1, offset);
9848       else
9849         sprintf (buffer, "%s", l + 1);
9850       emitcode ("mov", "%s,%s", buffer,
9851                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9852     }
9853
9854   freeAsmop (right, NULL, ic, TRUE);
9855   freeAsmop (result, NULL, ic, TRUE);
9856 }
9857
9858 /*-----------------------------------------------------------------*/
9859 /* genNearPointerSet - emitcode for near pointer put                */
9860 /*-----------------------------------------------------------------*/
9861 static void
9862 genNearPointerSet (operand * right,
9863                    operand * result,
9864                    iCode * ic,
9865                    iCode * pi)
9866 {
9867   asmop *aop = NULL;
9868   regs *preg = NULL;
9869   char *rname, *l;
9870   sym_link *retype, *letype;
9871   sym_link *ptype = operandType (result);
9872
9873   retype = getSpec (operandType (right));
9874   letype = getSpec (ptype);
9875
9876   aopOp (result, ic, FALSE, FALSE);
9877
9878   /* if the result is rematerializable &
9879      in data space & not a bit variable */
9880   if (AOP_TYPE (result) == AOP_IMMD &&
9881       DCL_TYPE (ptype) == POINTER &&
9882       !IS_BITVAR (retype) &&
9883       !IS_BITVAR (letype))
9884     {
9885       genDataPointerSet (right, result, ic);
9886       return;
9887     }
9888
9889   /* if the value is already in a pointer register
9890      then don't need anything more */
9891   if (!AOP_INPREG (AOP (result)))
9892     {
9893       /* otherwise get a free pointer register */
9894       aop = newAsmop (0);
9895       preg = getFreePtr (ic, &aop, FALSE);
9896       emitcode ("mov", "%s,%s",
9897                 preg->name,
9898                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9899       rname = preg->name;
9900     }
9901   else
9902     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9903
9904   aopOp (right, ic, FALSE, FALSE);
9905
9906   /* if bitfield then unpack the bits */
9907   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9908     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9909   else
9910     {
9911       /* we have can just get the values */
9912       int size = AOP_SIZE (right);
9913       int offset = 0;
9914
9915       while (size--)
9916         {
9917           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9918           if (*l == '@')
9919             {
9920               MOVA (l);
9921               emitcode ("mov", "@%s,a", rname);
9922             }
9923           else
9924             emitcode ("mov", "@%s,%s", rname, l);
9925           if (size || pi)
9926             emitcode ("inc", "%s", rname);
9927           offset++;
9928         }
9929     }
9930
9931   /* now some housekeeping stuff */
9932   if (aop)
9933     {
9934       /* we had to allocate for this iCode */
9935       if (pi) aopPut (AOP (result),rname,0);
9936       freeAsmop (NULL, aop, ic, TRUE);
9937     }
9938   else
9939     {
9940       /* we did not allocate which means left
9941          already in a pointer register, then
9942          if size > 0 && this could be used again
9943          we have to point it back to where it
9944          belongs */
9945       if (AOP_SIZE (right) > 1 &&
9946           !OP_SYMBOL (result)->remat &&
9947           (OP_SYMBOL (result)->liveTo > ic->seq ||
9948            ic->depth) &&
9949           !pi)
9950         {
9951           int size = AOP_SIZE (right) - 1;
9952           while (size--)
9953             emitcode ("dec", "%s", rname);
9954         }
9955     }
9956
9957   /* done */
9958   if (pi) pi->generated = 1;
9959   freeAsmop (result, NULL, ic, TRUE);
9960   freeAsmop (right, NULL, ic, TRUE);
9961
9962
9963 }
9964
9965 /*-----------------------------------------------------------------*/
9966 /* genPagedPointerSet - emitcode for Paged pointer put             */
9967 /*-----------------------------------------------------------------*/
9968 static void
9969 genPagedPointerSet (operand * right,
9970                     operand * result,
9971                     iCode * ic,
9972                     iCode *pi)
9973 {
9974   asmop *aop = NULL;
9975   regs *preg = NULL;
9976   char *rname, *l;
9977   sym_link *retype, *letype;
9978
9979   retype = getSpec (operandType (right));
9980   letype = getSpec (operandType (result));
9981
9982   aopOp (result, ic, FALSE, FALSE);
9983
9984   /* if the value is already in a pointer register
9985      then don't need anything more */
9986   if (!AOP_INPREG (AOP (result)))
9987     {
9988       /* otherwise get a free pointer register */
9989       aop = newAsmop (0);
9990       preg = getFreePtr (ic, &aop, FALSE);
9991       emitcode ("mov", "%s,%s",
9992                 preg->name,
9993                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9994       rname = preg->name;
9995     }
9996   else
9997     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9998
9999   aopOp (right, ic, FALSE, FALSE);
10000
10001   /* if bitfield then unpack the bits */
10002   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10003     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10004   else
10005     {
10006       /* we have can just get the values */
10007       int size = AOP_SIZE (right);
10008       int offset = 0;
10009
10010       while (size--)
10011         {
10012           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
10013
10014           MOVA (l);
10015           emitcode ("movx", "@%s,a", rname);
10016
10017           if (size || pi)
10018             emitcode ("inc", "%s", rname);
10019
10020           offset++;
10021         }
10022     }
10023
10024   /* now some housekeeping stuff */
10025   if (aop)
10026     {
10027       if (pi) aopPut (AOP (result),rname,0);
10028       /* we had to allocate for this iCode */
10029       freeAsmop (NULL, aop, ic, TRUE);
10030     }
10031   else
10032     {
10033       /* we did not allocate which means left
10034          already in a pointer register, then
10035          if size > 0 && this could be used again
10036          we have to point it back to where it
10037          belongs */
10038       if (AOP_SIZE (right) > 1 &&
10039           !OP_SYMBOL (result)->remat &&
10040           (OP_SYMBOL (result)->liveTo > ic->seq ||
10041            ic->depth) &&
10042           !pi)
10043         {
10044           int size = AOP_SIZE (right) - 1;
10045           while (size--)
10046             emitcode ("dec", "%s", rname);
10047         }
10048     }
10049
10050   /* done */
10051   if (pi) pi->generated = 1;
10052   freeAsmop (result, NULL, ic, TRUE);
10053   freeAsmop (right, NULL, ic, TRUE);
10054
10055
10056 }
10057
10058 /*-----------------------------------------------------------------*/
10059 /* genFarPointerSet - set value from far space                     */
10060 /*-----------------------------------------------------------------*/
10061 static void
10062 genFarPointerSet (operand * right,
10063                   operand * result, iCode * ic, iCode *pi)
10064 {
10065   int size, offset, dopi=1;
10066   sym_link *retype = getSpec (operandType (right));
10067   sym_link *letype = getSpec (operandType (result));
10068
10069   aopOp (result, ic, FALSE, FALSE);
10070
10071   /* if the operand is already in dptr
10072      then we do nothing else we move the value to dptr */
10073   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10074     {
10075       /* if this is remateriazable */
10076       if (AOP_TYPE (result) == AOP_IMMD)
10077         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10078       else
10079         {
10080           /* we need to get it byte by byte */
10081           _startLazyDPSEvaluation ();
10082           if (AOP_TYPE (result) != AOP_DPTR)
10083             {
10084               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10085               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10086               if (options.model == MODEL_FLAT24)
10087                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10088             }
10089           else
10090             {
10091               /* We need to generate a load to DPTR indirect through DPTR. */
10092               D (emitcode (";", "genFarPointerSet -- indirection special case.");
10093                 );
10094               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
10095               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
10096               if (options.model == MODEL_FLAT24)
10097                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10098               emitcode ("pop", "dph");
10099               emitcode ("pop", "dpl");
10100               dopi=0;
10101             }
10102           _endLazyDPSEvaluation ();
10103         }
10104     }
10105   /* so dptr know contains the address */
10106   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10107
10108   /* if bit then unpack */
10109   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10110       if (AOP_INDPTRn(result)) {
10111           genSetDPTR(AOP(result)->aopu.dptr);
10112       }
10113       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10114       if (AOP_INDPTRn(result)) {
10115           genSetDPTR(0);
10116       }
10117   } else {
10118       size = AOP_SIZE (right);
10119       offset = 0;
10120       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10121           while (size--) {
10122               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10123               MOVA (l);
10124               
10125               genSetDPTR(AOP(result)->aopu.dptr);
10126               emitcode ("movx", "@dptr,a");
10127               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10128                   emitcode ("inc", "dptr");
10129               genSetDPTR (0);
10130           }
10131       } else {
10132           _startLazyDPSEvaluation ();
10133           while (size--) {
10134               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10135               MOVA (l);
10136               
10137               if (AOP_INDPTRn(result)) {
10138                   genSetDPTR(AOP(result)->aopu.dptr);
10139               } else {
10140                   genSetDPTR (0);
10141               }
10142               _flushLazyDPS ();
10143               
10144               emitcode ("movx", "@dptr,a");
10145               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10146                   emitcode ("inc", "dptr");
10147           }
10148           _endLazyDPSEvaluation ();
10149       }
10150   }
10151   
10152   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10153       if (!AOP_INDPTRn(result)) {
10154           aopPut (AOP(result),"dpl",0);
10155           aopPut (AOP(result),"dph",1);
10156           if (options.model == MODEL_FLAT24)
10157               aopPut (AOP(result),"dpx",2);
10158       }
10159       pi->generated=1;
10160   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10161              AOP_SIZE(right) > 1 &&
10162              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10163       
10164       size = AOP_SIZE (right) - 1;
10165       if (AOP_INDPTRn(result)) {
10166           genSetDPTR(AOP(result)->aopu.dptr);
10167       } 
10168       while (size--) emitcode ("lcall","__decdptr");
10169       if (AOP_INDPTRn(result)) {
10170           genSetDPTR(0);
10171       }
10172   }
10173   freeAsmop (result, NULL, ic, TRUE);
10174   freeAsmop (right, NULL, ic, TRUE);
10175 }
10176
10177 /*-----------------------------------------------------------------*/
10178 /* genGenPointerSet - set value from generic pointer space         */
10179 /*-----------------------------------------------------------------*/
10180 static void
10181 genGenPointerSet (operand * right,
10182                   operand * result, iCode * ic, iCode *pi)
10183 {
10184   int size, offset;
10185   sym_link *retype = getSpec (operandType (right));
10186   sym_link *letype = getSpec (operandType (result));
10187
10188   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
10189
10190   /* if the operand is already in dptr
10191      then we do nothing else we move the value to dptr */
10192   if (AOP_TYPE (result) != AOP_STR)
10193     {
10194       _startLazyDPSEvaluation ();
10195       /* if this is remateriazable */
10196       if (AOP_TYPE (result) == AOP_IMMD)
10197         {
10198           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10199           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10200                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10201           else
10202                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10203         }
10204       else
10205         {                       /* we need to get it byte by byte */
10206           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10207           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10208           if (options.model == MODEL_FLAT24) {
10209             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10210             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10211           } else {
10212             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10213           }
10214         }
10215       _endLazyDPSEvaluation ();
10216     }
10217   /* so dptr know contains the address */
10218   aopOp (right, ic, FALSE, TRUE);
10219
10220   /* if bit then unpack */
10221   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10222     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10223   else
10224     {
10225       size = AOP_SIZE (right);
10226       offset = 0;
10227
10228       _startLazyDPSEvaluation ();
10229       while (size--)
10230         {
10231           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10232           MOVA (l);
10233
10234           genSetDPTR (0);
10235           _flushLazyDPS ();
10236
10237           emitcode ("lcall", "__gptrput");
10238           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10239             emitcode ("inc", "dptr");
10240         }
10241       _endLazyDPSEvaluation ();
10242     }
10243
10244   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10245       aopPut (AOP(result),"dpl",0);
10246       aopPut (AOP(result),"dph",1);
10247       if (options.model == MODEL_FLAT24) {
10248           aopPut (AOP(result),"dpx",2);
10249           aopPut (AOP(result),"b",3);
10250       } else {
10251           aopPut (AOP(result),"b",2);
10252       }
10253       pi->generated=1;
10254   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10255              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10256       
10257       size = AOP_SIZE (right) - 1;
10258       while (size--) emitcode ("lcall","__decdptr");
10259   }
10260   freeAsmop (result, NULL, ic, TRUE);
10261   freeAsmop (right, NULL, ic, TRUE);
10262 }
10263
10264 /*-----------------------------------------------------------------*/
10265 /* genPointerSet - stores the value into a pointer location        */
10266 /*-----------------------------------------------------------------*/
10267 static void
10268 genPointerSet (iCode * ic, iCode *pi)
10269 {
10270   operand *right, *result;
10271   sym_link *type, *etype;
10272   int p_type;
10273
10274   D (emitcode (";", "genPointerSet ");
10275     );
10276
10277   right = IC_RIGHT (ic);
10278   result = IC_RESULT (ic);
10279
10280   /* depending on the type of pointer we need to
10281      move it to the correct pointer register */
10282   type = operandType (result);
10283   etype = getSpec (type);
10284   /* if left is of type of pointer then it is simple */
10285   if (IS_PTR (type) && !IS_FUNC (type->next))
10286     {
10287       p_type = DCL_TYPE (type);
10288     }
10289   else
10290     {
10291       /* we have to go by the storage class */
10292       p_type = PTR_TYPE (SPEC_OCLS (etype));
10293     }
10294   /* special case when cast remat */
10295   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10296       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10297           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10298           type = operandType (result);
10299           p_type = DCL_TYPE (type);
10300   }
10301
10302   /* now that we have the pointer type we assign
10303      the pointer values */
10304   switch (p_type)
10305     {
10306
10307     case POINTER:
10308     case IPOINTER:
10309       genNearPointerSet (right, result, ic, pi);
10310       break;
10311
10312     case PPOINTER:
10313       genPagedPointerSet (right, result, ic, pi);
10314       break;
10315
10316     case FPOINTER:
10317       genFarPointerSet (right, result, ic, pi);
10318       break;
10319
10320     case GPOINTER:
10321       genGenPointerSet (right, result, ic, pi);
10322       break;
10323
10324     default:
10325       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10326               "genPointerSet: illegal pointer type");
10327     }
10328
10329 }
10330
10331 /*-----------------------------------------------------------------*/
10332 /* genIfx - generate code for Ifx statement                        */
10333 /*-----------------------------------------------------------------*/
10334 static void
10335 genIfx (iCode * ic, iCode * popIc)
10336 {
10337   operand *cond = IC_COND (ic);
10338   int isbit = 0;
10339
10340   D (emitcode (";", "genIfx "););
10341
10342   aopOp (cond, ic, FALSE, FALSE);
10343
10344   /* get the value into acc */
10345   if (AOP_TYPE (cond) != AOP_CRY)
10346     toBoolean (cond);
10347   else
10348     isbit = 1;
10349   /* the result is now in the accumulator */
10350   freeAsmop (cond, NULL, ic, TRUE);
10351
10352   /* if there was something to be popped then do it */
10353   if (popIc)
10354     genIpop (popIc);
10355
10356   /* if the condition is  a bit variable */
10357   if (isbit && IS_ITEMP (cond) &&
10358       SPIL_LOC (cond))
10359     genIfxJump (ic, SPIL_LOC (cond)->rname);
10360   else if (isbit && !IS_ITEMP (cond))
10361     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10362   else
10363     genIfxJump (ic, "a");
10364
10365   ic->generated = 1;
10366 }
10367
10368 /*-----------------------------------------------------------------*/
10369 /* genAddrOf - generates code for address of                       */
10370 /*-----------------------------------------------------------------*/
10371 static void
10372 genAddrOf (iCode * ic)
10373 {
10374   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10375   int size, offset;
10376
10377   D (emitcode (";", "genAddrOf ");
10378     );
10379
10380   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10381
10382   /* if the operand is on the stack then we
10383      need to get the stack offset of this
10384      variable */
10385   if (sym->onStack) {
10386       
10387       /* if 10 bit stack */
10388       if (options.stack10bit) {
10389           char buff[10];
10390           tsprintf(buff, sizeof(buff), 
10391                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10392           /* if it has an offset then we need to compute it */
10393 /*        emitcode ("subb", "a,#!constbyte", */
10394 /*                  -((sym->stack < 0) ? */
10395 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10396 /*                    ((short) sym->stack)) & 0xff); */
10397 /*        emitcode ("mov","b,a"); */
10398 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10399 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10400 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10401           if (sym->stack) {
10402               emitcode ("mov", "a,_bpx");
10403               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10404                                              ((char) (sym->stack - _G.nRegsSaved)) :
10405                                              ((char) sym->stack )) & 0xff);
10406               emitcode ("mov", "b,a");
10407               emitcode ("mov", "a,_bpx+1");
10408               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10409                                               ((short) (sym->stack - _G.nRegsSaved)) :
10410                                               ((short) sym->stack )) >> 8) & 0xff);
10411               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10412               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10413               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10414           } else {
10415               /* we can just move _bp */
10416               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10417               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10418               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10419           }       
10420       } else {
10421           /* if it has an offset then we need to compute it */
10422           if (sym->stack) {
10423               emitcode ("mov", "a,_bp");
10424               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10425               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10426           } else {
10427               /* we can just move _bp */
10428               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10429           }
10430           /* fill the result with zero */
10431           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10432           
10433           
10434           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10435               fprintf (stderr,
10436                        "*** warning: pointer to stack var truncated.\n");
10437           }
10438
10439           offset = 1;
10440           while (size--) {
10441               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10442           }      
10443       }
10444       goto release;
10445   }
10446
10447   /* object not on stack then we need the name */
10448   size = AOP_SIZE (IC_RESULT (ic));
10449   offset = 0;
10450
10451   while (size--)
10452     {
10453       char s[SDCC_NAME_MAX];
10454       if (offset) {
10455           switch (offset) {
10456           case 1:
10457               tsprintf(s, sizeof(s), "!his",sym->rname);
10458               break;
10459           case 2:
10460               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10461               break;
10462           case 3:
10463               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10464               break;
10465           default: /* should not need this (just in case) */
10466               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10467                        sym->rname,
10468                        offset * 8);
10469           }
10470       } else
10471           sprintf (s, "#%s", sym->rname);
10472       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10473     }
10474
10475 release:
10476   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10477
10478 }
10479
10480 /*-----------------------------------------------------------------*/
10481 /* genArrayInit - generates code for address of                       */
10482 /*-----------------------------------------------------------------*/
10483 static void
10484 genArrayInit (iCode * ic)
10485 {
10486     literalList *iLoop;
10487     int         ix, count;
10488     int         elementSize = 0, eIndex;
10489     unsigned    val, lastVal;
10490     sym_link    *type;
10491     operand     *left=IC_LEFT(ic);
10492     
10493     D (emitcode (";", "genArrayInit "););
10494
10495     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10496     
10497     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10498     {
10499         // Load immediate value into DPTR.
10500         emitcode("mov", "dptr, %s",
10501              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10502     }
10503     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10504     {
10505 #if 0
10506       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10507               "Unexpected operand to genArrayInit.\n");
10508       exit(1);
10509 #else
10510       // a regression because of SDCCcse.c:1.52
10511       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10512       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10513       if (options.model == MODEL_FLAT24)
10514         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10515 #endif
10516     }
10517     
10518     type = operandType(IC_LEFT(ic));
10519     
10520     if (type && type->next)
10521     {
10522         elementSize = getSize(type->next);
10523     }
10524     else
10525     {
10526         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10527                                 "can't determine element size in genArrayInit.\n");
10528         exit(1);
10529     }
10530     
10531     iLoop = IC_ARRAYILIST(ic);
10532     lastVal = 0xffff;
10533     
10534     while (iLoop)
10535     {
10536         bool firstpass = TRUE;
10537         
10538         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10539                  iLoop->count, (int)iLoop->literalValue, elementSize);
10540         
10541         ix = iLoop->count;
10542         
10543         while (ix)
10544         {
10545             symbol *tlbl = NULL;
10546             
10547             count = ix > 256 ? 256 : ix;
10548             
10549             if (count > 1)
10550             {
10551                 tlbl = newiTempLabel (NULL);
10552                 if (firstpass || (count & 0xff))
10553                 {
10554                     emitcode("mov", "b, #!constbyte", count & 0xff);
10555                 }
10556                 
10557                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10558             }
10559             
10560             firstpass = FALSE;
10561                 
10562             for (eIndex = 0; eIndex < elementSize; eIndex++)
10563             {
10564                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10565                 if (val != lastVal)
10566                 {
10567                     emitcode("mov", "a, #!constbyte", val);
10568                     lastVal = val;
10569                 }
10570                 
10571                 emitcode("movx", "@dptr, a");
10572                 emitcode("inc", "dptr");
10573             }
10574             
10575             if (count > 1)
10576             {
10577                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10578             }
10579             
10580             ix -= count;
10581         }
10582         
10583         iLoop = iLoop->next;
10584     }
10585     
10586     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10587 }
10588
10589 /*-----------------------------------------------------------------*/
10590 /* genFarFarAssign - assignment when both are in far space         */
10591 /*-----------------------------------------------------------------*/
10592 static void
10593 genFarFarAssign (operand * result, operand * right, iCode * ic)
10594 {
10595   int size = AOP_SIZE (right);
10596   int offset = 0;
10597   symbol *rSym = NULL;
10598
10599   if (size == 1)
10600   {
10601       /* quick & easy case. */
10602       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10603       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10604       freeAsmop (right, NULL, ic, FALSE);
10605       /* now assign DPTR to result */
10606       _G.accInUse++;
10607       aopOp(result, ic, FALSE, FALSE);
10608       _G.accInUse--;
10609       aopPut(AOP(result), "a", 0);
10610       freeAsmop(result, NULL, ic, FALSE);
10611       return;
10612   }
10613   
10614   /* See if we've got an underlying symbol to abuse. */
10615   if (IS_SYMOP(result) && OP_SYMBOL(result))
10616   {
10617       if (IS_TRUE_SYMOP(result))
10618       {
10619           rSym = OP_SYMBOL(result);
10620       }
10621       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10622       {
10623           rSym = OP_SYMBOL(result)->usl.spillLoc;
10624       }
10625   }
10626              
10627   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10628   {
10629       /* We can use the '390 auto-toggle feature to good effect here. */
10630       
10631       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10632       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10633       emitcode ("mov", "dptr,#%s", rSym->rname); 
10634       /* DP2 = result, DP1 = right, DP1 is current. */
10635       while (size)
10636       {
10637           emitcode("movx", "a,@dptr");
10638           emitcode("movx", "@dptr,a");
10639           if (--size)
10640           {
10641                emitcode("inc", "dptr");
10642                emitcode("inc", "dptr");
10643           }
10644       }
10645       emitcode("mov", "dps,#0");
10646       freeAsmop (right, NULL, ic, FALSE);
10647 #if 0
10648 some alternative code for processors without auto-toggle
10649 no time to test now, so later well put in...kpb
10650         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10651         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10652         emitcode ("mov", "dptr,#%s", rSym->rname); 
10653         /* DP2 = result, DP1 = right, DP1 is current. */
10654         while (size)
10655         {
10656           --size;
10657           emitcode("movx", "a,@dptr");
10658           if (size)
10659             emitcode("inc", "dptr");
10660           emitcode("inc", "dps");
10661           emitcode("movx", "@dptr,a");
10662           if (size)
10663             emitcode("inc", "dptr");
10664           emitcode("inc", "dps");
10665         }
10666         emitcode("mov", "dps,#0");
10667         freeAsmop (right, NULL, ic, FALSE);
10668 #endif
10669   }
10670   else
10671   {
10672       D (emitcode (";", "genFarFarAssign"););
10673       aopOp (result, ic, TRUE, TRUE);
10674
10675       _startLazyDPSEvaluation ();
10676       
10677       while (size--)
10678         {
10679           aopPut (AOP (result),
10680                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10681           offset++;
10682         }
10683       _endLazyDPSEvaluation ();
10684       freeAsmop (result, NULL, ic, FALSE);
10685       freeAsmop (right, NULL, ic, FALSE);
10686   }
10687 }
10688
10689 /*-----------------------------------------------------------------*/
10690 /* genAssign - generate code for assignment                        */
10691 /*-----------------------------------------------------------------*/
10692 static void
10693 genAssign (iCode * ic)
10694 {
10695   operand *result, *right;
10696   int size, offset;
10697   unsigned long lit = 0L;
10698
10699   D (emitcode (";", "genAssign ");
10700     );
10701
10702   result = IC_RESULT (ic);
10703   right = IC_RIGHT (ic);
10704
10705   /* if they are the same */
10706   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10707     return;
10708
10709   aopOp (right, ic, FALSE, FALSE);
10710
10711   emitcode (";", "genAssign: resultIsFar = %s",
10712             isOperandInFarSpace (result) ?
10713             "TRUE" : "FALSE");
10714
10715   /* special case both in far space */
10716   if ((AOP_TYPE (right) == AOP_DPTR ||
10717        AOP_TYPE (right) == AOP_DPTR2) &&
10718   /* IS_TRUE_SYMOP(result)       && */
10719       isOperandInFarSpace (result))
10720     {
10721       genFarFarAssign (result, right, ic);
10722       return;
10723     }
10724
10725   aopOp (result, ic, TRUE, FALSE);
10726
10727   /* if they are the same registers */
10728   if (sameRegs (AOP (right), AOP (result)))
10729     goto release;
10730
10731   /* if the result is a bit */
10732   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10733     {
10734       /* if the right size is a literal then
10735          we know what the value is */
10736       if (AOP_TYPE (right) == AOP_LIT)
10737         {
10738           if (((int) operandLitValue (right)))
10739             aopPut (AOP (result), one, 0);
10740           else
10741             aopPut (AOP (result), zero, 0);
10742           goto release;
10743         }
10744
10745       /* the right is also a bit variable */
10746       if (AOP_TYPE (right) == AOP_CRY)
10747         {
10748           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10749           aopPut (AOP (result), "c", 0);
10750           goto release;
10751         }
10752
10753       /* we need to or */
10754       toBoolean (right);
10755       aopPut (AOP (result), "a", 0);
10756       goto release;
10757     }
10758
10759   /* bit variables done */
10760   /* general case */
10761   size = AOP_SIZE (result);
10762   offset = 0;
10763   if (AOP_TYPE (right) == AOP_LIT)
10764     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10765
10766   if ((size > 1) &&
10767       (AOP_TYPE (result) != AOP_REG) &&
10768       (AOP_TYPE (right) == AOP_LIT) &&
10769       !IS_FLOAT (operandType (right)))
10770     {
10771       _startLazyDPSEvaluation ();
10772       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10773         {
10774           aopPut (AOP (result),
10775                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10776                   offset);
10777           offset++;
10778           size--;
10779         }
10780       /* And now fill the rest with zeros. */
10781       if (size)
10782         {
10783           emitcode ("clr", "a");
10784         }
10785       while (size--)
10786         {
10787           aopPut (AOP (result), "a", offset++);
10788         }
10789       _endLazyDPSEvaluation ();
10790     }
10791   else
10792     {
10793       _startLazyDPSEvaluation ();
10794       while (size--)
10795         {
10796           aopPut (AOP (result),
10797                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10798                   offset);
10799           offset++;
10800         }
10801       _endLazyDPSEvaluation ();
10802     }
10803
10804 release:
10805   freeAsmop (right, NULL, ic, FALSE);
10806   freeAsmop (result, NULL, ic, TRUE);
10807 }
10808
10809 /*-----------------------------------------------------------------*/
10810 /* genJumpTab - generates code for jump table                      */
10811 /*-----------------------------------------------------------------*/
10812 static void
10813 genJumpTab (iCode * ic)
10814 {
10815   symbol *jtab;
10816   char *l;
10817
10818   D (emitcode (";", "genJumpTab ");
10819     );
10820
10821   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10822   /* get the condition into accumulator */
10823   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10824   MOVA (l);
10825   /* multiply by four! */
10826   emitcode ("add", "a,acc");
10827   emitcode ("add", "a,acc");
10828   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10829
10830   jtab = newiTempLabel (NULL);
10831   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10832   emitcode ("jmp", "@a+dptr");
10833   emitcode ("", "!tlabeldef", jtab->key + 100);
10834   /* now generate the jump labels */
10835   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10836        jtab = setNextItem (IC_JTLABELS (ic)))
10837     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10838
10839 }
10840
10841 /*-----------------------------------------------------------------*/
10842 /* genCast - gen code for casting                                  */
10843 /*-----------------------------------------------------------------*/
10844 static void
10845 genCast (iCode * ic)
10846 {
10847   operand *result = IC_RESULT (ic);
10848   sym_link *ctype = operandType (IC_LEFT (ic));
10849   sym_link *rtype = operandType (IC_RIGHT (ic));
10850   operand *right = IC_RIGHT (ic);
10851   int size, offset;
10852
10853   D (emitcode (";", "genCast ");
10854     );
10855
10856   /* if they are equivalent then do nothing */
10857   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10858     return;
10859
10860   aopOp (right, ic, FALSE, FALSE);
10861   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10862
10863   /* if the result is a bit */
10864   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10865   if (IS_BITVAR(OP_SYMBOL(result)->type))
10866     {
10867       /* if the right size is a literal then
10868          we know what the value is */
10869       if (AOP_TYPE (right) == AOP_LIT)
10870         {
10871           if (((int) operandLitValue (right)))
10872             aopPut (AOP (result), one, 0);
10873           else
10874             aopPut (AOP (result), zero, 0);
10875
10876           goto release;
10877         }
10878
10879       /* the right is also a bit variable */
10880       if (AOP_TYPE (right) == AOP_CRY)
10881         {
10882           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10883           aopPut (AOP (result), "c", 0);
10884           goto release;
10885         }
10886
10887       /* we need to or */
10888       toBoolean (right);
10889       aopPut (AOP (result), "a", 0);
10890       goto release;
10891     }
10892
10893   /* if they are the same size : or less */
10894   if (AOP_SIZE (result) <= AOP_SIZE (right))
10895     {
10896
10897       /* if they are in the same place */
10898       if (sameRegs (AOP (right), AOP (result)))
10899         goto release;
10900
10901       /* if they in different places then copy */
10902       size = AOP_SIZE (result);
10903       offset = 0;
10904       _startLazyDPSEvaluation ();
10905       while (size--)
10906         {
10907           aopPut (AOP (result),
10908                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10909                   offset);
10910           offset++;
10911         }
10912       _endLazyDPSEvaluation ();
10913       goto release;
10914     }
10915
10916
10917   /* if the result is of type pointer */
10918   if (IS_PTR (ctype))
10919     {
10920
10921       int p_type;
10922       sym_link *type = operandType (right);
10923
10924       /* pointer to generic pointer */
10925       if (IS_GENPTR (ctype))
10926         {
10927           if (IS_PTR (type))
10928             {
10929               p_type = DCL_TYPE (type);
10930             }
10931           else
10932             {
10933 #if OLD_CAST_BEHAVIOR
10934               /* KV: we are converting a non-pointer type to
10935                * a generic pointer. This (ifdef'd out) code
10936                * says that the resulting generic pointer
10937                * should have the same class as the storage
10938                * location of the non-pointer variable.
10939                *
10940                * For example, converting an int (which happens
10941                * to be stored in DATA space) to a pointer results
10942                * in a DATA generic pointer; if the original int
10943                * in XDATA space, so will be the resulting pointer.
10944                *
10945                * I don't like that behavior, and thus this change:
10946                * all such conversions will be forced to XDATA and
10947                * throw a warning. If you want some non-XDATA
10948                * type, or you want to suppress the warning, you
10949                * must go through an intermediate cast, like so:
10950                *
10951                * char _generic *gp = (char _xdata *)(intVar);
10952                */
10953               sym_link *etype = getSpec (type);
10954
10955               /* we have to go by the storage class */
10956               if (SPEC_OCLS (etype) != generic)
10957                 {
10958                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10959                 }
10960               else
10961 #endif
10962                 {
10963                   /* Converting unknown class (i.e. register variable)
10964                    * to generic pointer. This is not good, but
10965                    * we'll make a guess (and throw a warning).
10966                    */
10967                   p_type = FPOINTER;
10968                   werror (W_INT_TO_GEN_PTR_CAST);
10969                 }
10970             }
10971
10972           /* the first two bytes are known */
10973           size = GPTRSIZE - 1;
10974           offset = 0;
10975           _startLazyDPSEvaluation ();
10976           while (size--)
10977             {
10978               aopPut (AOP (result),
10979                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10980                       offset);
10981               offset++;
10982             }
10983           _endLazyDPSEvaluation ();
10984
10985           /* the last byte depending on type */
10986             {
10987                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10988                 char gpValStr[10];
10989             
10990                 if (gpVal == -1)
10991                 {
10992                     // pointerTypeToGPByte will have bitched.
10993                     exit(1);
10994                 }
10995             
10996                 sprintf(gpValStr, "#0x%d", gpVal);
10997                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
10998             }
10999           goto release;
11000         }
11001
11002       /* just copy the pointers */
11003       size = AOP_SIZE (result);
11004       offset = 0;
11005       _startLazyDPSEvaluation ();
11006       while (size--)
11007         {
11008           aopPut (AOP (result),
11009                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11010                   offset);
11011           offset++;
11012         }
11013       _endLazyDPSEvaluation ();
11014       goto release;
11015     }
11016
11017   /* so we now know that the size of destination is greater
11018      than the size of the source */
11019   /* we move to result for the size of source */
11020   size = AOP_SIZE (right);
11021   offset = 0;
11022   _startLazyDPSEvaluation ();
11023   while (size--)
11024     {
11025       aopPut (AOP (result),
11026               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11027               offset);
11028       offset++;
11029     }
11030   _endLazyDPSEvaluation ();
11031
11032   /* now depending on the sign of the source && destination */
11033   size = AOP_SIZE (result) - AOP_SIZE (right);
11034   /* if unsigned or not an integral type */
11035   /* also, if the source is a bit, we don't need to sign extend, because
11036    * it can't possibly have set the sign bit.
11037    */
11038   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11039     {
11040       while (size--)
11041         {
11042           aopPut (AOP (result), zero, offset++);
11043         }
11044     }
11045   else
11046     {
11047       /* we need to extend the sign :{ */
11048       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
11049                         FALSE, FALSE, TRUE);
11050       MOVA (l);
11051       emitcode ("rlc", "a");
11052       emitcode ("subb", "a,acc");
11053       while (size--)
11054         aopPut (AOP (result), "a", offset++);
11055     }
11056
11057   /* we are done hurray !!!! */
11058
11059 release:
11060   freeAsmop (right, NULL, ic, TRUE);
11061   freeAsmop (result, NULL, ic, TRUE);
11062
11063 }
11064
11065 /*-----------------------------------------------------------------*/
11066 /* genDjnz - generate decrement & jump if not zero instrucion      */
11067 /*-----------------------------------------------------------------*/
11068 static int
11069 genDjnz (iCode * ic, iCode * ifx)
11070 {
11071   symbol *lbl, *lbl1;
11072   if (!ifx)
11073     return 0;
11074
11075   /* if the if condition has a false label
11076      then we cannot save */
11077   if (IC_FALSE (ifx))
11078     return 0;
11079
11080   /* if the minus is not of the form
11081      a = a - 1 */
11082   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11083       !IS_OP_LITERAL (IC_RIGHT (ic)))
11084     return 0;
11085
11086   if (operandLitValue (IC_RIGHT (ic)) != 1)
11087     return 0;
11088
11089   /* if the size of this greater than one then no
11090      saving */
11091   if (getSize (operandType (IC_RESULT (ic))) > 1)
11092     return 0;
11093
11094   /* otherwise we can save BIG */
11095   D(emitcode(";", "genDjnz"););
11096
11097   lbl = newiTempLabel (NULL);
11098   lbl1 = newiTempLabel (NULL);
11099
11100   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11101
11102   if (AOP_NEEDSACC(IC_RESULT(ic)))
11103   {
11104       /* If the result is accessed indirectly via
11105        * the accumulator, we must explicitly write
11106        * it back after the decrement.
11107        */
11108       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
11109       
11110       if (strcmp(rByte, "a"))
11111       {
11112            /* Something is hopelessly wrong */
11113            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11114                    __FILE__, __LINE__);
11115            /* We can just give up; the generated code will be inefficient,
11116             * but what the hey.
11117             */
11118            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11119            return 0;
11120       }
11121       emitcode ("dec", "%s", rByte);
11122       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11123       emitcode ("jnz", "!tlabel", lbl->key + 100);
11124   }
11125   else if (IS_AOP_PREG (IC_RESULT (ic)))
11126     {
11127       emitcode ("dec", "%s",
11128                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11129       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11130       emitcode ("jnz", "!tlabel", lbl->key + 100);
11131     }
11132   else
11133     {
11134       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
11135                 lbl->key + 100);
11136     }
11137   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11138   emitcode ("", "!tlabeldef", lbl->key + 100);
11139   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11140   emitcode ("", "!tlabeldef", lbl1->key + 100);
11141
11142   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11143   ifx->generated = 1;
11144   return 1;
11145 }
11146
11147 /*-----------------------------------------------------------------*/
11148 /* genReceive - generate code for a receive iCode                  */
11149 /*-----------------------------------------------------------------*/
11150 static void
11151 genReceive (iCode * ic)
11152 {
11153
11154     int size = getSize (operandType (IC_RESULT (ic)));
11155     int offset = 0;
11156     int rb1off ;
11157     
11158     D (emitcode (";", "genReceive ");
11159        );
11160
11161   if (ic->argreg == 1) { /* first parameter */
11162       if (isOperandInFarSpace (IC_RESULT (ic)) &&
11163           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11164            IS_TRUE_SYMOP (IC_RESULT (ic))))
11165           {
11166               offset = fReturnSizeDS390 - size;
11167               while (size--)
11168                   {
11169                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11170                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11171                       offset++;
11172                   }
11173               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11174               size = AOP_SIZE (IC_RESULT (ic));
11175               offset = 0;
11176               while (size--)
11177                   {
11178                       emitcode ("pop", "acc");
11179                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11180                   }
11181               
11182           } else {
11183               _G.accInUse++;
11184               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11185               _G.accInUse--;
11186               assignResultValue (IC_RESULT (ic));
11187           }
11188   } else { /* second receive onwards */
11189       /* this gets a little tricky since unused recevies will be
11190          eliminated, we have saved the reg in the type field . and
11191          we use that to figure out which register to use */
11192       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11193       rb1off = ic->argreg;
11194       while (size--) {
11195           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11196       }
11197       
11198   }
11199   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11200 }
11201
11202 /*-----------------------------------------------------------------*/
11203 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11204 /*-----------------------------------------------------------------*/
11205 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11206 {
11207     operand *from , *to , *count;
11208     symbol *lbl;
11209     bitVect *rsave;
11210     int i;
11211
11212     /* we know it has to be 3 parameters */
11213     assert (nparms == 3);
11214     
11215     rsave = newBitVect(16);
11216     /* save DPTR if it needs to be saved */
11217     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11218             if (bitVectBitValue(ic->rMask,i))
11219                     rsave = bitVectSetBit(rsave,i);
11220     }
11221     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11222                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11223     savermask(rsave);
11224     
11225     to = parms[0];
11226     from = parms[1];
11227     count = parms[2];
11228
11229     aopOp (from, ic->next, FALSE, FALSE);
11230
11231     /* get from into DPTR1 */
11232     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11233     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11234     if (options.model == MODEL_FLAT24) {
11235         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11236     }
11237
11238     freeAsmop (from, NULL, ic, FALSE);
11239     aopOp (to, ic, FALSE, FALSE);
11240     /* get "to" into DPTR */
11241     /* if the operand is already in dptr
11242        then we do nothing else we move the value to dptr */
11243     if (AOP_TYPE (to) != AOP_STR) {
11244         /* if already in DPTR then we need to push */
11245         if (AOP_TYPE(to) == AOP_DPTR) {
11246             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11247             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11248             if (options.model == MODEL_FLAT24)
11249                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11250             emitcode ("pop", "dph");
11251             emitcode ("pop", "dpl");        
11252         } else {
11253             _startLazyDPSEvaluation ();
11254             /* if this is remateriazable */
11255             if (AOP_TYPE (to) == AOP_IMMD) {
11256                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11257             } else {                    /* we need to get it byte by byte */
11258                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11259                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11260                 if (options.model == MODEL_FLAT24) {
11261                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11262                 }
11263             }
11264             _endLazyDPSEvaluation ();
11265         }
11266     }
11267     freeAsmop (to, NULL, ic, FALSE);
11268     _G.dptrInUse = _G.dptr1InUse = 1;
11269     aopOp (count, ic->next->next, FALSE,FALSE);
11270     lbl =newiTempLabel(NULL);
11271
11272     /* now for the actual copy */
11273     if (AOP_TYPE(count) == AOP_LIT && 
11274         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11275         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11276         if (fromc) {
11277             emitcode ("lcall","__bi_memcpyc2x_s");
11278         } else {
11279             emitcode ("lcall","__bi_memcpyx2x_s");
11280         }
11281         freeAsmop (count, NULL, ic, FALSE);
11282     } else {
11283         symbol *lbl1 = newiTempLabel(NULL);
11284         
11285         emitcode (";"," Auto increment but no djnz");
11286         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11287         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11288         freeAsmop (count, NULL, ic, FALSE);
11289         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11290         emitcode ("","!tlabeldef",lbl->key+100);
11291         if (fromc) {
11292             emitcode ("clr","a");
11293             emitcode ("movc", "a,@a+dptr");
11294         } else 
11295             emitcode ("movx", "a,@dptr");
11296         emitcode ("movx", "@dptr,a");
11297         emitcode ("inc", "dptr");
11298         emitcode ("inc", "dptr");
11299         emitcode ("mov","a,b");
11300         emitcode ("orl","a,_ap");
11301         emitcode ("jz","!tlabel",lbl1->key+100);
11302         emitcode ("mov","a,_ap");
11303         emitcode ("add","a,#!constbyte",0xFF);
11304         emitcode ("mov","_ap,a");
11305         emitcode ("mov","a,b");
11306         emitcode ("addc","a,#!constbyte",0xFF);
11307         emitcode ("mov","b,a");
11308         emitcode ("sjmp","!tlabel",lbl->key+100);
11309         emitcode ("","!tlabeldef",lbl1->key+100);
11310     }
11311     emitcode ("mov", "dps,#0"); 
11312     _G.dptrInUse = _G.dptr1InUse = 0;
11313     unsavermask(rsave);
11314
11315 }
11316
11317 /*-----------------------------------------------------------------*/
11318 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11319 /*-----------------------------------------------------------------*/
11320 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11321 {
11322     operand *from , *to , *count;
11323     symbol *lbl,*lbl2;
11324     bitVect *rsave;
11325     int i;
11326
11327     /* we know it has to be 3 parameters */
11328     assert (nparms == 3);
11329     
11330     rsave = newBitVect(16);
11331     /* save DPTR if it needs to be saved */
11332     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11333             if (bitVectBitValue(ic->rMask,i))
11334                     rsave = bitVectSetBit(rsave,i);
11335     }
11336     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11337                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11338     savermask(rsave);
11339     
11340     to = parms[0];
11341     from = parms[1];
11342     count = parms[2];
11343
11344     aopOp (from, ic->next, FALSE, FALSE);
11345
11346     /* get from into DPTR1 */
11347     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11348     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11349     if (options.model == MODEL_FLAT24) {
11350         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11351     }
11352
11353     freeAsmop (from, NULL, ic, FALSE);
11354     aopOp (to, ic, FALSE, FALSE);
11355     /* get "to" into DPTR */
11356     /* if the operand is already in dptr
11357        then we do nothing else we move the value to dptr */
11358     if (AOP_TYPE (to) != AOP_STR) {
11359         /* if already in DPTR then we need to push */
11360         if (AOP_TYPE(to) == AOP_DPTR) {
11361             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11362             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11363             if (options.model == MODEL_FLAT24)
11364                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11365             emitcode ("pop", "dph");
11366             emitcode ("pop", "dpl");        
11367         } else {
11368             _startLazyDPSEvaluation ();
11369             /* if this is remateriazable */
11370             if (AOP_TYPE (to) == AOP_IMMD) {
11371                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11372             } else {                    /* we need to get it byte by byte */
11373                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11374                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11375                 if (options.model == MODEL_FLAT24) {
11376                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11377                 }
11378             }
11379             _endLazyDPSEvaluation ();
11380         }
11381     }
11382     freeAsmop (to, NULL, ic, FALSE);
11383     _G.dptrInUse = _G.dptr1InUse = 1;
11384     aopOp (count, ic->next->next, FALSE,FALSE);
11385     lbl =newiTempLabel(NULL);
11386     lbl2 =newiTempLabel(NULL);
11387
11388     /* now for the actual compare */
11389     if (AOP_TYPE(count) == AOP_LIT && 
11390         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11391         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11392         if (fromc)
11393             emitcode("lcall","__bi_memcmpc2x_s");
11394         else
11395             emitcode("lcall","__bi_memcmpx2x_s");
11396         freeAsmop (count, NULL, ic, FALSE);
11397         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11398         aopPut(AOP(IC_RESULT(ic)),"a",0);
11399         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11400     } else {
11401         symbol *lbl1 = newiTempLabel(NULL);
11402
11403         emitcode("push","ar0");         
11404         emitcode (";"," Auto increment but no djnz");
11405         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11406         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11407         freeAsmop (count, NULL, ic, FALSE);
11408         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11409         emitcode ("","!tlabeldef",lbl->key+100);
11410         if (fromc) {
11411             emitcode ("clr","a");
11412             emitcode ("movc", "a,@a+dptr");
11413         } else 
11414             emitcode ("movx", "a,@dptr");
11415         emitcode ("mov","r0,a");
11416         emitcode ("movx", "a,@dptr");
11417         emitcode ("clr","c");
11418         emitcode ("subb","a,r0");
11419         emitcode ("jnz","!tlabel",lbl2->key+100);
11420         emitcode ("inc", "dptr");
11421         emitcode ("inc", "dptr");
11422         emitcode ("mov","a,b");
11423         emitcode ("orl","a,_ap");
11424         emitcode ("jz","!tlabel",lbl1->key+100);
11425         emitcode ("mov","a,_ap");
11426         emitcode ("add","a,#!constbyte",0xFF);
11427         emitcode ("mov","_ap,a");
11428         emitcode ("mov","a,b");
11429         emitcode ("addc","a,#!constbyte",0xFF);
11430         emitcode ("mov","b,a");
11431         emitcode ("sjmp","!tlabel",lbl->key+100);
11432         emitcode ("","!tlabeldef",lbl1->key+100);
11433         emitcode ("clr","a");
11434         emitcode ("","!tlabeldef",lbl2->key+100);
11435         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11436         aopPut(AOP(IC_RESULT(ic)),"a",0);
11437         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11438         emitcode("pop","ar0");
11439         emitcode ("mov", "dps,#0");      
11440     }
11441     _G.dptrInUse = _G.dptr1InUse = 0;
11442     unsavermask(rsave);
11443
11444 }
11445
11446 /*-----------------------------------------------------------------*/
11447 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11448 /* port, first parameter output area second parameter pointer to   */
11449 /* port third parameter count                                      */
11450 /*-----------------------------------------------------------------*/
11451 static void genInp( iCode *ic, int nparms, operand **parms)
11452 {
11453     operand *from , *to , *count;
11454     symbol *lbl;
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, TRUE));
11479     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11480     if (options.model == MODEL_FLAT24) {
11481         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
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, TRUE));
11493             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11494             if (options.model == MODEL_FLAT24)
11495                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
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, FALSE));
11503             } else {                    /* we need to get it byte by byte */
11504                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11505                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11506                 if (options.model == MODEL_FLAT24) {
11507                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11508                 }
11509             }
11510             _endLazyDPSEvaluation ();
11511         }
11512     }
11513     freeAsmop (to, NULL, ic, FALSE);
11514
11515     _G.dptrInUse = _G.dptr1InUse = 1;
11516     aopOp (count, ic->next->next, FALSE,FALSE);
11517     lbl =newiTempLabel(NULL);
11518
11519     /* now for the actual copy */
11520     if (AOP_TYPE(count) == AOP_LIT && 
11521         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11522         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11523         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11524         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11525         freeAsmop (count, NULL, ic, FALSE);
11526         emitcode ("","!tlabeldef",lbl->key+100);
11527         emitcode ("movx", "a,@dptr");   /* read data from port */
11528         emitcode ("dec","dps");         /* switch to DPTR */
11529         emitcode ("movx", "@dptr,a");   /* save into location */
11530         emitcode ("inc", "dptr");       /* point to next area */
11531         emitcode ("inc","dps");         /* switch to DPTR2 */
11532         emitcode ("djnz","b,!tlabel",lbl->key+100);
11533     } else {
11534         symbol *lbl1 = newiTempLabel(NULL);
11535         
11536         emitcode (";"," Auto increment but no djnz");
11537         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11538         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11539         freeAsmop (count, NULL, ic, FALSE);
11540         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11541         emitcode ("","!tlabeldef",lbl->key+100);
11542         emitcode ("movx", "a,@dptr");
11543         emitcode ("dec","dps");         /* switch to DPTR */
11544         emitcode ("movx", "@dptr,a");
11545         emitcode ("inc", "dptr");
11546         emitcode ("inc","dps");         /* switch to DPTR2 */
11547 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11548 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11549         emitcode ("mov","a,b");
11550         emitcode ("orl","a,_ap");
11551         emitcode ("jz","!tlabel",lbl1->key+100);
11552         emitcode ("mov","a,_ap");
11553         emitcode ("add","a,#!constbyte",0xFF);
11554         emitcode ("mov","_ap,a");
11555         emitcode ("mov","a,b");
11556         emitcode ("addc","a,#!constbyte",0xFF);
11557         emitcode ("mov","b,a");
11558         emitcode ("sjmp","!tlabel",lbl->key+100);
11559         emitcode ("","!tlabeldef",lbl1->key+100);
11560     }
11561     emitcode ("mov", "dps,#0"); 
11562     _G.dptrInUse = _G.dptr1InUse = 0;
11563     unsavermask(rsave);
11564
11565 }
11566
11567 /*-----------------------------------------------------------------*/
11568 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11569 /* port, first parameter output area second parameter pointer to   */
11570 /* port third parameter count                                      */
11571 /*-----------------------------------------------------------------*/
11572 static void genOutp( iCode *ic, int nparms, operand **parms)
11573 {
11574     operand *from , *to , *count;
11575     symbol *lbl;
11576     bitVect *rsave;
11577     int i;
11578
11579     /* we know it has to be 3 parameters */
11580     assert (nparms == 3);
11581     
11582     rsave = newBitVect(16);
11583     /* save DPTR if it needs to be saved */
11584     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11585             if (bitVectBitValue(ic->rMask,i))
11586                     rsave = bitVectSetBit(rsave,i);
11587     }
11588     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11589                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11590     savermask(rsave);
11591     
11592     to = parms[0];
11593     from = parms[1];
11594     count = parms[2];
11595
11596     aopOp (from, ic->next, FALSE, FALSE);
11597
11598     /* get from into DPTR1 */
11599     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11600     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11601     if (options.model == MODEL_FLAT24) {
11602         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11603     }
11604
11605     freeAsmop (from, NULL, ic, FALSE);
11606     aopOp (to, ic, FALSE, FALSE);
11607     /* get "to" into DPTR */
11608     /* if the operand is already in dptr
11609        then we do nothing else we move the value to dptr */
11610     if (AOP_TYPE (to) != AOP_STR) {
11611         /* if already in DPTR then we need to push */
11612         if (AOP_TYPE(to) == AOP_DPTR) {
11613             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11614             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11615             if (options.model == MODEL_FLAT24)
11616                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11617             emitcode ("pop", "dph");
11618             emitcode ("pop", "dpl");        
11619         } else {
11620             _startLazyDPSEvaluation ();
11621             /* if this is remateriazable */
11622             if (AOP_TYPE (to) == AOP_IMMD) {
11623                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11624             } else {                    /* we need to get it byte by byte */
11625                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11626                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11627                 if (options.model == MODEL_FLAT24) {
11628                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11629                 }
11630             }
11631             _endLazyDPSEvaluation ();
11632         }
11633     }
11634     freeAsmop (to, NULL, ic, FALSE);
11635
11636     _G.dptrInUse = _G.dptr1InUse = 1;
11637     aopOp (count, ic->next->next, FALSE,FALSE);
11638     lbl =newiTempLabel(NULL);
11639
11640     /* now for the actual copy */
11641     if (AOP_TYPE(count) == AOP_LIT && 
11642         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11643         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11644         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11645         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11646         emitcode ("","!tlabeldef",lbl->key+100);
11647         emitcode ("movx", "a,@dptr");   /* read data from port */
11648         emitcode ("inc","dps");         /* switch to DPTR2 */
11649         emitcode ("movx", "@dptr,a");   /* save into location */
11650         emitcode ("inc", "dptr");       /* point to next area */
11651         emitcode ("dec","dps");         /* switch to DPTR */
11652         emitcode ("djnz","b,!tlabel",lbl->key+100);
11653         freeAsmop (count, NULL, ic, FALSE);
11654     } else {
11655         symbol *lbl1 = newiTempLabel(NULL);
11656         
11657         emitcode (";"," Auto increment but no djnz");
11658         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11659         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11660         freeAsmop (count, NULL, ic, FALSE);
11661         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11662         emitcode ("","!tlabeldef",lbl->key+100);
11663         emitcode ("movx", "a,@dptr");
11664         emitcode ("inc", "dptr");
11665         emitcode ("inc","dps");         /* switch to DPTR2 */
11666         emitcode ("movx", "@dptr,a");
11667         emitcode ("dec","dps");         /* switch to DPTR */
11668         emitcode ("mov","a,b");
11669         emitcode ("orl","a,_ap");
11670         emitcode ("jz","!tlabel",lbl1->key+100);
11671         emitcode ("mov","a,_ap");
11672         emitcode ("add","a,#!constbyte",0xFF);
11673         emitcode ("mov","_ap,a");
11674         emitcode ("mov","a,b");
11675         emitcode ("addc","a,#!constbyte",0xFF);
11676         emitcode ("mov","b,a");
11677         emitcode ("sjmp","!tlabel",lbl->key+100);
11678         emitcode ("","!tlabeldef",lbl1->key+100);
11679     }
11680     emitcode ("mov", "dps,#0"); 
11681     _G.dptrInUse = _G.dptr1InUse = 0;
11682     unsavermask(rsave);
11683
11684 }
11685
11686 /*-----------------------------------------------------------------*/
11687 /* genSwapW - swap lower & high order bytes                        */
11688 /*-----------------------------------------------------------------*/
11689 static void genSwapW(iCode *ic, int nparms, operand **parms)
11690 {
11691     operand *dest;
11692     operand *src;
11693     assert (nparms==1);
11694
11695     src = parms[0];
11696     dest=IC_RESULT(ic);
11697
11698     assert(getSize(operandType(src))==2);
11699
11700     aopOp (src, ic, FALSE, FALSE);
11701     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11702     _G.accInUse++;
11703     emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11704     _G.accInUse--;
11705     freeAsmop (src, NULL, ic, FALSE);
11706     
11707     aopOp (dest,ic, FALSE, FALSE);
11708     aopPut(AOP(dest),"b",0);
11709     aopPut(AOP(dest),"a",1);
11710     freeAsmop (dest, NULL, ic, FALSE);    
11711 }
11712
11713 /*-----------------------------------------------------------------*/
11714 /* genMemsetX - gencode for memSetX data                           */
11715 /*-----------------------------------------------------------------*/
11716 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11717 {
11718     operand *to , *val , *count;
11719     symbol *lbl;
11720     char *l;
11721     int i;
11722     bitVect *rsave = NULL;
11723
11724     /* we know it has to be 3 parameters */
11725     assert (nparms == 3);
11726     
11727     to = parms[0];
11728     val = parms[1];
11729     count = parms[2];
11730         
11731     /* save DPTR if it needs to be saved */
11732     rsave = newBitVect(16);
11733     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11734             if (bitVectBitValue(ic->rMask,i))
11735                     rsave = bitVectSetBit(rsave,i);
11736     }
11737     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11738                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11739     savermask(rsave);
11740
11741     aopOp (to, ic, FALSE, FALSE);
11742     /* get "to" into DPTR */
11743     /* if the operand is already in dptr
11744        then we do nothing else we move the value to dptr */
11745     if (AOP_TYPE (to) != AOP_STR) {
11746         /* if already in DPTR then we need to push */
11747         if (AOP_TYPE(to) == AOP_DPTR) {
11748             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11749             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11750             if (options.model == MODEL_FLAT24)
11751                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11752             emitcode ("pop", "dph");
11753             emitcode ("pop", "dpl");        
11754         } else {
11755             _startLazyDPSEvaluation ();
11756             /* if this is remateriazable */
11757             if (AOP_TYPE (to) == AOP_IMMD) {
11758                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11759             } else {                    /* we need to get it byte by byte */
11760                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11761                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11762                 if (options.model == MODEL_FLAT24) {
11763                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11764                 }
11765             }
11766             _endLazyDPSEvaluation ();
11767         }
11768     }
11769     freeAsmop (to, NULL, ic, FALSE);
11770
11771     aopOp (val, ic->next->next, FALSE,FALSE);
11772     aopOp (count, ic->next->next, FALSE,FALSE);    
11773     lbl =newiTempLabel(NULL);
11774     /* now for the actual copy */
11775     if (AOP_TYPE(count) == AOP_LIT && 
11776         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11777         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11778         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11779         MOVA(l);
11780         emitcode ("","!tlabeldef",lbl->key+100);
11781         emitcode ("movx", "@dptr,a");
11782         emitcode ("inc", "dptr");
11783         emitcode ("djnz","b,!tlabel",lbl->key+100);
11784     } else {
11785         symbol *lbl1 = newiTempLabel(NULL);
11786         
11787         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11788         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11789         emitcode ("","!tlabeldef",lbl->key+100);
11790         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11791         MOVA(l);
11792         emitcode ("movx", "@dptr,a");
11793         emitcode ("inc", "dptr");
11794         emitcode ("mov","a,b");
11795         emitcode ("orl","a,_ap");
11796         emitcode ("jz","!tlabel",lbl1->key+100);
11797         emitcode ("mov","a,_ap");
11798         emitcode ("add","a,#!constbyte",0xFF);
11799         emitcode ("mov","_ap,a");
11800         emitcode ("mov","a,b");
11801         emitcode ("addc","a,#!constbyte",0xFF);
11802         emitcode ("mov","b,a");
11803         emitcode ("sjmp","!tlabel",lbl->key+100);
11804         emitcode ("","!tlabeldef",lbl1->key+100);
11805     }
11806     freeAsmop (count, NULL, ic, FALSE);
11807     unsavermask(rsave);
11808 }
11809
11810 /*-----------------------------------------------------------------*/
11811 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11812 /*-----------------------------------------------------------------*/
11813 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11814 {
11815         bitVect *rsave ;
11816         operand *pnum, *result;
11817         int i;
11818     
11819         assert (nparms==1);
11820         /* save registers that need to be saved */
11821         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11822                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11823     
11824         pnum = parms[0]; 
11825         aopOp (pnum, ic, FALSE, FALSE);
11826         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11827         freeAsmop (pnum, NULL, ic, FALSE);
11828         emitcode ("lcall","NatLib_LoadPrimitive");
11829         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11830         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11831             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11832                 for (i = (size-1) ; i >= 0 ; i-- ) {
11833                         emitcode ("push","a%s",javaRet[i]);
11834                 }
11835                 for (i=0; i < size ; i++ ) {
11836                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11837                 }
11838         } else {
11839                 for (i = 0 ; i < size ; i++ ) {
11840                         aopPut(AOP(result),javaRet[i],i);
11841                 }
11842         }    
11843         freeAsmop (result, NULL, ic, FALSE);
11844         unsavermask(rsave);
11845 }
11846
11847 /*-----------------------------------------------------------------*/
11848 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11849 /*-----------------------------------------------------------------*/
11850 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11851 {
11852         bitVect *rsave ;
11853         operand *pnum, *result;
11854         int size = 3;
11855         int i;
11856     
11857         assert (nparms==1);
11858         /* save registers that need to be saved */
11859         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11860                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11861     
11862         pnum = parms[0]; 
11863         aopOp (pnum, ic, FALSE, FALSE);
11864         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11865         freeAsmop (pnum, NULL, ic, FALSE);
11866         emitcode ("lcall","NatLib_LoadPointer");
11867         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11868         if (AOP_TYPE(result)!=AOP_STR) {
11869                 for (i = 0 ; i < size ; i++ ) {
11870                         aopPut(AOP(result),fReturn[i],i);
11871                 }
11872         }    
11873         freeAsmop (result, NULL, ic, FALSE);
11874         unsavermask(rsave);
11875 }
11876
11877 /*-----------------------------------------------------------------*/
11878 /* genNatLibInstallStateBlock -                                    */
11879 /*-----------------------------------------------------------------*/
11880 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11881                                        operand **parms, const char *name)
11882 {
11883         bitVect *rsave ;
11884         operand *psb, *handle;
11885         assert (nparms==2);
11886
11887         /* save registers that need to be saved */
11888         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11889                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11890         psb = parms[0];
11891         handle = parms[1];
11892
11893         /* put pointer to state block into DPTR1 */
11894         aopOp (psb, ic, FALSE, FALSE);
11895         if (AOP_TYPE (psb) == AOP_IMMD) {
11896                 emitcode ("mov","dps,#1");
11897                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11898                 emitcode ("mov","dps,#0");
11899         } else {
11900                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11901                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11902                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11903         }
11904         freeAsmop (psb, NULL, ic, FALSE);
11905
11906         /* put libraryID into DPTR */
11907         emitcode ("mov","dptr,#LibraryID");
11908
11909         /* put handle into r3:r2 */
11910         aopOp (handle, ic, FALSE, FALSE);
11911         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11912                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11913                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11914                 emitcode ("pop","ar3");
11915                 emitcode ("pop","ar2");
11916         } else {        
11917                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11918                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11919         }
11920         freeAsmop (psb, NULL, ic, FALSE);
11921
11922         /* make the call */
11923         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11924
11925         /* put return value into place*/
11926         _G.accInUse++;
11927         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11928         _G.accInUse--;
11929         aopPut(AOP(IC_RESULT(ic)),"a",0);
11930         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11931         unsavermask(rsave);
11932 }
11933
11934 /*-----------------------------------------------------------------*/
11935 /* genNatLibRemoveStateBlock -                                     */
11936 /*-----------------------------------------------------------------*/
11937 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11938 {
11939         bitVect *rsave ;
11940
11941         assert(nparms==0);
11942
11943         /* save registers that need to be saved */
11944         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11945                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11946
11947         /* put libraryID into DPTR */
11948         emitcode ("mov","dptr,#LibraryID");
11949         /* make the call */
11950         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11951         unsavermask(rsave);
11952 }
11953
11954 /*-----------------------------------------------------------------*/
11955 /* genNatLibGetStateBlock -                                        */
11956 /*-----------------------------------------------------------------*/
11957 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11958                                    operand **parms,const char *name)
11959 {
11960         bitVect *rsave ;
11961         symbol *lbl = newiTempLabel(NULL);
11962         
11963         assert(nparms==0);
11964         /* save registers that need to be saved */
11965         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11966                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11967
11968         /* put libraryID into DPTR */
11969         emitcode ("mov","dptr,#LibraryID");
11970         /* make the call */
11971         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11972         emitcode ("jnz","!tlabel",lbl->key+100);
11973
11974         /* put return value into place */
11975         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11976         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11977                 emitcode ("push","ar3");
11978                 emitcode ("push","ar2");
11979                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11980                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11981         } else {
11982                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11983                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11984         }
11985         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11986         emitcode ("","!tlabeldef",lbl->key+100);
11987         unsavermask(rsave);
11988 }
11989
11990 /*-----------------------------------------------------------------*/
11991 /* genMMMalloc -                                                   */
11992 /*-----------------------------------------------------------------*/
11993 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11994                          int size, const char *name)
11995 {
11996         bitVect *rsave ;
11997         operand *bsize;
11998         symbol *rsym;
11999         symbol *lbl = newiTempLabel(NULL);
12000
12001         assert (nparms == 1);
12002         /* save registers that need to be saved */
12003         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12004                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12005         
12006         bsize=parms[0];
12007         aopOp (bsize,ic,FALSE,FALSE);
12008
12009         /* put the size in R4-R2 */
12010         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12011                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12012                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12013                 if (size==3) {
12014                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12015                         emitcode("pop","ar4");
12016                 }
12017                 emitcode("pop","ar3");
12018                 emitcode("pop","ar2");          
12019         } else {
12020                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12021                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12022                 if (size==3) {
12023                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12024                 }
12025         }
12026         freeAsmop (bsize, NULL, ic, FALSE);
12027
12028         /* make the call */
12029         emitcode ("lcall","MM_%s",name);
12030         emitcode ("jz","!tlabel",lbl->key+100);
12031         emitcode ("mov","r2,#!constbyte",0xff);
12032         emitcode ("mov","r3,#!constbyte",0xff);
12033         emitcode ("","!tlabeldef",lbl->key+100);
12034         /* we don't care about the pointer : we just save the handle */
12035         rsym = OP_SYMBOL(IC_RESULT(ic));
12036         if (rsym->liveFrom != rsym->liveTo) {
12037                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12038                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12039                         emitcode ("push","ar3");
12040                         emitcode ("push","ar2");
12041                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12042                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12043                 } else {
12044                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12045                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12046                 }
12047                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12048         }
12049         unsavermask(rsave);
12050 }
12051
12052 /*-----------------------------------------------------------------*/
12053 /* genMMDeref -                                                    */
12054 /*-----------------------------------------------------------------*/
12055 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12056 {
12057         bitVect *rsave ;
12058         operand *handle;
12059
12060         assert (nparms == 1);
12061         /* save registers that need to be saved */
12062         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12063                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12064         
12065         handle=parms[0];
12066         aopOp (handle,ic,FALSE,FALSE);
12067
12068         /* put the size in R4-R2 */
12069         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12070                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12071                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12072                 emitcode("pop","ar3");
12073                 emitcode("pop","ar2");          
12074         } else {
12075                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12076                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12077         }
12078         freeAsmop (handle, NULL, ic, FALSE);
12079
12080         /* make the call */
12081         emitcode ("lcall","MM_Deref");
12082         
12083         {
12084                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12085                 if (rsym->liveFrom != rsym->liveTo) {                   
12086                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12087                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12088                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12089                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12090                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12091                         }
12092                 }
12093         }
12094         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12095         unsavermask(rsave);
12096 }
12097
12098 /*-----------------------------------------------------------------*/
12099 /* genMMUnrestrictedPersist -                                      */
12100 /*-----------------------------------------------------------------*/
12101 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12102 {
12103         bitVect *rsave ;
12104         operand *handle;
12105
12106         assert (nparms == 1);
12107         /* save registers that need to be saved */
12108         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12109                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12110         
12111         handle=parms[0];
12112         aopOp (handle,ic,FALSE,FALSE);
12113
12114         /* put the size in R3-R2 */
12115         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12116                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12117                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12118                 emitcode("pop","ar3");
12119                 emitcode("pop","ar2");          
12120         } else {
12121                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12122                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12123         }
12124         freeAsmop (handle, NULL, ic, FALSE);
12125
12126         /* make the call */
12127         emitcode ("lcall","MM_UnrestrictedPersist");
12128
12129         {
12130                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12131                 if (rsym->liveFrom != rsym->liveTo) {   
12132                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12133                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12134                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12135                 }
12136         }
12137         unsavermask(rsave);
12138 }
12139
12140 /*-----------------------------------------------------------------*/
12141 /* genSystemExecJavaProcess -                                      */
12142 /*-----------------------------------------------------------------*/
12143 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12144 {
12145         bitVect *rsave ;
12146         operand *handle, *pp;
12147
12148         assert (nparms==2);
12149         /* save registers that need to be saved */
12150         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12151                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12152         
12153         pp = parms[0];
12154         handle = parms[1];
12155         
12156         /* put the handle in R3-R2 */
12157         aopOp (handle,ic,FALSE,FALSE);
12158         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12159                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12160                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12161                 emitcode("pop","ar3");
12162                 emitcode("pop","ar2");          
12163         } else {
12164                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12165                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12166         }
12167         freeAsmop (handle, NULL, ic, FALSE);
12168         
12169         /* put pointer in DPTR */
12170         aopOp (pp,ic,FALSE,FALSE);
12171         if (AOP_TYPE(pp) == AOP_IMMD) {
12172                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
12173         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12174                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12175                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12176                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12177         }
12178         freeAsmop (handle, NULL, ic, FALSE);
12179
12180         /* make the call */
12181         emitcode ("lcall","System_ExecJavaProcess");
12182         
12183         /* put result in place */
12184         {
12185                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12186                 if (rsym->liveFrom != rsym->liveTo) {   
12187                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12188                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12189                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12190                 }
12191         }
12192         
12193         unsavermask(rsave);
12194 }
12195
12196 /*-----------------------------------------------------------------*/
12197 /* genSystemRTCRegisters -                                         */
12198 /*-----------------------------------------------------------------*/
12199 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12200                                   char *name)
12201 {
12202         bitVect *rsave ;
12203         operand *pp;
12204
12205         assert (nparms==1);
12206         /* save registers that need to be saved */
12207         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12208                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12209         
12210         pp=parms[0];
12211         /* put pointer in DPTR */
12212         aopOp (pp,ic,FALSE,FALSE);
12213         if (AOP_TYPE (pp) == AOP_IMMD) {
12214                 emitcode ("mov","dps,#1");
12215                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12216                 emitcode ("mov","dps,#0");
12217         } else {
12218                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12219                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12220                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12221         }
12222         freeAsmop (pp, NULL, ic, FALSE);
12223
12224         /* make the call */
12225         emitcode ("lcall","System_%sRTCRegisters",name);
12226
12227         unsavermask(rsave);
12228 }
12229
12230 /*-----------------------------------------------------------------*/
12231 /* genSystemThreadSleep -                                          */
12232 /*-----------------------------------------------------------------*/
12233 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12234 {
12235         bitVect *rsave ;
12236         operand *to, *s;
12237
12238         assert (nparms==1);
12239         /* save registers that need to be saved */
12240         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12241                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12242
12243         to = parms[0];
12244         aopOp(to,ic,FALSE,FALSE);
12245         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12246             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12247                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12248                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12249                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12250                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12251                 emitcode ("pop","ar3");
12252                 emitcode ("pop","ar2");
12253                 emitcode ("pop","ar1");
12254                 emitcode ("pop","ar0");
12255         } else {
12256                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12257                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12258                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12259                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12260         }
12261         freeAsmop (to, NULL, ic, FALSE);
12262
12263         /* suspend in acc */
12264         s = parms[1];
12265         aopOp(s,ic,FALSE,FALSE);
12266         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12267         freeAsmop (s, NULL, ic, FALSE);
12268
12269         /* make the call */
12270         emitcode ("lcall","System_%s",name);
12271
12272         unsavermask(rsave);
12273 }
12274
12275 /*-----------------------------------------------------------------*/
12276 /* genSystemThreadResume -                                         */
12277 /*-----------------------------------------------------------------*/
12278 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12279 {
12280         bitVect *rsave ;
12281         operand *tid,*pid;
12282
12283         assert (nparms==2);
12284         /* save registers that need to be saved */
12285         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12286                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12287         
12288         tid = parms[0];
12289         pid = parms[1];
12290         
12291         /* PID in R0 */
12292         aopOp(pid,ic,FALSE,FALSE);
12293         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12294         freeAsmop (pid, NULL, ic, FALSE);
12295         
12296         /* tid into ACC */
12297         aopOp(tid,ic,FALSE,FALSE);
12298         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12299         freeAsmop (tid, NULL, ic, FALSE);
12300         
12301         emitcode ("lcall","System_ThreadResume");
12302
12303         /* put result into place */
12304         {
12305                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12306                 if (rsym->liveFrom != rsym->liveTo) {   
12307                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12308                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12309                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12310                 }
12311         }
12312         unsavermask(rsave);
12313 }
12314
12315 /*-----------------------------------------------------------------*/
12316 /* genSystemProcessResume -                                        */
12317 /*-----------------------------------------------------------------*/
12318 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12319 {
12320         bitVect *rsave ;
12321         operand *pid;
12322
12323         assert (nparms==1);
12324         /* save registers that need to be saved */
12325         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12326                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12327         
12328         pid = parms[0];
12329         
12330         /* pid into ACC */
12331         aopOp(pid,ic,FALSE,FALSE);
12332         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12333         freeAsmop (pid, NULL, ic, FALSE);
12334         
12335         emitcode ("lcall","System_ProcessResume");
12336
12337         unsavermask(rsave);
12338 }
12339
12340 /*-----------------------------------------------------------------*/
12341 /* genSystem -                                                     */
12342 /*-----------------------------------------------------------------*/
12343 static void genSystem (iCode *ic,int nparms,char *name)
12344 {
12345         assert(nparms == 0);
12346
12347         emitcode ("lcall","System_%s",name);
12348 }
12349
12350 /*-----------------------------------------------------------------*/
12351 /* genSystemPoll -                                                  */
12352 /*-----------------------------------------------------------------*/
12353 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12354 {
12355         bitVect *rsave ;
12356         operand *fp;
12357
12358         assert (nparms==1);
12359         /* save registers that need to be saved */
12360         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12361                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12362
12363         fp = parms[0];
12364         aopOp (fp,ic,FALSE,FALSE);
12365         if (AOP_TYPE (fp) == AOP_IMMD) {
12366                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12367         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12368                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12369                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12370                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12371         }
12372         freeAsmop (fp, NULL, ic, FALSE);
12373
12374         emitcode ("lcall","System_%sPoll",name);
12375
12376         /* put result into place */
12377         {
12378                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12379                 if (rsym->liveFrom != rsym->liveTo) {   
12380                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12381                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12382                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12383                 }
12384         }
12385         unsavermask(rsave);
12386 }
12387
12388 /*-----------------------------------------------------------------*/
12389 /* genSystemGetCurrentID -                                         */
12390 /*-----------------------------------------------------------------*/
12391 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12392 {
12393         assert (nparms==0);
12394
12395         emitcode ("lcall","System_GetCurrent%sId",name);
12396         /* put result into place */
12397         {
12398                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12399                 if (rsym->liveFrom != rsym->liveTo) {   
12400                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12401                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12402                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12403                 }
12404         }
12405 }
12406
12407 /*-----------------------------------------------------------------*/
12408 /* genBuiltIn - calls the appropriate function to  generating code */
12409 /* for a built in function                                         */
12410 /*-----------------------------------------------------------------*/
12411 static void genBuiltIn (iCode *ic)
12412 {
12413         operand *bi_parms[MAX_BUILTIN_ARGS];
12414         int nbi_parms;
12415         iCode *bi_iCode;
12416         symbol *bif;
12417
12418         /* get all the arguments for a built in function */
12419         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12420
12421         /* which function is it */
12422         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12423         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12424                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12425         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12426                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12427         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12428                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12429         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12430                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12431         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12432                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12433         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12434                 genInp(bi_iCode,nbi_parms,bi_parms);
12435         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12436                 genOutp(bi_iCode,nbi_parms,bi_parms);
12437         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12438                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12439                 /* JavaNative builtIns */               
12440         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12441                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12442         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12443                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12444         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12445                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12446         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12447                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12448         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12449                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12450         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12451                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12452         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12453                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12454         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12455                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12456         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12457                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12458         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12459                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12460         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12461                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12462         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12463                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12464         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12465                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12466         } else if (strcmp(bif->name,"MM_Free")==0) {
12467                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12468         } else if (strcmp(bif->name,"MM_Deref")==0) {
12469                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12470         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12471                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12472         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12473                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12474         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12475                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12476         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12477                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12478         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12479                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12480         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12481                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12482         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12483                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12484         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12485                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12486         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12487                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12488         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12489                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12490         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12491                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12492         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12493                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12494         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12495                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12496         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12497                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12498         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12499                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12500         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12501                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12502         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12503                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12504         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12505                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12506         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12507                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12508         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12509                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12510         } else {
12511                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12512                 return ;
12513         }
12514         return ;    
12515 }
12516
12517 /*-----------------------------------------------------------------*/
12518 /* gen390Code - generate code for Dallas 390 based controllers     */
12519 /*-----------------------------------------------------------------*/
12520 void
12521 gen390Code (iCode * lic)
12522 {
12523   iCode *ic;
12524   int cln = 0;
12525
12526   lineHead = lineCurr = NULL;
12527   dptrn[1][0] = "dpl1";
12528   dptrn[1][1] = "dph1";
12529   dptrn[1][2] = "dpx1";
12530   
12531   if (options.model == MODEL_FLAT24) {
12532     fReturnSizeDS390 = 5;
12533     fReturn = fReturn24;
12534   } else {
12535     fReturnSizeDS390 = 4;
12536     fReturn = fReturn16;
12537     options.stack10bit=0;
12538   }
12539 #if 1
12540   /* print the allocation information */
12541   if (allocInfo)
12542     printAllocInfo (currFunc, codeOutFile);
12543 #endif
12544   /* if debug information required */
12545   if (options.debug && currFunc)
12546     {
12547       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12548       _G.debugLine = 1;
12549       if (IS_STATIC (currFunc->etype))
12550         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12551       else
12552         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12553       _G.debugLine = 0;
12554     }
12555   /* stack pointer name */
12556   if (options.useXstack)
12557     spname = "_spx";
12558   else
12559     spname = "sp";
12560
12561
12562   for (ic = lic; ic; ic = ic->next)
12563     {
12564
12565       if (ic->lineno && cln != ic->lineno)
12566         {
12567           if (options.debug)
12568             {
12569               _G.debugLine = 1;
12570               emitcode ("", "C$%s$%d$%d$%d ==.",
12571                         FileBaseName (ic->filename), ic->lineno,
12572                         ic->level, ic->block);
12573               _G.debugLine = 0;
12574             }
12575           if (!options.noCcodeInAsm) {
12576             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12577                       printCLine(ic->filename, ic->lineno));
12578           }
12579           cln = ic->lineno;
12580         }
12581       if (options.iCodeInAsm) {
12582         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12583       }
12584       /* if the result is marked as
12585          spilt and rematerializable or code for
12586          this has already been generated then
12587          do nothing */
12588       if (resultRemat (ic) || ic->generated)
12589         continue;
12590
12591       /* depending on the operation */
12592       switch (ic->op)
12593         {
12594         case '!':
12595           genNot (ic);
12596           break;
12597
12598         case '~':
12599           genCpl (ic);
12600           break;
12601
12602         case UNARYMINUS:
12603           genUminus (ic);
12604           break;
12605
12606         case IPUSH:
12607           genIpush (ic);
12608           break;
12609
12610         case IPOP:
12611           /* IPOP happens only when trying to restore a
12612              spilt live range, if there is an ifx statement
12613              following this pop then the if statement might
12614              be using some of the registers being popped which
12615              would destory the contents of the register so
12616              we need to check for this condition and handle it */
12617           if (ic->next &&
12618               ic->next->op == IFX &&
12619               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12620             genIfx (ic->next, ic);
12621           else
12622             genIpop (ic);
12623           break;
12624
12625         case CALL:
12626           genCall (ic);
12627           break;
12628
12629         case PCALL:
12630           genPcall (ic);
12631           break;
12632
12633         case FUNCTION:
12634           genFunction (ic);
12635           break;
12636
12637         case ENDFUNCTION:
12638           genEndFunction (ic);
12639           break;
12640
12641         case RETURN:
12642           genRet (ic);
12643           break;
12644
12645         case LABEL:
12646           genLabel (ic);
12647           break;
12648
12649         case GOTO:
12650           genGoto (ic);
12651           break;
12652
12653         case '+':
12654           genPlus (ic);
12655           break;
12656
12657         case '-':
12658           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12659             genMinus (ic);
12660           break;
12661
12662         case '*':
12663           genMult (ic);
12664           break;
12665
12666         case '/':
12667           genDiv (ic);
12668           break;
12669
12670         case '%':
12671           genMod (ic);
12672           break;
12673
12674         case '>':
12675           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12676           break;
12677
12678         case '<':
12679           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12680           break;
12681
12682         case LE_OP:
12683         case GE_OP:
12684         case NE_OP:
12685
12686           /* note these two are xlated by algebraic equivalence
12687              during parsing SDCC.y */
12688           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12689                   "got '>=' or '<=' shouldn't have come here");
12690           break;
12691
12692         case EQ_OP:
12693           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12694           break;
12695
12696         case AND_OP:
12697           genAndOp (ic);
12698           break;
12699
12700         case OR_OP:
12701           genOrOp (ic);
12702           break;
12703
12704         case '^':
12705           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12706           break;
12707
12708         case '|':
12709           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12710           break;
12711
12712         case BITWISEAND:
12713           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12714           break;
12715
12716         case INLINEASM:
12717           genInline (ic);
12718           break;
12719
12720         case RRC:
12721           genRRC (ic);
12722           break;
12723
12724         case RLC:
12725           genRLC (ic);
12726           break;
12727
12728         case GETHBIT:
12729           genGetHbit (ic);
12730           break;
12731
12732         case LEFT_OP:
12733           genLeftShift (ic);
12734           break;
12735
12736         case RIGHT_OP:
12737           genRightShift (ic);
12738           break;
12739
12740         case GET_VALUE_AT_ADDRESS:
12741           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12742           break;
12743
12744         case '=':
12745           if (POINTER_SET (ic))
12746             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12747           else
12748             genAssign (ic);
12749           break;
12750
12751         case IFX:
12752           genIfx (ic, NULL);
12753           break;
12754
12755         case ADDRESS_OF:
12756           genAddrOf (ic);
12757           break;
12758
12759         case JUMPTABLE:
12760           genJumpTab (ic);
12761           break;
12762
12763         case CAST:
12764           genCast (ic);
12765           break;
12766
12767         case RECEIVE:
12768           genReceive (ic);
12769           break;
12770
12771         case SEND:
12772           if (ic->builtinSEND) genBuiltIn(ic);
12773           else addSet (&_G.sendSet, ic);
12774           break;
12775
12776         case ARRAYINIT:
12777             genArrayInit(ic);
12778             break;
12779             
12780         default:
12781           ic = ic;
12782         }
12783     }
12784
12785
12786   /* now we are ready to call the
12787      peep hole optimizer */
12788   if (!options.nopeep)
12789     peepHole (&lineHead);
12790
12791   /* now do the actual printing */
12792   printLine (lineHead, codeOutFile);
12793   return;
12794 }