Cleanups, minor improvements, death to strcpy strcat sprintf
[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_strdup(sym->rname);   
594       aop->size = FPTRSIZE;
595       return aop;
596     }
597   
598   /* only remaining is far space */
599   /* in which case DPTR gets the address */
600   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
601   if (useDP2)
602     {
603       genSetDPTR (1);
604       _flushLazyDPS ();
605       emitcode ("mov", "dptr,#%s", sym->rname);
606       genSetDPTR (0);
607     }
608   else
609     {
610       emitcode ("mov", "dptr,#%s", sym->rname);
611     }
612   aop->size = getSize (sym->type);
613
614   /* if it is in code space */
615   if (IN_CODESPACE (space))
616     aop->code = 1;
617
618   return aop;
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object                           */
623 /*-----------------------------------------------------------------*/
624 static asmop *
625 aopForRemat (symbol * sym)
626 {
627   iCode *ic = sym->rematiCode;
628   asmop *aop = newAsmop (AOP_IMMD);
629   int ptr_type =0;
630   int val = 0;
631
632   for (;;)
633     {
634       if (ic->op == '+')
635         val += (int) operandLitValue (IC_RIGHT (ic));
636       else if (ic->op == '-')
637         val -= (int) operandLitValue (IC_RIGHT (ic));
638       else if (IS_CAST_ICODE(ic)) {
639               sym_link *from_type = operandType(IC_RIGHT(ic));
640               aop->aopu.aop_immd.from_cast_remat = 1;
641               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
642               ptr_type = DCL_TYPE(from_type);
643               if (ptr_type == IPOINTER) {
644                 // bug #481053
645                 ptr_type = POINTER;
646               }
647               continue ;
648       } else break;
649       
650       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
651     }
652
653   if (val)
654   {
655       SNPRINTF (buffer, sizeof(buffer),
656                 "(%s %c 0x%04x)",
657                 OP_SYMBOL (IC_LEFT (ic))->rname,
658                 val >= 0 ? '+' : '-',
659                 abs (val) & 0xffff);
660   }
661   else 
662   {
663       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
664       {
665           SNPRINTF(buffer, sizeof(buffer), 
666                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
667       }
668       else
669       {
670           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
671       }
672   }
673
674   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
675   /* set immd2 field if required */
676   if (aop->aopu.aop_immd.from_cast_remat) 
677   {
678       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
679       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
680   }
681
682   return aop;
683 }
684
685 /*-----------------------------------------------------------------*/
686 /* aopHasRegs - returns true if aop has regs between from-to       */
687 /*-----------------------------------------------------------------*/
688 static int aopHasRegs(asmop *aop, int from, int to)
689 {
690     int size =0;
691
692     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
693
694     for (; size < aop->size ; size++) {
695         int reg;
696         for (reg = from ; reg <= to ; reg++)
697             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
698     }
699     return 0;
700 }
701
702 /*-----------------------------------------------------------------*/
703 /* regsInCommon - two operands have some registers in common       */
704 /*-----------------------------------------------------------------*/
705 static bool
706 regsInCommon (operand * op1, operand * op2)
707 {
708   symbol *sym1, *sym2;
709   int i;
710
711   /* if they have registers in common */
712   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
713     return FALSE;
714
715   sym1 = OP_SYMBOL (op1);
716   sym2 = OP_SYMBOL (op2);
717
718   if (sym1->nRegs == 0 || sym2->nRegs == 0)
719     return FALSE;
720
721   for (i = 0; i < sym1->nRegs; i++)
722     {
723       int j;
724       if (!sym1->regs[i])
725         continue;
726
727       for (j = 0; j < sym2->nRegs; j++)
728         {
729           if (!sym2->regs[j])
730             continue;
731
732           if (sym2->regs[j] == sym1->regs[i])
733             return TRUE;
734         }
735     }
736
737   return FALSE;
738 }
739
740 /*-----------------------------------------------------------------*/
741 /* operandsEqu - equivalent                                        */
742 /*-----------------------------------------------------------------*/
743 static bool
744 operandsEqu (operand * op1, operand * op2)
745 {
746   symbol *sym1, *sym2;
747
748   /* if they not symbols */
749   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
750     return FALSE;
751
752   sym1 = OP_SYMBOL (op1);
753   sym2 = OP_SYMBOL (op2);
754
755   /* if both are itemps & one is spilt
756      and the other is not then false */
757   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
758       sym1->isspilt != sym2->isspilt)
759     return FALSE;
760
761   /* if they are the same */
762   if (sym1 == sym2)
763     return TRUE;
764
765   if (strcmp (sym1->rname, sym2->rname) == 0)
766     return TRUE;
767
768
769   /* if left is a tmp & right is not */
770   if (IS_ITEMP (op1) &&
771       !IS_ITEMP (op2) &&
772       sym1->isspilt &&
773       (sym1->usl.spillLoc == sym2))
774     return TRUE;
775
776   if (IS_ITEMP (op2) &&
777       !IS_ITEMP (op1) &&
778       sym2->isspilt &&
779       sym1->level > 0 &&
780       (sym2->usl.spillLoc == sym1))
781     return TRUE;
782
783   return FALSE;
784 }
785
786 /*-----------------------------------------------------------------*/
787 /* sameRegs - two asmops have the same registers                   */
788 /*-----------------------------------------------------------------*/
789 static bool
790 sameRegs (asmop * aop1, asmop * aop2)
791 {
792   int i;
793
794   if (aop1 == aop2)
795     {
796       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
797         {
798           return FALSE;
799         }
800       return TRUE;
801     }
802
803   if (aop1->type != AOP_REG ||
804       aop2->type != AOP_REG)
805     return FALSE;
806
807   if (aop1->size != aop2->size)
808     return FALSE;
809
810   for (i = 0; i < aop1->size; i++)
811     if (aop1->aopu.aop_reg[i] !=
812         aop2->aopu.aop_reg[i])
813       return FALSE;
814
815   return TRUE;
816 }
817
818 /*-----------------------------------------------------------------*/
819 /* aopOp - allocates an asmop for an operand  :                    */
820 /*-----------------------------------------------------------------*/
821 static void
822 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
823 {
824   asmop *aop;
825   symbol *sym;
826   int i;
827
828   if (!op)
829     return;
830
831   /* if this a literal */
832   if (IS_OP_LITERAL (op))
833     {
834       op->aop = aop = newAsmop (AOP_LIT);
835       aop->aopu.aop_lit = op->operand.valOperand;
836       aop->size = getSize (operandType (op));
837       return;
838     }
839
840   /* if already has a asmop then continue */
841   if (op->aop)
842     return;
843
844   /* if the underlying symbol has a aop */
845   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
846     {
847       op->aop = OP_SYMBOL (op)->aop;
848       return;
849     }
850
851   /* if this is a true symbol */
852   if (IS_TRUE_SYMOP (op))
853     {
854       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
855       return;
856     }
857
858   /* this is a temporary : this has
859      only four choices :
860      a) register
861      b) spillocation
862      c) rematerialize
863      d) conditional
864      e) can be a return use only */
865
866   sym = OP_SYMBOL (op);
867
868
869   /* if the type is a conditional */
870   if (sym->regType == REG_CND)
871     {
872       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
873       aop->size = 0;
874       return;
875     }
876
877   /* if it is spilt then two situations
878      a) is rematerialize
879      b) has a spill location */
880   if (sym->isspilt || sym->nRegs == 0)
881     {
882
883       /* rematerialize it NOW */
884       if (sym->remat)
885         {
886           sym->aop = op->aop = aop =
887             aopForRemat (sym);
888           aop->size = getSize (sym->type);
889           return;
890         }
891
892       if (sym->accuse)
893         {
894           int i;
895           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
896           aop->size = getSize (sym->type);
897           for (i = 0; i < 2; i++)
898             aop->aopu.aop_str[i] = accUse[i];
899           return;
900         }
901
902       if (sym->ruonly)
903         {
904           int i;
905
906           if (useDP2)
907             {
908               /* a AOP_STR uses DPTR, but DPTR is already in use;
909                * we're just hosed.
910                */
911                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
912             }
913
914           aop = op->aop = sym->aop = newAsmop (AOP_STR);
915           aop->size = getSize (sym->type);
916           for (i = 0; i < (int) fReturnSizeDS390; i++)
917             aop->aopu.aop_str[i] = fReturn[i];
918           return;
919         }
920       
921       if (sym->dptr) { /* has been allocated to a DPTRn */
922           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
923           aop->size = getSize (sym->type);
924           aop->aopu.dptr = sym->dptr;
925           return ;
926       }
927       /* else spill location  */
928       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
929           /* force a new aop if sizes differ */
930           sym->usl.spillLoc->aop = NULL;
931       }
932       sym->aop = op->aop = aop =
933         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
934       aop->size = getSize (sym->type);
935       return;
936     }
937
938   /* must be in a register */
939   sym->aop = op->aop = aop = newAsmop (AOP_REG);
940   aop->size = sym->nRegs;
941   for (i = 0; i < sym->nRegs; i++)
942     aop->aopu.aop_reg[i] = sym->regs[i];
943 }
944
945 /*-----------------------------------------------------------------*/
946 /* freeAsmop - free up the asmop given to an operand               */
947 /*----------------------------------------------------------------*/
948 static void
949 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
950 {
951   asmop *aop;
952
953   if (!op)
954     aop = aaop;
955   else
956     aop = op->aop;
957
958   if (!aop)
959     return;
960
961   if (aop->freed)
962     goto dealloc;
963
964   aop->freed = 1;
965
966   /* depending on the asmop type only three cases need work AOP_RO
967      , AOP_R1 && AOP_STK */
968   switch (aop->type)
969     {
970     case AOP_R0:
971       if (_G.r0Pushed)
972         {
973           if (pop)
974             {
975               emitcode ("pop", "ar0");
976               _G.r0Pushed--;
977             }
978         }
979       bitVectUnSetBit (ic->rUsed, R0_IDX);
980       break;
981
982     case AOP_R1:
983       if (_G.r1Pushed)
984         {
985           if (pop)
986             {
987               emitcode ("pop", "ar1");
988               _G.r1Pushed--;
989             }
990         }
991       bitVectUnSetBit (ic->rUsed, R1_IDX);
992       break;
993
994     case AOP_STK:
995       {
996         int sz = aop->size;
997         int stk = aop->aopu.aop_stk + aop->size;
998         bitVectUnSetBit (ic->rUsed, R0_IDX);
999         bitVectUnSetBit (ic->rUsed, R1_IDX);
1000
1001         getFreePtr (ic, &aop, FALSE);
1002
1003         if (options.stack10bit)
1004           {
1005             /* I'm not sure what to do here yet... */
1006             /* #STUB */
1007             fprintf (stderr,
1008                      "*** Warning: probably generating bad code for "
1009                      "10 bit stack mode.\n");
1010           }
1011
1012         if (stk)
1013           {
1014             emitcode ("mov", "a,_bp");
1015             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1016             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1017           }
1018         else
1019           {
1020             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1021           }
1022
1023         while (sz--)
1024           {
1025             emitcode ("pop", "acc");
1026             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1027             if (!sz)
1028               break;
1029             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1030           }
1031         op->aop = aop;
1032         freeAsmop (op, NULL, ic, TRUE);
1033         if (_G.r0Pushed)
1034           {
1035             emitcode ("pop", "ar0");
1036             _G.r0Pushed--;
1037           }
1038
1039         if (_G.r1Pushed)
1040           {
1041             emitcode ("pop", "ar1");
1042             _G.r1Pushed--;
1043           }
1044       }
1045     case AOP_DPTR2:
1046         if (_G.dptr1InUse) {
1047             emitcode ("pop","dpx1");
1048             emitcode ("pop","dph1");
1049             emitcode ("pop","dpl1");
1050         }
1051         break;
1052     case AOP_DPTR:
1053         if (_G.dptrInUse) {
1054             emitcode ("pop","dpx");
1055             emitcode ("pop","dph");
1056             emitcode ("pop","dpl");
1057         }
1058         break;
1059     }
1060 dealloc:
1061   /* all other cases just dealloc */
1062   if (op)
1063     {
1064       op->aop = NULL;
1065       if (IS_SYMOP (op))
1066         {
1067           OP_SYMBOL (op)->aop = NULL;
1068           /* if the symbol has a spill */
1069           if (SPIL_LOC (op))
1070             SPIL_LOC (op)->aop = NULL;
1071         }
1072     }
1073 }
1074
1075 /*------------------------------------------------------------------*/
1076 /* aopGet - for fetching value of the aop                           */
1077 /*                    */
1078 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1079 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1080 /* just less efficient.               */
1081 /*------------------------------------------------------------------*/
1082
1083 static char *
1084 aopGet (asmop * aop,
1085         int offset,
1086         bool bit16,
1087         bool dname,
1088         bool canClobberACC)
1089 {
1090   /* offset is greater than
1091      size then zero */
1092   if (offset > (aop->size - 1) &&
1093       aop->type != AOP_LIT)
1094     return zero;
1095
1096   /* depending on type */
1097   switch (aop->type)
1098     {
1099
1100     case AOP_R0:
1101     case AOP_R1:
1102       /* if we need to increment it */
1103       while (offset > aop->coff)
1104         {
1105           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1106           aop->coff++;
1107         }
1108
1109       while (offset < aop->coff)
1110         {
1111           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1112           aop->coff--;
1113         }
1114
1115       aop->coff = offset;
1116       if (aop->paged)
1117         {
1118           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1119           return (dname ? "acc" : "a");
1120         }
1121       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1122       return Safe_strdup(buffer);       
1123
1124     case AOP_DPTRn:
1125         assert(offset <= 3);
1126         return dptrn[aop->aopu.dptr][offset];
1127
1128     case AOP_DPTR:
1129     case AOP_DPTR2:
1130
1131       if (aop->type == AOP_DPTR2)
1132         {
1133           genSetDPTR (1);
1134           if (!canClobberACC)
1135             {
1136                     TR_AP("#1");
1137                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1138             }
1139         }
1140
1141       _flushLazyDPS ();
1142
1143       while (offset > aop->coff)
1144         {
1145           emitcode ("inc", "dptr");
1146           aop->coff++;
1147         }
1148
1149       while (offset < aop->coff)
1150         {
1151           emitcode ("lcall", "__decdptr");
1152           aop->coff--;
1153         }
1154
1155       aop->coff = offset;
1156       if (aop->code)
1157         {
1158           emitcode ("clr", "a");
1159           emitcode ("movc", "a,@a+dptr");
1160         }
1161       else
1162         {
1163           emitcode ("movx", "a,@dptr");
1164         }
1165
1166       if (aop->type == AOP_DPTR2)
1167         {
1168           genSetDPTR (0);
1169           if (!canClobberACC)
1170             {
1171        TR_AP("#2");
1172               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1173               return DP2_RESULT_REG;
1174             }
1175         }
1176       return (dname ? "acc" : "a");
1177
1178     case AOP_IMMD:
1179       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1180       {
1181           SNPRINTF(buffer, sizeof(buffer), 
1182                    "%s",aop->aopu.aop_immd.aop_immd2);
1183       } 
1184       else if (bit16)
1185       {
1186          SNPRINTF(buffer, sizeof(buffer), 
1187                   "#%s", aop->aopu.aop_immd.aop_immd1);
1188       }
1189       else if (offset) 
1190       {
1191           switch (offset) {
1192           case 1:
1193               tsprintf(buffer, sizeof(buffer),
1194                        "#!his",aop->aopu.aop_immd.aop_immd1);
1195               break;
1196           case 2:
1197               tsprintf(buffer, sizeof(buffer), 
1198                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1199               break;
1200           case 3:
1201               tsprintf(buffer, sizeof(buffer),
1202                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1203               break;
1204           default: /* should not need this (just in case) */
1205               SNPRINTF (buffer, sizeof(buffer), 
1206                         "#(%s >> %d)",
1207                        aop->aopu.aop_immd.aop_immd1,
1208                        offset * 8);
1209           }
1210       }
1211       else
1212       {
1213         SNPRINTF (buffer, sizeof(buffer), 
1214                   "#%s", aop->aopu.aop_immd.aop_immd1);
1215       }
1216       return Safe_strdup(buffer);       
1217
1218     case AOP_DIR:
1219       if (offset)
1220       {
1221         SNPRINTF (buffer, sizeof(buffer),
1222                   "(%s + %d)",
1223                  aop->aopu.aop_dir,
1224                  offset);
1225       }
1226       else
1227       {
1228         SNPRINTF(buffer, sizeof(buffer), 
1229                  "%s", aop->aopu.aop_dir);
1230       }
1231
1232       return Safe_strdup(buffer);
1233
1234     case AOP_REG:
1235       if (dname)
1236         return aop->aopu.aop_reg[offset]->dname;
1237       else
1238         return aop->aopu.aop_reg[offset]->name;
1239
1240     case AOP_CRY:
1241       emitcode ("clr", "a");
1242       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1243       emitcode ("rlc", "a");
1244       return (dname ? "acc" : "a");
1245
1246     case AOP_ACC:
1247       if (!offset && dname)
1248         return "acc";
1249       return aop->aopu.aop_str[offset];
1250
1251     case AOP_LIT:
1252       return aopLiteral (aop->aopu.aop_lit, offset);
1253
1254     case AOP_STR:
1255       aop->coff = offset;
1256       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1257           dname)
1258         return "acc";
1259
1260       return aop->aopu.aop_str[offset];
1261
1262     }
1263
1264   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1265           "aopget got unsupported aop->type");
1266   exit (1);
1267 }
1268 /*-----------------------------------------------------------------*/
1269 /* aopPut - puts a string for a aop                                */
1270 /*-----------------------------------------------------------------*/
1271 static void
1272 aopPut (asmop * aop, char *s, int offset)
1273 {
1274   if (aop->size && offset > (aop->size - 1))
1275     {
1276       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1277               "aopPut got offset > aop->size");
1278       exit (1);
1279     }
1280
1281   /* will assign value to value */
1282   /* depending on where it is ofcourse */
1283   switch (aop->type)
1284     {
1285     case AOP_DIR:
1286         if (offset)
1287         {
1288             SNPRINTF (buffer, sizeof(buffer),
1289                       "(%s + %d)",
1290                       aop->aopu.aop_dir, offset);
1291         }
1292         else
1293         {
1294             SNPRINTF (buffer, sizeof(buffer), 
1295                      "%s", aop->aopu.aop_dir);
1296         }
1297         
1298
1299         if (strcmp (buffer, s))
1300         {
1301             emitcode ("mov", "%s,%s", buffer, s);
1302         }
1303       break;
1304
1305     case AOP_REG:
1306       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1307           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1308         {
1309           if (*s == '@' ||
1310               strcmp (s, "r0") == 0 ||
1311               strcmp (s, "r1") == 0 ||
1312               strcmp (s, "r2") == 0 ||
1313               strcmp (s, "r3") == 0 ||
1314               strcmp (s, "r4") == 0 ||
1315               strcmp (s, "r5") == 0 ||
1316               strcmp (s, "r6") == 0 ||
1317               strcmp (s, "r7") == 0)
1318             {
1319                 emitcode ("mov", "%s,%s",
1320                           aop->aopu.aop_reg[offset]->dname, s);
1321             }
1322             else
1323             {
1324                 emitcode ("mov", "%s,%s",
1325                           aop->aopu.aop_reg[offset]->name, s);
1326             }
1327         }
1328       break;
1329
1330     case AOP_DPTRn:
1331         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1332         break;
1333
1334     case AOP_DPTR:
1335     case AOP_DPTR2:
1336
1337       if (aop->type == AOP_DPTR2)
1338         {
1339           genSetDPTR (1);
1340         }
1341       _flushLazyDPS ();
1342
1343       if (aop->code)
1344         {
1345           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1346                   "aopPut writting to code space");
1347           exit (1);
1348         }
1349
1350       while (offset > aop->coff)
1351         {
1352           aop->coff++;
1353           emitcode ("inc", "dptr");
1354         }
1355
1356       while (offset < aop->coff)
1357         {
1358           aop->coff--;
1359           emitcode ("lcall", "__decdptr");
1360         }
1361
1362       aop->coff = offset;
1363
1364       /* if not in accumulater */
1365       MOVA (s);
1366
1367       emitcode ("movx", "@dptr,a");
1368
1369       if (aop->type == AOP_DPTR2)
1370         {
1371           genSetDPTR (0);
1372         }
1373       break;
1374
1375     case AOP_R0:
1376     case AOP_R1:
1377       while (offset > aop->coff)
1378         {
1379           aop->coff++;
1380           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1381         }
1382       while (offset < aop->coff)
1383         {
1384           aop->coff--;
1385           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1386         }
1387       aop->coff = offset;
1388
1389       if (aop->paged)
1390         {
1391           MOVA (s);
1392           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1393
1394         }
1395       else if (*s == '@')
1396         {
1397           MOVA (s);
1398           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1399         }
1400       else if (strcmp (s, "r0") == 0 ||
1401                strcmp (s, "r1") == 0 ||
1402                strcmp (s, "r2") == 0 ||
1403                strcmp (s, "r3") == 0 ||
1404                strcmp (s, "r4") == 0 ||
1405                strcmp (s, "r5") == 0 ||
1406                strcmp (s, "r6") == 0 ||
1407                strcmp (s, "r7") == 0)
1408         {
1409           char buff[10];
1410           SNPRINTF(buff, sizeof(buff), 
1411                    "a%s", s);
1412           emitcode ("mov", "@%s,%s",
1413                     aop->aopu.aop_ptr->name, buff);
1414         }
1415         else
1416         {
1417             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1418         }
1419       break;
1420
1421     case AOP_STK:
1422       if (strcmp (s, "a") == 0)
1423         emitcode ("push", "acc");
1424       else
1425         if (*s=='@') {
1426           MOVA(s);
1427           emitcode ("push", "acc");
1428         } else {
1429           emitcode ("push", s);
1430         }
1431
1432       break;
1433
1434     case AOP_CRY:
1435       /* if bit variable */
1436       if (!aop->aopu.aop_dir)
1437         {
1438           emitcode ("clr", "a");
1439           emitcode ("rlc", "a");
1440         }
1441       else
1442         {
1443           if (s == zero)
1444             emitcode ("clr", "%s", aop->aopu.aop_dir);
1445           else if (s == one)
1446             emitcode ("setb", "%s", aop->aopu.aop_dir);
1447           else if (!strcmp (s, "c"))
1448             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1449           else
1450             {
1451               if (strcmp (s, "a"))
1452                 {
1453                   MOVA (s);
1454                 }
1455               {
1456                 /* set C, if a >= 1 */
1457                 emitcode ("add", "a,#!constbyte",0xff);
1458                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1459               }
1460             }
1461         }
1462       break;
1463
1464     case AOP_STR:
1465       aop->coff = offset;
1466       if (strcmp (aop->aopu.aop_str[offset], s))
1467         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1468       break;
1469
1470     case AOP_ACC:
1471       aop->coff = offset;
1472       if (!offset && (strcmp (s, "acc") == 0))
1473         break;
1474
1475       if (strcmp (aop->aopu.aop_str[offset], s))
1476         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1477       break;
1478
1479     default:
1480       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1481               "aopPut got unsupported aop->type");
1482       exit (1);
1483     }
1484
1485 }
1486
1487
1488 /*--------------------------------------------------------------------*/
1489 /* reAdjustPreg - points a register back to where it should (coff==0) */
1490 /*--------------------------------------------------------------------*/
1491 static void
1492 reAdjustPreg (asmop * aop)
1493 {
1494   if ((aop->coff==0) || (aop->size <= 1)) {
1495     return;
1496   }
1497
1498   switch (aop->type)
1499     {
1500     case AOP_R0:
1501     case AOP_R1:
1502       while (aop->coff--)
1503         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1504       break;
1505     case AOP_DPTR:
1506     case AOP_DPTR2:
1507       if (aop->type == AOP_DPTR2)
1508         {
1509           genSetDPTR (1);
1510           _flushLazyDPS ();
1511         }
1512       while (aop->coff--)
1513         {
1514           emitcode ("lcall", "__decdptr");
1515         }
1516
1517       if (aop->type == AOP_DPTR2)
1518         {
1519           genSetDPTR (0);
1520         }
1521       break;
1522
1523     }
1524   aop->coff=0;
1525 }
1526
1527 #define AOP(op) op->aop
1528 #define AOP_TYPE(op) AOP(op)->type
1529 #define AOP_SIZE(op) AOP(op)->size
1530 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1531                        AOP_TYPE(x) == AOP_R0))
1532
1533 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1534                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1535                          AOP(x)->paged))
1536
1537 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1538                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1539                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1540 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1541 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1542 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1543
1544 // The following two macros can be used even if the aop has not yet been aopOp'd.
1545 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1546 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1547
1548 /* Workaround for DS80C390 bug: div ab may return bogus results
1549  * if A is accessed in instruction immediately before the div.
1550  *
1551  * Will be fixed in B4 rev of processor, Dallas claims.
1552  */
1553
1554 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1555     if (!AOP_NEEDSACC(RIGHT))         \
1556     {               \
1557       /* We can load A first, then B, since     \
1558        * B (the RIGHT operand) won't clobber A,   \
1559        * thus avoiding touching A right before the div. \
1560        */             \
1561       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1562       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1563       MOVA(L);            \
1564       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1565     }               \
1566     else              \
1567     {               \
1568       /* Just stuff in a nop after loading A. */    \
1569       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1570       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1571       MOVA(L);            \
1572       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1573     }
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genNotFloat - generates not for float operations              */
1577 /*-----------------------------------------------------------------*/
1578 static void
1579 genNotFloat (operand * op, operand * res)
1580 {
1581   int size, offset;
1582   char *l;
1583   symbol *tlbl;
1584
1585   D (emitcode (";", "genNotFloat ");
1586     );
1587
1588   /* we will put 127 in the first byte of
1589      the result */
1590   aopPut (AOP (res), "#127", 0);
1591   size = AOP_SIZE (op) - 1;
1592   offset = 1;
1593
1594   _startLazyDPSEvaluation ();
1595   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1596   MOVA (l);
1597
1598   while (size--)
1599     {
1600       emitcode ("orl", "a,%s",
1601                 aopGet (op->aop,
1602                         offset++, FALSE, FALSE, FALSE));
1603     }
1604   _endLazyDPSEvaluation ();
1605
1606   tlbl = newiTempLabel (NULL);
1607   aopPut (res->aop, one, 1);
1608   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1609   aopPut (res->aop, zero, 1);
1610   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1611
1612   size = res->aop->size - 2;
1613   offset = 2;
1614   /* put zeros in the rest */
1615   while (size--)
1616     aopPut (res->aop, zero, offset++);
1617 }
1618
1619 /*-----------------------------------------------------------------*/
1620 /* opIsGptr: returns non-zero if the passed operand is       */
1621 /* a generic pointer type.             */
1622 /*-----------------------------------------------------------------*/
1623 static int
1624 opIsGptr (operand * op)
1625 {
1626   sym_link *type = operandType (op);
1627
1628   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1629     {
1630       return 1;
1631     }
1632   return 0;
1633 }
1634
1635 /*-----------------------------------------------------------------*/
1636 /* getDataSize - get the operand data size                         */
1637 /*-----------------------------------------------------------------*/
1638 static int
1639 getDataSize (operand * op)
1640 {
1641   int size;
1642   size = AOP_SIZE (op);
1643   if (size == GPTRSIZE)
1644     {
1645       sym_link *type = operandType (op);
1646       if (IS_GENPTR (type))
1647         {
1648           /* generic pointer; arithmetic operations
1649            * should ignore the high byte (pointer type).
1650            */
1651           size--;
1652         }
1653     }
1654   return size;
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* outAcc - output Acc                                             */
1659 /*-----------------------------------------------------------------*/
1660 static void
1661 outAcc (operand * result)
1662 {
1663   int size, offset;
1664   size = getDataSize (result);
1665   if (size)
1666     {
1667       aopPut (AOP (result), "a", 0);
1668       size--;
1669       offset = 1;
1670       /* unsigned or positive */
1671       while (size--)
1672         {
1673           aopPut (AOP (result), zero, offset++);
1674         }
1675     }
1676 }
1677
1678 /*-----------------------------------------------------------------*/
1679 /* outBitC - output a bit C                                        */
1680 /*-----------------------------------------------------------------*/
1681 static void
1682 outBitC (operand * result)
1683 {
1684   /* if the result is bit */
1685   if (AOP_TYPE (result) == AOP_CRY)
1686     {
1687       aopPut (AOP (result), "c", 0);
1688     }
1689   else
1690     {
1691       emitcode ("clr", "a");
1692       emitcode ("rlc", "a");
1693       outAcc (result);
1694     }
1695 }
1696
1697 /*-----------------------------------------------------------------*/
1698 /* toBoolean - emit code for orl a,operator(sizeop)                */
1699 /*-----------------------------------------------------------------*/
1700 static void
1701 toBoolean (operand * oper)
1702 {
1703   int   size = AOP_SIZE (oper) - 1;
1704   int   offset = 1;
1705   bool usedB = FALSE;
1706
1707   /* The generic part of a generic pointer should
1708    * not participate in it's truth value.
1709    *
1710    * i.e. 0x10000000 is zero.
1711    */
1712   if (opIsGptr (oper))
1713     {
1714       D (emitcode (";", "toBoolean: generic ptr special case."););
1715       size--;
1716     }
1717
1718   _startLazyDPSEvaluation ();
1719   if (AOP_NEEDSACC (oper) && size)
1720     {
1721       usedB = TRUE;
1722       emitcode ("push", "b");
1723       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1724     }
1725   else
1726     {
1727       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1728     }
1729   while (size--)
1730     {
1731       if (usedB)
1732         {
1733           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1734         }
1735       else
1736         {
1737           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1738         }
1739     }
1740   _endLazyDPSEvaluation ();
1741
1742   if (usedB)
1743     {
1744       emitcode ("mov", "a,b");
1745       emitcode ("pop", "b");
1746     }
1747 }
1748
1749
1750 /*-----------------------------------------------------------------*/
1751 /* genNot - generate code for ! operation                          */
1752 /*-----------------------------------------------------------------*/
1753 static void
1754 genNot (iCode * ic)
1755 {
1756   symbol *tlbl;
1757   sym_link *optype = operandType (IC_LEFT (ic));
1758
1759   D (emitcode (";", "genNot ");
1760     );
1761
1762   /* assign asmOps to operand & result */
1763   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1765
1766   /* if in bit space then a special case */
1767   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1768     {
1769       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770       emitcode ("cpl", "c");
1771       outBitC (IC_RESULT (ic));
1772       goto release;
1773     }
1774
1775   /* if type float then do float */
1776   if (IS_FLOAT (optype))
1777     {
1778       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1779       goto release;
1780     }
1781
1782   toBoolean (IC_LEFT (ic));
1783
1784   tlbl = newiTempLabel (NULL);
1785   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1786   emitcode ("", "!tlabeldef", tlbl->key + 100);
1787   outBitC (IC_RESULT (ic));
1788
1789 release:
1790   /* release the aops */
1791   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1792   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1793 }
1794
1795
1796 /*-----------------------------------------------------------------*/
1797 /* genCpl - generate code for complement                           */
1798 /*-----------------------------------------------------------------*/
1799 static void
1800 genCpl (iCode * ic)
1801 {
1802   int offset = 0;
1803   int size;
1804   symbol *tlbl;
1805
1806   D (emitcode (";", "genCpl ");
1807     );
1808
1809
1810   /* assign asmOps to operand & result */
1811   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1812   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1813
1814   /* special case if in bit space */
1815   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1816     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1817       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1818       emitcode ("cpl", "c");
1819       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1820       goto release;
1821     }
1822     tlbl=newiTempLabel(NULL);
1823     emitcode ("cjne", "%s,#0x01,%05d$", 
1824               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1825     emitcode ("", "%05d$:", tlbl->key+100);
1826     outBitC (IC_RESULT(ic));
1827     goto release;
1828   }
1829
1830   size = AOP_SIZE (IC_RESULT (ic));
1831   _startLazyDPSEvaluation ();
1832   while (size--)
1833     {
1834       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1835       MOVA (l);
1836       emitcode ("cpl", "a");
1837       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1838     }
1839   _endLazyDPSEvaluation ();
1840
1841
1842 release:
1843   /* release the aops */
1844   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1845   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* genUminusFloat - unary minus for floating points                */
1850 /*-----------------------------------------------------------------*/
1851 static void
1852 genUminusFloat (operand * op, operand * result)
1853 {
1854   int size, offset = 0;
1855     
1856   D(emitcode (";", "genUminusFloat"););
1857   
1858   /* for this we just copy and then flip the bit */
1859     
1860   _startLazyDPSEvaluation ();
1861   size = AOP_SIZE (op) - 1;
1862
1863   while (size--)
1864   {
1865       aopPut (AOP (result),
1866               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1867               offset);
1868       offset++;
1869     }
1870   
1871   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, TRUE));
1872
1873   emitcode ("cpl", "acc.7");
1874   aopPut (AOP (result), "a", offset);    
1875   _endLazyDPSEvaluation ();
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* genUminus - unary minus code generation                         */
1880 /*-----------------------------------------------------------------*/
1881 static void
1882 genUminus (iCode * ic)
1883 {
1884   int offset, size;
1885   sym_link *optype, *rtype;
1886
1887   D (emitcode (";", "genUminus ");
1888     );
1889
1890
1891   /* assign asmops */
1892   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1893   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1894
1895   /* if both in bit space then special
1896      case */
1897   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1898       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1899     {
1900
1901       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1902       emitcode ("cpl", "c");
1903       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1904       goto release;
1905     }
1906
1907   optype = operandType (IC_LEFT (ic));
1908   rtype = operandType (IC_RESULT (ic));
1909
1910   /* if float then do float stuff */
1911   if (IS_FLOAT (optype))
1912     {
1913       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1914       goto release;
1915     }
1916
1917   /* otherwise subtract from zero */
1918   size = AOP_SIZE (IC_LEFT (ic));
1919   offset = 0;
1920   _startLazyDPSEvaluation ();
1921   while (size--)
1922     {
1923       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1924       if (!strcmp (l, "a"))
1925         {
1926           if (offset == 0)
1927             SETC;
1928           emitcode ("cpl", "a");
1929           emitcode ("addc", "a,#0");
1930         }
1931       else
1932         {
1933           if (offset == 0)
1934             CLRC;
1935           emitcode ("clr", "a");
1936           emitcode ("subb", "a,%s", l);
1937         }
1938       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1939     }
1940   _endLazyDPSEvaluation ();
1941
1942   /* if any remaining bytes in the result */
1943   /* we just need to propagate the sign   */
1944   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1945     {
1946       emitcode ("rlc", "a");
1947       emitcode ("subb", "a,acc");
1948       while (size--)
1949         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1950     }
1951
1952 release:
1953   /* release the aops */
1954   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1955   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* savermask - saves registers in the mask                         */
1960 /*-----------------------------------------------------------------*/
1961 static void savermask(bitVect *rs_mask)
1962 {
1963     int i;
1964     if (options.useXstack) {
1965         if (bitVectBitValue (rs_mask, R0_IDX))
1966             emitcode ("mov", "b,r0");
1967         emitcode ("mov", "r0,%s", spname);
1968         for (i = 0; i < ds390_nRegs; i++) {
1969             if (bitVectBitValue (rs_mask, i)) {
1970                 if (i == R0_IDX)
1971                     emitcode ("mov", "a,b");
1972                 else
1973                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1974                 emitcode ("movx", "@r0,a");
1975                 emitcode ("inc", "r0");
1976             }
1977         }
1978         emitcode ("mov", "%s,r0", spname);
1979         if (bitVectBitValue (rs_mask, R0_IDX))
1980             emitcode ("mov", "r0,b");
1981     } else {
1982         for (i = 0; i < ds390_nRegs; i++) {
1983             if (bitVectBitValue (rs_mask, i))
1984                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1985         }
1986     }
1987 }
1988
1989 /*-----------------------------------------------------------------*/
1990 /* saveRegisters - will look for a call and save the registers     */
1991 /*-----------------------------------------------------------------*/
1992 static void
1993 saveRegisters (iCode * lic)
1994 {
1995   iCode *ic;
1996   bitVect *rsave;
1997
1998   /* look for call */
1999   for (ic = lic; ic; ic = ic->next)
2000     if (ic->op == CALL || ic->op == PCALL)
2001       break;
2002
2003   if (!ic)
2004     {
2005       fprintf (stderr, "found parameter push with no function call\n");
2006       return;
2007     }
2008
2009   /* if the registers have been saved already then
2010      do nothing */
2011   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
2012
2013   /* special case if DPTR alive across a function call then must save it 
2014      even though callee saves */
2015   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2016       int i =0;
2017       rsave = newBitVect(ic->rMask->size);
2018       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2019           if (bitVectBitValue(ic->rMask,i))
2020               rsave = bitVectSetBit(rsave,i);
2021       }
2022       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2023   } else {
2024     /* safe the registers in use at this time but skip the
2025        ones for the result */
2026     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2027                            ds390_rUmaskForOp (IC_RESULT(ic)));
2028   }
2029   ic->regsSaved = 1;
2030   savermask(rsave);
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* usavermask - restore registers with mask                        */
2035 /*-----------------------------------------------------------------*/
2036 static void unsavermask(bitVect *rs_mask)
2037 {
2038     int i;
2039     if (options.useXstack) {
2040         emitcode ("mov", "r0,%s", spname);
2041         for (i = ds390_nRegs; i >= 0; i--) {
2042             if (bitVectBitValue (rs_mask, i)) {
2043                 emitcode ("dec", "r0");
2044                 emitcode ("movx", "a,@r0");
2045                 if (i == R0_IDX)
2046                     emitcode ("mov", "b,a");
2047                 else
2048                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2049             }       
2050         }
2051         emitcode ("mov", "%s,r0", spname);
2052         if (bitVectBitValue (rs_mask, R0_IDX))
2053             emitcode ("mov", "r0,b");
2054     } else {
2055         for (i = ds390_nRegs; i >= 0; i--) {
2056             if (bitVectBitValue (rs_mask, i))
2057                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2058         }
2059     }
2060 }
2061
2062 /*-----------------------------------------------------------------*/
2063 /* unsaveRegisters - pop the pushed registers                      */
2064 /*-----------------------------------------------------------------*/
2065 static void
2066 unsaveRegisters (iCode * ic)
2067 {
2068   bitVect *rsave;
2069
2070   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2071       int i =0;
2072       rsave = newBitVect(ic->rMask->size);
2073       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2074           if (bitVectBitValue(ic->rMask,i))
2075               rsave = bitVectSetBit(rsave,i);
2076       }
2077       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2078   } else {
2079     /* restore the registers in use at this time but skip the
2080        ones for the result */
2081     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2082                            ds390_rUmaskForOp (IC_RESULT(ic)));
2083   }
2084   unsavermask(rsave);
2085 }
2086
2087
2088 /*-----------------------------------------------------------------*/
2089 /* pushSide -                */
2090 /*-----------------------------------------------------------------*/
2091 static void
2092 pushSide (operand * oper, int size)
2093 {
2094   int offset = 0;
2095   _startLazyDPSEvaluation ();
2096   while (size--)
2097     {
2098       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
2099       if (AOP_TYPE (oper) != AOP_REG &&
2100           AOP_TYPE (oper) != AOP_DIR &&
2101           strcmp (l, "a"))
2102         {
2103           emitcode ("mov", "a,%s", l);
2104           emitcode ("push", "acc");
2105         }
2106       else
2107         emitcode ("push", "%s", l);
2108     }
2109   _endLazyDPSEvaluation ();
2110 }
2111
2112 /*-----------------------------------------------------------------*/
2113 /* assignResultValue -               */
2114 /*-----------------------------------------------------------------*/
2115 static void
2116 assignResultValue (operand * oper)
2117 {
2118   int offset = 0;
2119   int size = AOP_SIZE (oper);
2120
2121   _startLazyDPSEvaluation ();
2122   while (size--)
2123     {
2124       aopPut (AOP (oper), fReturn[offset], offset);
2125       offset++;
2126     }
2127   _endLazyDPSEvaluation ();
2128 }
2129
2130
2131 /*-----------------------------------------------------------------*/
2132 /* genXpush - pushes onto the external stack                       */
2133 /*-----------------------------------------------------------------*/
2134 static void
2135 genXpush (iCode * ic)
2136 {
2137   asmop *aop = newAsmop (0);
2138   regs *r;
2139   int size, offset = 0;
2140
2141   D (emitcode (";", "genXpush ");
2142     );
2143
2144   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2145   r = getFreePtr (ic, &aop, FALSE);
2146
2147
2148   emitcode ("mov", "%s,_spx", r->name);
2149
2150   size = AOP_SIZE (IC_LEFT (ic));
2151   _startLazyDPSEvaluation ();
2152   while (size--)
2153     {
2154
2155       char *l = aopGet (AOP (IC_LEFT (ic)),
2156                         offset++, FALSE, FALSE, TRUE);
2157       MOVA (l);
2158       emitcode ("movx", "@%s,a", r->name);
2159       emitcode ("inc", "%s", r->name);
2160
2161     }
2162   _endLazyDPSEvaluation ();
2163
2164
2165   emitcode ("mov", "_spx,%s", r->name);
2166
2167   freeAsmop (NULL, aop, ic, TRUE);
2168   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2169 }
2170
2171 /*-----------------------------------------------------------------*/
2172 /* genIpush - genrate code for pushing this gets a little complex  */
2173 /*-----------------------------------------------------------------*/
2174 static void
2175 genIpush (iCode * ic)
2176 {
2177   int size, offset = 0;
2178   char *l;
2179
2180   D (emitcode (";", "genIpush ");
2181     );
2182
2183   /* if this is not a parm push : ie. it is spill push
2184      and spill push is always done on the local stack */
2185   if (!ic->parmPush)
2186     {
2187
2188       /* and the item is spilt then do nothing */
2189       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2190         return;
2191
2192       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2193       size = AOP_SIZE (IC_LEFT (ic));
2194       /* push it on the stack */
2195       _startLazyDPSEvaluation ();
2196       while (size--)
2197         {
2198           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2199           if (*l == '#')
2200             {
2201               MOVA (l);
2202               l = "acc";
2203             }
2204           emitcode ("push", "%s", l);
2205         }
2206       _endLazyDPSEvaluation ();
2207       return;
2208     }
2209
2210   /* this is a paramter push: in this case we call
2211      the routine to find the call and save those
2212      registers that need to be saved */
2213   saveRegisters (ic);
2214
2215   /* if use external stack then call the external
2216      stack pushing routine */
2217   if (options.useXstack)
2218     {
2219       genXpush (ic);
2220       return;
2221     }
2222
2223   /* then do the push */
2224   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2225
2226   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2227   size = AOP_SIZE (IC_LEFT (ic));
2228
2229   _startLazyDPSEvaluation ();
2230   while (size--)
2231     {
2232       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2233       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2234           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2235           strcmp (l, "a"))
2236         {
2237           emitcode ("mov", "a,%s", l);
2238           emitcode ("push", "acc");
2239         }
2240       else
2241         emitcode ("push", "%s", l);
2242     }
2243   _endLazyDPSEvaluation ();
2244
2245   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2246 }
2247
2248 /*-----------------------------------------------------------------*/
2249 /* genIpop - recover the registers: can happen only for spilling   */
2250 /*-----------------------------------------------------------------*/
2251 static void
2252 genIpop (iCode * ic)
2253 {
2254   int size, offset;
2255
2256   D (emitcode (";", "genIpop ");
2257     );
2258
2259
2260   /* if the temp was not pushed then */
2261   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2262     return;
2263
2264   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265   size = AOP_SIZE (IC_LEFT (ic));
2266   offset = (size - 1);
2267   _startLazyDPSEvaluation ();
2268   while (size--)
2269     {
2270       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2271                                      FALSE, TRUE, TRUE));
2272     }
2273   _endLazyDPSEvaluation ();
2274
2275   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2276 }
2277
2278 /*-----------------------------------------------------------------*/
2279 /* unsaveRBank - restores the resgister bank from stack            */
2280 /*-----------------------------------------------------------------*/
2281 static void
2282 unsaveRBank (int bank, iCode * ic, bool popPsw)
2283 {
2284   int i;
2285   asmop *aop = NULL;
2286   regs *r = NULL;
2287
2288   if (options.useXstack)
2289   {
2290       if (!ic)
2291       {
2292           /* Assume r0 is available for use. */
2293           r = ds390_regWithIdx (R0_IDX);;          
2294       } 
2295       else
2296       {
2297           aop = newAsmop (0);
2298           r = getFreePtr (ic, &aop, FALSE);
2299       }
2300       emitcode ("mov", "%s,_spx", r->name);      
2301   }
2302   
2303   if (popPsw)
2304     {
2305       if (options.useXstack)
2306       {
2307           emitcode ("movx", "a,@%s", r->name);
2308           emitcode ("mov", "psw,a");
2309           emitcode ("dec", "%s", r->name);
2310         }
2311       else
2312       {
2313         emitcode ("pop", "psw");
2314       }
2315     }
2316
2317   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2318     {
2319       if (options.useXstack)
2320         {
2321           emitcode ("movx", "a,@%s", r->name);
2322           emitcode ("mov", "(%s+%d),a",
2323                     regs390[i].base, 8 * bank + regs390[i].offset);
2324           emitcode ("dec", "%s", r->name);
2325
2326         }
2327       else
2328         emitcode ("pop", "(%s+%d)",
2329                   regs390[i].base, 8 * bank + regs390[i].offset);
2330     }
2331
2332   if (options.useXstack)
2333     {
2334       emitcode ("mov", "_spx,%s", r->name);
2335     }
2336     
2337   if (aop)
2338   {
2339       freeAsmop (NULL, aop, ic, TRUE);  
2340   }    
2341 }
2342
2343 /*-----------------------------------------------------------------*/
2344 /* saveRBank - saves an entire register bank on the stack          */
2345 /*-----------------------------------------------------------------*/
2346 static void
2347 saveRBank (int bank, iCode * ic, bool pushPsw)
2348 {
2349   int i;
2350   asmop *aop = NULL;
2351   regs *r = NULL;
2352
2353   if (options.useXstack)
2354     {
2355         if (!ic)
2356         {
2357           /* Assume r0 is available for use. */
2358                   r = ds390_regWithIdx (R0_IDX);;
2359         }
2360         else
2361         {
2362           aop = newAsmop (0);
2363           r = getFreePtr (ic, &aop, FALSE);
2364         }
2365         emitcode ("mov", "%s,_spx", r->name);    
2366     }
2367
2368   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2369     {
2370       if (options.useXstack)
2371         {
2372           emitcode ("inc", "%s", r->name);
2373           emitcode ("mov", "a,(%s+%d)",
2374                     regs390[i].base, 8 * bank + regs390[i].offset);
2375           emitcode ("movx", "@%s,a", r->name);
2376         }
2377       else
2378         emitcode ("push", "(%s+%d)",
2379                   regs390[i].base, 8 * bank + regs390[i].offset);
2380     }
2381
2382   if (pushPsw)
2383     {
2384       if (options.useXstack)
2385         {
2386           emitcode ("mov", "a,psw");
2387           emitcode ("movx", "@%s,a", r->name);
2388           emitcode ("inc", "%s", r->name);
2389           emitcode ("mov", "_spx,%s", r->name);
2390         }
2391       else
2392       {
2393         emitcode ("push", "psw");
2394       }
2395
2396       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2397     }
2398   
2399   if (aop)
2400   {
2401        freeAsmop (NULL, aop, ic, TRUE);
2402   }    
2403     
2404   if (ic)
2405   {  
2406       ic->bankSaved = 1;
2407   }
2408 }
2409
2410 /*-----------------------------------------------------------------*/
2411 /* genSend - gen code for SEND                                     */
2412 /*-----------------------------------------------------------------*/
2413 static void genSend(set *sendSet)
2414 {
2415     iCode *sic;
2416     int sendCount = 0 ;
2417     static int rb1_count = 0;
2418
2419     for (sic = setFirstItem (sendSet); sic;
2420          sic = setNextItem (sendSet)) {     
2421         int size, offset = 0;
2422         
2423         size=getSize(operandType(IC_LEFT(sic)));
2424         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2425         if (sendCount == 0) { /* first parameter */
2426             // we know that dpl(hxb) is the result, so
2427             rb1_count = 0 ;
2428             _startLazyDPSEvaluation ();
2429             if (size>1) {
2430                 aopOp (IC_LEFT (sic), sic, FALSE, 
2431                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2432             } else {
2433                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2434             }
2435             while (size--) {
2436                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2437                                   FALSE, FALSE, TRUE);
2438                 if (strcmp (l, fReturn[offset])) {
2439                     emitcode ("mov", "%s,%s",
2440                               fReturn[offset],
2441                               l);
2442                 }
2443                 offset++;
2444             }
2445             _endLazyDPSEvaluation ();
2446             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2447             rb1_count =0;
2448         } else { /* if more parameter in registers */
2449             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2450             while (size--) {
2451                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2452                                                                 FALSE, FALSE, TRUE));
2453             }
2454             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2455         }
2456         sendCount++;
2457     }
2458 }
2459
2460 /*-----------------------------------------------------------------*/
2461 /* genCall - generates a call statement                            */
2462 /*-----------------------------------------------------------------*/
2463 static void
2464 genCall (iCode * ic)
2465 {
2466   sym_link *dtype;
2467   bool restoreBank = FALSE;
2468   bool swapBanks = FALSE;
2469
2470   D (emitcode (";", "genCall "););
2471
2472   /* if we are calling a not _naked function that is not using
2473      the same register bank then we need to save the
2474      destination registers on the stack */
2475   dtype = operandType (IC_LEFT (ic));
2476   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2477       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2478       IFFUNC_ISISR (currFunc->type))
2479   {
2480       if (!ic->bankSaved) 
2481       {
2482            /* This is unexpected; the bank should have been saved in
2483             * genFunction.
2484             */
2485            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2486            restoreBank = TRUE;
2487       }
2488       swapBanks = TRUE;
2489   }
2490   
2491     /* if caller saves & we have not saved then */
2492     if (!ic->regsSaved)
2493       saveRegisters (ic);
2494   
2495   /* if send set is not empty the assign */
2496   /* We've saved all the registers we care about;
2497   * therefore, we may clobber any register not used
2498   * in the calling convention (i.e. anything not in
2499   * fReturn.
2500   */
2501   if (_G.sendSet)
2502     {
2503         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2504             genSend(reverseSet(_G.sendSet));
2505         } else {
2506             genSend(_G.sendSet);
2507         }
2508       _G.sendSet = NULL;
2509     }  
2510     
2511   if (swapBanks)
2512   {
2513         emitcode ("mov", "psw,#!constbyte", 
2514            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2515   }
2516
2517   /* make the call */
2518   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2519                             OP_SYMBOL (IC_LEFT (ic))->rname :
2520                             OP_SYMBOL (IC_LEFT (ic))->name));
2521
2522   if (swapBanks)
2523   {
2524        emitcode ("mov", "psw,#!constbyte", 
2525           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2526   }
2527
2528   /* if we need assign a result value */
2529   if ((IS_ITEMP (IC_RESULT (ic)) &&
2530        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2531         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2532         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2533       IS_TRUE_SYMOP (IC_RESULT (ic)))
2534     {
2535       if (isOperandInFarSpace (IC_RESULT (ic))
2536           && getSize (operandType (IC_RESULT (ic))) <= 2)
2537         {
2538           int size = getSize (operandType (IC_RESULT (ic)));
2539
2540           /* Special case for 1 or 2 byte return in far space. */
2541           MOVA (fReturn[0]);
2542           if (size > 1)
2543             {
2544               emitcode ("mov", "b,%s", fReturn[1]);
2545             }
2546
2547           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2548           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2549
2550           if (size > 1)
2551             {
2552               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2553             }
2554           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2555         }
2556       else
2557         {
2558           _G.accInUse++;
2559           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2560           _G.accInUse--;
2561
2562           assignResultValue (IC_RESULT (ic));
2563
2564           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2565         }
2566     }
2567
2568   /* adjust the stack for parameters if
2569      required */
2570   if (ic->parmBytes) {
2571       int i;
2572       if (options.stack10bit) {
2573           if (ic->parmBytes <= 10) {
2574               emitcode(";","stack adjustment for parms");
2575               for (i=0; i < ic->parmBytes ; i++) {
2576                   emitcode("pop","acc");
2577               }
2578           } else {            
2579               PROTECT_SP;
2580               emitcode ("clr","c");
2581               emitcode ("mov","a,sp");
2582               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2583               emitcode ("mov","sp,a");
2584               emitcode ("mov","a,esp");
2585               emitcode ("anl","a,#3");
2586               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2587               emitcode ("mov","esp,a");   
2588               UNPROTECT_SP;
2589           }
2590       } else {
2591           if (ic->parmBytes > 3) {
2592               emitcode ("mov", "a,%s", spname);
2593               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2594               emitcode ("mov", "%s,a", spname);
2595           } else
2596               for (i = 0; i < ic->parmBytes; i++)
2597                   emitcode ("dec", "%s", spname);
2598       }
2599   }
2600
2601   /* if we hade saved some registers then unsave them */
2602   if (ic->regsSaved)
2603     unsaveRegisters (ic);
2604
2605   /* if register bank was saved then pop them */
2606   if (restoreBank)
2607     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2608 }
2609
2610 /*-----------------------------------------------------------------*/
2611 /* genPcall - generates a call by pointer statement                */
2612 /*-----------------------------------------------------------------*/
2613 static void
2614 genPcall (iCode * ic)
2615 {
2616   sym_link *dtype;
2617   symbol *rlbl = newiTempLabel (NULL);
2618   bool restoreBank=FALSE;
2619
2620   D (emitcode (";", "genPcall ");
2621     );
2622
2623
2624   /* if caller saves & we have not saved then */
2625   if (!ic->regsSaved)
2626     saveRegisters (ic);
2627
2628   /* if we are calling a function that is not using
2629      the same register bank then we need to save the
2630      destination registers on the stack */
2631   dtype = operandType (IC_LEFT (ic));
2632   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2633       IFFUNC_ISISR (currFunc->type) &&
2634       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2635     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2636     restoreBank=TRUE;
2637   }
2638
2639   /* push the return address on to the stack */
2640   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2641   emitcode ("push", "acc");
2642   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2643   emitcode ("push", "acc");
2644
2645   if (options.model == MODEL_FLAT24)
2646     {
2647       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2648       emitcode ("push", "acc");
2649     }
2650
2651   /* now push the calling address */
2652   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2653
2654   pushSide (IC_LEFT (ic), FPTRSIZE);
2655
2656   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2657
2658   /* if send set is not empty the assign */
2659   if (_G.sendSet)
2660     {
2661         genSend(reverseSet(_G.sendSet));
2662         _G.sendSet = NULL;
2663     }
2664
2665   emitcode ("ret", "");
2666   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2667
2668
2669   /* if we need assign a result value */
2670   if ((IS_ITEMP (IC_RESULT (ic)) &&
2671        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2672         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2673       IS_TRUE_SYMOP (IC_RESULT (ic)))
2674     {
2675
2676       _G.accInUse++;
2677       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2678       _G.accInUse--;
2679
2680       assignResultValue (IC_RESULT (ic));
2681
2682       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2683     }
2684
2685   /* adjust the stack for parameters if
2686      required */
2687   if (ic->parmBytes)
2688     {
2689       int i;
2690       if (options.stack10bit) {
2691           if (ic->parmBytes <= 10) {
2692               emitcode(";","stack adjustment for parms");
2693               for (i=0; i < ic->parmBytes ; i++) {
2694                   emitcode("pop","acc");
2695               }
2696           } else {            
2697               PROTECT_SP;
2698               emitcode ("clr","c");
2699               emitcode ("mov","a,sp");
2700               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2701               emitcode ("mov","sp,a");
2702               emitcode ("mov","a,esp");
2703               emitcode ("anl","a,#3");
2704               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2705               emitcode ("mov","esp,a");   
2706               UNPROTECT_SP;
2707           }
2708       } else {
2709           if (ic->parmBytes > 3) {
2710               emitcode ("mov", "a,%s", spname);
2711               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2712               emitcode ("mov", "%s,a", spname);
2713           }
2714           else
2715               for (i = 0; i < ic->parmBytes; i++)
2716                   emitcode ("dec", "%s", spname);
2717           
2718       }
2719     }
2720   /* if register bank was saved then unsave them */
2721   if (restoreBank)
2722     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2723   
2724   /* if we hade saved some registers then
2725      unsave them */
2726   if (ic->regsSaved)
2727     unsaveRegisters (ic);
2728
2729 }
2730
2731 /*-----------------------------------------------------------------*/
2732 /* resultRemat - result  is rematerializable                       */
2733 /*-----------------------------------------------------------------*/
2734 static int
2735 resultRemat (iCode * ic)
2736 {
2737   if (SKIP_IC (ic) || ic->op == IFX)
2738     return 0;
2739
2740   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2741     {
2742       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2743       if (sym->remat && !POINTER_SET (ic))
2744         return 1;
2745     }
2746
2747   return 0;
2748 }
2749
2750 #if defined(__BORLANDC__) || defined(_MSC_VER)
2751 #define STRCASECMP stricmp
2752 #else
2753 #define STRCASECMP strcasecmp
2754 #endif
2755
2756 /*-----------------------------------------------------------------*/
2757 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2758 /*-----------------------------------------------------------------*/
2759 static bool
2760 inExcludeList (char *s)
2761 {
2762   int i = 0;
2763
2764   if (options.excludeRegs[i] &&
2765       STRCASECMP (options.excludeRegs[i], "none") == 0)
2766     return FALSE;
2767
2768   for (i = 0; options.excludeRegs[i]; i++)
2769     {
2770       if (options.excludeRegs[i] &&
2771           STRCASECMP (s, options.excludeRegs[i]) == 0)
2772         return TRUE;
2773     }
2774   return FALSE;
2775 }
2776
2777 /*-----------------------------------------------------------------*/
2778 /* genFunction - generated code for function entry                 */
2779 /*-----------------------------------------------------------------*/
2780 static void
2781 genFunction (iCode * ic)
2782 {
2783   symbol *sym;
2784   sym_link *ftype;
2785   bool   switchedPSW = FALSE;
2786
2787   D (emitcode (";", "genFunction "););
2788
2789   _G.nRegsSaved = 0;
2790   /* create the function header */
2791   emitcode (";", "-----------------------------------------");
2792   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2793   emitcode (";", "-----------------------------------------");
2794
2795   emitcode ("", "%s:", sym->rname);
2796   ftype = operandType (IC_LEFT (ic));
2797
2798   if (IFFUNC_ISNAKED(ftype))
2799   {
2800       emitcode(";", "naked function: no prologue.");
2801       return;
2802   }
2803   
2804   if (options.stack_probe) 
2805       emitcode ("lcall","__stack_probe");
2806   /* if critical function then turn interrupts off */
2807   if (IFFUNC_ISCRITICAL (ftype))
2808     emitcode ("clr", "ea");
2809
2810   /* here we need to generate the equates for the
2811      register bank if required */
2812   if (FUNC_REGBANK (ftype) != rbank)
2813     {
2814       int i;
2815
2816       rbank = FUNC_REGBANK (ftype);
2817       for (i = 0; i < ds390_nRegs; i++)
2818         {
2819           if (regs390[i].print) {
2820               if (strcmp (regs390[i].base, "0") == 0)
2821                   emitcode ("", "%s !equ !constbyte",
2822                             regs390[i].dname,
2823                             8 * rbank + regs390[i].offset);
2824               else
2825                   emitcode ("", "%s !equ %s + !constbyte",
2826                             regs390[i].dname,
2827                             regs390[i].base,
2828                             8 * rbank + regs390[i].offset);
2829           }
2830         }
2831     }
2832
2833   /* if this is an interrupt service routine then
2834      save acc, b, dpl, dph  */
2835   if (IFFUNC_ISISR (sym->type))
2836       { /* is ISR */
2837       if (!inExcludeList ("acc"))
2838         emitcode ("push", "acc");
2839       if (!inExcludeList ("b"))
2840         emitcode ("push", "b");
2841       if (!inExcludeList ("dpl"))
2842         emitcode ("push", "dpl");
2843       if (!inExcludeList ("dph"))
2844         emitcode ("push", "dph");
2845       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2846         {
2847           emitcode ("push", "dpx");
2848           /* Make sure we're using standard DPTR */
2849           emitcode ("push", "dps");
2850           emitcode ("mov", "dps,#0");
2851           if (options.stack10bit)
2852             {
2853               /* This ISR could conceivably use DPTR2. Better save it. */
2854               emitcode ("push", "dpl1");
2855               emitcode ("push", "dph1");
2856               emitcode ("push", "dpx1");
2857               emitcode ("push",  DP2_RESULT_REG);
2858             }
2859         }
2860       /* if this isr has no bank i.e. is going to
2861          run with bank 0 , then we need to save more
2862          registers :-) */
2863       if (!FUNC_REGBANK (sym->type))
2864         {
2865             int i;
2866
2867           /* if this function does not call any other
2868              function then we can be economical and
2869              save only those registers that are used */
2870           if (!IFFUNC_HASFCALL(sym->type))
2871             {
2872
2873               /* if any registers used */
2874               if (sym->regsUsed)
2875                 {
2876                   /* save the registers used */
2877                   for (i = 0; i < sym->regsUsed->size; i++)
2878                     {
2879                       if (bitVectBitValue (sym->regsUsed, i) ||
2880                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2881                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2882                     }
2883                 }
2884
2885             }
2886           else
2887             {
2888               /* this function has  a function call cannot
2889                  determines register usage so we will have to push the
2890                  entire bank */
2891               saveRBank (0, ic, FALSE);
2892               if (options.parms_in_bank1) {
2893                   for (i=0; i < 8 ; i++ ) {
2894                       emitcode ("push","%s",rb1regs[i]);
2895                   }
2896               }
2897             }
2898         }
2899         else
2900         {
2901             /* This ISR uses a non-zero bank.
2902              *
2903              * We assume that the bank is available for our
2904              * exclusive use.
2905              *
2906              * However, if this ISR calls a function which uses some
2907              * other bank, we must save that bank entirely.
2908              */
2909             unsigned long banksToSave = 0;
2910             
2911             if (IFFUNC_HASFCALL(sym->type))
2912             {
2913
2914 #define MAX_REGISTER_BANKS 4
2915
2916                 iCode *i;
2917                 int ix;
2918
2919                 for (i = ic; i; i = i->next)
2920                 {
2921                     if (i->op == ENDFUNCTION)
2922                     {
2923                         /* we got to the end OK. */
2924                         break;
2925                     }
2926                     
2927                     if (i->op == CALL)
2928                     {
2929                         sym_link *dtype;
2930                         
2931                         dtype = operandType (IC_LEFT(i));
2932                         if (dtype 
2933                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2934                         {
2935                              /* Mark this bank for saving. */
2936                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2937                              {
2938                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2939                              }
2940                              else
2941                              {
2942                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2943                              }
2944                              
2945                              /* And note that we don't need to do it in 
2946                               * genCall.
2947                               */
2948                              i->bankSaved = 1;
2949                         }
2950                     }
2951                     if (i->op == PCALL)
2952                     {
2953                         /* This is a mess; we have no idea what
2954                          * register bank the called function might
2955                          * use.
2956                          *
2957                          * The only thing I can think of to do is
2958                          * throw a warning and hope.
2959                          */
2960                         werror(W_FUNCPTR_IN_USING_ISR);   
2961                     }
2962                 }
2963
2964                 if (banksToSave && options.useXstack)
2965                 {
2966                     /* Since we aren't passing it an ic, 
2967                      * saveRBank will assume r0 is available to abuse.
2968                      *
2969                      * So switch to our (trashable) bank now, so
2970                      * the caller's R0 isn't trashed.
2971                      */
2972                     emitcode ("push", "psw");
2973                     emitcode ("mov", "psw,#!constbyte", 
2974                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2975                     switchedPSW = TRUE;
2976                 }
2977                 
2978                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2979                 {
2980                      if (banksToSave & (1 << ix))
2981                      {
2982                          saveRBank(ix, NULL, FALSE);
2983                      }
2984                 }
2985             }
2986             // jwk: this needs a closer look
2987             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2988         }
2989     }
2990   else
2991     {
2992       /* if callee-save to be used for this function
2993          then save the registers being used in this function */
2994       if (IFFUNC_CALLEESAVES(sym->type))
2995         {
2996           int i;
2997
2998           /* if any registers used */
2999           if (sym->regsUsed)
3000             {
3001               /* save the registers used */
3002               for (i = 0; i < sym->regsUsed->size; i++)
3003                 {
3004                   if (bitVectBitValue (sym->regsUsed, i) ||
3005                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3006                     {
3007                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3008                       _G.nRegsSaved++;
3009                     }
3010                 }
3011             }
3012         }
3013     }
3014
3015   /* set the register bank to the desired value */
3016   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3017    && !switchedPSW)
3018     {
3019       emitcode ("push", "psw");
3020       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3021     }
3022
3023   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3024        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3025       if (options.stack10bit) {
3026           emitcode ("push","_bpx");
3027           emitcode ("push","_bpx+1");
3028           emitcode ("mov","_bpx,%s",spname);
3029           emitcode ("mov","_bpx+1,esp");
3030           emitcode ("anl","_bpx+1,#3");
3031       } else {
3032           if (options.useXstack) {
3033               emitcode ("mov", "r0,%s", spname);
3034               emitcode ("mov", "a,_bp");
3035               emitcode ("movx", "@r0,a");
3036               emitcode ("inc", "%s", spname);
3037           } else {
3038               /* set up the stack */
3039               emitcode ("push", "_bp"); /* save the callers stack  */
3040           }
3041           emitcode ("mov", "_bp,%s", spname);
3042       }
3043   }
3044
3045   /* adjust the stack for the function */
3046   if (sym->stack) {
3047       int i = sym->stack;
3048       if (options.stack10bit) {
3049           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3050           assert (sym->recvSize <= 4);
3051           if (sym->stack <= 8) {
3052               while (i--) emitcode ("push","acc");
3053           } else {
3054               PROTECT_SP;
3055               emitcode ("mov","a,sp");
3056               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3057               emitcode ("mov","sp,a");
3058               emitcode ("mov","a,esp");
3059               emitcode ("anl","a,#3");
3060               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3061               emitcode ("mov","esp,a");
3062               UNPROTECT_SP;
3063           }
3064       } else {
3065           if (i > 256)
3066               werror (W_STACK_OVERFLOW, sym->name);
3067           
3068           if (i > 3 && sym->recvSize < 4) {
3069               
3070               emitcode ("mov", "a,sp");
3071               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3072               emitcode ("mov", "sp,a");
3073               
3074           } else
3075               while (i--)
3076                   emitcode ("inc", "sp");
3077       }
3078   }
3079
3080   if (sym->xstack)
3081     {
3082
3083       emitcode ("mov", "a,_spx");
3084       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3085       emitcode ("mov", "_spx,a");
3086     }
3087
3088 }
3089
3090 /*-----------------------------------------------------------------*/
3091 /* genEndFunction - generates epilogue for functions               */
3092 /*-----------------------------------------------------------------*/
3093 static void
3094 genEndFunction (iCode * ic)
3095 {
3096   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3097
3098   D (emitcode (";", "genEndFunction "););
3099
3100   if (IFFUNC_ISNAKED(sym->type))
3101   {
3102       emitcode(";", "naked function: no epilogue.");
3103       return;
3104   }
3105
3106   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3107        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3108
3109       if (options.stack10bit) {
3110           PROTECT_SP;     
3111           emitcode ("mov", "sp,_bpx", spname);
3112           emitcode ("mov", "esp,_bpx+1", spname);
3113           UNPROTECT_SP;
3114       } else {
3115           emitcode ("mov", "%s,_bp", spname);
3116       }
3117   }
3118
3119   /* if use external stack but some variables were
3120      added to the local stack then decrement the
3121      local stack */
3122   if (options.useXstack && sym->stack) {
3123       emitcode ("mov", "a,sp");
3124       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3125       emitcode ("mov", "sp,a");
3126   }
3127
3128
3129   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131
3132       if (options.useXstack) {
3133           emitcode ("mov", "r0,%s", spname);
3134           emitcode ("movx", "a,@r0");
3135           emitcode ("mov", "_bp,a");
3136           emitcode ("dec", "%s", spname);
3137       } else {
3138           if (options.stack10bit) {
3139               emitcode ("pop", "_bpx+1");
3140               emitcode ("pop", "_bpx");
3141           } else {
3142               emitcode ("pop", "_bp");
3143           }
3144       }
3145   }
3146
3147   /* restore the register bank  */
3148   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3149   {
3150     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3151      || !options.useXstack)
3152     {
3153         /* Special case of ISR using non-zero bank with useXstack
3154          * is handled below.
3155          */
3156         emitcode ("pop", "psw");
3157     }
3158   } 
3159
3160   if (IFFUNC_ISISR (sym->type))
3161       { /* is ISR */  
3162
3163       /* now we need to restore the registers */
3164       /* if this isr has no bank i.e. is going to
3165          run with bank 0 , then we need to save more
3166          registers :-) */
3167       if (!FUNC_REGBANK (sym->type))
3168         {
3169             int i;
3170           /* if this function does not call any other
3171              function then we can be economical and
3172              save only those registers that are used */
3173           if (!IFFUNC_HASFCALL(sym->type))
3174             {
3175
3176               /* if any registers used */
3177               if (sym->regsUsed)
3178                 {
3179                   /* save the registers used */
3180                   for (i = sym->regsUsed->size; i >= 0; i--)
3181                     {
3182                       if (bitVectBitValue (sym->regsUsed, i) ||
3183                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3184                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3185                     }
3186                 }
3187
3188             }
3189           else
3190             {
3191               /* this function has  a function call cannot
3192                  determines register usage so we will have to pop the
3193                  entire bank */
3194               if (options.parms_in_bank1) {
3195                   for (i = 7 ; i >= 0 ; i-- ) {
3196                       emitcode ("pop","%s",rb1regs[i]);
3197                   }
3198               }
3199               unsaveRBank (0, ic, FALSE);
3200             }
3201         }
3202         else
3203         {
3204             /* This ISR uses a non-zero bank.
3205              *
3206              * Restore any register banks saved by genFunction
3207              * in reverse order.
3208              */
3209           // jwk: this needs a closer look
3210             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3211             int ix;
3212           
3213             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3214             {
3215                 if (savedBanks & (1 << ix))
3216                 {
3217                     unsaveRBank(ix, NULL, FALSE);
3218                 }
3219             }
3220             
3221             if (options.useXstack)
3222             {
3223                 /* Restore bank AFTER calling unsaveRBank,
3224                  * since it can trash r0.
3225                  */
3226                 emitcode ("pop", "psw");
3227             }
3228         }
3229
3230       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3231         {
3232           if (options.stack10bit)
3233             {
3234               emitcode ("pop", DP2_RESULT_REG);
3235               emitcode ("pop", "dpx1");
3236               emitcode ("pop", "dph1");
3237               emitcode ("pop", "dpl1");
3238             }
3239           emitcode ("pop", "dps");
3240           emitcode ("pop", "dpx");
3241         }
3242       if (!inExcludeList ("dph"))
3243         emitcode ("pop", "dph");
3244       if (!inExcludeList ("dpl"))
3245         emitcode ("pop", "dpl");
3246       if (!inExcludeList ("b"))
3247         emitcode ("pop", "b");
3248       if (!inExcludeList ("acc"))
3249         emitcode ("pop", "acc");
3250
3251       if (IFFUNC_ISCRITICAL (sym->type))
3252         emitcode ("setb", "ea");
3253
3254       /* if debug then send end of function */
3255       if (options.debug && currFunc) {
3256           _G.debugLine = 1;
3257           emitcode ("", "C$%s$%d$%d$%d ==.",
3258                     FileBaseName (ic->filename), currFunc->lastLine,
3259                     ic->level, ic->block);
3260           if (IS_STATIC (currFunc->etype))
3261             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3262           else
3263             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3264           _G.debugLine = 0;
3265         }
3266
3267       emitcode ("reti", "");
3268     }
3269   else
3270     {
3271       if (IFFUNC_ISCRITICAL (sym->type))
3272         emitcode ("setb", "ea");
3273
3274       if (IFFUNC_CALLEESAVES(sym->type))
3275         {
3276           int i;
3277
3278           /* if any registers used */
3279           if (sym->regsUsed)
3280             {
3281               /* save the registers used */
3282               for (i = sym->regsUsed->size; i >= 0; i--)
3283                 {
3284                   if (bitVectBitValue (sym->regsUsed, i) ||
3285                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3286                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3287                 }
3288             }
3289
3290         }
3291
3292       /* if debug then send end of function */
3293       if (options.debug && currFunc)
3294         {
3295           _G.debugLine = 1;
3296           emitcode ("", "C$%s$%d$%d$%d ==.",
3297                     FileBaseName (ic->filename), currFunc->lastLine,
3298                     ic->level, ic->block);
3299           if (IS_STATIC (currFunc->etype))
3300             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3301           else
3302             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3303           _G.debugLine = 0;
3304         }
3305
3306       emitcode ("ret", "");
3307     }
3308
3309 }
3310
3311 /*-----------------------------------------------------------------*/
3312 /* genJavaNativeRet - generate code for return JavaNative          */
3313 /*-----------------------------------------------------------------*/
3314 static void genJavaNativeRet(iCode *ic)
3315 {
3316     int i, size;
3317
3318     aopOp (IC_LEFT (ic), ic, FALSE, 
3319            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3320     size = AOP_SIZE (IC_LEFT (ic));
3321
3322     assert (size <= 4);
3323
3324     /* it is assigned to GPR0-R3 then push them */
3325     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3326         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3327         for (i = 0 ; i < size ; i++ ) {
3328             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3329         }
3330         for (i = (size-1) ; i >= 0 ; i--) {
3331             emitcode ("pop","a%s",javaRet[i]);
3332         }
3333     } else {
3334         for (i = 0 ; i < size ; i++) 
3335             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3336     }
3337     for (i = size ; i < 4 ; i++ )
3338             emitcode ("mov","%s,#0",javaRet[i]);
3339     return;
3340 }
3341
3342 /*-----------------------------------------------------------------*/
3343 /* genRet - generate code for return statement                     */
3344 /*-----------------------------------------------------------------*/
3345 static void
3346 genRet (iCode * ic)
3347 {
3348   int size, offset = 0, pushed = 0;
3349
3350   D (emitcode (";", "genRet ");
3351     );
3352
3353   /* if we have no return value then
3354      just generate the "ret" */
3355   if (!IC_LEFT (ic))
3356     goto jumpret;
3357
3358   /* if this is a JavaNative function then return 
3359      value in different register */
3360   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3361       genJavaNativeRet(ic);
3362       goto jumpret;
3363   }
3364   /* we have something to return then
3365      move the return value into place */
3366   aopOp (IC_LEFT (ic), ic, FALSE, 
3367          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3368   size = AOP_SIZE (IC_LEFT (ic));
3369
3370   _startLazyDPSEvaluation ();
3371   while (size--)
3372     {
3373       char *l;
3374       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3375         {
3376           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3377                       FALSE, TRUE, FALSE);
3378           emitcode ("push", "%s", l);
3379           pushed++;
3380         }
3381       else
3382         {
3383           /* Since A is the last element of fReturn,
3384            * is is OK to clobber it in the aopGet.
3385            */
3386           l = aopGet (AOP (IC_LEFT (ic)), offset,
3387                       FALSE, FALSE, TRUE);
3388           if (strcmp (fReturn[offset], l))
3389             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3390         }
3391     }
3392   _endLazyDPSEvaluation ();
3393
3394   if (pushed)
3395     {
3396       while (pushed)
3397         {
3398           pushed--;
3399           if (strcmp (fReturn[pushed], "a"))
3400             emitcode ("pop", fReturn[pushed]);
3401           else
3402             emitcode ("pop", "acc");
3403         }
3404     }
3405   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3406
3407 jumpret:
3408   /* generate a jump to the return label
3409      if the next is not the return statement */
3410   if (!(ic->next && ic->next->op == LABEL &&
3411         IC_LABEL (ic->next) == returnLabel))
3412
3413     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3414
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genLabel - generates a label                                    */
3419 /*-----------------------------------------------------------------*/
3420 static void
3421 genLabel (iCode * ic)
3422 {
3423   /* special case never generate */
3424   if (IC_LABEL (ic) == entryLabel)
3425     return;
3426
3427   D (emitcode (";", "genLabel ");
3428     );
3429
3430   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3431 }
3432
3433 /*-----------------------------------------------------------------*/
3434 /* genGoto - generates a ljmp                                      */
3435 /*-----------------------------------------------------------------*/
3436 static void
3437 genGoto (iCode * ic)
3438 {
3439   D (emitcode (";", "genGoto ");
3440     );
3441   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* findLabelBackwards: walks back through the iCode chain looking  */
3446 /* for the given label. Returns number of iCode instructions     */
3447 /* between that label and given ic.          */
3448 /* Returns zero if label not found.          */
3449 /*-----------------------------------------------------------------*/
3450 static int
3451 findLabelBackwards (iCode * ic, int key)
3452 {
3453   int count = 0;
3454
3455   while (ic->prev)
3456     {
3457       ic = ic->prev;
3458       count++;
3459
3460       /* If we have any pushes or pops, we cannot predict the distance.
3461          I don't like this at all, this should be dealt with in the 
3462          back-end */
3463       if (ic->op == IPUSH || ic->op == IPOP) {
3464         return 0;
3465       }
3466
3467       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3468         {
3469           /* printf("findLabelBackwards = %d\n", count); */
3470           return count;
3471         }
3472     }
3473
3474   return 0;
3475 }
3476
3477 /*-----------------------------------------------------------------*/
3478 /* genPlusIncr :- does addition with increment if possible         */
3479 /*-----------------------------------------------------------------*/
3480 static bool
3481 genPlusIncr (iCode * ic)
3482 {
3483   unsigned int icount;
3484   unsigned int size = getDataSize (IC_RESULT (ic));
3485
3486   /* will try to generate an increment */
3487   /* if the right side is not a literal
3488      we cannot */
3489   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3490     return FALSE;
3491
3492   /* if the literal value of the right hand side
3493      is greater than 4 then it is not worth it */
3494   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3495     return FALSE;
3496
3497   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3498       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3499       while (icount--) {
3500           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3501       }
3502       return TRUE;
3503   }
3504   /* if increment 16 bits in register */
3505   if (
3506        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3507        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3508        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3509        (size > 1) &&
3510        (icount == 1))
3511     {
3512       symbol *tlbl;
3513       int emitTlbl;
3514       int labelRange;
3515
3516       /* If the next instruction is a goto and the goto target
3517        * is <= 5 instructions previous to this, we can generate
3518        * jumps straight to that target.
3519        */
3520       if (ic->next && ic->next->op == GOTO
3521           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3522           && labelRange <= 5)
3523         {
3524           emitcode (";", "tail increment optimized (range %d)", labelRange);
3525           tlbl = IC_LABEL (ic->next);
3526           emitTlbl = 0;
3527         }
3528       else
3529         {
3530           tlbl = newiTempLabel (NULL);
3531           emitTlbl = 1;
3532         }
3533       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3534       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3535           IS_AOP_PREG (IC_RESULT (ic)))
3536         emitcode ("cjne", "%s,#0,!tlabel"
3537                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3538                   ,tlbl->key + 100);
3539       else
3540         {
3541           emitcode ("clr", "a");
3542           emitcode ("cjne", "a,%s,!tlabel"
3543                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3544                     ,tlbl->key + 100);
3545         }
3546
3547       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3548       if (size > 2)
3549         {
3550           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3551               IS_AOP_PREG (IC_RESULT (ic)))
3552             emitcode ("cjne", "%s,#0,!tlabel"
3553                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3554                       ,tlbl->key + 100);
3555           else
3556             emitcode ("cjne", "a,%s,!tlabel"
3557                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3558                       ,tlbl->key + 100);
3559
3560           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3561         }
3562       if (size > 3)
3563         {
3564           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3565               IS_AOP_PREG (IC_RESULT (ic)))
3566             emitcode ("cjne", "%s,#0,!tlabel"
3567                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3568                       ,tlbl->key + 100);
3569           else
3570             {
3571               emitcode ("cjne", "a,%s,!tlabel"
3572                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3573                         ,tlbl->key + 100);
3574             }
3575           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3576         }
3577
3578       if (emitTlbl)
3579         {
3580           emitcode ("", "!tlabeldef", tlbl->key + 100);
3581         }
3582       return TRUE;
3583     }
3584
3585   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3586       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3587       options.model == MODEL_FLAT24 ) {
3588
3589       switch (size) {
3590       case 3:
3591           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, FALSE));
3592       case 2:
3593           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, FALSE));
3594       case 1:
3595           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3596           break;
3597       }
3598       while (icount--) emitcode ("inc","dptr");      
3599       return TRUE;
3600   }
3601
3602   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3603       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3604       icount <= 5 ) {
3605       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3606       while (icount--) emitcode ("inc","dptr");
3607       emitcode ("mov","dps,#0");
3608       return TRUE;
3609   }
3610
3611   /* if the sizes are greater than 1 then we cannot */
3612   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3613       AOP_SIZE (IC_LEFT (ic)) > 1)
3614     return FALSE;
3615
3616   /* we can if the aops of the left & result match or
3617      if they are in registers and the registers are the
3618      same */
3619   if (
3620        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3621        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3622        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3623     {
3624
3625       if (icount > 3)
3626         {
3627           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3628           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3629           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3630         }
3631       else
3632         {
3633
3634           _startLazyDPSEvaluation ();
3635           while (icount--)
3636             {
3637               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3638             }
3639           _endLazyDPSEvaluation ();
3640         }
3641
3642       return TRUE;
3643     }
3644
3645   return FALSE;
3646 }
3647
3648 /*-----------------------------------------------------------------*/
3649 /* outBitAcc - output a bit in acc                                 */
3650 /*-----------------------------------------------------------------*/
3651 static void
3652 outBitAcc (operand * result)
3653 {
3654   symbol *tlbl = newiTempLabel (NULL);
3655   /* if the result is a bit */
3656   if (AOP_TYPE (result) == AOP_CRY)
3657     {
3658       aopPut (AOP (result), "a", 0);
3659     }
3660   else
3661     {
3662       emitcode ("jz", "!tlabel", tlbl->key + 100);
3663       emitcode ("mov", "a,%s", one);
3664       emitcode ("", "!tlabeldef", tlbl->key + 100);
3665       outAcc (result);
3666     }
3667 }
3668
3669 /*-----------------------------------------------------------------*/
3670 /* genPlusBits - generates code for addition of two bits           */
3671 /*-----------------------------------------------------------------*/
3672 static void
3673 genPlusBits (iCode * ic)
3674 {
3675   D (emitcode (";", "genPlusBits ");
3676     );
3677   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3678     {
3679       symbol *lbl = newiTempLabel (NULL);
3680       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3681       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3682       emitcode ("cpl", "c");
3683       emitcode ("", "!tlabeldef", (lbl->key + 100));
3684       outBitC (IC_RESULT (ic));
3685     }
3686   else
3687     {
3688       emitcode ("clr", "a");
3689       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3690       emitcode ("rlc", "a");
3691       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3692       emitcode ("addc", "a,#0");
3693       outAcc (IC_RESULT (ic));
3694     }
3695 }
3696
3697 static void
3698 adjustArithmeticResult (iCode * ic)
3699 {
3700   if (opIsGptr (IC_RESULT (ic)) &&
3701       opIsGptr (IC_LEFT (ic)) &&
3702       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3703     {
3704       aopPut (AOP (IC_RESULT (ic)),
3705               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3706               GPTRSIZE - 1);
3707     }
3708
3709   if (opIsGptr (IC_RESULT (ic)) &&
3710       opIsGptr (IC_RIGHT (ic)) &&
3711       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3712     {
3713       aopPut (AOP (IC_RESULT (ic)),
3714             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3715               GPTRSIZE - 1);
3716     }
3717
3718   if (opIsGptr (IC_RESULT (ic)) &&
3719       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3720       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3721       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3722       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3723     {
3724       char buff[5];
3725       SNPRINTF (buff, sizeof(buff), 
3726                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3727       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3728     }
3729 }
3730
3731 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3732 // generates the result if possible. If result is generated, returns TRUE; otherwise
3733 // returns false and caller must deal with fact that result isn't aopOp'd.
3734 bool aopOp3(iCode * ic)
3735 {
3736     bool dp1InUse, dp2InUse;
3737     bool useDp2;
3738     
3739     // First, generate the right opcode. DPTR may be used if neither left nor result are
3740     // of type AOP_STR.
3741     
3742 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3743 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3744 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3745 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3746 //      );
3747 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3748 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3749 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3750 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3751 //      );      
3752
3753     
3754     // Right uses DPTR unless left or result is an AOP_STR.
3755     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3756     
3757     // if the right used DPTR, left MUST use DPTR2.
3758     // if the right used DPTR2, left MUST use DPTR.
3759     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3760     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3761     // enabling us to assign DPTR to result.
3762      
3763     if (AOP_USESDPTR(IC_RIGHT(ic)))
3764     {
3765         useDp2 = TRUE;
3766     }
3767     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3768     {
3769         useDp2 = FALSE;
3770     }
3771     else
3772     {
3773         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3774         {
3775             useDp2 = TRUE;
3776         }
3777         else
3778         {
3779             useDp2 = FALSE;
3780         }
3781     }
3782
3783     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3784     
3785     // We've op'd the left & right. So, if left or right are the same operand as result, 
3786     // we know aopOp will succeed, and we can just do it & bail.
3787     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3788         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3789     {
3790 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3791         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3792         return TRUE;
3793     }
3794     
3795     // Note which dptrs are currently in use.
3796     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3797     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3798     
3799     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3800     // generate it.
3801     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3802     {
3803         return FALSE;
3804     }
3805     
3806     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3807     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3808     {
3809         return FALSE;
3810     }
3811     
3812     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3813     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3814     {
3815         return FALSE;
3816     }
3817
3818     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3819
3820     // Some sanity checking...
3821     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3822     {
3823         fprintf(stderr,
3824                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3825                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3826         emitcode(";", ">>> unexpected DPTR here.");
3827     }
3828     
3829     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3830     {
3831         fprintf(stderr,
3832                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3833                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3834         emitcode(";", ">>> unexpected DPTR2 here.");
3835     }    
3836     
3837     return TRUE;
3838 }
3839
3840 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3841 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3842 // will be set TRUE. The caller must then handle the case specially, noting
3843 // that the IC_RESULT operand is not aopOp'd.
3844 // 
3845 #define AOP_OP_3_NOFATAL(ic, rc) \
3846             do { rc = !aopOp3(ic); } while (0)
3847
3848 // aopOp the left & right operands of an ic.
3849 #define AOP_OP_2(ic) \
3850     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3851     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3852
3853 // convienience macro.
3854 #define AOP_SET_LOCALS(ic) \
3855     left = IC_LEFT(ic); \
3856     right = IC_RIGHT(ic); \
3857     result = IC_RESULT(ic);
3858
3859
3860 // Given an integer value of pushedSize bytes on the stack,
3861 // adjust it to be resultSize bytes, either by discarding
3862 // the most significant bytes or by zero-padding.
3863 //
3864 // On exit from this macro, pushedSize will have been adjusted to
3865 // equal resultSize, and ACC may be trashed.
3866 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3867       /* If the pushed data is bigger than the result,          \
3868        * simply discard unused bytes. Icky, but works.          \
3869        */                                                       \
3870       while (pushedSize > resultSize)                           \
3871       {                                                         \
3872           D (emitcode (";", "discarding unused result byte."););\
3873           emitcode ("pop", "acc");                              \
3874           pushedSize--;                                         \
3875       }                                                         \
3876       if (pushedSize < resultSize)                              \
3877       {                                                         \
3878           emitcode ("clr", "a");                                \
3879           /* Conversly, we haven't pushed enough here.          \
3880            * just zero-pad, and all is well.                    \
3881            */                                                   \
3882           while (pushedSize < resultSize)                       \
3883           {                                                     \
3884               emitcode("push", "acc");                          \
3885               pushedSize++;                                     \
3886           }                                                     \
3887       }                                                         \
3888       assert(pushedSize == resultSize);
3889
3890 /*-----------------------------------------------------------------*/
3891 /* genPlus - generates code for addition                           */
3892 /*-----------------------------------------------------------------*/
3893 static void
3894 genPlus (iCode * ic)
3895 {
3896   int size, offset = 0;
3897   bool pushResult = FALSE;
3898   int rSize;
3899
3900   D (emitcode (";", "genPlus "););
3901
3902   /* special cases :- */
3903   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3904       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3905       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3906       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3907       if (size <= 9) {
3908           while (size--) emitcode ("inc","dptr");
3909       } else {
3910           emitcode ("mov","a,dpl");
3911           emitcode ("add","a,#!constbyte",size & 0xff);
3912           emitcode ("mov","dpl,a");
3913           emitcode ("mov","a,dph");
3914           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3915           emitcode ("mov","dph,a");
3916           emitcode ("mov","a,dpx");
3917           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3918           emitcode ("mov","dpx,a");
3919       }
3920       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3921       return ;
3922   }
3923   if ( IS_SYMOP(IC_LEFT(ic)) && 
3924        OP_SYMBOL(IC_LEFT(ic))->remat &&
3925        isOperandInFarSpace(IC_RIGHT(ic))) {
3926       operand *op = IC_RIGHT(ic);
3927       IC_RIGHT(ic) = IC_LEFT(ic);
3928       IC_LEFT(ic) = op;
3929   }
3930                 
3931   AOP_OP_3_NOFATAL (ic, pushResult);
3932     
3933   if (pushResult)
3934     {
3935       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3936     }
3937
3938   if (!pushResult)
3939     {
3940       /* if literal, literal on the right or
3941          if left requires ACC or right is already
3942          in ACC */
3943       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3944        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3945           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3946         {
3947           operand *t = IC_RIGHT (ic);
3948           IC_RIGHT (ic) = IC_LEFT (ic);
3949           IC_LEFT (ic) = t;
3950           emitcode (";", "Swapped plus args.");
3951         }
3952
3953       /* if both left & right are in bit
3954          space */
3955       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3956           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3957         {
3958           genPlusBits (ic);
3959           goto release;
3960         }
3961
3962       /* if left in bit space & right literal */
3963       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3964           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3965         {
3966           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3967           /* if result in bit space */
3968           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3969             {
3970               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3971                 emitcode ("cpl", "c");
3972               outBitC (IC_RESULT (ic));
3973             }
3974           else
3975             {
3976               size = getDataSize (IC_RESULT (ic));
3977               _startLazyDPSEvaluation ();
3978               while (size--)
3979                 {
3980                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3981                   emitcode ("addc", "a,#0");
3982                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3983                 }
3984               _endLazyDPSEvaluation ();
3985             }
3986           goto release;
3987         }
3988
3989       /* if I can do an increment instead
3990          of add then GOOD for ME */
3991       if (genPlusIncr (ic) == TRUE)
3992         {
3993           emitcode (";", "did genPlusIncr");
3994           goto release;
3995         }
3996
3997     }
3998   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3999
4000   _startLazyDPSEvaluation ();
4001   while (size--)
4002     {
4003       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4004         {
4005           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4006           if (offset == 0)
4007             emitcode ("add", "a,%s",
4008                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4009           else
4010             emitcode ("addc", "a,%s",
4011                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4012         }
4013       else
4014         {
4015           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4016           {
4017               /* right is going to use ACC or we would have taken the
4018                * above branch.
4019                */
4020               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4021        TR_AP("#3");
4022               D(emitcode(";", "+ AOP_ACC special case."););
4023               emitcode("xch", "a, %s", DP2_RESULT_REG);
4024           }
4025           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
4026           if (offset == 0)
4027           {
4028             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4029             {
4030          TR_AP("#4");
4031                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4032             }
4033             else
4034             {
4035                 emitcode ("add", "a,%s",
4036                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
4037             }
4038           }
4039           else
4040           {
4041             emitcode ("addc", "a,%s",
4042                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
4043           }
4044         }
4045       if (!pushResult)
4046         {
4047           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4048         }
4049       else
4050         {
4051           emitcode ("push", "acc");
4052         }
4053       offset++;
4054     }
4055   _endLazyDPSEvaluation ();
4056
4057   if (pushResult)
4058     {
4059       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4060
4061       size = getDataSize (IC_LEFT (ic));
4062       rSize = getDataSize (IC_RESULT (ic));
4063
4064       ADJUST_PUSHED_RESULT(size, rSize);
4065
4066       _startLazyDPSEvaluation ();
4067       while (size--)
4068         {
4069           emitcode ("pop", "acc");
4070           aopPut (AOP (IC_RESULT (ic)), "a", size);
4071         }
4072       _endLazyDPSEvaluation ();
4073     }
4074
4075   adjustArithmeticResult (ic);
4076
4077 release:
4078   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4079   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4080   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4081 }
4082
4083 /*-----------------------------------------------------------------*/
4084 /* genMinusDec :- does subtraction with deccrement if possible     */
4085 /*-----------------------------------------------------------------*/
4086 static bool
4087 genMinusDec (iCode * ic)
4088 {
4089   unsigned int icount;
4090   unsigned int size = getDataSize (IC_RESULT (ic));
4091
4092   /* will try to generate an increment */
4093   /* if the right side is not a literal
4094      we cannot */
4095   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4096     return FALSE;
4097
4098   /* if the literal value of the right hand side
4099      is greater than 4 then it is not worth it */
4100   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4101     return FALSE;
4102
4103   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4104       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4105       while (icount--) {
4106           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
4107       }
4108       return TRUE;
4109   }
4110   /* if decrement 16 bits in register */
4111   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4112       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4113       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4114       (size > 1) &&
4115       (icount == 1))
4116     {
4117       symbol *tlbl;
4118       int emitTlbl;
4119       int labelRange;
4120
4121       /* If the next instruction is a goto and the goto target
4122          * is <= 5 instructions previous to this, we can generate
4123          * jumps straight to that target.
4124        */
4125       if (ic->next && ic->next->op == GOTO
4126           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4127           && labelRange <= 5)
4128         {
4129           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4130           tlbl = IC_LABEL (ic->next);
4131           emitTlbl = 0;
4132         }
4133       else
4134         {
4135           tlbl = newiTempLabel (NULL);
4136           emitTlbl = 1;
4137         }
4138
4139       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
4140       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4141           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4142           IS_AOP_PREG (IC_RESULT (ic)))
4143         emitcode ("cjne", "%s,#!constbyte,!tlabel"
4144                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
4145                   ,tlbl->key + 100);
4146       else
4147         {
4148           emitcode ("mov", "a,#!constbyte",0xff);
4149           emitcode ("cjne", "a,%s,!tlabel"
4150                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
4151                     ,tlbl->key + 100);
4152         }
4153       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
4154       if (size > 2)
4155         {
4156           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4157               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4158               IS_AOP_PREG (IC_RESULT (ic)))
4159             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4160                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
4161                       ,tlbl->key + 100);
4162           else
4163             {
4164               emitcode ("cjne", "a,%s,!tlabel"
4165                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
4166                         ,tlbl->key + 100);
4167             }
4168           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
4169         }
4170       if (size > 3)
4171         {
4172           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4173               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4174               IS_AOP_PREG (IC_RESULT (ic)))
4175             emitcode ("cjne", "%s,#!constbyte,!tlabel"
4176                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
4177                       ,tlbl->key + 100);
4178           else
4179             {
4180               emitcode ("cjne", "a,%s,!tlabel"
4181                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
4182                         ,tlbl->key + 100);
4183             }
4184           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
4185         }
4186       if (emitTlbl)
4187         {
4188           emitcode ("", "!tlabeldef", tlbl->key + 100);
4189         }
4190       return TRUE;
4191     }
4192
4193   /* if the sizes are greater than 1 then we cannot */
4194   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4195       AOP_SIZE (IC_LEFT (ic)) > 1)
4196     return FALSE;
4197
4198   /* we can if the aops of the left & result match or
4199      if they are in registers and the registers are the
4200      same */
4201   if (
4202        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4203        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4204        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4205     {
4206
4207       _startLazyDPSEvaluation ();
4208       while (icount--)
4209         {
4210           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
4211         }
4212       _endLazyDPSEvaluation ();
4213
4214       return TRUE;
4215     }
4216
4217   return FALSE;
4218 }
4219
4220 /*-----------------------------------------------------------------*/
4221 /* addSign - complete with sign                                    */
4222 /*-----------------------------------------------------------------*/
4223 static void
4224 addSign (operand * result, int offset, int sign)
4225 {
4226   int size = (getDataSize (result) - offset);
4227   if (size > 0)
4228     {
4229       _startLazyDPSEvaluation();
4230       if (sign)
4231         {
4232           emitcode ("rlc", "a");
4233           emitcode ("subb", "a,acc");
4234           while (size--)
4235           {
4236             aopPut (AOP (result), "a", offset++);
4237           }
4238         }
4239       else
4240       {
4241         while (size--)
4242         {
4243           aopPut (AOP (result), zero, offset++);
4244         }
4245       }
4246       _endLazyDPSEvaluation();
4247     }
4248 }
4249
4250 /*-----------------------------------------------------------------*/
4251 /* genMinusBits - generates code for subtraction  of two bits      */
4252 /*-----------------------------------------------------------------*/
4253 static void
4254 genMinusBits (iCode * ic)
4255 {
4256   symbol *lbl = newiTempLabel (NULL);
4257
4258   D (emitcode (";", "genMinusBits "););
4259
4260   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4261     {
4262       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4263       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4264       emitcode ("cpl", "c");
4265       emitcode ("", "!tlabeldef", (lbl->key + 100));
4266       outBitC (IC_RESULT (ic));
4267     }
4268   else
4269     {
4270       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4271       emitcode ("subb", "a,acc");
4272       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4273       emitcode ("inc", "a");
4274       emitcode ("", "!tlabeldef", (lbl->key + 100));
4275       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4276       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4277     }
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genMinus - generates code for subtraction                       */
4282 /*-----------------------------------------------------------------*/
4283 static void
4284 genMinus (iCode * ic)
4285 {
4286     int size, offset = 0;
4287     int rSize;
4288     unsigned long lit = 0L;
4289     bool pushResult = FALSE;
4290
4291     D (emitcode (";", "genMinus "););
4292
4293     AOP_OP_3_NOFATAL(ic, pushResult);   
4294
4295     if (!pushResult)
4296     {
4297       /* special cases :- */
4298       /* if both left & right are in bit space */
4299       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4300           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4301         {
4302           genMinusBits (ic);
4303           goto release;
4304         }
4305
4306       /* if I can do an decrement instead
4307          of subtract then GOOD for ME */
4308       if (genMinusDec (ic) == TRUE)
4309         goto release;
4310
4311     }
4312
4313   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4314
4315   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4316     {
4317       CLRC;
4318     }
4319   else
4320     {
4321       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4322       lit = -(long) lit;
4323     }
4324
4325
4326   /* if literal, add a,#-lit, else normal subb */
4327   _startLazyDPSEvaluation ();
4328   while (size--) {
4329       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4330           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4331               emitcode ("mov","b,%s",
4332                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
4333               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4334               emitcode ("subb","a,b");
4335           } else {
4336               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4337               emitcode ("subb", "a,%s",
4338                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4339           }
4340       } else {
4341           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4342           /* first add without previous c */
4343           if (!offset) {
4344               if (!size && lit==-1) {
4345                   emitcode ("dec", "a");
4346               } else {
4347                   emitcode ("add", "a,#!constbyte",
4348                             (unsigned int) (lit & 0x0FFL));
4349               }
4350           } else {
4351               emitcode ("addc", "a,#!constbyte",
4352                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4353           }
4354       }
4355       
4356       if (pushResult) {
4357           emitcode ("push", "acc");
4358       } else {
4359           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4360       }
4361       offset++;
4362   }
4363   _endLazyDPSEvaluation ();
4364   
4365   if (pushResult)
4366     {
4367       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4368
4369       size = getDataSize (IC_LEFT (ic));
4370       rSize = getDataSize (IC_RESULT (ic));
4371
4372       ADJUST_PUSHED_RESULT(size, rSize);
4373
4374       _startLazyDPSEvaluation ();
4375       while (size--)
4376         {
4377           emitcode ("pop", "acc");
4378           aopPut (AOP (IC_RESULT (ic)), "a", size);
4379         }
4380       _endLazyDPSEvaluation ();
4381     }
4382
4383   adjustArithmeticResult (ic);
4384
4385 release:
4386   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4387   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4389 }
4390
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genMultbits :- multiplication of bits                           */
4394 /*-----------------------------------------------------------------*/
4395 static void
4396 genMultbits (operand * left,
4397              operand * right,
4398              operand * result,
4399              iCode   * ic)
4400 {
4401   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4402   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4403   aopOp(result, ic, TRUE, FALSE);
4404   outBitC (result);
4405 }
4406
4407
4408 /*-----------------------------------------------------------------*/
4409 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4410 /*-----------------------------------------------------------------*/
4411 static void
4412 genMultOneByte (operand * left,
4413                 operand * right,
4414                 operand * result,
4415                 iCode   * ic)
4416 {
4417   sym_link *opetype = operandType (result);
4418   symbol *lbl;
4419
4420
4421   /* (if two literals: the value is computed before) */
4422   /* if one literal, literal on the right */
4423   if (AOP_TYPE (left) == AOP_LIT)
4424     {
4425       operand *t = right;
4426       right = left;
4427       left = t;
4428       emitcode (";", "swapped left and right");
4429     }
4430
4431   if (SPEC_USIGN(opetype)
4432       // ignore the sign of left and right, what else can we do?
4433       || (SPEC_USIGN(operandType(left)) && 
4434           SPEC_USIGN(operandType(right)))) {
4435     // just an unsigned 8*8=8/16 multiply
4436     //emitcode (";","unsigned");
4437     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4438     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4439     emitcode ("mul", "ab");
4440    
4441     _G.accInUse++; _G.bInUse++;
4442     aopOp(result, ic, TRUE, FALSE);
4443       
4444       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4445       {
4446           // this should never happen
4447           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4448                    AOP_SIZE(result), __FILE__, lineno);
4449           exit (1);
4450       }      
4451       
4452     aopPut (AOP (result), "a", 0);
4453     _G.accInUse--; _G.bInUse--;
4454     if (AOP_SIZE(result)==2) 
4455     {
4456       aopPut (AOP (result), "b", 1);
4457     }
4458     return;
4459   }
4460
4461   // we have to do a signed multiply
4462
4463   emitcode (";", "signed");
4464   emitcode ("clr", "F0"); // reset sign flag
4465   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4466
4467   lbl=newiTempLabel(NULL);
4468   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4469   // left side is negative, 8-bit two's complement, this fails for -128
4470   emitcode ("setb", "F0"); // set sign flag
4471   emitcode ("cpl", "a");
4472   emitcode ("inc", "a");
4473
4474   emitcode ("", "!tlabeldef", lbl->key+100);
4475
4476   /* if literal */
4477   if (AOP_TYPE(right)==AOP_LIT) {
4478     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4479     /* AND literal negative */
4480     if ((int) val < 0) {
4481       emitcode ("cpl", "F0"); // complement sign flag
4482       emitcode ("mov", "b,#!constbyte", -val);
4483     } else {
4484       emitcode ("mov", "b,#!constbyte", val);
4485     }
4486   } else {
4487     lbl=newiTempLabel(NULL);
4488     emitcode ("mov", "b,a");
4489     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4490     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4491     // right side is negative, 8-bit two's complement
4492     emitcode ("cpl", "F0"); // complement sign flag
4493     emitcode ("cpl", "a");
4494     emitcode ("inc", "a");
4495     emitcode ("", "!tlabeldef", lbl->key+100);
4496   }
4497   emitcode ("mul", "ab");
4498     
4499   _G.accInUse++;_G.bInUse++;
4500   aopOp(result, ic, TRUE, FALSE);
4501     
4502   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4503   {
4504     // this should never happen
4505       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4506                AOP_SIZE(result), __FILE__, lineno);
4507       exit (1);
4508   }    
4509     
4510   lbl=newiTempLabel(NULL);
4511   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4512   // only ONE op was negative, we have to do a 8/16-bit two's complement
4513   emitcode ("cpl", "a"); // lsb
4514   if (AOP_SIZE(result)==1) {
4515     emitcode ("inc", "a");
4516   } else {
4517     emitcode ("add", "a,#1");
4518     emitcode ("xch", "a,b");
4519     emitcode ("cpl", "a"); // msb
4520     emitcode ("addc", "a,#0");
4521     emitcode ("xch", "a,b");
4522   }
4523
4524   emitcode ("", "!tlabeldef", lbl->key+100);
4525   aopPut (AOP (result), "a", 0);
4526   _G.accInUse--;_G.bInUse--;
4527   if (AOP_SIZE(result)==2) {
4528     aopPut (AOP (result), "b", 1);
4529   }
4530 }
4531
4532 /*-----------------------------------------------------------------*/
4533 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4534 /*-----------------------------------------------------------------*/
4535 static void genMultTwoByte (operand *left, operand *right, 
4536                             operand *result, iCode *ic)
4537 {
4538         sym_link *retype = getSpec(operandType(right));
4539         sym_link *letype = getSpec(operandType(left));
4540         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4541         symbol *lbl;
4542
4543         if (AOP_TYPE (left) == AOP_LIT) {
4544                 operand *t = right;
4545                 right = left;
4546                 left = t;
4547         }
4548         /* save EA bit in F1 */
4549         lbl = newiTempLabel(NULL);
4550         emitcode ("setb","F1");
4551         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4552         emitcode ("clr","F1");
4553         emitcode("","!tlabeldef",lbl->key+100);
4554
4555         /* load up MB with right */
4556         if (!umult) {
4557                 emitcode("clr","F0");
4558                 if (AOP_TYPE(right) == AOP_LIT) {
4559                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4560                         if (val < 0) {
4561                                 emitcode("setb","F0");
4562                                 val = -val;
4563                         }
4564                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4565                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4566                 } else {
4567                         lbl = newiTempLabel(NULL);
4568                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4569                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4570                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4571                         emitcode ("xch", "a,b");
4572                         emitcode ("cpl","a");
4573                         emitcode ("add", "a,#1");
4574                         emitcode ("xch", "a,b");
4575                         emitcode ("cpl", "a"); // msb
4576                         emitcode ("addc", "a,#0");
4577                         emitcode ("setb","F0");
4578                         emitcode ("","!tlabeldef",lbl->key+100);
4579                         emitcode ("mov","mb,b");
4580                         emitcode ("mov","mb,a");
4581                 }
4582         } else {
4583                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4584                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4585         }
4586         /* load up MA with left */
4587         if (!umult) {
4588                 lbl = newiTempLabel(NULL);
4589                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4590                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4591                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4592                 emitcode ("xch", "a,b");
4593                 emitcode ("cpl","a");
4594                 emitcode ("add", "a,#1");
4595                 emitcode ("xch", "a,b");
4596                 emitcode ("cpl", "a"); // msb
4597                 emitcode ("addc","a,#0");
4598                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4599                 emitcode ("setb","F0");
4600                 emitcode ("","!tlabeldef",lbl->key+100);
4601                 emitcode ("mov","ma,b");
4602                 emitcode ("mov","ma,a");
4603         } else {
4604                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4605                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4606         }
4607         /* wait for multiplication to finish */
4608         lbl = newiTempLabel(NULL);
4609         emitcode("","!tlabeldef", lbl->key+100);
4610         emitcode("mov","a,mcnt1");
4611         emitcode("anl","a,#!constbyte",0x80);
4612         emitcode("jnz","!tlabel",lbl->key+100);
4613         
4614         freeAsmop (left, NULL, ic, TRUE);
4615         freeAsmop (right, NULL, ic,TRUE);
4616         aopOp(result, ic, TRUE, FALSE);
4617
4618         /* if unsigned then simple */   
4619         if (umult) {
4620                 emitcode ("mov","a,ma");
4621                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4622                 emitcode ("mov","a,ma");
4623                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4624                 aopPut(AOP(result),"ma",1);
4625                 aopPut(AOP(result),"ma",0);
4626         } else {
4627                 emitcode("push","ma");
4628                 emitcode("push","ma");
4629                 emitcode("push","ma");
4630                 MOVA("ma");
4631                 /* negate result if needed */
4632                 lbl = newiTempLabel(NULL);      
4633                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4634                 emitcode("cpl","a");
4635                 emitcode("add","a,#1");
4636                 emitcode("","!tlabeldef", lbl->key+100);
4637                 if (AOP_TYPE(result) == AOP_ACC)
4638                 {
4639                     D(emitcode(";", "ACC special case."););
4640                     /* We know result is the only live aop, and 
4641                      * it's obviously not a DPTR2, so AP is available.
4642                      */
4643                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4644                 }
4645                 else
4646                 {
4647                     aopPut(AOP(result),"a",0);
4648                 }
4649             
4650                 emitcode("pop","acc");
4651                 lbl = newiTempLabel(NULL);      
4652                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4653                 emitcode("cpl","a");
4654                 emitcode("addc","a,#0");
4655                 emitcode("","!tlabeldef", lbl->key+100);
4656                 aopPut(AOP(result),"a",1);
4657                 emitcode("pop","acc");
4658                 if (AOP_SIZE(result) >= 3) {
4659                         lbl = newiTempLabel(NULL);      
4660                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4661                         emitcode("cpl","a");
4662                         emitcode("addc","a,#0");                        
4663                         emitcode("","!tlabeldef", lbl->key+100);
4664                         aopPut(AOP(result),"a",2);
4665                 }
4666                 emitcode("pop","acc");
4667                 if (AOP_SIZE(result) >= 4) {
4668                         lbl = newiTempLabel(NULL);      
4669                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4670                         emitcode("cpl","a");
4671                         emitcode("addc","a,#0");                        
4672                         emitcode("","!tlabeldef", lbl->key+100);
4673                         aopPut(AOP(result),"a",3);
4674                 }
4675                 if (AOP_TYPE(result) == AOP_ACC)
4676                 {
4677                     /* We stashed the result away above. */
4678                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4679                 }           
4680                 
4681         }
4682         freeAsmop (result, NULL, ic, TRUE);
4683
4684         /* restore EA bit in F1 */
4685         lbl = newiTempLabel(NULL);
4686         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4687         emitcode ("setb","EA");
4688         emitcode("","!tlabeldef",lbl->key+100);
4689         return ;
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genMult - generates code for multiplication                     */
4694 /*-----------------------------------------------------------------*/
4695 static void
4696 genMult (iCode * ic)
4697 {
4698   operand *left = IC_LEFT (ic);
4699   operand *right = IC_RIGHT (ic);
4700   operand *result = IC_RESULT (ic);
4701
4702   D (emitcode (";", "genMult "););
4703
4704   /* assign the amsops */
4705   AOP_OP_2 (ic);
4706
4707   /* special cases first */
4708   /* both are bits */
4709   if (AOP_TYPE (left) == AOP_CRY &&
4710       AOP_TYPE (right) == AOP_CRY)
4711     {
4712       genMultbits (left, right, result, ic);
4713       goto release;
4714     }
4715
4716   /* if both are of size == 1 */
4717   if (AOP_SIZE (left) == 1 &&
4718       AOP_SIZE (right) == 1)
4719     {
4720       genMultOneByte (left, right, result, ic);
4721       goto release;
4722     }
4723
4724   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4725           /* use the ds390 ARITHMETIC accel UNIT */
4726           genMultTwoByte (left, right, result, ic);
4727           return ;
4728   }
4729   /* should have been converted to function call */
4730   assert (0);
4731
4732 release:
4733   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4734   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4735   freeAsmop (result, NULL, ic, TRUE);
4736 }
4737
4738 /*-----------------------------------------------------------------*/
4739 /* genDivbits :- division of bits                                  */
4740 /*-----------------------------------------------------------------*/
4741 static void
4742 genDivbits (operand * left,
4743             operand * right,
4744             operand * result,
4745             iCode   * ic)
4746 {
4747
4748   char *l;
4749
4750   /* the result must be bit */
4751   LOAD_AB_FOR_DIV (left, right, l);
4752   emitcode ("div", "ab");
4753   emitcode ("rrc", "a");
4754   aopOp(result, ic, TRUE, FALSE);
4755     
4756   aopPut (AOP (result), "c", 0);
4757 }
4758
4759 /*-----------------------------------------------------------------*/
4760 /* genDivOneByte : 8 bit division                                  */
4761 /*-----------------------------------------------------------------*/
4762 static void
4763 genDivOneByte (operand * left,
4764                operand * right,
4765                operand * result,
4766                iCode   * ic)
4767 {
4768   sym_link *opetype = operandType (result);
4769   char *l;
4770   symbol *lbl;
4771   int size, offset;
4772
4773   offset = 1;
4774   /* signed or unsigned */
4775   if (SPEC_USIGN (opetype))
4776     {
4777         /* unsigned is easy */
4778         LOAD_AB_FOR_DIV (left, right, l);
4779         emitcode ("div", "ab");
4780
4781         _G.accInUse++;
4782         aopOp(result, ic, TRUE, FALSE);
4783         aopPut (AOP (result), "a", 0);
4784         _G.accInUse--;
4785
4786         size = AOP_SIZE (result) - 1;
4787         
4788         while (size--)
4789         {
4790             aopPut (AOP (result), zero, offset++);
4791         }
4792       return;
4793     }
4794
4795   /* signed is a little bit more difficult */
4796
4797   /* save the signs of the operands */
4798   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4799   MOVA (l);
4800   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4801   emitcode ("push", "acc");     /* save it on the stack */
4802
4803   /* now sign adjust for both left & right */
4804   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4805   MOVA (l);
4806   lbl = newiTempLabel (NULL);
4807   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4808   emitcode ("cpl", "a");
4809   emitcode ("inc", "a");
4810   emitcode ("", "!tlabeldef", (lbl->key + 100));
4811   emitcode ("mov", "b,a");
4812
4813   /* sign adjust left side */
4814   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4815   MOVA (l);
4816
4817   lbl = newiTempLabel (NULL);
4818   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4819   emitcode ("cpl", "a");
4820   emitcode ("inc", "a");
4821   emitcode ("", "!tlabeldef", (lbl->key + 100));
4822
4823   /* now the division */
4824   emitcode ("nop", "; workaround for DS80C390 div bug.");
4825   emitcode ("div", "ab");
4826   /* we are interested in the lower order
4827      only */
4828   emitcode ("mov", "b,a");
4829   lbl = newiTempLabel (NULL);
4830   emitcode ("pop", "acc");
4831   /* if there was an over flow we don't
4832      adjust the sign of the result */
4833   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4834   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4835   CLRC;
4836   emitcode ("clr", "a");
4837   emitcode ("subb", "a,b");
4838   emitcode ("mov", "b,a");
4839   emitcode ("", "!tlabeldef", (lbl->key + 100));
4840
4841   /* now we are done */
4842   _G.accInUse++;     _G.bInUse++;
4843     aopOp(result, ic, TRUE, FALSE);
4844     
4845     aopPut (AOP (result), "b", 0);
4846     
4847     size = AOP_SIZE (result) - 1;
4848     
4849     if (size > 0)
4850     {
4851       emitcode ("mov", "c,b.7");
4852       emitcode ("subb", "a,acc");
4853     }
4854     while (size--)
4855     {
4856         aopPut (AOP (result), "a", offset++);
4857     }
4858     _G.accInUse--;     _G.bInUse--;
4859
4860 }
4861
4862 /*-----------------------------------------------------------------*/
4863 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4864 /*-----------------------------------------------------------------*/
4865 static void genDivTwoByte (operand *left, operand *right, 
4866                             operand *result, iCode *ic)
4867 {
4868         sym_link *retype = getSpec(operandType(right));
4869         sym_link *letype = getSpec(operandType(left));
4870         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4871         symbol *lbl;
4872
4873         /* save EA bit in F1 */
4874         lbl = newiTempLabel(NULL);
4875         emitcode ("setb","F1");
4876         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4877         emitcode ("clr","F1");
4878         emitcode("","!tlabeldef",lbl->key+100);
4879
4880         /* load up MA with left */
4881         if (!umult) {
4882                 emitcode("clr","F0");
4883                 lbl = newiTempLabel(NULL);
4884                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4885                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4886                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4887                 emitcode ("xch", "a,b");
4888                 emitcode ("cpl","a");
4889                 emitcode ("add", "a,#1");
4890                 emitcode ("xch", "a,b");
4891                 emitcode ("cpl", "a"); // msb
4892                 emitcode ("addc","a,#0");
4893                 emitcode ("setb","F0");
4894                 emitcode ("","!tlabeldef",lbl->key+100);
4895                 emitcode ("mov","ma,b");
4896                 emitcode ("mov","ma,a");
4897         } else {
4898                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4899                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4900         }
4901
4902         /* load up MB with right */
4903         if (!umult) {
4904                 if (AOP_TYPE(right) == AOP_LIT) {
4905                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4906                         if (val < 0) {
4907                                 lbl = newiTempLabel(NULL);
4908                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4909                                 emitcode("setb","F0");
4910                                 emitcode ("","!tlabeldef",lbl->key+100);
4911                                 val = -val;
4912                         } 
4913                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4914                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4915                 } else {
4916                         lbl = newiTempLabel(NULL);
4917                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4918                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4919                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4920                         emitcode ("xch", "a,b");
4921                         emitcode ("cpl","a");
4922                         emitcode ("add", "a,#1");
4923                         emitcode ("xch", "a,b");
4924                         emitcode ("cpl", "a"); // msb
4925                         emitcode ("addc", "a,#0");
4926                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4927                         emitcode ("setb","F0");
4928                         emitcode ("","!tlabeldef",lbl->key+100);
4929                         emitcode ("mov","mb,b");
4930                         emitcode ("mov","mb,a");
4931                 }
4932         } else {
4933                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4934                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4935         }
4936
4937         /* wait for multiplication to finish */
4938         lbl = newiTempLabel(NULL);
4939         emitcode("","!tlabeldef", lbl->key+100);
4940         emitcode("mov","a,mcnt1");
4941         emitcode("anl","a,#!constbyte",0x80);
4942         emitcode("jnz","!tlabel",lbl->key+100);
4943         
4944         freeAsmop (left, NULL, ic, TRUE);
4945         freeAsmop (right, NULL, ic,TRUE);
4946         aopOp(result, ic, TRUE, FALSE);
4947
4948         /* if unsigned then simple */   
4949         if (umult) {
4950                 aopPut(AOP(result),"ma",1);
4951                 aopPut(AOP(result),"ma",0);
4952         } else {
4953                 emitcode("push","ma");
4954                 MOVA("ma");
4955                 /* negate result if needed */
4956                 lbl = newiTempLabel(NULL);      
4957                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4958                 emitcode("cpl","a");
4959                 emitcode("add","a,#1");
4960                 emitcode("","!tlabeldef", lbl->key+100);
4961                 aopPut(AOP(result),"a",0);
4962                 emitcode("pop","acc");
4963                 lbl = newiTempLabel(NULL);      
4964                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4965                 emitcode("cpl","a");
4966                 emitcode("addc","a,#0");
4967                 emitcode("","!tlabeldef", lbl->key+100);
4968                 aopPut(AOP(result),"a",1);
4969         }
4970         freeAsmop (result, NULL, ic, TRUE);
4971         /* restore EA bit in F1 */
4972         lbl = newiTempLabel(NULL);
4973         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4974         emitcode ("setb","EA");
4975         emitcode("","!tlabeldef",lbl->key+100);
4976         return ;
4977 }
4978
4979 /*-----------------------------------------------------------------*/
4980 /* genDiv - generates code for division                            */
4981 /*-----------------------------------------------------------------*/
4982 static void
4983 genDiv (iCode * ic)
4984 {
4985   operand *left = IC_LEFT (ic);
4986   operand *right = IC_RIGHT (ic);
4987   operand *result = IC_RESULT (ic);
4988
4989   D (emitcode (";", "genDiv "););
4990
4991   /* assign the amsops */
4992   AOP_OP_2 (ic);
4993
4994   /* special cases first */
4995   /* both are bits */
4996   if (AOP_TYPE (left) == AOP_CRY &&
4997       AOP_TYPE (right) == AOP_CRY)
4998     {
4999       genDivbits (left, right, result, ic);
5000       goto release;
5001     }
5002
5003   /* if both are of size == 1 */
5004   if (AOP_SIZE (left) == 1 &&
5005       AOP_SIZE (right) == 1)
5006     {
5007       genDivOneByte (left, right, result, ic);
5008       goto release;
5009     }
5010
5011   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5012           /* use the ds390 ARITHMETIC accel UNIT */
5013           genDivTwoByte (left, right, result, ic);
5014           return ;
5015   }
5016   /* should have been converted to function call */
5017   assert (0);
5018 release:
5019   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5020   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5021   freeAsmop (result, NULL, ic, TRUE);
5022 }
5023
5024 /*-----------------------------------------------------------------*/
5025 /* genModbits :- modulus of bits                                   */
5026 /*-----------------------------------------------------------------*/
5027 static void
5028 genModbits (operand * left,
5029             operand * right,
5030             operand * result,
5031             iCode   * ic)
5032 {
5033
5034   char *l;
5035
5036   /* the result must be bit */
5037   LOAD_AB_FOR_DIV (left, right, l);
5038   emitcode ("div", "ab");
5039   emitcode ("mov", "a,b");
5040   emitcode ("rrc", "a");
5041   aopOp(result, ic, TRUE, FALSE);
5042   aopPut (AOP (result), "c", 0);
5043 }
5044
5045 /*-----------------------------------------------------------------*/
5046 /* genModOneByte : 8 bit modulus                                   */
5047 /*-----------------------------------------------------------------*/
5048 static void
5049 genModOneByte (operand * left,
5050                operand * right,
5051                operand * result,
5052                iCode   * ic)
5053 {
5054   sym_link *opetype = operandType (result);
5055   char *l;
5056   symbol *lbl;
5057
5058   /* signed or unsigned */
5059   if (SPEC_USIGN (opetype))
5060     {
5061       /* unsigned is easy */
5062       LOAD_AB_FOR_DIV (left, right, l);
5063       emitcode ("div", "ab");
5064       aopOp(result, ic, TRUE, FALSE);   
5065       aopPut (AOP (result), "b", 0);
5066       return;
5067     }
5068
5069   /* signed is a little bit more difficult */
5070
5071   /* save the signs of the operands */
5072   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5073   MOVA (l);
5074
5075   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5076   emitcode ("push", "acc");     /* save it on the stack */
5077
5078   /* now sign adjust for both left & right */
5079   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
5080   MOVA (l);
5081
5082   lbl = newiTempLabel (NULL);
5083   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5084   emitcode ("cpl", "a");
5085   emitcode ("inc", "a");
5086   emitcode ("", "!tlabeldef", (lbl->key + 100));
5087   emitcode ("mov", "b,a");
5088
5089   /* sign adjust left side */
5090   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
5091   MOVA (l);
5092
5093   lbl = newiTempLabel (NULL);
5094   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5095   emitcode ("cpl", "a");
5096   emitcode ("inc", "a");
5097   emitcode ("", "!tlabeldef", (lbl->key + 100));
5098
5099   /* now the multiplication */
5100   emitcode ("nop", "; workaround for DS80C390 div bug.");
5101   emitcode ("div", "ab");
5102   /* we are interested in the lower order
5103      only */
5104   lbl = newiTempLabel (NULL);
5105   emitcode ("pop", "acc");
5106   /* if there was an over flow we don't
5107      adjust the sign of the result */
5108   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5109   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5110   CLRC;
5111   emitcode ("clr", "a");
5112   emitcode ("subb", "a,b");
5113   emitcode ("mov", "b,a");
5114   emitcode ("", "!tlabeldef", (lbl->key + 100));
5115   
5116   _G.bInUse++;
5117   /* now we are done */
5118   aopOp(result, ic, TRUE, FALSE);    
5119   aopPut (AOP (result), "b", 0);
5120   _G.bInUse--;
5121
5122 }
5123
5124 /*-----------------------------------------------------------------*/
5125 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5126 /*-----------------------------------------------------------------*/
5127 static void genModTwoByte (operand *left, operand *right, 
5128                             operand *result, iCode *ic)
5129 {
5130         sym_link *retype = getSpec(operandType(right));
5131         sym_link *letype = getSpec(operandType(left));
5132         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5133         symbol *lbl;
5134
5135         /* load up MA with left */
5136         /* save EA bit in F1 */
5137         lbl = newiTempLabel(NULL);
5138         emitcode ("setb","F1");
5139         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5140         emitcode ("clr","F1");
5141         emitcode("","!tlabeldef",lbl->key+100);
5142
5143         if (!umult) {
5144                 lbl = newiTempLabel(NULL);
5145                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5146                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5147                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5148                 emitcode ("xch", "a,b");
5149                 emitcode ("cpl","a");
5150                 emitcode ("add", "a,#1");
5151                 emitcode ("xch", "a,b");
5152                 emitcode ("cpl", "a"); // msb
5153                 emitcode ("addc","a,#0");
5154                 emitcode ("","!tlabeldef",lbl->key+100);
5155                 emitcode ("mov","ma,b");
5156                 emitcode ("mov","ma,a");
5157         } else {
5158                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
5159                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
5160         }
5161
5162         /* load up MB with right */
5163         if (!umult) {
5164                 if (AOP_TYPE(right) == AOP_LIT) {
5165                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5166                         if (val < 0) {
5167                                 val = -val;
5168                         } 
5169                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5170                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5171                 } else {
5172                         lbl = newiTempLabel(NULL);
5173                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5174                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5175                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5176                         emitcode ("xch", "a,b");
5177                         emitcode ("cpl","a");
5178                         emitcode ("add", "a,#1");
5179                         emitcode ("xch", "a,b");
5180                         emitcode ("cpl", "a"); // msb
5181                         emitcode ("addc", "a,#0");
5182                         emitcode ("","!tlabeldef",lbl->key+100);
5183                         emitcode ("mov","mb,b");
5184                         emitcode ("mov","mb,a");
5185                 }
5186         } else {
5187                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
5188                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
5189         }
5190
5191         /* wait for multiplication to finish */
5192         lbl = newiTempLabel(NULL);
5193         emitcode("","!tlabeldef", lbl->key+100);
5194         emitcode("mov","a,mcnt1");
5195         emitcode("anl","a,#!constbyte",0x80);
5196         emitcode("jnz","!tlabel",lbl->key+100);
5197         
5198         freeAsmop (left, NULL, ic, TRUE);
5199         freeAsmop (right, NULL, ic,TRUE);
5200         aopOp(result, ic, TRUE, FALSE);
5201
5202         aopPut(AOP(result),"mb",1);
5203         aopPut(AOP(result),"mb",0);
5204         freeAsmop (result, NULL, ic, TRUE);
5205
5206         /* restore EA bit in F1 */
5207         lbl = newiTempLabel(NULL);
5208         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5209         emitcode ("setb","EA");
5210         emitcode("","!tlabeldef",lbl->key+100);
5211         return ;
5212 }
5213
5214 /*-----------------------------------------------------------------*/
5215 /* genMod - generates code for division                            */
5216 /*-----------------------------------------------------------------*/
5217 static void
5218 genMod (iCode * ic)
5219 {
5220   operand *left = IC_LEFT (ic);
5221   operand *right = IC_RIGHT (ic);
5222   operand *result = IC_RESULT (ic);
5223
5224   D (emitcode (";", "genMod "); );
5225
5226   /* assign the amsops */
5227   AOP_OP_2 (ic);
5228
5229   /* special cases first */
5230   /* both are bits */
5231   if (AOP_TYPE (left) == AOP_CRY &&
5232       AOP_TYPE (right) == AOP_CRY)
5233     {
5234       genModbits (left, right, result, ic);
5235       goto release;
5236     }
5237
5238   /* if both are of size == 1 */
5239   if (AOP_SIZE (left) == 1 &&
5240       AOP_SIZE (right) == 1)
5241     {
5242       genModOneByte (left, right, result, ic);
5243       goto release;
5244     }
5245
5246   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5247           /* use the ds390 ARITHMETIC accel UNIT */
5248           genModTwoByte (left, right, result, ic);
5249           return ;
5250   }
5251
5252   /* should have been converted to function call */
5253   assert (0);
5254
5255 release:
5256   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5257   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5258   freeAsmop (result, NULL, ic, TRUE);
5259 }
5260
5261 /*-----------------------------------------------------------------*/
5262 /* genIfxJump :- will create a jump depending on the ifx           */
5263 /*-----------------------------------------------------------------*/
5264 static void
5265 genIfxJump (iCode * ic, char *jval)
5266 {
5267   symbol *jlbl;
5268   symbol *tlbl = newiTempLabel (NULL);
5269   char *inst;
5270
5271   D (emitcode (";", "genIfxJump"););
5272
5273   /* if true label then we jump if condition
5274      supplied is true */
5275   if (IC_TRUE (ic))
5276     {
5277       jlbl = IC_TRUE (ic);
5278       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5279                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5280     }
5281   else
5282     {
5283       /* false label is present */
5284       jlbl = IC_FALSE (ic);
5285       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5286                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5287     }
5288   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5289     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5290   else
5291     emitcode (inst, "!tlabel", tlbl->key + 100);
5292   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5293   emitcode ("", "!tlabeldef", tlbl->key + 100);
5294
5295   /* mark the icode as generated */
5296   ic->generated = 1;
5297 }
5298
5299 /*-----------------------------------------------------------------*/
5300 /* genCmp :- greater or less than comparison                       */
5301 /*-----------------------------------------------------------------*/
5302 static void
5303 genCmp (operand * left, operand * right,
5304         iCode * ic, iCode * ifx, int sign)
5305 {
5306   int size, offset = 0;
5307   unsigned long lit = 0L;
5308   operand *result;
5309
5310   D (emitcode (";", "genCmp");
5311     );
5312
5313   result = IC_RESULT (ic);
5314
5315   /* if left & right are bit variables */
5316   if (AOP_TYPE (left) == AOP_CRY &&
5317       AOP_TYPE (right) == AOP_CRY)
5318     {
5319       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5320       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5321     }
5322   else
5323     {
5324       /* subtract right from left if at the
5325          end the carry flag is set then we know that
5326          left is greater than right */
5327       size = max (AOP_SIZE (left), AOP_SIZE (right));
5328
5329       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5330       if ((size == 1) && !sign &&
5331           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5332         {
5333           symbol *lbl = newiTempLabel (NULL);
5334           emitcode ("cjne", "%s,%s,!tlabel",
5335                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5336                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5337                     lbl->key + 100);
5338           emitcode ("", "!tlabeldef", lbl->key + 100);
5339         }
5340       else
5341         {
5342           if (AOP_TYPE (right) == AOP_LIT)
5343             {
5344               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5345               /* optimize if(x < 0) or if(x >= 0) */
5346               if (lit == 0L)
5347                 {
5348                   if (!sign)
5349                     {
5350                       CLRC;
5351                     }
5352                   else
5353                     {
5354                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5355
5356                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5357                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5358
5359                       aopOp (result, ic, FALSE, FALSE);
5360
5361                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5362                         {
5363                           freeAsmop (result, NULL, ic, TRUE);
5364                           genIfxJump (ifx, "acc.7");
5365                           return;
5366                         }
5367                       else
5368                         {
5369                           emitcode ("rlc", "a");
5370                         }
5371                       goto release_freedLR;
5372                     }
5373                   goto release;
5374                 }
5375             }
5376           CLRC;
5377           while (size--)
5378             {
5379               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5380               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5381               //emitcode (";", "genCmp #2");
5382               if (sign && (size == 0))
5383                 {
5384                     //emitcode (";", "genCmp #3");
5385                   emitcode ("xrl", "a,#!constbyte",0x80);
5386                   if (AOP_TYPE (right) == AOP_LIT)
5387                     {
5388                       unsigned long lit = (unsigned long)
5389                       floatFromVal (AOP (right)->aopu.aop_lit);
5390                       //emitcode (";", "genCmp #3.1");
5391                       emitcode ("subb", "a,#!constbyte",
5392                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5393                     }
5394                   else
5395                     {
5396                       //emitcode (";", "genCmp #3.2");
5397                       if (AOP_NEEDSACC (right))
5398                         {
5399                           emitcode ("push", "acc");
5400                         }
5401                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5402                                                        FALSE, FALSE, FALSE));
5403                       emitcode ("xrl", "b,#!constbyte",0x80);
5404                       if (AOP_NEEDSACC (right))
5405                         {
5406                           emitcode ("pop", "acc");
5407                         }
5408                       emitcode ("subb", "a,b");
5409                     }
5410                 }
5411               else
5412                 {
5413                   const char *s;
5414
5415                   //emitcode (";", "genCmp #4");
5416                   if (AOP_NEEDSACC (right))
5417                     {
5418                       /* Yuck!! */
5419                       //emitcode (";", "genCmp #4.1");
5420                       emitcode ("xch", "a, b");
5421                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5422                       emitcode ("xch", "a, b");
5423                       s = "b";
5424                     }
5425                   else
5426                     {
5427                       //emitcode (";", "genCmp #4.2");
5428                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5429                     }
5430
5431                   emitcode ("subb", "a,%s", s);
5432                 }
5433             }
5434         }
5435     }
5436
5437 release:
5438 /* Don't need the left & right operands any more; do need the result. */
5439   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441
5442   aopOp (result, ic, FALSE, FALSE);
5443
5444 release_freedLR:
5445
5446   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5447     {
5448       outBitC (result);
5449     }
5450   else
5451     {
5452       /* if the result is used in the next
5453          ifx conditional branch then generate
5454          code a little differently */
5455       if (ifx)
5456         {
5457           genIfxJump (ifx, "c");
5458         }
5459       else
5460         {
5461           outBitC (result);
5462         }
5463       /* leave the result in acc */
5464     }
5465   freeAsmop (result, NULL, ic, TRUE);
5466 }
5467
5468 /*-----------------------------------------------------------------*/
5469 /* genCmpGt :- greater than comparison                             */
5470 /*-----------------------------------------------------------------*/
5471 static void
5472 genCmpGt (iCode * ic, iCode * ifx)
5473 {
5474   operand *left, *right;
5475   sym_link *letype, *retype;
5476   int sign;
5477
5478   D (emitcode (";", "genCmpGt ");
5479     );
5480
5481   left = IC_LEFT (ic);
5482   right = IC_RIGHT (ic);
5483
5484   letype = getSpec (operandType (left));
5485   retype = getSpec (operandType (right));
5486   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5487
5488   /* assign the left & right amsops */
5489   AOP_OP_2 (ic);
5490
5491   genCmp (right, left, ic, ifx, sign);
5492 }
5493
5494 /*-----------------------------------------------------------------*/
5495 /* genCmpLt - less than comparisons                                */
5496 /*-----------------------------------------------------------------*/
5497 static void
5498 genCmpLt (iCode * ic, iCode * ifx)
5499 {
5500   operand *left, *right;
5501   sym_link *letype, *retype;
5502   int sign;
5503
5504   D (emitcode (";", "genCmpLt "););
5505
5506   left = IC_LEFT (ic);
5507   right = IC_RIGHT (ic);
5508
5509   letype = getSpec (operandType (left));
5510   retype = getSpec (operandType (right));
5511   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5512
5513   /* assign the left & right amsops */
5514   AOP_OP_2 (ic);
5515
5516   genCmp (left, right, ic, ifx, sign);
5517 }
5518
5519 /*-----------------------------------------------------------------*/
5520 /* gencjneshort - compare and jump if not equal                    */
5521 /*-----------------------------------------------------------------*/
5522 static void
5523 gencjneshort (operand * left, operand * right, symbol * lbl)
5524 {
5525   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5526   int offset = 0;
5527   unsigned long lit = 0L;
5528
5529   D (emitcode (";", "gencjneshort");
5530     );
5531
5532   /* if the left side is a literal or
5533      if the right is in a pointer register and left
5534      is not */
5535   if ((AOP_TYPE (left) == AOP_LIT) ||
5536       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5537     {
5538       operand *t = right;
5539       right = left;
5540       left = t;
5541     }
5542
5543   if (AOP_TYPE (right) == AOP_LIT)
5544     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5545
5546   if (opIsGptr (left) || opIsGptr (right))
5547     {
5548       /* We are comparing a generic pointer to something.
5549        * Exclude the generic type byte from the comparison.
5550        */
5551       size--;
5552       D (emitcode (";", "cjneshort: generic ptr special case.");
5553         )
5554     }
5555
5556
5557   /* if the right side is a literal then anything goes */
5558   if (AOP_TYPE (right) == AOP_LIT &&
5559       AOP_TYPE (left) != AOP_DIR)
5560     {
5561       while (size--)
5562         {
5563           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5564           MOVA (l);
5565           emitcode ("cjne", "a,%s,!tlabel",
5566                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5567                     lbl->key + 100);
5568           offset++;
5569         }
5570     }
5571
5572   /* if the right side is in a register or in direct space or
5573      if the left is a pointer register & right is not */
5574   else if (AOP_TYPE (right) == AOP_REG ||
5575            AOP_TYPE (right) == AOP_DIR ||
5576            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5577            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5578     {
5579       while (size--)
5580         {
5581           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5582           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5583               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5584             emitcode ("jnz", "!tlabel", lbl->key + 100);
5585           else
5586             emitcode ("cjne", "a,%s,!tlabel",
5587                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5588                       lbl->key + 100);
5589           offset++;
5590         }
5591     }
5592   else
5593     {
5594       /* right is a pointer reg need both a & b */
5595       while (size--)
5596         {
5597           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5598           if (strcmp (l, "b"))
5599             emitcode ("mov", "b,%s", l);
5600           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5601           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5602           offset++;
5603         }
5604     }
5605 }
5606
5607 /*-----------------------------------------------------------------*/
5608 /* gencjne - compare and jump if not equal                         */
5609 /*-----------------------------------------------------------------*/
5610 static void
5611 gencjne (operand * left, operand * right, symbol * lbl)
5612 {
5613   symbol *tlbl = newiTempLabel (NULL);
5614
5615   D (emitcode (";", "gencjne");
5616     );
5617
5618   gencjneshort (left, right, lbl);
5619
5620   emitcode ("mov", "a,%s", one);
5621   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5622   emitcode ("", "!tlabeldef", lbl->key + 100);
5623   emitcode ("clr", "a");
5624   emitcode ("", "!tlabeldef", tlbl->key + 100);
5625 }
5626
5627 /*-----------------------------------------------------------------*/
5628 /* genCmpEq - generates code for equal to                          */
5629 /*-----------------------------------------------------------------*/
5630 static void
5631 genCmpEq (iCode * ic, iCode * ifx)
5632 {
5633   operand *left, *right, *result;
5634
5635   D (emitcode (";", "genCmpEq ");
5636     );
5637
5638   AOP_OP_2 (ic);
5639   AOP_SET_LOCALS (ic);
5640
5641   /* if literal, literal on the right or
5642      if the right is in a pointer register and left
5643      is not */
5644   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5645       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5646     {
5647       operand *t = IC_RIGHT (ic);
5648       IC_RIGHT (ic) = IC_LEFT (ic);
5649       IC_LEFT (ic) = t;
5650     }
5651
5652   if (ifx &&                    /* !AOP_SIZE(result) */
5653       OP_SYMBOL (result) &&
5654       OP_SYMBOL (result)->regType == REG_CND)
5655     {
5656       symbol *tlbl;
5657       /* if they are both bit variables */
5658       if (AOP_TYPE (left) == AOP_CRY &&
5659           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5660         {
5661           if (AOP_TYPE (right) == AOP_LIT)
5662             {
5663               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5664               if (lit == 0L)
5665                 {
5666                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5667                   emitcode ("cpl", "c");
5668                 }
5669               else if (lit == 1L)
5670                 {
5671                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5672                 }
5673               else
5674                 {
5675                   emitcode ("clr", "c");
5676                 }
5677               /* AOP_TYPE(right) == AOP_CRY */
5678             }
5679           else
5680             {
5681               symbol *lbl = newiTempLabel (NULL);
5682               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5683               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5684               emitcode ("cpl", "c");
5685               emitcode ("", "!tlabeldef", (lbl->key + 100));
5686             }
5687           /* if true label then we jump if condition
5688              supplied is true */
5689           tlbl = newiTempLabel (NULL);
5690           if (IC_TRUE (ifx))
5691             {
5692               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5693               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5694             }
5695           else
5696             {
5697               emitcode ("jc", "!tlabel", tlbl->key + 100);
5698               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5699             }
5700           emitcode ("", "!tlabeldef", tlbl->key + 100);
5701         }
5702       else
5703         {
5704           tlbl = newiTempLabel (NULL);
5705           gencjneshort (left, right, tlbl);
5706           if (IC_TRUE (ifx))
5707             {
5708               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5709               emitcode ("", "!tlabeldef", tlbl->key + 100);
5710             }
5711           else
5712             {
5713               symbol *lbl = newiTempLabel (NULL);
5714               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5715               emitcode ("", "!tlabeldef", tlbl->key + 100);
5716               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5717               emitcode ("", "!tlabeldef", lbl->key + 100);
5718             }
5719         }
5720       /* mark the icode as generated */
5721       ifx->generated = 1;
5722
5723       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5724       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5725       return;
5726     }
5727
5728   /* if they are both bit variables */
5729   if (AOP_TYPE (left) == AOP_CRY &&
5730       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5731     {
5732       if (AOP_TYPE (right) == AOP_LIT)
5733         {
5734           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5735           if (lit == 0L)
5736             {
5737               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5738               emitcode ("cpl", "c");
5739             }
5740           else if (lit == 1L)
5741             {
5742               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5743             }
5744           else
5745             {
5746               emitcode ("clr", "c");
5747             }
5748           /* AOP_TYPE(right) == AOP_CRY */
5749         }
5750       else
5751         {
5752           symbol *lbl = newiTempLabel (NULL);
5753           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5755           emitcode ("cpl", "c");
5756           emitcode ("", "!tlabeldef", (lbl->key + 100));
5757         }
5758
5759       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761
5762       aopOp (result, ic, TRUE, FALSE);
5763
5764       /* c = 1 if egal */
5765       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5766         {
5767           outBitC (result);
5768           goto release;
5769         }
5770       if (ifx)
5771         {
5772           genIfxJump (ifx, "c");
5773           goto release;
5774         }
5775       /* if the result is used in an arithmetic operation
5776          then put the result in place */
5777       outBitC (result);
5778     }
5779   else
5780     {
5781       gencjne (left, right, newiTempLabel (NULL));
5782
5783       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5784       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5785
5786       aopOp (result, ic, TRUE, FALSE);
5787
5788       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5789         {
5790           aopPut (AOP (result), "a", 0);
5791           goto release;
5792         }
5793       if (ifx)
5794         {
5795           genIfxJump (ifx, "a");
5796           goto release;
5797         }
5798       /* if the result is used in an arithmetic operation
5799          then put the result in place */
5800       if (AOP_TYPE (result) != AOP_CRY)
5801         outAcc (result);
5802       /* leave the result in acc */
5803     }
5804
5805 release:
5806   freeAsmop (result, NULL, ic, TRUE);
5807 }
5808
5809 /*-----------------------------------------------------------------*/
5810 /* ifxForOp - returns the icode containing the ifx for operand     */
5811 /*-----------------------------------------------------------------*/
5812 static iCode *
5813 ifxForOp (operand * op, iCode * ic)
5814 {
5815   /* if true symbol then needs to be assigned */
5816   if (IS_TRUE_SYMOP (op))
5817     return NULL;
5818
5819   /* if this has register type condition and
5820      the next instruction is ifx with the same operand
5821      and live to of the operand is upto the ifx only then */
5822   if (ic->next &&
5823       ic->next->op == IFX &&
5824       IC_COND (ic->next)->key == op->key &&
5825       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5826     return ic->next;
5827
5828   return NULL;
5829 }
5830 /*-----------------------------------------------------------------*/
5831 /* hasInc - operand is incremented before any other use            */
5832 /*-----------------------------------------------------------------*/
5833 static iCode *
5834 hasInc (operand *op, iCode *ic, int osize)
5835 {
5836   sym_link *type = operandType(op);
5837   sym_link *retype = getSpec (type);
5838   iCode *lic = ic->next;
5839   int isize ;
5840   
5841   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5842   if (!IS_SYMOP(op)) return NULL;
5843
5844   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5845   if (IS_AGGREGATE(type->next)) return NULL;
5846   if (osize != (isize = getSize(type->next))) return NULL;
5847
5848   while (lic) {
5849       /* if operand of the form op = op + <sizeof *op> */
5850       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5851           isOperandEqual(IC_RESULT(lic),op) && 
5852           isOperandLiteral(IC_RIGHT(lic)) &&
5853           operandLitValue(IC_RIGHT(lic)) == isize) {
5854           return lic;
5855       }
5856       /* if the operand used or deffed */
5857       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5858           return NULL;
5859       }
5860       /* if GOTO or IFX */
5861       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5862       lic = lic->next;
5863   }
5864   return NULL;
5865 }
5866
5867 /*-----------------------------------------------------------------*/
5868 /* genAndOp - for && operation                                     */
5869 /*-----------------------------------------------------------------*/
5870 static void
5871 genAndOp (iCode * ic)
5872 {
5873   operand *left, *right, *result;
5874   symbol *tlbl;
5875
5876   D (emitcode (";", "genAndOp "););
5877
5878   /* note here that && operations that are in an
5879      if statement are taken away by backPatchLabels
5880      only those used in arthmetic operations remain */
5881   AOP_OP_2 (ic);
5882   AOP_SET_LOCALS (ic);
5883
5884   /* if both are bit variables */
5885   if (AOP_TYPE (left) == AOP_CRY &&
5886       AOP_TYPE (right) == AOP_CRY)
5887     {
5888       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5890       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5891       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5892   
5893       aopOp (result,ic,FALSE, FALSE);
5894       outBitC (result);
5895     }
5896   else
5897     {
5898       tlbl = newiTempLabel (NULL);
5899       toBoolean (left);
5900       emitcode ("jz", "!tlabel", tlbl->key + 100);
5901       toBoolean (right);
5902       emitcode ("", "!tlabeldef", tlbl->key + 100);
5903       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5904       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5905   
5906       aopOp (result,ic,FALSE, FALSE);
5907       outBitAcc (result);
5908     }
5909     freeAsmop (result, NULL, ic, TRUE);
5910 }
5911
5912
5913 /*-----------------------------------------------------------------*/
5914 /* genOrOp - for || operation                                      */
5915 /*-----------------------------------------------------------------*/
5916 static void
5917 genOrOp (iCode * ic)
5918 {
5919   operand *left, *right, *result;
5920   symbol *tlbl;
5921
5922   D (emitcode (";", "genOrOp "););
5923
5924   /* note here that || operations that are in an
5925      if statement are taken away by backPatchLabels
5926      only those used in arthmetic operations remain */
5927   AOP_OP_2 (ic);
5928   AOP_SET_LOCALS (ic);
5929
5930   /* if both are bit variables */
5931   if (AOP_TYPE (left) == AOP_CRY &&
5932       AOP_TYPE (right) == AOP_CRY)
5933     {
5934       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5935       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5936       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938   
5939       aopOp (result,ic,FALSE, FALSE);
5940       
5941       outBitC (result);
5942     }
5943   else
5944     {
5945       tlbl = newiTempLabel (NULL);
5946       toBoolean (left);
5947       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5948       toBoolean (right);
5949       emitcode ("", "!tlabeldef", tlbl->key + 100);
5950       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952   
5953       aopOp (result,ic,FALSE, FALSE);
5954       
5955       outBitAcc (result);
5956     }
5957
5958   freeAsmop (result, NULL, ic, TRUE);
5959 }
5960
5961 /*-----------------------------------------------------------------*/
5962 /* isLiteralBit - test if lit == 2^n                               */
5963 /*-----------------------------------------------------------------*/
5964 static int
5965 isLiteralBit (unsigned long lit)
5966 {
5967   unsigned long pw[32] =
5968   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5969    0x100L, 0x200L, 0x400L, 0x800L,
5970    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5971    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5972    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5973    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5974    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5975   int idx;
5976
5977   for (idx = 0; idx < 32; idx++)
5978     if (lit == pw[idx])
5979       return idx + 1;
5980   return 0;
5981 }
5982
5983 /*-----------------------------------------------------------------*/
5984 /* continueIfTrue -                                                */
5985 /*-----------------------------------------------------------------*/
5986 static void
5987 continueIfTrue (iCode * ic)
5988 {
5989   if (IC_TRUE (ic))
5990     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5991   ic->generated = 1;
5992 }
5993
5994 /*-----------------------------------------------------------------*/
5995 /* jmpIfTrue -                                                     */
5996 /*-----------------------------------------------------------------*/
5997 static void
5998 jumpIfTrue (iCode * ic)
5999 {
6000   if (!IC_TRUE (ic))
6001     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6002   ic->generated = 1;
6003 }
6004
6005 /*-----------------------------------------------------------------*/
6006 /* jmpTrueOrFalse -                                                */
6007 /*-----------------------------------------------------------------*/
6008 static void
6009 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6010 {
6011   // ugly but optimized by peephole
6012   if (IC_TRUE (ic))
6013     {
6014       symbol *nlbl = newiTempLabel (NULL);
6015       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6016       emitcode ("", "!tlabeldef", tlbl->key + 100);
6017       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6018       emitcode ("", "!tlabeldef", nlbl->key + 100);
6019     }
6020   else
6021     {
6022       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6023       emitcode ("", "!tlabeldef", tlbl->key + 100);
6024     }
6025   ic->generated = 1;
6026 }
6027
6028 // Generate code to perform a bit-wise logic operation
6029 // on two operands in far space (assumed to already have been 
6030 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6031 // in far space. This requires pushing the result on the stack
6032 // then popping it into the result.
6033 static void
6034 genFarFarLogicOp(iCode *ic, char *logicOp)
6035 {
6036       int size, resultSize, compSize;
6037       int offset = 0;
6038       
6039       TR_AP("#5");
6040       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6041       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6042                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6043       
6044       _startLazyDPSEvaluation();
6045       for (size = compSize; (size--); offset++)
6046       {
6047           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
6048           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6049           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
6050           
6051           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6052           emitcode ("push", "acc");
6053       }
6054       _endLazyDPSEvaluation();
6055      
6056       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6057       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6058       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6059      
6060       resultSize = AOP_SIZE(IC_RESULT(ic));
6061
6062       ADJUST_PUSHED_RESULT(compSize, resultSize);
6063
6064       _startLazyDPSEvaluation();
6065       while (compSize--)
6066       {
6067           emitcode ("pop", "acc");
6068           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6069       }
6070       _endLazyDPSEvaluation();
6071       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6072 }
6073
6074
6075 /*-----------------------------------------------------------------*/
6076 /* genAnd  - code for and                                          */
6077 /*-----------------------------------------------------------------*/
6078 static void
6079 genAnd (iCode * ic, iCode * ifx)
6080 {
6081   operand *left, *right, *result;
6082   int size, offset = 0;
6083   unsigned long lit = 0L;
6084   int bytelit = 0;
6085   char buff[10];
6086   bool pushResult;
6087
6088   D (emitcode (";", "genAnd "););
6089
6090   AOP_OP_3_NOFATAL (ic, pushResult);
6091   AOP_SET_LOCALS (ic);
6092
6093   if (pushResult)
6094   {
6095       genFarFarLogicOp(ic, "anl");
6096       return;
6097   }  
6098
6099 #ifdef DEBUG_TYPE
6100   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6101             AOP_TYPE (result),
6102             AOP_TYPE (left), AOP_TYPE (right));
6103   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6104             AOP_SIZE (result),
6105             AOP_SIZE (left), AOP_SIZE (right));
6106 #endif
6107
6108   /* if left is a literal & right is not then exchange them */
6109   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6110 #ifdef LOGIC_OPS_BROKEN      
6111     ||  AOP_NEEDSACC (left)
6112 #endif
6113     )
6114     {
6115       operand *tmp = right;
6116       right = left;
6117       left = tmp;
6118     }
6119
6120   /* if result = right then exchange them */
6121   if (sameRegs (AOP (result), AOP (right)))
6122     {
6123       operand *tmp = right;
6124       right = left;
6125       left = tmp;
6126     }
6127
6128   /* if right is bit then exchange them */
6129   if (AOP_TYPE (right) == AOP_CRY &&
6130       AOP_TYPE (left) != AOP_CRY)
6131     {
6132       operand *tmp = right;
6133       right = left;
6134       left = tmp;
6135     }
6136   if (AOP_TYPE (right) == AOP_LIT)
6137     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6138
6139   size = AOP_SIZE (result);
6140
6141   // if(bit & yy)
6142   // result = bit & yy;
6143   if (AOP_TYPE (left) == AOP_CRY)
6144     {
6145       // c = bit & literal;
6146       if (AOP_TYPE (right) == AOP_LIT)
6147         {
6148           if (lit & 1)
6149             {
6150               if (size && sameRegs (AOP (result), AOP (left)))
6151                 // no change
6152                 goto release;
6153               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6154             }
6155           else
6156             {
6157               // bit(result) = 0;
6158               if (size && (AOP_TYPE (result) == AOP_CRY))
6159                 {
6160                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6161                   goto release;
6162                 }
6163               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6164                 {
6165                   jumpIfTrue (ifx);
6166                   goto release;
6167                 }
6168               emitcode ("clr", "c");
6169             }
6170         }
6171       else
6172         {
6173           if (AOP_TYPE (right) == AOP_CRY)
6174             {
6175               // c = bit & bit;
6176               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6177               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6178             }
6179           else
6180             {
6181               // c = bit & val;
6182               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
6183               // c = lsb
6184               emitcode ("rrc", "a");
6185               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6186             }
6187         }
6188       // bit = c
6189       // val = c
6190       if (size)
6191         outBitC (result);
6192       // if(bit & ...)
6193       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6194         genIfxJump (ifx, "c");
6195       goto release;
6196     }
6197
6198   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6199   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6200   if ((AOP_TYPE (right) == AOP_LIT) &&
6201       (AOP_TYPE (result) == AOP_CRY) &&
6202       (AOP_TYPE (left) != AOP_CRY))
6203     {
6204       int posbit = isLiteralBit (lit);
6205       /* left &  2^n */
6206       if (posbit)
6207         {
6208           posbit--;
6209           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
6210           // bit = left & 2^n
6211           if (size)
6212             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6213           // if(left &  2^n)
6214           else
6215             {
6216               if (ifx)
6217                 {
6218                   SNPRINTF (buff, sizeof(buff), 
6219                             "acc.%d", posbit & 0x07);
6220                   genIfxJump (ifx, buff);
6221                 }
6222               else 
6223                   {
6224                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6225                   }
6226               goto release;
6227             }
6228         }
6229       else
6230         {
6231           symbol *tlbl = newiTempLabel (NULL);
6232           int sizel = AOP_SIZE (left);
6233           if (size)
6234             emitcode ("setb", "c");
6235           while (sizel--)
6236             {
6237               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6238                 {
6239                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6240                   // byte ==  2^n ?
6241                   if ((posbit = isLiteralBit (bytelit)) != 0)
6242                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6243                   else
6244                     {
6245                       if (bytelit != 0x0FFL)
6246                         emitcode ("anl", "a,%s",
6247                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6248                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6249                     }
6250                 }
6251               offset++;
6252             }
6253           // bit = left & literal
6254           if (size)
6255             {
6256               emitcode ("clr", "c");
6257               emitcode ("", "!tlabeldef", tlbl->key + 100);
6258             }
6259           // if(left & literal)
6260           else
6261             {
6262               if (ifx)
6263                 jmpTrueOrFalse (ifx, tlbl);
6264               goto release;
6265             }
6266         }
6267       outBitC (result);
6268       goto release;
6269     }
6270
6271   /* if left is same as result */
6272   if (sameRegs (AOP (result), AOP (left)))
6273     {
6274       for (; size--; offset++)
6275         {
6276           if (AOP_TYPE (right) == AOP_LIT)
6277             {
6278               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6279                 continue;
6280               else if (bytelit == 0)
6281                 aopPut (AOP (result), zero, offset);
6282               else if (IS_AOP_PREG (result))
6283                 {
6284                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6285                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6286                   aopPut (AOP (result), "a", offset);
6287                 }
6288               else
6289                 emitcode ("anl", "%s,%s",
6290                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6291                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6292             }
6293           else
6294             {
6295               if (AOP_TYPE (left) == AOP_ACC)
6296                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6297               else
6298                 {
6299                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6300                   if (IS_AOP_PREG (result))
6301                     {
6302                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6303                       aopPut (AOP (result), "a", offset);
6304
6305                     }
6306                   else
6307                     emitcode ("anl", "%s,a",
6308                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6309                 }
6310             }
6311         }
6312     }
6313   else
6314     {
6315       // left & result in different registers
6316       if (AOP_TYPE (result) == AOP_CRY)
6317         {
6318           // result = bit
6319           // if(size), result in bit
6320           // if(!size && ifx), conditional oper: if(left & right)
6321           symbol *tlbl = newiTempLabel (NULL);
6322           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6323           if (size)
6324             emitcode ("setb", "c");
6325           while (sizer--)
6326             {
6327               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6328                 emitcode ("anl", "a,%s",
6329                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6330               } else {
6331                 if (AOP_TYPE(left)==AOP_ACC) {
6332                   emitcode("mov", "b,a");
6333                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6334                   emitcode("anl", "a,b");
6335                 }else {
6336                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6337                   emitcode ("anl", "a,%s",
6338                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6339                 }
6340               }
6341               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6342               offset++;
6343             }
6344           if (size)
6345             {
6346               CLRC;
6347               emitcode ("", "!tlabeldef", tlbl->key + 100);
6348               outBitC (result);
6349             }
6350           else if (ifx)
6351             jmpTrueOrFalse (ifx, tlbl);
6352         }
6353       else
6354         {
6355           for (; (size--); offset++)
6356             {
6357               // normal case
6358               // result = left & right
6359               if (AOP_TYPE (right) == AOP_LIT)
6360                 {
6361                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6362                     {
6363                       aopPut (AOP (result),
6364                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6365                               offset);
6366                       continue;
6367                     }
6368                   else if (bytelit == 0)
6369                     {
6370                       aopPut (AOP (result), zero, offset);
6371                       continue;
6372                     }
6373                   D (emitcode (";", "better literal AND."););
6374                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6375                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6376                                                     FALSE, FALSE, FALSE));
6377
6378                 }
6379               else
6380                 {
6381                   // faster than result <- left, anl result,right
6382                   // and better if result is SFR
6383                   if (AOP_TYPE (left) == AOP_ACC)
6384                     {
6385                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6386                                                        FALSE, FALSE, FALSE));
6387                     }
6388                   else
6389                     {
6390                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6391                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6392                       {
6393                           emitcode("mov", "b,a");
6394                           rOp = "b";
6395                       }
6396                         
6397                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6398                       emitcode ("anl", "a,%s", rOp);
6399                     }                   
6400                 }
6401               aopPut (AOP (result), "a", offset);
6402             }
6403         }
6404     }
6405
6406 release:
6407   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6408   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6409   freeAsmop (result, NULL, ic, TRUE);
6410 }
6411
6412
6413 /*-----------------------------------------------------------------*/
6414 /* genOr  - code for or                                            */
6415 /*-----------------------------------------------------------------*/
6416 static void
6417 genOr (iCode * ic, iCode * ifx)
6418 {
6419   operand *left, *right, *result;
6420   int size, offset = 0;
6421   unsigned long lit = 0L;
6422   bool     pushResult;
6423
6424   D (emitcode (";", "genOr "););
6425
6426   AOP_OP_3_NOFATAL (ic, pushResult);
6427   AOP_SET_LOCALS (ic);
6428
6429   if (pushResult)
6430   {
6431       genFarFarLogicOp(ic, "orl");
6432       return;
6433   }
6434
6435
6436 #ifdef DEBUG_TYPE
6437   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6438             AOP_TYPE (result),
6439             AOP_TYPE (left), AOP_TYPE (right));
6440   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6441             AOP_SIZE (result),
6442             AOP_SIZE (left), AOP_SIZE (right));
6443 #endif
6444
6445   /* if left is a literal & right is not then exchange them */
6446   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6447 #ifdef LOGIC_OPS_BROKEN
6448    || AOP_NEEDSACC (left) // I think this is a net loss now.
6449 #endif      
6450       )
6451     {
6452       operand *tmp = right;
6453       right = left;
6454       left = tmp;
6455     }
6456
6457   /* if result = right then exchange them */
6458   if (sameRegs (AOP (result), AOP (right)))
6459     {
6460       operand *tmp = right;
6461       right = left;
6462       left = tmp;
6463     }
6464
6465   /* if right is bit then exchange them */
6466   if (AOP_TYPE (right) == AOP_CRY &&
6467       AOP_TYPE (left) != AOP_CRY)
6468     {
6469       operand *tmp = right;
6470       right = left;
6471       left = tmp;
6472     }
6473   if (AOP_TYPE (right) == AOP_LIT)
6474     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6475
6476   size = AOP_SIZE (result);
6477
6478   // if(bit | yy)
6479   // xx = bit | yy;
6480   if (AOP_TYPE (left) == AOP_CRY)
6481     {
6482       if (AOP_TYPE (right) == AOP_LIT)
6483         {
6484           // c = bit & literal;
6485           if (lit)
6486             {
6487               // lit != 0 => result = 1
6488               if (AOP_TYPE (result) == AOP_CRY)
6489                 {
6490                   if (size)
6491                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6492                   else if (ifx)
6493                     continueIfTrue (ifx);
6494                   goto release;
6495                 }
6496               emitcode ("setb", "c");
6497             }
6498           else
6499             {
6500               // lit == 0 => result = left
6501               if (size && sameRegs (AOP (result), AOP (left)))
6502                 goto release;
6503               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6504             }
6505         }
6506       else
6507         {
6508           if (AOP_TYPE (right) == AOP_CRY)
6509             {
6510               // c = bit | bit;
6511               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6512               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6513             }
6514           else
6515             {
6516               // c = bit | val;
6517               symbol *tlbl = newiTempLabel (NULL);
6518               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6519                 emitcode ("setb", "c");
6520               emitcode ("jb", "%s,!tlabel",
6521                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6522               toBoolean (right);
6523               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6524               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6525                 {
6526                   jmpTrueOrFalse (ifx, tlbl);
6527                   goto release;
6528                 }
6529               else
6530                 {
6531                   CLRC;
6532                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6533                 }
6534             }
6535         }
6536       // bit = c
6537       // val = c
6538       if (size)
6539         outBitC (result);
6540       // if(bit | ...)
6541       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542            genIfxJump (ifx, "c");
6543       goto release;
6544     }
6545
6546   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6547   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6548   if ((AOP_TYPE (right) == AOP_LIT) &&
6549       (AOP_TYPE (result) == AOP_CRY) &&
6550       (AOP_TYPE (left) != AOP_CRY))
6551     {
6552       if (lit)
6553         {
6554           // result = 1
6555           if (size)
6556             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6557           else
6558             continueIfTrue (ifx);
6559           goto release;
6560         }
6561       else
6562         {
6563           // lit = 0, result = boolean(left)
6564           if (size)
6565             emitcode ("setb", "c");
6566           toBoolean (right);
6567           if (size)
6568             {
6569               symbol *tlbl = newiTempLabel (NULL);
6570               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6571               CLRC;
6572               emitcode ("", "!tlabeldef", tlbl->key + 100);
6573             }
6574           else
6575             {
6576               genIfxJump (ifx, "a");
6577               goto release;
6578             }
6579         }
6580       outBitC (result);
6581       goto release;
6582     }
6583
6584   /* if left is same as result */
6585   if (sameRegs (AOP (result), AOP (left)))
6586     {
6587       for (; size--; offset++)
6588         {
6589           if (AOP_TYPE (right) == AOP_LIT)
6590             {
6591               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6592                 {
6593                   continue;
6594                 }
6595               else
6596                 {
6597                   if (IS_AOP_PREG (left))
6598                     {
6599                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6600                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6601                       aopPut (AOP (result), "a", offset);
6602                     }
6603                   else
6604                     {
6605                       emitcode ("orl", "%s,%s",
6606                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6607                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6608                     }
6609                 }
6610             }
6611           else
6612             {
6613               if (AOP_TYPE (left) == AOP_ACC)
6614                 {
6615                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6616                 }
6617               else
6618                 {
6619                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6620                   if (IS_AOP_PREG (left))
6621                     {
6622                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6623                       aopPut (AOP (result), "a", offset);
6624                     }
6625                   else
6626                     {
6627                       emitcode ("orl", "%s,a",
6628                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6629                     }
6630                 }
6631             }
6632         }
6633     }
6634   else
6635     {
6636       // left & result in different registers
6637       if (AOP_TYPE (result) == AOP_CRY)
6638         {
6639           // result = bit
6640           // if(size), result in bit
6641           // if(!size && ifx), conditional oper: if(left | right)
6642           symbol *tlbl = newiTempLabel (NULL);
6643           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6644           if (size)
6645             emitcode ("setb", "c");
6646           while (sizer--)
6647             {
6648               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6649                 emitcode ("orl", "a,%s",
6650                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6651               } else {
6652                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6653                 emitcode ("orl", "a,%s",
6654                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6655               }
6656               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6657               offset++;
6658             }
6659           if (size)
6660             {
6661               CLRC;
6662               emitcode ("", "!tlabeldef", tlbl->key + 100);
6663               outBitC (result);
6664             }
6665           else if (ifx)
6666             jmpTrueOrFalse (ifx, tlbl);
6667         }
6668       else
6669         {
6670             _startLazyDPSEvaluation();
6671           for (; (size--); offset++)
6672             {
6673               // normal case
6674               // result = left & right
6675               if (AOP_TYPE (right) == AOP_LIT)
6676                 {
6677                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6678                     {
6679                       aopPut (AOP (result),
6680                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6681                               offset);
6682                       continue;
6683                     }
6684                   D (emitcode (";", "better literal OR."););
6685                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6686                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6687                                                     FALSE, FALSE, FALSE));
6688
6689                 }
6690               else
6691                 {
6692                   // faster than result <- left, anl result,right
6693                   // and better if result is SFR
6694                   if (AOP_TYPE (left) == AOP_ACC)
6695                     {
6696                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6697                                                        FALSE, FALSE, FALSE));
6698                     }
6699                   else
6700                     {
6701                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6702                         
6703                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6704                       {
6705                           emitcode("mov", "b,a");
6706                           rOp = "b";
6707                       }
6708                         
6709                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6710                       emitcode ("orl", "a,%s", rOp);
6711                     }
6712                 }
6713               aopPut (AOP (result), "a", offset);
6714             }
6715             _endLazyDPSEvaluation();
6716         }
6717     }
6718
6719 release:
6720   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6721   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6722   freeAsmop (result, NULL, ic, TRUE);
6723 }
6724
6725 /*-----------------------------------------------------------------*/
6726 /* genXor - code for xclusive or                                   */
6727 /*-----------------------------------------------------------------*/
6728 static void
6729 genXor (iCode * ic, iCode * ifx)
6730 {
6731   operand *left, *right, *result;
6732   int size, offset = 0;
6733   unsigned long lit = 0L;
6734   bool pushResult;
6735
6736   D (emitcode (";", "genXor "););
6737
6738   AOP_OP_3_NOFATAL (ic, pushResult);
6739   AOP_SET_LOCALS (ic);
6740
6741   if (pushResult)
6742   {
6743       genFarFarLogicOp(ic, "xrl");
6744       return;
6745   }  
6746
6747 #ifdef DEBUG_TYPE
6748   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6749             AOP_TYPE (result),
6750             AOP_TYPE (left), AOP_TYPE (right));
6751   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6752             AOP_SIZE (result),
6753             AOP_SIZE (left), AOP_SIZE (right));
6754 #endif
6755
6756   /* if left is a literal & right is not ||
6757      if left needs acc & right does not */
6758   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6759 #ifdef LOGIC_OPS_BROKEN      
6760       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6761 #endif
6762      )
6763     {
6764       operand *tmp = right;
6765       right = left;
6766       left = tmp;
6767     }
6768
6769   /* if result = right then exchange them */
6770   if (sameRegs (AOP (result), AOP (right)))
6771     {
6772       operand *tmp = right;
6773       right = left;
6774       left = tmp;
6775     }
6776
6777   /* if right is bit then exchange them */
6778   if (AOP_TYPE (right) == AOP_CRY &&
6779       AOP_TYPE (left) != AOP_CRY)
6780     {
6781       operand *tmp = right;
6782       right = left;
6783       left = tmp;
6784     }
6785   if (AOP_TYPE (right) == AOP_LIT)
6786     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6787
6788   size = AOP_SIZE (result);
6789
6790   // if(bit ^ yy)
6791   // xx = bit ^ yy;
6792   if (AOP_TYPE (left) == AOP_CRY)
6793     {
6794       if (AOP_TYPE (right) == AOP_LIT)
6795         {
6796           // c = bit & literal;
6797           if (lit >> 1)
6798             {
6799               // lit>>1  != 0 => result = 1
6800               if (AOP_TYPE (result) == AOP_CRY)
6801                 {
6802                   if (size)
6803                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6804                   else if (ifx)
6805                     continueIfTrue (ifx);
6806                   goto release;
6807                 }
6808               emitcode ("setb", "c");
6809             }
6810           else
6811             {
6812               // lit == (0 or 1)
6813               if (lit == 0)
6814                 {
6815                   // lit == 0, result = left
6816                   if (size && sameRegs (AOP (result), AOP (left)))
6817                     goto release;
6818                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6819                 }
6820               else
6821                 {
6822                   // lit == 1, result = not(left)
6823                   if (size && sameRegs (AOP (result), AOP (left)))
6824                     {
6825                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6826                       goto release;
6827                     }
6828                   else
6829                     {
6830                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6831                       emitcode ("cpl", "c");
6832                     }
6833                 }
6834             }
6835
6836         }
6837       else
6838         {
6839           // right != literal
6840           symbol *tlbl = newiTempLabel (NULL);
6841           if (AOP_TYPE (right) == AOP_CRY)
6842             {
6843               // c = bit ^ bit;
6844               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6845             }
6846           else
6847             {
6848               int sizer = AOP_SIZE (right);
6849               // c = bit ^ val
6850               // if val>>1 != 0, result = 1
6851               emitcode ("setb", "c");
6852               while (sizer)
6853                 {
6854                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6855                   if (sizer == 1)
6856                     // test the msb of the lsb
6857                     emitcode ("anl", "a,#!constbyte",0xfe);
6858                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6859                   sizer--;
6860                 }
6861               // val = (0,1)
6862               emitcode ("rrc", "a");
6863             }
6864           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6865           emitcode ("cpl", "c");
6866           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6867         }
6868       // bit = c
6869       // val = c
6870       if (size)
6871         outBitC (result);
6872       // if(bit | ...)
6873       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6874         genIfxJump (ifx, "c");
6875       goto release;
6876     }
6877
6878   if (sameRegs (AOP (result), AOP (left)))
6879     {
6880       /* if left is same as result */
6881       for (; size--; offset++)
6882         {
6883           if (AOP_TYPE (right) == AOP_LIT)
6884             {
6885               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6886                 continue;
6887               else if (IS_AOP_PREG (left))
6888                 {
6889                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6890                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6891                   aopPut (AOP (result), "a", offset);
6892                 }
6893               else
6894                 emitcode ("xrl", "%s,%s",
6895                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6896                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6897             }
6898           else
6899             {
6900               if (AOP_TYPE (left) == AOP_ACC)
6901                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6902               else
6903                 {
6904                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6905                   if (IS_AOP_PREG (left))
6906                     {
6907                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6908                       aopPut (AOP (result), "a", offset);
6909                     }
6910                   else
6911                     emitcode ("xrl", "%s,a",
6912                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6913                 }
6914             }
6915         }
6916     }
6917   else
6918     {
6919       // left & result in different registers
6920       if (AOP_TYPE (result) == AOP_CRY)
6921         {
6922           // result = bit
6923           // if(size), result in bit
6924           // if(!size && ifx), conditional oper: if(left ^ right)
6925           symbol *tlbl = newiTempLabel (NULL);
6926           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6927                   
6928           if (size)
6929             emitcode ("setb", "c");
6930           while (sizer--)
6931             {
6932               if ((AOP_TYPE (right) == AOP_LIT) &&
6933                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6934                 {
6935                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6936                 }
6937               else
6938                 {
6939                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6940                     emitcode ("xrl", "a,%s",
6941                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6942                   } else {
6943                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6944                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6945                       {
6946                           emitcode("mov", "b,a");
6947                           rOp = "b";
6948                       }
6949                         
6950                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6951                       emitcode ("xrl", "a,%s", rOp);                  
6952                   }
6953                 }
6954               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6955               offset++;
6956             }
6957           if (size)
6958             {
6959               CLRC;
6960               emitcode ("", "!tlabeldef", tlbl->key + 100);
6961               outBitC (result);
6962             }
6963           else if (ifx)
6964             jmpTrueOrFalse (ifx, tlbl);
6965         }
6966       else
6967         {
6968         for (; (size--); offset++)
6969           {
6970             // normal case
6971             // result = left & right
6972             if (AOP_TYPE (right) == AOP_LIT)
6973               {
6974                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6975                   {
6976                     aopPut (AOP (result),
6977                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6978                             offset);
6979                     continue;
6980                   }
6981                 D (emitcode (";", "better literal XOR."););
6982                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6983                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6984                                                   FALSE, FALSE, FALSE));
6985               }
6986             else
6987               {
6988                 // faster than result <- left, anl result,right
6989                 // and better if result is SFR
6990                 if (AOP_TYPE (left) == AOP_ACC)
6991                   {
6992                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6993                                                      FALSE, FALSE, FALSE));
6994                   }
6995                 else
6996                   {
6997                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6998                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6999                       {
7000                           emitcode("mov", "b,a");
7001                           rOp = "b";
7002                       }
7003                         
7004                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
7005                       emitcode ("xrl", "a,%s", rOp);
7006                   }
7007               }
7008             aopPut (AOP (result), "a", offset);
7009           }
7010         }
7011         
7012     }
7013
7014 release:
7015   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7016   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7017   freeAsmop (result, NULL, ic, TRUE);
7018 }
7019
7020 /*-----------------------------------------------------------------*/
7021 /* genInline - write the inline code out                           */
7022 /*-----------------------------------------------------------------*/
7023 static void
7024 genInline (iCode * ic)
7025 {
7026   char *buffer, *bp, *bp1;
7027
7028   D (emitcode (";", "genInline "); );
7029
7030   _G.inLine += (!options.asmpeep);
7031
7032   buffer = Safe_strdup(IC_INLINE(ic));
7033   bp = buffer;
7034   bp1 = buffer;
7035
7036   /* emit each line as a code */
7037   while (*bp)
7038     {
7039       if (*bp == '\n')
7040         {
7041           *bp++ = '\0';
7042           emitcode (bp1, "");
7043           bp1 = bp;
7044         }
7045       else
7046         {
7047           if (*bp == ':')
7048             {
7049               bp++;
7050               *bp = '\0';
7051               bp++;
7052               emitcode (bp1, "");
7053               bp1 = bp;
7054             }
7055           else
7056             bp++;
7057         }
7058     }
7059   if (bp1 != bp)
7060     emitcode (bp1, "");
7061   /*     emitcode("",buffer); */
7062   _G.inLine -= (!options.asmpeep);
7063 }
7064
7065 /*-----------------------------------------------------------------*/
7066 /* genRRC - rotate right with carry                                */
7067 /*-----------------------------------------------------------------*/
7068 static void
7069 genRRC (iCode * ic)
7070 {
7071   operand *left, *result;
7072   int size, offset = 0;
7073   char *l;
7074
7075   D (emitcode (";", "genRRC ");
7076     );
7077
7078   /* rotate right with carry */
7079   left = IC_LEFT (ic);
7080   result = IC_RESULT (ic);
7081   aopOp (left, ic, FALSE, FALSE);
7082   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7083
7084   /* move it to the result */
7085   size = AOP_SIZE (result);
7086   offset = size - 1;
7087   CLRC;
7088
7089   _startLazyDPSEvaluation ();
7090   while (size--)
7091     {
7092       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7093       MOVA (l);
7094       emitcode ("rrc", "a");
7095       if (AOP_SIZE (result) > 1)
7096         aopPut (AOP (result), "a", offset--);
7097     }
7098   _endLazyDPSEvaluation ();
7099
7100   /* now we need to put the carry into the
7101      highest order byte of the result */
7102   if (AOP_SIZE (result) > 1)
7103     {
7104       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
7105       MOVA (l);
7106     }
7107   emitcode ("mov", "acc.7,c");
7108   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7109   freeAsmop (left, NULL, ic, TRUE);
7110   freeAsmop (result, NULL, ic, TRUE);
7111 }
7112
7113 /*-----------------------------------------------------------------*/
7114 /* genRLC - generate code for rotate left with carry               */
7115 /*-----------------------------------------------------------------*/
7116 static void
7117 genRLC (iCode * ic)
7118 {
7119   operand *left, *result;
7120   int size, offset = 0;
7121   char *l;
7122
7123   D (emitcode (";", "genRLC ");
7124     );
7125
7126   /* rotate right with carry */
7127   left = IC_LEFT (ic);
7128   result = IC_RESULT (ic);
7129   aopOp (left, ic, FALSE, FALSE);
7130   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7131
7132   /* move it to the result */
7133   size = AOP_SIZE (result);
7134   offset = 0;
7135   if (size--)
7136     {
7137       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7138       MOVA (l);
7139       emitcode ("add", "a,acc");
7140       if (AOP_SIZE (result) > 1)
7141         {
7142           aopPut (AOP (result), "a", offset++);
7143         }
7144
7145       _startLazyDPSEvaluation ();
7146       while (size--)
7147         {
7148           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
7149           MOVA (l);
7150           emitcode ("rlc", "a");
7151           if (AOP_SIZE (result) > 1)
7152             aopPut (AOP (result), "a", offset++);
7153         }
7154       _endLazyDPSEvaluation ();
7155     }
7156   /* now we need to put the carry into the
7157      highest order byte of the result */
7158   if (AOP_SIZE (result) > 1)
7159     {
7160       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
7161       MOVA (l);
7162     }
7163   emitcode ("mov", "acc.0,c");
7164   aopPut (AOP (result), "a", 0);
7165   freeAsmop (left, NULL, ic, TRUE);
7166   freeAsmop (result, NULL, ic, TRUE);
7167 }
7168
7169 /*-----------------------------------------------------------------*/
7170 /* genGetHbit - generates code get highest order bit               */
7171 /*-----------------------------------------------------------------*/
7172 static void
7173 genGetHbit (iCode * ic)
7174 {
7175   operand *left, *result;
7176   left = IC_LEFT (ic);
7177   result = IC_RESULT (ic);
7178   aopOp (left, ic, FALSE, FALSE);
7179   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7180
7181   D (emitcode (";", "genGetHbit ");
7182     );
7183
7184   /* get the highest order byte into a */
7185   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
7186   if (AOP_TYPE (result) == AOP_CRY)
7187     {
7188       emitcode ("rlc", "a");
7189       outBitC (result);
7190     }
7191   else
7192     {
7193       emitcode ("rl", "a");
7194       emitcode ("anl", "a,#1");
7195       outAcc (result);
7196     }
7197
7198
7199   freeAsmop (left, NULL, ic, TRUE);
7200   freeAsmop (result, NULL, ic, TRUE);
7201 }
7202
7203 /*-----------------------------------------------------------------*/
7204 /* AccRol - rotate left accumulator by known count                 */
7205 /*-----------------------------------------------------------------*/
7206 static void
7207 AccRol (int shCount)
7208 {
7209   shCount &= 0x0007;            // shCount : 0..7
7210
7211   switch (shCount)
7212     {
7213     case 0:
7214       break;
7215     case 1:
7216       emitcode ("rl", "a");
7217       break;
7218     case 2:
7219       emitcode ("rl", "a");
7220       emitcode ("rl", "a");
7221       break;
7222     case 3:
7223       emitcode ("swap", "a");
7224       emitcode ("rr", "a");
7225       break;
7226     case 4:
7227       emitcode ("swap", "a");
7228       break;
7229     case 5:
7230       emitcode ("swap", "a");
7231       emitcode ("rl", "a");
7232       break;
7233     case 6:
7234       emitcode ("rr", "a");
7235       emitcode ("rr", "a");
7236       break;
7237     case 7:
7238       emitcode ("rr", "a");
7239       break;
7240     }
7241 }
7242
7243 /*-----------------------------------------------------------------*/
7244 /* AccLsh - left shift accumulator by known count                  */
7245 /*-----------------------------------------------------------------*/
7246 static void
7247 AccLsh (int shCount)
7248 {
7249   if (shCount != 0)
7250     {
7251       if (shCount == 1)
7252         emitcode ("add", "a,acc");
7253       else if (shCount == 2)
7254         {
7255           emitcode ("add", "a,acc");
7256           emitcode ("add", "a,acc");
7257         }
7258       else
7259         {
7260           /* rotate left accumulator */
7261           AccRol (shCount);
7262           /* and kill the lower order bits */
7263           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7264         }
7265     }
7266 }
7267
7268 /*-----------------------------------------------------------------*/
7269 /* AccRsh - right shift accumulator by known count                 */
7270 /*-----------------------------------------------------------------*/
7271 static void
7272 AccRsh (int shCount)
7273 {
7274   if (shCount != 0)
7275     {
7276       if (shCount == 1)
7277         {
7278           CLRC;
7279           emitcode ("rrc", "a");
7280         }
7281       else
7282         {
7283           /* rotate right accumulator */
7284           AccRol (8 - shCount);
7285           /* and kill the higher order bits */
7286           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7287         }
7288     }
7289 }
7290
7291 #ifdef BETTER_LITERAL_SHIFT
7292 /*-----------------------------------------------------------------*/
7293 /* AccSRsh - signed right shift accumulator by known count                 */
7294 /*-----------------------------------------------------------------*/
7295 static void
7296 AccSRsh (int shCount)
7297 {
7298   symbol *tlbl;
7299   if (shCount != 0)
7300     {
7301       if (shCount == 1)
7302         {
7303           emitcode ("mov", "c,acc.7");
7304           emitcode ("rrc", "a");
7305         }
7306       else if (shCount == 2)
7307         {
7308           emitcode ("mov", "c,acc.7");
7309           emitcode ("rrc", "a");
7310           emitcode ("mov", "c,acc.7");
7311           emitcode ("rrc", "a");
7312         }
7313       else
7314         {
7315           tlbl = newiTempLabel (NULL);
7316           /* rotate right accumulator */
7317           AccRol (8 - shCount);
7318           /* and kill the higher order bits */
7319           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7320           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7321           emitcode ("orl", "a,#!constbyte",
7322                     (unsigned char) ~SRMask[shCount]);
7323           emitcode ("", "!tlabeldef", tlbl->key + 100);
7324         }
7325     }
7326 }
7327 #endif
7328
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* shiftR1Left2Result - shift right one byte from left to result   */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 shiftR1Left2Result (operand * left, int offl,
7335                     operand * result, int offr,
7336                     int shCount, int sign)
7337 {
7338   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7339   /* shift right accumulator */
7340   if (sign)
7341     AccSRsh (shCount);
7342   else
7343     AccRsh (shCount);
7344   aopPut (AOP (result), "a", offr);
7345 }
7346 #endif
7347
7348 #ifdef BETTER_LITERAL_SHIFT
7349 /*-----------------------------------------------------------------*/
7350 /* shiftL1Left2Result - shift left one byte from left to result    */
7351 /*-----------------------------------------------------------------*/
7352 static void
7353 shiftL1Left2Result (operand * left, int offl,
7354                     operand * result, int offr, int shCount)
7355 {
7356   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7357   /* shift left accumulator */
7358   AccLsh (shCount);
7359   aopPut (AOP (result), "a", offr);
7360 }
7361 #endif
7362
7363 #ifdef BETTER_LITERAL_SHIFT
7364 /*-----------------------------------------------------------------*/
7365 /* movLeft2Result - move byte from left to result                  */
7366 /*-----------------------------------------------------------------*/
7367 static void
7368 movLeft2Result (operand * left, int offl,
7369                 operand * result, int offr, int sign)
7370 {
7371   char *l;
7372   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7373   {
7374       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7375
7376       if (*l == '@' && (IS_AOP_PREG (result)))
7377       {
7378           emitcode ("mov", "a,%s", l);
7379           aopPut (AOP (result), "a", offr);
7380       }
7381       else
7382       {
7383           if (!sign)
7384           {
7385             aopPut (AOP (result), l, offr);
7386           }
7387           else
7388             {
7389               /* MSB sign in acc.7 ! */
7390               if (getDataSize (left) == offl + 1)
7391                 {
7392                   emitcode ("mov", "a,%s", l);
7393                   aopPut (AOP (result), "a", offr);
7394                 }
7395             }
7396       }
7397   }
7398 }
7399 #endif
7400
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7404 /*-----------------------------------------------------------------*/
7405 static void
7406 AccAXRrl1 (char *x)
7407 {
7408   emitcode ("rrc", "a");
7409   emitcode ("xch", "a,%s", x);
7410   emitcode ("rrc", "a");
7411   emitcode ("xch", "a,%s", x);
7412 }
7413 #endif
7414
7415 #ifdef BETTER_LITERAL_SHIFT
7416 //REMOVE ME!!!
7417 /*-----------------------------------------------------------------*/
7418 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7419 /*-----------------------------------------------------------------*/
7420 static void
7421 AccAXLrl1 (char *x)
7422 {
7423   emitcode ("xch", "a,%s", x);
7424   emitcode ("rlc", "a");
7425   emitcode ("xch", "a,%s", x);
7426   emitcode ("rlc", "a");
7427 }
7428 #endif
7429
7430 #ifdef BETTER_LITERAL_SHIFT
7431 /*-----------------------------------------------------------------*/
7432 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7433 /*-----------------------------------------------------------------*/
7434 static void
7435 AccAXLsh1 (char *x)
7436 {
7437   emitcode ("xch", "a,%s", x);
7438   emitcode ("add", "a,acc");
7439   emitcode ("xch", "a,%s", x);
7440   emitcode ("rlc", "a");
7441 }
7442 #endif
7443
7444 #ifdef BETTER_LITERAL_SHIFT
7445 /*-----------------------------------------------------------------*/
7446 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7447 /*-----------------------------------------------------------------*/
7448 static void
7449 AccAXLsh (char *x, int shCount)
7450 {
7451   switch (shCount)
7452     {
7453     case 0:
7454       break;
7455     case 1:
7456       AccAXLsh1 (x);
7457       break;
7458     case 2:
7459       AccAXLsh1 (x);
7460       AccAXLsh1 (x);
7461       break;
7462     case 3:
7463     case 4:
7464     case 5:                     // AAAAABBB:CCCCCDDD
7465
7466       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7467
7468       emitcode ("anl", "a,#!constbyte",
7469                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7470
7471       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7472
7473       AccRol (shCount);         // DDDCCCCC:BBB00000
7474
7475       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7476
7477       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7478
7479       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7480
7481       emitcode ("anl", "a,#!constbyte",
7482                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7483
7484       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7485
7486       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7487
7488       break;
7489     case 6:                     // AAAAAABB:CCCCCCDD
7490       emitcode ("anl", "a,#!constbyte",
7491                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7492       emitcode ("mov", "c,acc.0");      // c = B
7493       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7494 #if 0
7495       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7496       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7497 #else
7498       emitcode("rrc","a"); 
7499       emitcode("xch","a,%s", x); 
7500       emitcode("rrc","a"); 
7501       emitcode("mov","c,acc.0"); //<< get correct bit 
7502       emitcode("xch","a,%s", x); 
7503
7504       emitcode("rrc","a"); 
7505       emitcode("xch","a,%s", x); 
7506       emitcode("rrc","a"); 
7507       emitcode("xch","a,%s", x); 
7508 #endif
7509       break;
7510     case 7:                     // a:x <<= 7
7511
7512       emitcode ("anl", "a,#!constbyte",
7513                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7514
7515       emitcode ("mov", "c,acc.0");      // c = B
7516
7517       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7518
7519       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7520
7521       break;
7522     default:
7523       break;
7524     }
7525 }
7526 #endif
7527
7528 #ifdef BETTER_LITERAL_SHIFT
7529 //REMOVE ME!!!
7530 /*-----------------------------------------------------------------*/
7531 /* AccAXRsh - right shift a:x known count (0..7)                   */
7532 /*-----------------------------------------------------------------*/
7533 static void
7534 AccAXRsh (char *x, int shCount)
7535 {
7536   switch (shCount)
7537     {
7538     case 0:
7539       break;
7540     case 1:
7541       CLRC;
7542       AccAXRrl1 (x);            // 0->a:x
7543
7544       break;
7545     case 2:
7546       CLRC;
7547       AccAXRrl1 (x);            // 0->a:x
7548
7549       CLRC;
7550       AccAXRrl1 (x);            // 0->a:x
7551
7552       break;
7553     case 3:
7554     case 4:
7555     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7556
7557       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7558
7559       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7560
7561       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7562
7563       emitcode ("anl", "a,#!constbyte",
7564                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7565
7566       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7567
7568       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7569
7570       emitcode ("anl", "a,#!constbyte",
7571                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7572
7573       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7574
7575       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7576
7577       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7578
7579       break;
7580     case 6:                     // AABBBBBB:CCDDDDDD
7581
7582       emitcode ("mov", "c,acc.7");
7583       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7584
7585       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7586
7587       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7588
7589       emitcode ("anl", "a,#!constbyte",
7590                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7591
7592       break;
7593     case 7:                     // ABBBBBBB:CDDDDDDD
7594
7595       emitcode ("mov", "c,acc.7");      // c = A
7596
7597       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7598
7599       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7600
7601       emitcode ("anl", "a,#!constbyte",
7602                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7603
7604       break;
7605     default:
7606       break;
7607     }
7608 }
7609 #endif
7610
7611 #ifdef BETTER_LITERAL_SHIFT
7612 /*-----------------------------------------------------------------*/
7613 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7614 /*-----------------------------------------------------------------*/
7615 static void
7616 AccAXRshS (char *x, int shCount)
7617 {
7618   symbol *tlbl;
7619   switch (shCount)
7620     {
7621     case 0:
7622       break;
7623     case 1:
7624       emitcode ("mov", "c,acc.7");
7625       AccAXRrl1 (x);            // s->a:x
7626
7627       break;
7628     case 2:
7629       emitcode ("mov", "c,acc.7");
7630       AccAXRrl1 (x);            // s->a:x
7631
7632       emitcode ("mov", "c,acc.7");
7633       AccAXRrl1 (x);            // s->a:x
7634
7635       break;
7636     case 3:
7637     case 4:
7638     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7639
7640       tlbl = newiTempLabel (NULL);
7641       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7642
7643       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7644
7645       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7646
7647       emitcode ("anl", "a,#!constbyte",
7648                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7649
7650       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7651
7652       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7653
7654       emitcode ("anl", "a,#!constbyte",
7655                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7656
7657       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7658
7659       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7660
7661       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7662
7663       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7664       emitcode ("orl", "a,#!constbyte",
7665                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7666
7667       emitcode ("", "!tlabeldef", tlbl->key + 100);
7668       break;                    // SSSSAAAA:BBBCCCCC
7669
7670     case 6:                     // AABBBBBB:CCDDDDDD
7671
7672       tlbl = newiTempLabel (NULL);
7673       emitcode ("mov", "c,acc.7");
7674       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7675
7676       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7677
7678       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7679
7680       emitcode ("anl", "a,#!constbyte",
7681                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7682
7683       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7684       emitcode ("orl", "a,#!constbyte",
7685                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7686
7687       emitcode ("", "!tlabeldef", tlbl->key + 100);
7688       break;
7689     case 7:                     // ABBBBBBB:CDDDDDDD
7690
7691       tlbl = newiTempLabel (NULL);
7692       emitcode ("mov", "c,acc.7");      // c = A
7693
7694       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7695
7696       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7697
7698       emitcode ("anl", "a,#!constbyte",
7699                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7700
7701       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7702       emitcode ("orl", "a,#!constbyte",
7703                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7704
7705       emitcode ("", "!tlabeldef", tlbl->key + 100);
7706       break;
7707     default:
7708       break;
7709     }
7710 }
7711 #endif
7712
7713 #ifdef BETTER_LITERAL_SHIFT
7714 static void
7715 _loadLeftIntoAx(char    **lsb, 
7716                 operand *left, 
7717                 operand *result,
7718                 int     offl,
7719                 int     offr)
7720 {
7721   // Get the initial value from left into a pair of registers.
7722   // MSB must be in A, LSB can be any register.
7723   //
7724   // If the result is held in registers, it is an optimization
7725   // if the LSB can be held in the register which will hold the,
7726   // result LSB since this saves us from having to copy it into
7727   // the result following AccAXLsh.
7728   //
7729   // If the result is addressed indirectly, this is not a gain.
7730   if (AOP_NEEDSACC(result))
7731   {
7732        char *leftByte;
7733        
7734        _startLazyDPSEvaluation();
7735       if (AOP_TYPE(left) == AOP_DPTR2)
7736        {
7737            // Get MSB in A.
7738            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7739            // get LSB in DP2_RESULT_REG.
7740            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7741            assert(!strcmp(leftByte, DP2_RESULT_REG));
7742        }
7743        else
7744        {
7745            // get LSB into DP2_RESULT_REG
7746            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7747            if (strcmp(leftByte, DP2_RESULT_REG))
7748            {
7749                TR_AP("#7");
7750                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7751            }
7752            // And MSB in A.
7753            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7754            assert(strcmp(leftByte, DP2_RESULT_REG));
7755            MOVA(leftByte);
7756        }
7757        _endLazyDPSEvaluation();
7758        *lsb = DP2_RESULT_REG;
7759   }
7760   else
7761   {
7762       if (sameRegs (AOP (result), AOP (left)) &&
7763         ((offl + MSB16) == offr))
7764       {
7765           /* don't crash result[offr] */
7766           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7767           emitcode ("xch", "a,%s", 
7768                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7769       }
7770       else
7771       {
7772           movLeft2Result (left, offl, result, offr, 0);
7773           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7774       }
7775       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7776       assert(strcmp(*lsb,"a"));      
7777   }
7778 }
7779
7780 static void
7781 _storeAxResults(char    *lsb,
7782                 operand *result,
7783                 int     offr)
7784 {
7785   _startLazyDPSEvaluation();
7786   if (AOP_NEEDSACC(result))
7787   {
7788       /* We have to explicitly update the result LSB.
7789        */
7790       emitcode("xch","a,%s", lsb);
7791       aopPut(AOP(result), "a", offr);
7792       emitcode("mov","a,%s", lsb);
7793   }
7794   if (getDataSize (result) > 1)
7795   {
7796       aopPut (AOP (result), "a", offr + MSB16);
7797   }
7798   _endLazyDPSEvaluation();
7799 }
7800
7801 /*-----------------------------------------------------------------*/
7802 /* shiftL2Left2Result - shift left two bytes from left to result   */
7803 /*-----------------------------------------------------------------*/
7804 static void
7805 shiftL2Left2Result (operand * left, int offl,
7806                     operand * result, int offr, int shCount)
7807 {
7808   char *lsb;
7809
7810   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7811   
7812   AccAXLsh (lsb, shCount);
7813   
7814   _storeAxResults(lsb, result, offr);
7815 }
7816 #endif
7817
7818 #ifdef BETTER_LITERAL_SHIFT
7819 /*-----------------------------------------------------------------*/
7820 /* shiftR2Left2Result - shift right two bytes from left to result  */
7821 /*-----------------------------------------------------------------*/
7822 static void
7823 shiftR2Left2Result (operand * left, int offl,
7824                     operand * result, int offr,
7825                     int shCount, int sign)
7826 {
7827   char *lsb;
7828   
7829   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7830   
7831   /* a:x >> shCount (x = lsb(result)) */
7832   if (sign)
7833   {
7834      AccAXRshS(lsb, shCount);
7835   }
7836   else
7837   {
7838     AccAXRsh(lsb, shCount);
7839   }
7840   
7841   _storeAxResults(lsb, result, offr);
7842 }
7843 #endif
7844
7845 #if 0
7846 //REMOVE ME!!!
7847 /*-----------------------------------------------------------------*/
7848 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7849 /*-----------------------------------------------------------------*/
7850 static void
7851 shiftLLeftOrResult (operand * left, int offl,
7852                     operand * result, int offr, int shCount)
7853 {
7854   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7855   /* shift left accumulator */
7856   AccLsh (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 #if 0
7865 //REMOVE ME!!!
7866 /*-----------------------------------------------------------------*/
7867 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7868 /*-----------------------------------------------------------------*/
7869 static void
7870 shiftRLeftOrResult (operand * left, int offl,
7871                     operand * result, int offr, int shCount)
7872 {
7873   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7874   /* shift right accumulator */
7875   AccRsh (shCount);
7876   /* or with result */
7877   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7878   /* back to result */
7879   aopPut (AOP (result), "a", offr);
7880 }
7881 #endif
7882
7883 #ifdef BETTER_LITERAL_SHIFT
7884 /*-----------------------------------------------------------------*/
7885 /* genlshOne - left shift a one byte quantity by known count       */
7886 /*-----------------------------------------------------------------*/
7887 static void
7888 genlshOne (operand * result, operand * left, int shCount)
7889 {
7890   D (emitcode (";", "genlshOne "););
7891   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7892 }
7893 #endif
7894
7895 #ifdef BETTER_LITERAL_SHIFT
7896 /*-----------------------------------------------------------------*/
7897 /* genlshTwo - left shift two bytes by known amount != 0           */
7898 /*-----------------------------------------------------------------*/
7899 static void
7900 genlshTwo (operand * result, operand * left, int shCount)
7901 {
7902   int size;
7903
7904   D (emitcode (";", "genlshTwo "););
7905
7906   size = getDataSize (result);
7907
7908   /* if shCount >= 8 */
7909   if (shCount >= 8)
7910   {
7911       shCount -= 8;
7912
7913       _startLazyDPSEvaluation();
7914
7915       if (size > 1)
7916         {
7917           if (shCount)
7918           {
7919             _endLazyDPSEvaluation();
7920             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7921             aopPut (AOP (result), zero, LSB);       
7922           }
7923           else
7924           {
7925             movLeft2Result (left, LSB, result, MSB16, 0);
7926             aopPut (AOP (result), zero, LSB);
7927             _endLazyDPSEvaluation();
7928           }
7929         }
7930         else
7931         {
7932           aopPut (AOP (result), zero, LSB);
7933           _endLazyDPSEvaluation();
7934         }
7935   }
7936
7937   /*  1 <= shCount <= 7 */
7938   else
7939     {
7940       if (size == 1)
7941       {
7942         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7943       }
7944       else
7945       {
7946         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7947       }
7948     }
7949 }
7950 #endif
7951
7952 #if 0
7953 //REMOVE ME!!!
7954 /*-----------------------------------------------------------------*/
7955 /* shiftLLong - shift left one long from left to result            */
7956 /* offl = LSB or MSB16                                             */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 shiftLLong (operand * left, operand * result, int offr)
7960 {
7961   char *l;
7962   int size = AOP_SIZE (result);
7963
7964   if (size >= LSB + offr)
7965     {
7966       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7967       MOVA (l);
7968       emitcode ("add", "a,acc");
7969       if (sameRegs (AOP (left), AOP (result)) &&
7970           size >= MSB16 + offr && offr != LSB)
7971         emitcode ("xch", "a,%s",
7972                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7973       else
7974         aopPut (AOP (result), "a", LSB + offr);
7975     }
7976
7977   if (size >= MSB16 + offr)
7978     {
7979       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7980         {
7981           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7982           MOVA (l);
7983         }
7984       emitcode ("rlc", "a");
7985       if (sameRegs (AOP (left), AOP (result)) &&
7986           size >= MSB24 + offr && offr != LSB)
7987         emitcode ("xch", "a,%s",
7988                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7989       else
7990         aopPut (AOP (result), "a", MSB16 + offr);
7991     }
7992
7993   if (size >= MSB24 + offr)
7994     {
7995       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7996         {
7997           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7998           MOVA (l);
7999         }
8000       emitcode ("rlc", "a");
8001       if (sameRegs (AOP (left), AOP (result)) &&
8002           size >= MSB32 + offr && offr != LSB)
8003         emitcode ("xch", "a,%s",
8004                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
8005       else
8006         aopPut (AOP (result), "a", MSB24 + offr);
8007     }
8008
8009   if (size > MSB32 + offr)
8010     {
8011       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8012         {
8013           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
8014           MOVA (l);
8015         }
8016       emitcode ("rlc", "a");
8017       aopPut (AOP (result), "a", MSB32 + offr);
8018     }
8019   if (offr != LSB)
8020     aopPut (AOP (result), zero, LSB);
8021 }
8022 #endif
8023
8024 #if 0
8025 //REMOVE ME!!!
8026 /*-----------------------------------------------------------------*/
8027 /* genlshFour - shift four byte by a known amount != 0             */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 genlshFour (operand * result, operand * left, int shCount)
8031 {
8032   int size;
8033
8034   D (emitcode (";", "genlshFour ");
8035     );
8036
8037   size = AOP_SIZE (result);
8038
8039   /* if shifting more that 3 bytes */
8040   if (shCount >= 24)
8041     {
8042       shCount -= 24;
8043       if (shCount)
8044         /* lowest order of left goes to the highest
8045            order of the destination */
8046         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8047       else
8048         movLeft2Result (left, LSB, result, MSB32, 0);
8049       aopPut (AOP (result), zero, LSB);
8050       aopPut (AOP (result), zero, MSB16);
8051       aopPut (AOP (result), zero, MSB24);
8052       return;
8053     }
8054
8055   /* more than two bytes */
8056   else if (shCount >= 16)
8057     {
8058       /* lower order two bytes goes to higher order two bytes */
8059       shCount -= 16;
8060       /* if some more remaining */
8061       if (shCount)
8062         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8063       else
8064         {
8065           movLeft2Result (left, MSB16, result, MSB32, 0);
8066           movLeft2Result (left, LSB, result, MSB24, 0);
8067         }
8068       aopPut (AOP (result), zero, MSB16);
8069       aopPut (AOP (result), zero, LSB);
8070       return;
8071     }
8072
8073   /* if more than 1 byte */
8074   else if (shCount >= 8)
8075     {
8076       /* lower order three bytes goes to higher order  three bytes */
8077       shCount -= 8;
8078       if (size == 2)
8079         {
8080           if (shCount)
8081             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8082           else
8083             movLeft2Result (left, LSB, result, MSB16, 0);
8084         }
8085       else
8086         {                       /* size = 4 */
8087           if (shCount == 0)
8088             {
8089               movLeft2Result (left, MSB24, result, MSB32, 0);
8090               movLeft2Result (left, MSB16, result, MSB24, 0);
8091               movLeft2Result (left, LSB, result, MSB16, 0);
8092               aopPut (AOP (result), zero, LSB);
8093             }
8094           else if (shCount == 1)
8095             shiftLLong (left, result, MSB16);
8096           else
8097             {
8098               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8099               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8100               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8101               aopPut (AOP (result), zero, LSB);
8102             }
8103         }
8104     }
8105
8106   /* 1 <= shCount <= 7 */
8107   else if (shCount <= 2)
8108     {
8109       shiftLLong (left, result, LSB);
8110       if (shCount == 2)
8111         shiftLLong (result, result, LSB);
8112     }
8113   /* 3 <= shCount <= 7, optimize */
8114   else
8115     {
8116       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8117       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8118       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8119     }
8120 }
8121 #endif
8122
8123 #ifdef BETTER_LITERAL_SHIFT
8124 /*-----------------------------------------------------------------*/
8125 /* genLeftShiftLiteral - left shifting by known count              */
8126 /*-----------------------------------------------------------------*/
8127 static bool
8128 genLeftShiftLiteral (operand * left,
8129                      operand * right,
8130                      operand * result,
8131                      iCode * ic)
8132 {
8133   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8134   int size;
8135
8136   size = getSize (operandType (result));
8137
8138   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8139
8140   /* We only handle certain easy cases so far. */
8141   if ((shCount != 0)
8142    && (shCount < (size * 8))
8143    && (size != 1)
8144    && (size != 2))
8145   {
8146       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8147       return FALSE;
8148   }
8149
8150   freeAsmop (right, NULL, ic, TRUE);
8151
8152   aopOp(left, ic, FALSE, FALSE);
8153   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
8154
8155 #if 0 // debug spew
8156   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8157   {
8158         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8159         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8160         {
8161            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8162         }
8163   }
8164   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8165   {
8166         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8167         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8168         {
8169            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8170         }       
8171   }  
8172 #endif
8173   
8174 #if VIEW_SIZE
8175   emitcode ("; shift left ", "result %d, left %d", size,
8176             AOP_SIZE (left));
8177 #endif
8178
8179   /* I suppose that the left size >= result size */
8180   if (shCount == 0)
8181   {
8182         _startLazyDPSEvaluation();
8183         while (size--)
8184         {
8185           movLeft2Result (left, size, result, size, 0);
8186         }
8187         _endLazyDPSEvaluation();
8188   }
8189   else if (shCount >= (size * 8))
8190   {
8191     _startLazyDPSEvaluation();
8192     while (size--)
8193     {
8194       aopPut (AOP (result), zero, size);
8195     }
8196     _endLazyDPSEvaluation();
8197   }
8198   else
8199   {
8200       switch (size)
8201         {
8202         case 1:
8203           genlshOne (result, left, shCount);
8204           break;
8205
8206         case 2:
8207           genlshTwo (result, left, shCount);
8208           break;
8209 #if 0
8210         case 4:
8211           genlshFour (result, left, shCount);
8212           break;
8213 #endif
8214         default:
8215           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8216           break;
8217         }
8218     }
8219   freeAsmop (left, NULL, ic, TRUE);
8220   freeAsmop (result, NULL, ic, TRUE);
8221   return TRUE;
8222 }
8223 #endif
8224
8225 /*-----------------------------------------------------------------*/
8226 /* genLeftShift - generates code for left shifting                 */
8227 /*-----------------------------------------------------------------*/
8228 static void
8229 genLeftShift (iCode * ic)
8230 {
8231   operand *left, *right, *result;
8232   int size, offset;
8233   char *l;
8234   symbol *tlbl, *tlbl1;
8235
8236   D (emitcode (";", "genLeftShift "););
8237
8238   right = IC_RIGHT (ic);
8239   left = IC_LEFT (ic);
8240   result = IC_RESULT (ic);
8241
8242   aopOp (right, ic, FALSE, FALSE);
8243
8244
8245 #ifdef BETTER_LITERAL_SHIFT
8246   /* if the shift count is known then do it
8247      as efficiently as possible */
8248   if (AOP_TYPE (right) == AOP_LIT)
8249     {
8250       if (genLeftShiftLiteral (left, right, result, ic))
8251       {
8252         return;
8253       }
8254     }
8255 #endif
8256
8257   /* shift count is unknown then we have to form
8258      a loop get the loop count in B : Note: we take
8259      only the lower order byte since shifting
8260      more that 32 bits make no sense anyway, ( the
8261      largest size of an object can be only 32 bits ) */
8262
8263   if (AOP_TYPE (right) == AOP_LIT)
8264   {
8265       /* Really should be handled by genLeftShiftLiteral,
8266        * but since I'm too lazy to fix that today, at least we can make
8267        * some small improvement.
8268        */
8269        emitcode("mov", "b,#!constbyte",
8270                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8271   }
8272   else
8273   {
8274         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8275         emitcode ("inc", "b");
8276   }
8277   freeAsmop (right, NULL, ic, TRUE);
8278   aopOp (left, ic, FALSE, FALSE);
8279   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8280
8281   /* now move the left to the result if they are not the
8282      same */
8283   if (!sameRegs (AOP (left), AOP (result)) &&
8284       AOP_SIZE (result) > 1)
8285     {
8286
8287       size = AOP_SIZE (result);
8288       offset = 0;
8289       _startLazyDPSEvaluation ();
8290       while (size--)
8291         {
8292           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8293           if (*l == '@' && (IS_AOP_PREG (result)))
8294             {
8295
8296               emitcode ("mov", "a,%s", l);
8297               aopPut (AOP (result), "a", offset);
8298             }
8299           else
8300             aopPut (AOP (result), l, offset);
8301           offset++;
8302         }
8303       _endLazyDPSEvaluation ();
8304     }
8305
8306   tlbl = newiTempLabel (NULL);
8307   size = AOP_SIZE (result);
8308   offset = 0;
8309   tlbl1 = newiTempLabel (NULL);
8310
8311   /* if it is only one byte then */
8312   if (size == 1)
8313     {
8314       symbol *tlbl1 = newiTempLabel (NULL);
8315
8316       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8317       MOVA (l);
8318       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8319       emitcode ("", "!tlabeldef", tlbl->key + 100);
8320       emitcode ("add", "a,acc");
8321       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8322       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8323       aopPut (AOP (result), "a", 0);
8324       goto release;
8325     }
8326
8327   reAdjustPreg (AOP (result));
8328
8329   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8330   emitcode ("", "!tlabeldef", tlbl->key + 100);
8331   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8332   MOVA (l);
8333   emitcode ("add", "a,acc");
8334   aopPut (AOP (result), "a", offset++);
8335   _startLazyDPSEvaluation ();
8336   while (--size)
8337     {
8338       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8339       MOVA (l);
8340       emitcode ("rlc", "a");
8341       aopPut (AOP (result), "a", offset++);
8342     }
8343   _endLazyDPSEvaluation ();
8344   reAdjustPreg (AOP (result));
8345
8346   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8347   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8348 release:
8349   freeAsmop (left, NULL, ic, TRUE);
8350   freeAsmop (result, NULL, ic, TRUE);
8351 }
8352
8353 #ifdef BETTER_LITERAL_SHIFT
8354 /*-----------------------------------------------------------------*/
8355 /* genrshOne - right shift a one byte quantity by known count      */
8356 /*-----------------------------------------------------------------*/
8357 static void
8358 genrshOne (operand * result, operand * left,
8359            int shCount, int sign)
8360 {
8361   D (emitcode (";", "genrshOne"););
8362   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8363 }
8364 #endif
8365
8366 #ifdef BETTER_LITERAL_SHIFT
8367 /*-----------------------------------------------------------------*/
8368 /* genrshTwo - right shift two bytes by known amount != 0          */
8369 /*-----------------------------------------------------------------*/
8370 static void
8371 genrshTwo (operand * result, operand * left,
8372            int shCount, int sign)
8373 {
8374   D (emitcode (";", "genrshTwo"););
8375
8376   /* if shCount >= 8 */
8377   if (shCount >= 8)
8378     {
8379       shCount -= 8;
8380       _startLazyDPSEvaluation();
8381       if (shCount)
8382       {
8383         shiftR1Left2Result (left, MSB16, result, LSB,
8384                             shCount, sign);
8385       }                     
8386       else
8387       {
8388         movLeft2Result (left, MSB16, result, LSB, sign);
8389       }
8390       addSign (result, MSB16, sign);
8391       _endLazyDPSEvaluation();
8392     }
8393
8394   /*  1 <= shCount <= 7 */
8395   else
8396   {
8397     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8398   }
8399 }
8400 #endif
8401
8402 #if 0
8403 //REMOVE ME!!!
8404 /*-----------------------------------------------------------------*/
8405 /* shiftRLong - shift right one long from left to result           */
8406 /* offl = LSB or MSB16                                             */
8407 /*-----------------------------------------------------------------*/
8408 static void
8409 shiftRLong (operand * left, int offl,
8410             operand * result, int sign)
8411 {
8412   int isSameRegs=sameRegs(AOP(left),AOP(result));
8413
8414   if (isSameRegs && offl>1) {
8415     // we are in big trouble, but this shouldn't happen
8416     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8417   }
8418
8419   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8420   
8421   if (offl==MSB16) {
8422     // shift is > 8
8423     if (sign) {
8424       emitcode ("rlc", "a");
8425       emitcode ("subb", "a,acc");
8426       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8427     } else {
8428       aopPut (AOP(result), zero, MSB32);
8429     }
8430   }
8431
8432   if (!sign) {
8433     emitcode ("clr", "c");
8434   } else {
8435     emitcode ("mov", "c,acc.7");
8436   }
8437
8438   emitcode ("rrc", "a");
8439
8440   if (isSameRegs && offl==MSB16) {
8441     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8442   } else {
8443     aopPut (AOP (result), "a", MSB32);
8444     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8445   }
8446
8447   emitcode ("rrc", "a");
8448   if (isSameRegs && offl==1) {
8449     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8450   } else {
8451     aopPut (AOP (result), "a", MSB24);
8452     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8453   }
8454   emitcode ("rrc", "a");
8455   aopPut (AOP (result), "a", MSB16 - offl);
8456
8457   if (offl == LSB)
8458     {
8459       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8460       emitcode ("rrc", "a");
8461       aopPut (AOP (result), "a", LSB);
8462     }
8463 }
8464 #endif
8465
8466 #if 0
8467 //REMOVE ME!!!
8468 /*-----------------------------------------------------------------*/
8469 /* genrshFour - shift four byte by a known amount != 0             */
8470 /*-----------------------------------------------------------------*/
8471 static void
8472 genrshFour (operand * result, operand * left,
8473             int shCount, int sign)
8474 {
8475   D (emitcode (";", "genrshFour");
8476     );
8477
8478   /* if shifting more that 3 bytes */
8479   if (shCount >= 24)
8480     {
8481       shCount -= 24;
8482       if (shCount)
8483         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8484       else
8485         movLeft2Result (left, MSB32, result, LSB, sign);
8486       addSign (result, MSB16, sign);
8487     }
8488   else if (shCount >= 16)
8489     {
8490       shCount -= 16;
8491       if (shCount)
8492         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8493       else
8494         {
8495           movLeft2Result (left, MSB24, result, LSB, 0);
8496           movLeft2Result (left, MSB32, result, MSB16, sign);
8497         }
8498       addSign (result, MSB24, sign);
8499     }
8500   else if (shCount >= 8)
8501     {
8502       shCount -= 8;
8503       if (shCount == 1)
8504         shiftRLong (left, MSB16, result, sign);
8505       else if (shCount == 0)
8506         {
8507           movLeft2Result (left, MSB16, result, LSB, 0);
8508           movLeft2Result (left, MSB24, result, MSB16, 0);
8509           movLeft2Result (left, MSB32, result, MSB24, sign);
8510           addSign (result, MSB32, sign);
8511         }
8512       else
8513         {
8514           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8515           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8516           /* the last shift is signed */
8517           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8518           addSign (result, MSB32, sign);
8519         }
8520     }
8521   else
8522     {                           /* 1 <= shCount <= 7 */
8523       if (shCount <= 2)
8524         {
8525           shiftRLong (left, LSB, result, sign);
8526           if (shCount == 2)
8527             shiftRLong (result, LSB, result, sign);
8528         }
8529       else
8530         {
8531           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8532           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8533           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8534         }
8535     }
8536 }
8537 #endif
8538
8539 #ifdef BETTER_LITERAL_SHIFT
8540 /*-----------------------------------------------------------------*/
8541 /* genRightShiftLiteral - right shifting by known count            */
8542 /*-----------------------------------------------------------------*/
8543 static bool
8544 genRightShiftLiteral (operand * left,
8545                       operand * right,
8546                       operand * result,
8547                       iCode * ic,
8548                       int sign)
8549 {
8550   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8551   int size;
8552
8553   size = getSize (operandType (result));
8554
8555   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8556
8557   /* We only handle certain easy cases so far. */
8558   if ((shCount != 0)
8559    && (shCount < (size * 8))
8560    && (size != 1)
8561    && (size != 2))
8562   {
8563       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8564       return FALSE;
8565   }
8566
8567   freeAsmop (right, NULL, ic, TRUE);
8568
8569   aopOp (left, ic, FALSE, FALSE);
8570   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8571
8572 #if VIEW_SIZE
8573   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8574             AOP_SIZE (left));
8575 #endif
8576
8577   /* test the LEFT size !!! */
8578
8579   /* I suppose that the left size >= result size */
8580   if (shCount == 0)
8581   {
8582       size = getDataSize (result);
8583       _startLazyDPSEvaluation();
8584       while (size--)
8585       {
8586         movLeft2Result (left, size, result, size, 0);
8587       }
8588       _endLazyDPSEvaluation();
8589   }
8590   else if (shCount >= (size * 8))
8591     {
8592       if (sign)
8593       {
8594         /* get sign in acc.7 */
8595         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8596       }
8597       addSign (result, LSB, sign);
8598     }
8599   else
8600     {
8601       switch (size)
8602         {
8603         case 1:
8604           genrshOne (result, left, shCount, sign);
8605           break;
8606
8607         case 2:
8608           genrshTwo (result, left, shCount, sign);
8609           break;
8610 #if 0
8611         case 4:
8612           genrshFour (result, left, shCount, sign);
8613           break;
8614 #endif    
8615         default:
8616           break;
8617         }
8618     }
8619   freeAsmop (left, NULL, ic, TRUE);
8620   freeAsmop (result, NULL, ic, TRUE);
8621   
8622   return TRUE;
8623 }
8624 #endif
8625
8626 /*-----------------------------------------------------------------*/
8627 /* genSignedRightShift - right shift of signed number              */
8628 /*-----------------------------------------------------------------*/
8629 static void
8630 genSignedRightShift (iCode * ic)
8631 {
8632   operand *right, *left, *result;
8633   int size, offset;
8634   char *l;
8635   symbol *tlbl, *tlbl1;
8636
8637   D (emitcode (";", "genSignedRightShift "););
8638
8639   /* we do it the hard way put the shift count in b
8640      and loop thru preserving the sign */
8641
8642   right = IC_RIGHT (ic);
8643   left = IC_LEFT (ic);
8644   result = IC_RESULT (ic);
8645
8646   aopOp (right, ic, FALSE, FALSE);
8647
8648 #ifdef BETTER_LITERAL_SHIFT
8649   if (AOP_TYPE (right) == AOP_LIT)
8650     {
8651       if (genRightShiftLiteral (left, right, result, ic, 1))
8652       {
8653         return;
8654       }
8655     }
8656 #endif
8657   /* shift count is unknown then we have to form
8658      a loop get the loop count in B : Note: we take
8659      only the lower order byte since shifting
8660      more that 32 bits make no sense anyway, ( the
8661      largest size of an object can be only 32 bits ) */
8662
8663   if (AOP_TYPE (right) == AOP_LIT)
8664   {
8665       /* Really should be handled by genRightShiftLiteral,
8666        * but since I'm too lazy to fix that today, at least we can make
8667        * some small improvement.
8668        */
8669        emitcode("mov", "b,#!constbyte",
8670                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8671   }
8672   else
8673   {
8674         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8675         emitcode ("inc", "b");
8676   }
8677   freeAsmop (right, NULL, ic, TRUE);
8678   aopOp (left, ic, FALSE, FALSE);
8679   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8680
8681   /* now move the left to the result if they are not the
8682      same */
8683   if (!sameRegs (AOP (left), AOP (result)) &&
8684       AOP_SIZE (result) > 1)
8685     {
8686
8687       size = AOP_SIZE (result);
8688       offset = 0;
8689       _startLazyDPSEvaluation ();
8690       while (size--)
8691         {
8692           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8693           if (*l == '@' && IS_AOP_PREG (result))
8694             {
8695
8696               emitcode ("mov", "a,%s", l);
8697               aopPut (AOP (result), "a", offset);
8698             }
8699           else
8700             aopPut (AOP (result), l, offset);
8701           offset++;
8702         }
8703       _endLazyDPSEvaluation ();
8704     }
8705
8706   /* mov the highest order bit to OVR */
8707   tlbl = newiTempLabel (NULL);
8708   tlbl1 = newiTempLabel (NULL);
8709
8710   size = AOP_SIZE (result);
8711   offset = size - 1;
8712   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8713   emitcode ("rlc", "a");
8714   emitcode ("mov", "ov,c");
8715   /* if it is only one byte then */
8716   if (size == 1)
8717     {
8718       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8719       MOVA (l);
8720       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8721       emitcode ("", "!tlabeldef", tlbl->key + 100);
8722       emitcode ("mov", "c,ov");
8723       emitcode ("rrc", "a");
8724       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8725       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8726       aopPut (AOP (result), "a", 0);
8727       goto release;
8728     }
8729
8730   reAdjustPreg (AOP (result));
8731   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8732   emitcode ("", "!tlabeldef", tlbl->key + 100);
8733   emitcode ("mov", "c,ov");
8734   _startLazyDPSEvaluation ();
8735   while (size--)
8736     {
8737       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8738       MOVA (l);
8739       emitcode ("rrc", "a");
8740       aopPut (AOP (result), "a", offset--);
8741     }
8742   _endLazyDPSEvaluation ();
8743   reAdjustPreg (AOP (result));
8744   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8745   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8746
8747 release:
8748   freeAsmop (left, NULL, ic, TRUE);
8749   freeAsmop (result, NULL, ic, TRUE);
8750 }
8751
8752 /*-----------------------------------------------------------------*/
8753 /* genRightShift - generate code for right shifting                */
8754 /*-----------------------------------------------------------------*/
8755 static void
8756 genRightShift (iCode * ic)
8757 {
8758   operand *right, *left, *result;
8759   sym_link *retype;
8760   int size, offset;
8761   char *l;
8762   symbol *tlbl, *tlbl1;
8763
8764   D (emitcode (";", "genRightShift "););
8765
8766   /* if signed then we do it the hard way preserve the
8767      sign bit moving it inwards */
8768   retype = getSpec (operandType (IC_RESULT (ic)));
8769
8770   if (!SPEC_USIGN (retype))
8771     {
8772       genSignedRightShift (ic);
8773       return;
8774     }
8775
8776   /* signed & unsigned types are treated the same : i.e. the
8777      signed is NOT propagated inwards : quoting from the
8778      ANSI - standard : "for E1 >> E2, is equivalent to division
8779      by 2**E2 if unsigned or if it has a non-negative value,
8780      otherwise the result is implementation defined ", MY definition
8781      is that the sign does not get propagated */
8782
8783   right = IC_RIGHT (ic);
8784   left = IC_LEFT (ic);
8785   result = IC_RESULT (ic);
8786
8787   aopOp (right, ic, FALSE, FALSE);
8788
8789 #ifdef BETTER_LITERAL_SHIFT
8790   /* if the shift count is known then do it
8791      as efficiently as possible */
8792   if (AOP_TYPE (right) == AOP_LIT)
8793     {
8794       if (genRightShiftLiteral (left, right, result, ic, 0))
8795       {
8796         return;
8797       }
8798     }
8799 #endif
8800
8801   /* shift count is unknown then we have to form
8802      a loop get the loop count in B : Note: we take
8803      only the lower order byte since shifting
8804      more that 32 bits make no sense anyway, ( the
8805      largest size of an object can be only 32 bits ) */
8806   
8807   if (AOP_TYPE (right) == AOP_LIT)
8808   {
8809       /* Really should be handled by genRightShiftLiteral,
8810        * but since I'm too lazy to fix that today, at least we can make
8811        * some small improvement.
8812        */
8813        emitcode("mov", "b,#!constbyte",
8814                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8815   }
8816   else
8817   {
8818         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8819         emitcode ("inc", "b");
8820   }
8821   freeAsmop (right, NULL, ic, TRUE);
8822   aopOp (left, ic, FALSE, FALSE);
8823   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8824
8825   /* now move the left to the result if they are not the
8826      same */
8827   if (!sameRegs (AOP (left), AOP (result)) &&
8828       AOP_SIZE (result) > 1)
8829     {
8830
8831       size = AOP_SIZE (result);
8832       offset = 0;
8833       _startLazyDPSEvaluation ();
8834       while (size--)
8835         {
8836           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8837           if (*l == '@' && IS_AOP_PREG (result))
8838             {
8839
8840               emitcode ("mov", "a,%s", l);
8841               aopPut (AOP (result), "a", offset);
8842             }
8843           else
8844             aopPut (AOP (result), l, offset);
8845           offset++;
8846         }
8847       _endLazyDPSEvaluation ();
8848     }
8849
8850   tlbl = newiTempLabel (NULL);
8851   tlbl1 = newiTempLabel (NULL);
8852   size = AOP_SIZE (result);
8853   offset = size - 1;
8854
8855   /* if it is only one byte then */
8856   if (size == 1)
8857     {
8858       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8859       MOVA (l);
8860       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8861       emitcode ("", "!tlabeldef", tlbl->key + 100);
8862       CLRC;
8863       emitcode ("rrc", "a");
8864       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8865       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8866       aopPut (AOP (result), "a", 0);
8867       goto release;
8868     }
8869
8870   reAdjustPreg (AOP (result));
8871   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8872   emitcode ("", "!tlabeldef", tlbl->key + 100);
8873   CLRC;
8874   _startLazyDPSEvaluation ();
8875   while (size--)
8876     {
8877       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8878       MOVA (l);
8879       emitcode ("rrc", "a");
8880       aopPut (AOP (result), "a", offset--);
8881     }
8882   _endLazyDPSEvaluation ();
8883   reAdjustPreg (AOP (result));
8884
8885   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8886   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8887
8888 release:
8889   freeAsmop (left, NULL, ic, TRUE);
8890   freeAsmop (result, NULL, ic, TRUE);
8891 }
8892
8893 /*-----------------------------------------------------------------*/
8894 /* genUnpackBits - generates code for unpacking bits               */
8895 /*-----------------------------------------------------------------*/
8896 static void
8897 genUnpackBits (operand * result, char *rname, int ptype)
8898 {
8899   int shCnt;
8900   int rlen = 0;
8901   sym_link *etype;
8902   int offset = 0;
8903
8904   D (emitcode (";", "genUnpackBits ");
8905     );
8906
8907   etype = getSpec (operandType (result));
8908
8909   /* read the first byte  */
8910   switch (ptype)
8911     {
8912
8913     case POINTER:
8914     case IPOINTER:
8915       emitcode ("mov", "a,@%s", rname);
8916       break;
8917
8918     case PPOINTER:
8919       emitcode ("movx", "a,@%s", rname);
8920       break;
8921
8922     case FPOINTER:
8923       emitcode ("movx", "a,@dptr");
8924       break;
8925
8926     case CPOINTER:
8927       emitcode ("clr", "a");
8928       emitcode ("movc", "a,@a+dptr");
8929       break;
8930
8931     case GPOINTER:
8932       emitcode ("lcall", "__gptrget");
8933       break;
8934     }
8935
8936   /* if we have bitdisplacement then it fits   */
8937   /* into this byte completely or if length is */
8938   /* less than a byte                          */
8939   if ((shCnt = SPEC_BSTR (etype)) ||
8940       (SPEC_BLEN (etype) <= 8))
8941     {
8942
8943       /* shift right acc */
8944       AccRsh (shCnt);
8945
8946       emitcode ("anl", "a,#!constbyte",
8947                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8948       aopPut (AOP (result), "a", offset);
8949       return;
8950     }
8951
8952   /* bit field did not fit in a byte  */
8953   rlen = SPEC_BLEN (etype) - 8;
8954   aopPut (AOP (result), "a", offset++);
8955
8956   while (1)
8957     {
8958
8959       switch (ptype)
8960         {
8961         case POINTER:
8962         case IPOINTER:
8963           emitcode ("inc", "%s", rname);
8964           emitcode ("mov", "a,@%s", rname);
8965           break;
8966
8967         case PPOINTER:
8968           emitcode ("inc", "%s", rname);
8969           emitcode ("movx", "a,@%s", rname);
8970           break;
8971
8972         case FPOINTER:
8973           emitcode ("inc", "dptr");
8974           emitcode ("movx", "a,@dptr");
8975           break;
8976
8977         case CPOINTER:
8978           emitcode ("clr", "a");
8979           emitcode ("inc", "dptr");
8980           emitcode ("movc", "a,@a+dptr");
8981           break;
8982
8983         case GPOINTER:
8984           emitcode ("inc", "dptr");
8985           emitcode ("lcall", "__gptrget");
8986           break;
8987         }
8988
8989       rlen -= 8;
8990       /* if we are done */
8991       if (rlen < 8)
8992         break;
8993
8994       aopPut (AOP (result), "a", offset++);
8995
8996     }
8997
8998   if (rlen)
8999     {
9000       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9001       aopPut (AOP (result), "a", offset);
9002     }
9003
9004   return;
9005 }
9006
9007
9008 /*-----------------------------------------------------------------*/
9009 /* genDataPointerGet - generates code when ptr offset is known     */
9010 /*-----------------------------------------------------------------*/
9011 static void
9012 genDataPointerGet (operand * left,
9013                    operand * result,
9014                    iCode * ic)
9015 {
9016   char *l;
9017   char buff[256];
9018   int size, offset = 0;
9019   aopOp (result, ic, TRUE, FALSE);
9020
9021   /* get the string representation of the name */
9022   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
9023   size = AOP_SIZE (result);
9024   _startLazyDPSEvaluation ();
9025   while (size--)
9026     {
9027         if (offset)
9028         {
9029             SNPRINTF (buff, sizeof(buff), 
9030                       "(%s + %d)", l + 1, offset);
9031         }
9032         else
9033         {
9034             SNPRINTF (buff, sizeof(buff), 
9035                       "%s", l + 1);
9036         }
9037       aopPut (AOP (result), buff, offset++);
9038     }
9039   _endLazyDPSEvaluation ();
9040
9041   freeAsmop (left, NULL, ic, TRUE);
9042   freeAsmop (result, NULL, ic, TRUE);
9043 }
9044
9045 /*-----------------------------------------------------------------*/
9046 /* genNearPointerGet - emitcode for near pointer fetch             */
9047 /*-----------------------------------------------------------------*/
9048 static void
9049 genNearPointerGet (operand * left,
9050                    operand * result,
9051                    iCode * ic,
9052                    iCode *pi)
9053 {
9054   asmop *aop = NULL;
9055   regs *preg = NULL;
9056   char *rname;
9057   sym_link *rtype, *retype, *letype;
9058   sym_link *ltype = operandType (left);
9059   char buff[80];
9060
9061   rtype = operandType (result);
9062   retype = getSpec (rtype);
9063   letype = getSpec (ltype);
9064
9065   aopOp (left, ic, FALSE, FALSE);
9066
9067   /* if left is rematerialisable and
9068      result is not bit variable type and
9069      the left is pointer to data space i.e
9070      lower 128 bytes of space */
9071   if (AOP_TYPE (left) == AOP_IMMD &&
9072       !IS_BITVAR (retype) &&
9073       !IS_BITVAR (letype) &&
9074       DCL_TYPE (ltype) == POINTER)
9075     {
9076       genDataPointerGet (left, result, ic);
9077       return;
9078     }
9079
9080   /* if the value is already in a pointer register
9081      then don't need anything more */
9082   if (!AOP_INPREG (AOP (left)))
9083     {
9084       /* otherwise get a free pointer register */
9085       aop = newAsmop (0);
9086       preg = getFreePtr (ic, &aop, FALSE);
9087       emitcode ("mov", "%s,%s",
9088                 preg->name,
9089                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9090       rname = preg->name;
9091     }
9092   else
9093     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9094
9095   freeAsmop (left, NULL, ic, TRUE);
9096   aopOp (result, ic, FALSE, FALSE);
9097
9098   /* if bitfield then unpack the bits */
9099   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9100     genUnpackBits (result, rname, POINTER);
9101   else
9102     {
9103       /* we have can just get the values */
9104       int size = AOP_SIZE (result);
9105       int offset = 0;
9106
9107       while (size--)
9108         {
9109           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9110             {
9111
9112               emitcode ("mov", "a,@%s", rname);
9113               aopPut (AOP (result), "a", offset);
9114             }
9115           else
9116             {
9117               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9118               aopPut (AOP (result), buff, offset);
9119             }
9120           offset++;
9121           if (size || pi)
9122             {
9123                 emitcode ("inc", "%s", rname);
9124             }
9125         }
9126     }
9127
9128   /* now some housekeeping stuff */
9129   if (aop)
9130     {
9131       /* we had to allocate for this iCode */
9132       if (pi) { /* post increment present */
9133         aopPut(AOP ( left ),rname,0);
9134       }
9135       freeAsmop (NULL, aop, ic, TRUE);
9136     }
9137   else
9138     {
9139       /* we did not allocate which means left
9140          already in a pointer register, then
9141          if size > 0 && this could be used again
9142          we have to point it back to where it
9143          belongs */
9144       if (AOP_SIZE (result) > 1 &&
9145           !OP_SYMBOL (left)->remat &&
9146           (OP_SYMBOL (left)->liveTo > ic->seq ||
9147            ic->depth) &&
9148           !pi)
9149         {
9150           int size = AOP_SIZE (result) - 1;
9151           while (size--)
9152             emitcode ("dec", "%s", rname);
9153         }
9154     }
9155
9156   /* done */
9157   freeAsmop (result, NULL, ic, TRUE);
9158   if (pi) pi->generated = 1;
9159 }
9160
9161 /*-----------------------------------------------------------------*/
9162 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9163 /*-----------------------------------------------------------------*/
9164 static void
9165 genPagedPointerGet (operand * left,
9166                     operand * result,
9167                     iCode * ic,
9168                     iCode * pi)
9169 {
9170   asmop *aop = NULL;
9171   regs *preg = NULL;
9172   char *rname;
9173   sym_link *rtype, *retype, *letype;
9174
9175   rtype = operandType (result);
9176   retype = getSpec (rtype);
9177   letype = getSpec (operandType (left));
9178   aopOp (left, ic, FALSE, FALSE);
9179
9180   /* if the value is already in a pointer register
9181      then don't need anything more */
9182   if (!AOP_INPREG (AOP (left)))
9183     {
9184       /* otherwise get a free pointer register */
9185       aop = newAsmop (0);
9186       preg = getFreePtr (ic, &aop, FALSE);
9187       emitcode ("mov", "%s,%s",
9188                 preg->name,
9189                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
9190       rname = preg->name;
9191     }
9192   else
9193     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
9194
9195   freeAsmop (left, NULL, ic, TRUE);
9196   aopOp (result, ic, FALSE, FALSE);
9197
9198   /* if bitfield then unpack the bits */
9199   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9200     genUnpackBits (result, rname, PPOINTER);
9201   else
9202     {
9203       /* we have can just get the values */
9204       int size = AOP_SIZE (result);
9205       int offset = 0;
9206
9207       while (size--)
9208         {
9209
9210           emitcode ("movx", "a,@%s", rname);
9211           aopPut (AOP (result), "a", offset);
9212
9213           offset++;
9214
9215           if (size || pi)
9216             emitcode ("inc", "%s", rname);
9217         }
9218     }
9219
9220   /* now some housekeeping stuff */
9221   if (aop)
9222     {
9223       /* we had to allocate for this iCode */
9224       if (pi) aopPut ( AOP (left), rname, 0);
9225       freeAsmop (NULL, aop, ic, TRUE);
9226     }
9227   else
9228     {
9229       /* we did not allocate which means left
9230          already in a pointer register, then
9231          if size > 0 && this could be used again
9232          we have to point it back to where it
9233          belongs */
9234       if (AOP_SIZE (result) > 1 &&
9235           !OP_SYMBOL (left)->remat &&
9236           (OP_SYMBOL (left)->liveTo > ic->seq ||
9237            ic->depth) &&
9238           !pi)
9239         {
9240           int size = AOP_SIZE (result) - 1;
9241           while (size--)
9242             emitcode ("dec", "%s", rname);
9243         }
9244     }
9245
9246   /* done */
9247   freeAsmop (result, NULL, ic, TRUE);
9248   if (pi) pi->generated = 1;
9249 }
9250
9251 /*-----------------------------------------------------------------*/
9252 /* genFarPointerGet - gget value from far space                    */
9253 /*-----------------------------------------------------------------*/
9254 static void
9255 genFarPointerGet (operand * left,
9256                   operand * result, iCode * ic, iCode *pi)
9257 {
9258     int size, offset, dopi=1;
9259   sym_link *retype = getSpec (operandType (result));
9260   sym_link *letype = getSpec (operandType (left));
9261   D (emitcode (";", "genFarPointerGet");
9262     );
9263
9264   aopOp (left, ic, FALSE, FALSE);
9265
9266   /* if the operand is already in dptr
9267      then we do nothing else we move the value to dptr */
9268   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9269     {
9270       /* if this is remateriazable */
9271       if (AOP_TYPE (left) == AOP_IMMD)
9272         {
9273           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9274         }
9275       else
9276         {
9277           /* we need to get it byte by byte */
9278           _startLazyDPSEvaluation ();
9279           if (AOP_TYPE (left) != AOP_DPTR)
9280             {
9281               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9282               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9283               if (options.model == MODEL_FLAT24)
9284                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9285             }
9286           else
9287             {
9288               /* We need to generate a load to DPTR indirect through DPTR. */
9289               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9290                 );
9291               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9292               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9293               if (options.model == MODEL_FLAT24)
9294                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9295               emitcode ("pop", "dph");
9296               emitcode ("pop", "dpl");
9297               dopi =0;
9298             }
9299           _endLazyDPSEvaluation ();
9300         }
9301     }
9302   /* so dptr know contains the address */
9303   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9304
9305   /* if bit then unpack */
9306   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9307       if (AOP_INDPTRn(left)) {
9308           genSetDPTR(AOP(left)->aopu.dptr);
9309       }
9310       genUnpackBits (result, "dptr", FPOINTER);
9311       if (AOP_INDPTRn(left)) {
9312           genSetDPTR(0);
9313       }
9314   } else
9315     {
9316       size = AOP_SIZE (result);
9317       offset = 0;
9318
9319       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9320           while (size--) {
9321               genSetDPTR(AOP(left)->aopu.dptr);
9322               emitcode ("movx", "a,@dptr");
9323               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9324                   emitcode ("inc", "dptr");
9325               genSetDPTR (0);
9326               aopPut (AOP (result), "a", offset++);
9327           }
9328       } else {
9329           _startLazyDPSEvaluation ();
9330           while (size--) {
9331               if (AOP_INDPTRn(left)) {
9332                   genSetDPTR(AOP(left)->aopu.dptr);
9333               } else {
9334                   genSetDPTR (0);
9335               }
9336               _flushLazyDPS ();
9337               
9338               emitcode ("movx", "a,@dptr");
9339               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9340                   emitcode ("inc", "dptr");
9341               
9342               aopPut (AOP (result), "a", offset++);
9343           }
9344           _endLazyDPSEvaluation ();
9345       }
9346     }
9347   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9348       if (!AOP_INDPTRn(left)) {
9349           aopPut ( AOP (left), "dpl", 0);
9350           aopPut ( AOP (left), "dph", 1);
9351           if (options.model == MODEL_FLAT24)
9352               aopPut ( AOP (left), "dpx", 2);
9353       }
9354     pi->generated = 1;
9355   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9356              AOP_SIZE(result) > 1 &&
9357              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9358       
9359       size = AOP_SIZE (result) - 1;
9360       if (AOP_INDPTRn(left)) {
9361           genSetDPTR(AOP(left)->aopu.dptr);
9362       }
9363       while (size--) emitcode ("lcall","__decdptr");
9364       if (AOP_INDPTRn(left)) {
9365           genSetDPTR(0);
9366       }
9367   }
9368
9369   freeAsmop (left, NULL, ic, TRUE);
9370   freeAsmop (result, NULL, ic, TRUE);
9371 }
9372
9373 /*-----------------------------------------------------------------*/
9374 /* genCodePointerGet - get value from code space                  */
9375 /*-----------------------------------------------------------------*/
9376 static void
9377 genCodePointerGet (operand * left,
9378                     operand * result, iCode * ic, iCode *pi)
9379 {
9380   int size, offset, dopi=1;
9381   sym_link *retype = getSpec (operandType (result));
9382
9383   aopOp (left, ic, FALSE, FALSE);
9384
9385   /* if the operand is already in dptr
9386      then we do nothing else we move the value to dptr */
9387   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9388     {
9389       /* if this is remateriazable */
9390       if (AOP_TYPE (left) == AOP_IMMD)
9391         {
9392           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9393         }
9394       else
9395         {                       /* we need to get it byte by byte */
9396           _startLazyDPSEvaluation ();
9397           if (AOP_TYPE (left) != AOP_DPTR)
9398             {
9399               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9400               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9401               if (options.model == MODEL_FLAT24)
9402                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9403             }
9404           else
9405             {
9406               /* We need to generate a load to DPTR indirect through DPTR. */
9407               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9408                 );
9409               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9410               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9411               if (options.model == MODEL_FLAT24)
9412                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9413               emitcode ("pop", "dph");
9414               emitcode ("pop", "dpl");
9415               dopi=0;
9416             }
9417           _endLazyDPSEvaluation ();
9418         }
9419     }
9420   /* so dptr know contains the address */
9421   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9422
9423   /* if bit then unpack */
9424   if (IS_BITVAR (retype)) {
9425       if (AOP_INDPTRn(left)) {
9426           genSetDPTR(AOP(left)->aopu.dptr);
9427       }
9428       genUnpackBits (result, "dptr", CPOINTER);
9429       if (AOP_INDPTRn(left)) {
9430           genSetDPTR(0);
9431       }
9432   } else
9433     {
9434       size = AOP_SIZE (result);
9435       offset = 0;
9436       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9437           while (size--) {
9438               genSetDPTR(AOP(left)->aopu.dptr);
9439               emitcode ("clr", "a");
9440               emitcode ("movc", "a,@a+dptr");
9441               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9442                   emitcode ("inc", "dptr");
9443               genSetDPTR (0);
9444               aopPut (AOP (result), "a", offset++);
9445           }
9446       } else {
9447           _startLazyDPSEvaluation ();
9448           while (size--)
9449               {
9450                   if (AOP_INDPTRn(left)) {
9451                       genSetDPTR(AOP(left)->aopu.dptr);
9452                   } else {
9453                       genSetDPTR (0);
9454                   }
9455                   _flushLazyDPS ();
9456                   
9457                   emitcode ("clr", "a");
9458                   emitcode ("movc", "a,@a+dptr");
9459                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9460                       emitcode ("inc", "dptr");
9461                   aopPut (AOP (result), "a", offset++);
9462               }
9463           _endLazyDPSEvaluation ();
9464       }
9465     }
9466   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9467       if (!AOP_INDPTRn(left)) {
9468           aopPut ( AOP (left), "dpl", 0);
9469           aopPut ( AOP (left), "dph", 1);
9470           if (options.model == MODEL_FLAT24)
9471               aopPut ( AOP (left), "dpx", 2);
9472       }
9473       pi->generated = 1;
9474   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9475              AOP_SIZE(result) > 1 &&
9476              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9477       
9478       size = AOP_SIZE (result) - 1;
9479       if (AOP_INDPTRn(left)) {
9480           genSetDPTR(AOP(left)->aopu.dptr);
9481       }
9482       while (size--) emitcode ("lcall","__decdptr");
9483       if (AOP_INDPTRn(left)) {
9484           genSetDPTR(0);
9485       }
9486   }
9487   
9488   freeAsmop (left, NULL, ic, TRUE);
9489   freeAsmop (result, NULL, ic, TRUE);
9490 }
9491
9492 /*-----------------------------------------------------------------*/
9493 /* genGenPointerGet - gget value from generic pointer space        */
9494 /*-----------------------------------------------------------------*/
9495 static void
9496 genGenPointerGet (operand * left,
9497                   operand * result, iCode * ic, iCode * pi)
9498 {
9499   int size, offset;
9500   sym_link *retype = getSpec (operandType (result));
9501   sym_link *letype = getSpec (operandType (left));
9502
9503   D (emitcode (";", "genGenPointerGet "); );
9504
9505   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9506
9507   /* if the operand is already in dptr
9508      then we do nothing else we move the value to dptr */
9509   if (AOP_TYPE (left) != AOP_STR)
9510     {
9511       /* if this is remateriazable */
9512       if (AOP_TYPE (left) == AOP_IMMD)
9513         {
9514           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9515           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9516                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9517           else
9518                   emitcode ("mov", "b,#%d", pointerCode (retype));
9519         }
9520       else
9521         {                       /* we need to get it byte by byte */
9522             _startLazyDPSEvaluation ();
9523             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9524             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9525             if (options.model == MODEL_FLAT24) {
9526                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9527                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9528             } else {
9529                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9530             }
9531             _endLazyDPSEvaluation ();
9532         }
9533     }
9534
9535   /* so dptr-b now contains the address */
9536   _G.bInUse++;
9537   aopOp (result, ic, FALSE, TRUE);
9538   _G.bInUse--;
9539
9540   /* if bit then unpack */
9541   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9542   {
9543     genUnpackBits (result, "dptr", GPOINTER);
9544   }
9545   else
9546     {
9547         size = AOP_SIZE (result);
9548         offset = 0;
9549
9550         while (size--)
9551         {
9552             if (size)
9553             {
9554                 // Get two bytes at a time, results in _AP & A.
9555                 // dptr will be incremented ONCE by __gptrgetWord.
9556                 //
9557                 // Note: any change here must be coordinated
9558                 // with the implementation of __gptrgetWord
9559                 // in device/lib/_gptrget.c
9560                 emitcode ("lcall", "__gptrgetWord");
9561                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9562                 aopPut (AOP (result), "a", offset++);
9563                 size--;
9564             }
9565             else
9566             {
9567                 // Only one byte to get.
9568                 emitcode ("lcall", "__gptrget");
9569                 aopPut (AOP (result), "a", offset++);
9570             }
9571             
9572             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9573             {
9574                 emitcode ("inc", "dptr");
9575             }
9576         }
9577     }
9578
9579   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9580     aopPut ( AOP (left), "dpl", 0);
9581     aopPut ( AOP (left), "dph", 1);
9582     if (options.model == MODEL_FLAT24) {
9583         aopPut ( AOP (left), "dpx", 2);
9584         aopPut ( AOP (left), "b", 3);   
9585     } else  aopPut ( AOP (left), "b", 2);       
9586     pi->generated = 1;
9587   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9588              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9589       
9590       size = AOP_SIZE (result) - 1;
9591       while (size--) emitcode ("lcall","__decdptr");
9592   }
9593
9594   freeAsmop (left, NULL, ic, TRUE);
9595   freeAsmop (result, NULL, ic, TRUE);
9596 }
9597
9598 /*-----------------------------------------------------------------*/
9599 /* genPointerGet - generate code for pointer get                   */
9600 /*-----------------------------------------------------------------*/
9601 static void
9602 genPointerGet (iCode * ic, iCode *pi)
9603 {
9604   operand *left, *result;
9605   sym_link *type, *etype;
9606   int p_type;
9607
9608   D (emitcode (";", "genPointerGet ");
9609     );
9610
9611   left = IC_LEFT (ic);
9612   result = IC_RESULT (ic);
9613
9614   /* depending on the type of pointer we need to
9615      move it to the correct pointer register */
9616   type = operandType (left);
9617   etype = getSpec (type);
9618   /* if left is of type of pointer then it is simple */
9619   if (IS_PTR (type) && !IS_FUNC (type->next))
9620     p_type = DCL_TYPE (type);
9621   else
9622     {
9623       /* we have to go by the storage class */
9624       p_type = PTR_TYPE (SPEC_OCLS (etype));
9625     }
9626   /* special case when cast remat */
9627   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9628       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9629           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9630           type = operandType (left);
9631           p_type = DCL_TYPE (type);
9632   }
9633   /* now that we have the pointer type we assign
9634      the pointer values */
9635   switch (p_type)
9636     {
9637
9638     case POINTER:
9639     case IPOINTER:
9640       genNearPointerGet (left, result, ic, pi);
9641       break;
9642
9643     case PPOINTER:
9644       genPagedPointerGet (left, result, ic, pi);
9645       break;
9646
9647     case FPOINTER:
9648       genFarPointerGet (left, result, ic, pi);
9649       break;
9650
9651     case CPOINTER:
9652       genCodePointerGet (left, result, ic, pi);
9653       break;
9654
9655     case GPOINTER:
9656       genGenPointerGet (left, result, ic, pi);
9657       break;
9658     }
9659
9660 }
9661
9662 /*-----------------------------------------------------------------*/
9663 /* genPackBits - generates code for packed bit storage             */
9664 /*-----------------------------------------------------------------*/
9665 static void
9666 genPackBits (sym_link * etype,
9667              operand * right,
9668              char *rname, int p_type)
9669 {
9670   int shCount = 0;
9671   int offset = 0;
9672   int rLen = 0;
9673   int blen, bstr;
9674   char *l;
9675
9676   blen = SPEC_BLEN (etype);
9677   bstr = SPEC_BSTR (etype);
9678
9679   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9680   MOVA (l);
9681
9682   /* if the bit lenth is less than or    */
9683   /* it exactly fits a byte then         */
9684   if (SPEC_BLEN (etype) <= 8)
9685     {
9686       shCount = SPEC_BSTR (etype);
9687
9688       /* shift left acc */
9689       AccLsh (shCount);
9690
9691       if (SPEC_BLEN (etype) < 8)
9692         {                       /* if smaller than a byte */
9693
9694
9695           switch (p_type)
9696             {
9697             case POINTER:
9698               emitcode ("mov", "b,a");
9699               emitcode ("mov", "a,@%s", rname);
9700               break;
9701
9702             case FPOINTER:
9703               emitcode ("mov", "b,a");
9704               emitcode ("movx", "a,@dptr");
9705               break;
9706
9707             case GPOINTER:
9708               emitcode ("push", "b");
9709               emitcode ("push", "acc");
9710               emitcode ("lcall", "__gptrget");
9711               emitcode ("pop", "b");
9712               break;
9713             }
9714
9715           emitcode ("anl", "a,#!constbyte", (unsigned char)
9716                     ((unsigned char) (0xFF << (blen + bstr)) |
9717                      (unsigned char) (0xFF >> (8 - bstr))));
9718           emitcode ("orl", "a,b");
9719           if (p_type == GPOINTER)
9720             emitcode ("pop", "b");
9721         }
9722     }
9723
9724   switch (p_type)
9725     {
9726     case POINTER:
9727       emitcode ("mov", "@%s,a", rname);
9728       break;
9729
9730     case FPOINTER:
9731       emitcode ("movx", "@dptr,a");
9732       break;
9733
9734     case GPOINTER:
9735       emitcode ("lcall", "__gptrput");
9736       break;
9737     }
9738
9739   /* if we r done */
9740   if (SPEC_BLEN (etype) <= 8)
9741     return;
9742
9743   emitcode ("inc", "%s", rname);
9744   rLen = SPEC_BLEN (etype);
9745
9746   /* now generate for lengths greater than one byte */
9747   while (1)
9748     {
9749
9750       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9751
9752       rLen -= 8;
9753       if (rLen < 8)
9754         break;
9755
9756       switch (p_type)
9757         {
9758         case POINTER:
9759           if (*l == '@')
9760             {
9761               MOVA (l);
9762               emitcode ("mov", "@%s,a", rname);
9763             }
9764           else
9765             emitcode ("mov", "@%s,%s", rname, l);
9766           break;
9767
9768         case FPOINTER:
9769           MOVA (l);
9770           emitcode ("movx", "@dptr,a");
9771           break;
9772
9773         case GPOINTER:
9774           MOVA (l);
9775           emitcode ("lcall", "__gptrput");
9776           break;
9777         }
9778       emitcode ("inc", "%s", rname);
9779     }
9780
9781   MOVA (l);
9782
9783   /* last last was not complete */
9784   if (rLen)
9785     {
9786       /* save the byte & read byte */
9787       switch (p_type)
9788         {
9789         case POINTER:
9790           emitcode ("mov", "b,a");
9791           emitcode ("mov", "a,@%s", rname);
9792           break;
9793
9794         case FPOINTER:
9795           emitcode ("mov", "b,a");
9796           emitcode ("movx", "a,@dptr");
9797           break;
9798
9799         case GPOINTER:
9800           emitcode ("push", "b");
9801           emitcode ("push", "acc");
9802           emitcode ("lcall", "__gptrget");
9803           emitcode ("pop", "b");
9804           break;
9805         }
9806
9807       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9808       emitcode ("orl", "a,b");
9809     }
9810
9811   if (p_type == GPOINTER)
9812     emitcode ("pop", "b");
9813
9814   switch (p_type)
9815     {
9816
9817     case POINTER:
9818       emitcode ("mov", "@%s,a", rname);
9819       break;
9820
9821     case FPOINTER:
9822       emitcode ("movx", "@dptr,a");
9823       break;
9824
9825     case GPOINTER:
9826       emitcode ("lcall", "__gptrput");
9827       break;
9828     }
9829 }
9830 /*-----------------------------------------------------------------*/
9831 /* genDataPointerSet - remat pointer to data space                 */
9832 /*-----------------------------------------------------------------*/
9833 static void
9834 genDataPointerSet (operand * right,
9835                    operand * result,
9836                    iCode * ic)
9837 {
9838   int size, offset = 0;
9839   char *l, buff[256];
9840
9841   aopOp (right, ic, FALSE, FALSE);
9842
9843   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9844   size = AOP_SIZE (right);
9845   while (size--)
9846     {
9847       if (offset)
9848         {
9849             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9850         }
9851       else
9852         {
9853             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9854         }
9855         
9856       emitcode ("mov", "%s,%s", buff,
9857                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9858     }
9859
9860   freeAsmop (right, NULL, ic, TRUE);
9861   freeAsmop (result, NULL, ic, TRUE);
9862 }
9863
9864 /*-----------------------------------------------------------------*/
9865 /* genNearPointerSet - emitcode for near pointer put                */
9866 /*-----------------------------------------------------------------*/
9867 static void
9868 genNearPointerSet (operand * right,
9869                    operand * result,
9870                    iCode * ic,
9871                    iCode * pi)
9872 {
9873   asmop *aop = NULL;
9874   regs *preg = NULL;
9875   char *rname, *l;
9876   sym_link *retype, *letype;
9877   sym_link *ptype = operandType (result);
9878
9879   retype = getSpec (operandType (right));
9880   letype = getSpec (ptype);
9881
9882   aopOp (result, ic, FALSE, FALSE);
9883
9884   /* if the result is rematerializable &
9885      in data space & not a bit variable */
9886   if (AOP_TYPE (result) == AOP_IMMD &&
9887       DCL_TYPE (ptype) == POINTER &&
9888       !IS_BITVAR (retype) &&
9889       !IS_BITVAR (letype))
9890     {
9891       genDataPointerSet (right, result, ic);
9892       return;
9893     }
9894
9895   /* if the value is already in a pointer register
9896      then don't need anything more */
9897   if (!AOP_INPREG (AOP (result)))
9898     {
9899       /* otherwise get a free pointer register */
9900       aop = newAsmop (0);
9901       preg = getFreePtr (ic, &aop, FALSE);
9902       emitcode ("mov", "%s,%s",
9903                 preg->name,
9904                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9905       rname = preg->name;
9906     }
9907   else
9908     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9909
9910   aopOp (right, ic, FALSE, FALSE);
9911
9912   /* if bitfield then unpack the bits */
9913   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9914     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9915   else
9916     {
9917       /* we have can just get the values */
9918       int size = AOP_SIZE (right);
9919       int offset = 0;
9920
9921       while (size--)
9922         {
9923           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9924           if (*l == '@')
9925             {
9926               MOVA (l);
9927               emitcode ("mov", "@%s,a", rname);
9928             }
9929           else
9930             emitcode ("mov", "@%s,%s", rname, l);
9931           if (size || pi)
9932             emitcode ("inc", "%s", rname);
9933           offset++;
9934         }
9935     }
9936
9937   /* now some housekeeping stuff */
9938   if (aop)
9939     {
9940       /* we had to allocate for this iCode */
9941       if (pi) aopPut (AOP (result),rname,0);
9942       freeAsmop (NULL, aop, ic, TRUE);
9943     }
9944   else
9945     {
9946       /* we did not allocate which means left
9947          already in a pointer register, then
9948          if size > 0 && this could be used again
9949          we have to point it back to where it
9950          belongs */
9951       if (AOP_SIZE (right) > 1 &&
9952           !OP_SYMBOL (result)->remat &&
9953           (OP_SYMBOL (result)->liveTo > ic->seq ||
9954            ic->depth) &&
9955           !pi)
9956         {
9957           int size = AOP_SIZE (right) - 1;
9958           while (size--)
9959             emitcode ("dec", "%s", rname);
9960         }
9961     }
9962
9963   /* done */
9964   if (pi) pi->generated = 1;
9965   freeAsmop (result, NULL, ic, TRUE);
9966   freeAsmop (right, NULL, ic, TRUE);
9967
9968
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genPagedPointerSet - emitcode for Paged pointer put             */
9973 /*-----------------------------------------------------------------*/
9974 static void
9975 genPagedPointerSet (operand * right,
9976                     operand * result,
9977                     iCode * ic,
9978                     iCode *pi)
9979 {
9980   asmop *aop = NULL;
9981   regs *preg = NULL;
9982   char *rname, *l;
9983   sym_link *retype, *letype;
9984
9985   retype = getSpec (operandType (right));
9986   letype = getSpec (operandType (result));
9987
9988   aopOp (result, ic, FALSE, FALSE);
9989
9990   /* if the value is already in a pointer register
9991      then don't need anything more */
9992   if (!AOP_INPREG (AOP (result)))
9993     {
9994       /* otherwise get a free pointer register */
9995       aop = newAsmop (0);
9996       preg = getFreePtr (ic, &aop, FALSE);
9997       emitcode ("mov", "%s,%s",
9998                 preg->name,
9999                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
10000       rname = preg->name;
10001     }
10002   else
10003     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
10004
10005   aopOp (right, ic, FALSE, FALSE);
10006
10007   /* if bitfield then unpack the bits */
10008   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10009     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10010   else
10011     {
10012       /* we have can just get the values */
10013       int size = AOP_SIZE (right);
10014       int offset = 0;
10015
10016       while (size--)
10017         {
10018           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
10019
10020           MOVA (l);
10021           emitcode ("movx", "@%s,a", rname);
10022
10023           if (size || pi)
10024             emitcode ("inc", "%s", rname);
10025
10026           offset++;
10027         }
10028     }
10029
10030   /* now some housekeeping stuff */
10031   if (aop)
10032     {
10033       if (pi) aopPut (AOP (result),rname,0);
10034       /* we had to allocate for this iCode */
10035       freeAsmop (NULL, aop, ic, TRUE);
10036     }
10037   else
10038     {
10039       /* we did not allocate which means left
10040          already in a pointer register, then
10041          if size > 0 && this could be used again
10042          we have to point it back to where it
10043          belongs */
10044       if (AOP_SIZE (right) > 1 &&
10045           !OP_SYMBOL (result)->remat &&
10046           (OP_SYMBOL (result)->liveTo > ic->seq ||
10047            ic->depth) &&
10048           !pi)
10049         {
10050           int size = AOP_SIZE (right) - 1;
10051           while (size--)
10052             emitcode ("dec", "%s", rname);
10053         }
10054     }
10055
10056   /* done */
10057   if (pi) pi->generated = 1;
10058   freeAsmop (result, NULL, ic, TRUE);
10059   freeAsmop (right, NULL, ic, TRUE);
10060
10061
10062 }
10063
10064 /*-----------------------------------------------------------------*/
10065 /* genFarPointerSet - set value from far space                     */
10066 /*-----------------------------------------------------------------*/
10067 static void
10068 genFarPointerSet (operand * right,
10069                   operand * result, iCode * ic, iCode *pi)
10070 {
10071   int size, offset, dopi=1;
10072   sym_link *retype = getSpec (operandType (right));
10073   sym_link *letype = getSpec (operandType (result));
10074
10075   aopOp (result, ic, FALSE, FALSE);
10076
10077   /* if the operand is already in dptr
10078      then we do nothing else we move the value to dptr */
10079   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10080     {
10081       /* if this is remateriazable */
10082       if (AOP_TYPE (result) == AOP_IMMD)
10083         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10084       else
10085         {
10086           /* we need to get it byte by byte */
10087           _startLazyDPSEvaluation ();
10088           if (AOP_TYPE (result) != AOP_DPTR)
10089             {
10090               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10091               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10092               if (options.model == MODEL_FLAT24)
10093                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10094             }
10095           else
10096             {
10097               /* We need to generate a load to DPTR indirect through DPTR. */
10098               D (emitcode (";", "genFarPointerSet -- indirection special case.");
10099                 );
10100               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
10101               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
10102               if (options.model == MODEL_FLAT24)
10103                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10104               emitcode ("pop", "dph");
10105               emitcode ("pop", "dpl");
10106               dopi=0;
10107             }
10108           _endLazyDPSEvaluation ();
10109         }
10110     }
10111   /* so dptr know contains the address */
10112   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10113
10114   /* if bit then unpack */
10115   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10116       if (AOP_INDPTRn(result)) {
10117           genSetDPTR(AOP(result)->aopu.dptr);
10118       }
10119       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10120       if (AOP_INDPTRn(result)) {
10121           genSetDPTR(0);
10122       }
10123   } else {
10124       size = AOP_SIZE (right);
10125       offset = 0;
10126       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10127           while (size--) {
10128               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10129               MOVA (l);
10130               
10131               genSetDPTR(AOP(result)->aopu.dptr);
10132               emitcode ("movx", "@dptr,a");
10133               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10134                   emitcode ("inc", "dptr");
10135               genSetDPTR (0);
10136           }
10137       } else {
10138           _startLazyDPSEvaluation ();
10139           while (size--) {
10140               char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10141               MOVA (l);
10142               
10143               if (AOP_INDPTRn(result)) {
10144                   genSetDPTR(AOP(result)->aopu.dptr);
10145               } else {
10146                   genSetDPTR (0);
10147               }
10148               _flushLazyDPS ();
10149               
10150               emitcode ("movx", "@dptr,a");
10151               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10152                   emitcode ("inc", "dptr");
10153           }
10154           _endLazyDPSEvaluation ();
10155       }
10156   }
10157   
10158   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10159       if (!AOP_INDPTRn(result)) {
10160           aopPut (AOP(result),"dpl",0);
10161           aopPut (AOP(result),"dph",1);
10162           if (options.model == MODEL_FLAT24)
10163               aopPut (AOP(result),"dpx",2);
10164       }
10165       pi->generated=1;
10166   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10167              AOP_SIZE(right) > 1 &&
10168              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10169       
10170       size = AOP_SIZE (right) - 1;
10171       if (AOP_INDPTRn(result)) {
10172           genSetDPTR(AOP(result)->aopu.dptr);
10173       } 
10174       while (size--) emitcode ("lcall","__decdptr");
10175       if (AOP_INDPTRn(result)) {
10176           genSetDPTR(0);
10177       }
10178   }
10179   freeAsmop (result, NULL, ic, TRUE);
10180   freeAsmop (right, NULL, ic, TRUE);
10181 }
10182
10183 /*-----------------------------------------------------------------*/
10184 /* genGenPointerSet - set value from generic pointer space         */
10185 /*-----------------------------------------------------------------*/
10186 static void
10187 genGenPointerSet (operand * right,
10188                   operand * result, iCode * ic, iCode *pi)
10189 {
10190   int size, offset;
10191   sym_link *retype = getSpec (operandType (right));
10192   sym_link *letype = getSpec (operandType (result));
10193
10194   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10195
10196   /* if the operand is already in dptr
10197      then we do nothing else we move the value to dptr */
10198   if (AOP_TYPE (result) != AOP_STR)
10199     {
10200       _startLazyDPSEvaluation ();
10201       /* if this is remateriazable */
10202       if (AOP_TYPE (result) == AOP_IMMD)
10203         {
10204           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10205           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10206                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
10207           else
10208                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
10209         }
10210       else
10211         {                       /* we need to get it byte by byte */
10212           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
10213           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
10214           if (options.model == MODEL_FLAT24) {
10215             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10216             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
10217           } else {
10218             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
10219           }
10220         }
10221       _endLazyDPSEvaluation ();
10222     }
10223   /* so dptr know contains the address */
10224   aopOp (right, ic, FALSE, TRUE);
10225
10226   /* if bit then unpack */
10227   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10228     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10229   else
10230     {
10231       size = AOP_SIZE (right);
10232       offset = 0;
10233
10234       _startLazyDPSEvaluation ();
10235       while (size--)
10236         {
10237           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
10238           MOVA (l);
10239
10240           genSetDPTR (0);
10241           _flushLazyDPS ();
10242
10243           emitcode ("lcall", "__gptrput");
10244           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10245             emitcode ("inc", "dptr");
10246         }
10247       _endLazyDPSEvaluation ();
10248     }
10249
10250   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10251       aopPut (AOP(result),"dpl",0);
10252       aopPut (AOP(result),"dph",1);
10253       if (options.model == MODEL_FLAT24) {
10254           aopPut (AOP(result),"dpx",2);
10255           aopPut (AOP(result),"b",3);
10256       } else {
10257           aopPut (AOP(result),"b",2);
10258       }
10259       pi->generated=1;
10260   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10261              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10262       
10263       size = AOP_SIZE (right) - 1;
10264       while (size--) emitcode ("lcall","__decdptr");
10265   }
10266   freeAsmop (result, NULL, ic, TRUE);
10267   freeAsmop (right, NULL, ic, TRUE);
10268 }
10269
10270 /*-----------------------------------------------------------------*/
10271 /* genPointerSet - stores the value into a pointer location        */
10272 /*-----------------------------------------------------------------*/
10273 static void
10274 genPointerSet (iCode * ic, iCode *pi)
10275 {
10276   operand *right, *result;
10277   sym_link *type, *etype;
10278   int p_type;
10279
10280   D (emitcode (";", "genPointerSet ");
10281     );
10282
10283   right = IC_RIGHT (ic);
10284   result = IC_RESULT (ic);
10285
10286   /* depending on the type of pointer we need to
10287      move it to the correct pointer register */
10288   type = operandType (result);
10289   etype = getSpec (type);
10290   /* if left is of type of pointer then it is simple */
10291   if (IS_PTR (type) && !IS_FUNC (type->next))
10292     {
10293       p_type = DCL_TYPE (type);
10294     }
10295   else
10296     {
10297       /* we have to go by the storage class */
10298       p_type = PTR_TYPE (SPEC_OCLS (etype));
10299     }
10300   /* special case when cast remat */
10301   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10302       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10303           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10304           type = operandType (result);
10305           p_type = DCL_TYPE (type);
10306   }
10307
10308   /* now that we have the pointer type we assign
10309      the pointer values */
10310   switch (p_type)
10311     {
10312
10313     case POINTER:
10314     case IPOINTER:
10315       genNearPointerSet (right, result, ic, pi);
10316       break;
10317
10318     case PPOINTER:
10319       genPagedPointerSet (right, result, ic, pi);
10320       break;
10321
10322     case FPOINTER:
10323       genFarPointerSet (right, result, ic, pi);
10324       break;
10325
10326     case GPOINTER:
10327       genGenPointerSet (right, result, ic, pi);
10328       break;
10329
10330     default:
10331       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10332               "genPointerSet: illegal pointer type");
10333     }
10334
10335 }
10336
10337 /*-----------------------------------------------------------------*/
10338 /* genIfx - generate code for Ifx statement                        */
10339 /*-----------------------------------------------------------------*/
10340 static void
10341 genIfx (iCode * ic, iCode * popIc)
10342 {
10343   operand *cond = IC_COND (ic);
10344   int isbit = 0;
10345
10346   D (emitcode (";", "genIfx "););
10347
10348   aopOp (cond, ic, FALSE, FALSE);
10349
10350   /* get the value into acc */
10351   if (AOP_TYPE (cond) != AOP_CRY)
10352     {
10353         toBoolean (cond);
10354     }
10355   else
10356     {
10357         isbit = 1;
10358     }
10359     
10360   /* the result is now in the accumulator */
10361   freeAsmop (cond, NULL, ic, TRUE);
10362
10363   /* if there was something to be popped then do it */
10364   if (popIc)
10365     genIpop (popIc);
10366
10367   /* if the condition is  a bit variable */
10368   if (isbit && IS_ITEMP (cond) &&
10369       SPIL_LOC (cond))
10370     {
10371         genIfxJump (ic, SPIL_LOC (cond)->rname);
10372     }
10373   else if (isbit && !IS_ITEMP (cond))
10374     {
10375         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10376     }
10377   else
10378     {
10379         genIfxJump (ic, "a");
10380     }
10381
10382   ic->generated = 1;
10383 }
10384
10385 /*-----------------------------------------------------------------*/
10386 /* genAddrOf - generates code for address of                       */
10387 /*-----------------------------------------------------------------*/
10388 static void
10389 genAddrOf (iCode * ic)
10390 {
10391   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10392   int size, offset;
10393
10394   D (emitcode (";", "genAddrOf ");
10395     );
10396
10397   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10398
10399   /* if the operand is on the stack then we
10400      need to get the stack offset of this
10401      variable */
10402   if (sym->onStack) {
10403       
10404       /* if 10 bit stack */
10405       if (options.stack10bit) {
10406           char buff[10];
10407           tsprintf(buff, sizeof(buff), 
10408                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10409           /* if it has an offset then we need to compute it */
10410 /*        emitcode ("subb", "a,#!constbyte", */
10411 /*                  -((sym->stack < 0) ? */
10412 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10413 /*                    ((short) sym->stack)) & 0xff); */
10414 /*        emitcode ("mov","b,a"); */
10415 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10416 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10417 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10418           if (sym->stack) {
10419               emitcode ("mov", "a,_bpx");
10420               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10421                                              ((char) (sym->stack - _G.nRegsSaved)) :
10422                                              ((char) sym->stack )) & 0xff);
10423               emitcode ("mov", "b,a");
10424               emitcode ("mov", "a,_bpx+1");
10425               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10426                                               ((short) (sym->stack - _G.nRegsSaved)) :
10427                                               ((short) sym->stack )) >> 8) & 0xff);
10428               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10429               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10430               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10431           } else {
10432               /* we can just move _bp */
10433               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10434               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10435               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10436           }       
10437       } else {
10438           /* if it has an offset then we need to compute it */
10439           if (sym->stack) {
10440               emitcode ("mov", "a,_bp");
10441               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10442               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10443           } else {
10444               /* we can just move _bp */
10445               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10446           }
10447           /* fill the result with zero */
10448           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10449           
10450           
10451           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10452               fprintf (stderr,
10453                        "*** warning: pointer to stack var truncated.\n");
10454           }
10455
10456           offset = 1;
10457           while (size--) {
10458               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10459           }      
10460       }
10461       goto release;
10462   }
10463
10464   /* object not on stack then we need the name */
10465   size = AOP_SIZE (IC_RESULT (ic));
10466   offset = 0;
10467
10468   while (size--)
10469     {
10470       char s[SDCC_NAME_MAX];
10471       if (offset) {
10472           switch (offset) {
10473           case 1:
10474               tsprintf(s, sizeof(s), "!his",sym->rname);
10475               break;
10476           case 2:
10477               tsprintf(s, sizeof(s), "!hihis",sym->rname);
10478               break;
10479           case 3:
10480               tsprintf(s, sizeof(s), "!hihihis",sym->rname);
10481               break;
10482           default: /* should not need this (just in case) */
10483               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10484                        sym->rname,
10485                        offset * 8);
10486           }
10487       } 
10488       else
10489       {
10490           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10491       }
10492         
10493       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10494     }
10495
10496 release:
10497   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10498
10499 }
10500
10501 /*-----------------------------------------------------------------*/
10502 /* genArrayInit - generates code for address of                       */
10503 /*-----------------------------------------------------------------*/
10504 static void
10505 genArrayInit (iCode * ic)
10506 {
10507     literalList *iLoop;
10508     int         ix, count;
10509     int         elementSize = 0, eIndex;
10510     unsigned    val, lastVal;
10511     sym_link    *type;
10512     operand     *left=IC_LEFT(ic);
10513     
10514     D (emitcode (";", "genArrayInit "););
10515
10516     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10517     
10518     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10519     {
10520         // Load immediate value into DPTR.
10521         emitcode("mov", "dptr, %s",
10522              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10523     }
10524     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10525     {
10526 #if 0
10527       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10528               "Unexpected operand to genArrayInit.\n");
10529       exit(1);
10530 #else
10531       // a regression because of SDCCcse.c:1.52
10532       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10533       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10534       if (options.model == MODEL_FLAT24)
10535         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10536 #endif
10537     }
10538     
10539     type = operandType(IC_LEFT(ic));
10540     
10541     if (type && type->next)
10542     {
10543         elementSize = getSize(type->next);
10544     }
10545     else
10546     {
10547         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10548                                 "can't determine element size in genArrayInit.\n");
10549         exit(1);
10550     }
10551     
10552     iLoop = IC_ARRAYILIST(ic);
10553     lastVal = 0xffff;
10554     
10555     while (iLoop)
10556     {
10557         bool firstpass = TRUE;
10558         
10559         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10560                  iLoop->count, (int)iLoop->literalValue, elementSize);
10561         
10562         ix = iLoop->count;
10563         
10564         while (ix)
10565         {
10566             symbol *tlbl = NULL;
10567             
10568             count = ix > 256 ? 256 : ix;
10569             
10570             if (count > 1)
10571             {
10572                 tlbl = newiTempLabel (NULL);
10573                 if (firstpass || (count & 0xff))
10574                 {
10575                     emitcode("mov", "b, #!constbyte", count & 0xff);
10576                 }
10577                 
10578                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10579             }
10580             
10581             firstpass = FALSE;
10582                 
10583             for (eIndex = 0; eIndex < elementSize; eIndex++)
10584             {
10585                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10586                 if (val != lastVal)
10587                 {
10588                     emitcode("mov", "a, #!constbyte", val);
10589                     lastVal = val;
10590                 }
10591                 
10592                 emitcode("movx", "@dptr, a");
10593                 emitcode("inc", "dptr");
10594             }
10595             
10596             if (count > 1)
10597             {
10598                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10599             }
10600             
10601             ix -= count;
10602         }
10603         
10604         iLoop = iLoop->next;
10605     }
10606     
10607     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10608 }
10609
10610 /*-----------------------------------------------------------------*/
10611 /* genFarFarAssign - assignment when both are in far space         */
10612 /*-----------------------------------------------------------------*/
10613 static void
10614 genFarFarAssign (operand * result, operand * right, iCode * ic)
10615 {
10616   int size = AOP_SIZE (right);
10617   int offset = 0;
10618   symbol *rSym = NULL;
10619
10620   if (size == 1)
10621   {
10622       /* quick & easy case. */
10623       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10624       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10625       freeAsmop (right, NULL, ic, FALSE);
10626       /* now assign DPTR to result */
10627       _G.accInUse++;
10628       aopOp(result, ic, FALSE, FALSE);
10629       _G.accInUse--;
10630       aopPut(AOP(result), "a", 0);
10631       freeAsmop(result, NULL, ic, FALSE);
10632       return;
10633   }
10634   
10635   /* See if we've got an underlying symbol to abuse. */
10636   if (IS_SYMOP(result) && OP_SYMBOL(result))
10637   {
10638       if (IS_TRUE_SYMOP(result))
10639       {
10640           rSym = OP_SYMBOL(result);
10641       }
10642       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10643       {
10644           rSym = OP_SYMBOL(result)->usl.spillLoc;
10645       }
10646   }
10647              
10648   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10649   {
10650       /* We can use the '390 auto-toggle feature to good effect here. */
10651       
10652       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10653       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10654       emitcode ("mov", "dptr,#%s", rSym->rname); 
10655       /* DP2 = result, DP1 = right, DP1 is current. */
10656       while (size)
10657       {
10658           emitcode("movx", "a,@dptr");
10659           emitcode("movx", "@dptr,a");
10660           if (--size)
10661           {
10662                emitcode("inc", "dptr");
10663                emitcode("inc", "dptr");
10664           }
10665       }
10666       emitcode("mov", "dps,#0");
10667       freeAsmop (right, NULL, ic, FALSE);
10668 #if 0
10669 some alternative code for processors without auto-toggle
10670 no time to test now, so later well put in...kpb
10671         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10672         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10673         emitcode ("mov", "dptr,#%s", rSym->rname); 
10674         /* DP2 = result, DP1 = right, DP1 is current. */
10675         while (size)
10676         {
10677           --size;
10678           emitcode("movx", "a,@dptr");
10679           if (size)
10680             emitcode("inc", "dptr");
10681           emitcode("inc", "dps");
10682           emitcode("movx", "@dptr,a");
10683           if (size)
10684             emitcode("inc", "dptr");
10685           emitcode("inc", "dps");
10686         }
10687         emitcode("mov", "dps,#0");
10688         freeAsmop (right, NULL, ic, FALSE);
10689 #endif
10690   }
10691   else
10692   {
10693       D (emitcode (";", "genFarFarAssign"););
10694       aopOp (result, ic, TRUE, TRUE);
10695
10696       _startLazyDPSEvaluation ();
10697       
10698       while (size--)
10699         {
10700           aopPut (AOP (result),
10701                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10702           offset++;
10703         }
10704       _endLazyDPSEvaluation ();
10705       freeAsmop (result, NULL, ic, FALSE);
10706       freeAsmop (right, NULL, ic, FALSE);
10707   }
10708 }
10709
10710 /*-----------------------------------------------------------------*/
10711 /* genAssign - generate code for assignment                        */
10712 /*-----------------------------------------------------------------*/
10713 static void
10714 genAssign (iCode * ic)
10715 {
10716   operand *result, *right;
10717   int size, offset;
10718   unsigned long lit = 0L;
10719
10720   D (emitcode (";", "genAssign ");
10721     );
10722
10723   result = IC_RESULT (ic);
10724   right = IC_RIGHT (ic);
10725
10726   /* if they are the same */
10727   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10728     return;
10729
10730   aopOp (right, ic, FALSE, FALSE);
10731
10732   emitcode (";", "genAssign: resultIsFar = %s",
10733             isOperandInFarSpace (result) ?
10734             "TRUE" : "FALSE");
10735
10736   /* special case both in far space */
10737   if ((AOP_TYPE (right) == AOP_DPTR ||
10738        AOP_TYPE (right) == AOP_DPTR2) &&
10739   /* IS_TRUE_SYMOP(result)       && */
10740       isOperandInFarSpace (result))
10741     {
10742       genFarFarAssign (result, right, ic);
10743       return;
10744     }
10745
10746   aopOp (result, ic, TRUE, FALSE);
10747
10748   /* if they are the same registers */
10749   if (sameRegs (AOP (right), AOP (result)))
10750     goto release;
10751
10752   /* if the result is a bit */
10753   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10754     {
10755       /* if the right size is a literal then
10756          we know what the value is */
10757       if (AOP_TYPE (right) == AOP_LIT)
10758         {
10759           if (((int) operandLitValue (right)))
10760             aopPut (AOP (result), one, 0);
10761           else
10762             aopPut (AOP (result), zero, 0);
10763           goto release;
10764         }
10765
10766       /* the right is also a bit variable */
10767       if (AOP_TYPE (right) == AOP_CRY)
10768         {
10769           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10770           aopPut (AOP (result), "c", 0);
10771           goto release;
10772         }
10773
10774       /* we need to or */
10775       toBoolean (right);
10776       aopPut (AOP (result), "a", 0);
10777       goto release;
10778     }
10779
10780   /* bit variables done */
10781   /* general case */
10782   size = AOP_SIZE (result);
10783   offset = 0;
10784   if (AOP_TYPE (right) == AOP_LIT)
10785     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10786
10787   if ((size > 1) &&
10788       (AOP_TYPE (result) != AOP_REG) &&
10789       (AOP_TYPE (right) == AOP_LIT) &&
10790       !IS_FLOAT (operandType (right)))
10791     {
10792       _startLazyDPSEvaluation ();
10793       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10794         {
10795           aopPut (AOP (result),
10796                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10797                   offset);
10798           offset++;
10799           size--;
10800         }
10801       /* And now fill the rest with zeros. */
10802       if (size)
10803         {
10804           emitcode ("clr", "a");
10805         }
10806       while (size--)
10807         {
10808           aopPut (AOP (result), "a", offset++);
10809         }
10810       _endLazyDPSEvaluation ();
10811     }
10812   else
10813     {
10814       _startLazyDPSEvaluation ();
10815       while (size--)
10816         {
10817           aopPut (AOP (result),
10818                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10819                   offset);
10820           offset++;
10821         }
10822       _endLazyDPSEvaluation ();
10823     }
10824
10825 release:
10826   freeAsmop (right, NULL, ic, FALSE);
10827   freeAsmop (result, NULL, ic, TRUE);
10828 }
10829
10830 /*-----------------------------------------------------------------*/
10831 /* genJumpTab - generates code for jump table                      */
10832 /*-----------------------------------------------------------------*/
10833 static void
10834 genJumpTab (iCode * ic)
10835 {
10836   symbol *jtab;
10837   char *l;
10838
10839   D (emitcode (";", "genJumpTab ");
10840     );
10841
10842   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10843   /* get the condition into accumulator */
10844   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10845   MOVA (l);
10846   /* multiply by four! */
10847   emitcode ("add", "a,acc");
10848   emitcode ("add", "a,acc");
10849   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10850
10851   jtab = newiTempLabel (NULL);
10852   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10853   emitcode ("jmp", "@a+dptr");
10854   emitcode ("", "!tlabeldef", jtab->key + 100);
10855   /* now generate the jump labels */
10856   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10857        jtab = setNextItem (IC_JTLABELS (ic)))
10858     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10859
10860 }
10861
10862 /*-----------------------------------------------------------------*/
10863 /* genCast - gen code for casting                                  */
10864 /*-----------------------------------------------------------------*/
10865 static void
10866 genCast (iCode * ic)
10867 {
10868   operand *result = IC_RESULT (ic);
10869   sym_link *ctype = operandType (IC_LEFT (ic));
10870   sym_link *rtype = operandType (IC_RIGHT (ic));
10871   operand *right = IC_RIGHT (ic);
10872   int size, offset;
10873
10874   D (emitcode (";", "genCast ");
10875     );
10876
10877   /* if they are equivalent then do nothing */
10878   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10879     return;
10880
10881   aopOp (right, ic, FALSE, FALSE);
10882   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10883
10884   /* if the result is a bit */
10885   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10886   if (IS_BITVAR(OP_SYMBOL(result)->type))
10887     {
10888       /* if the right size is a literal then
10889          we know what the value is */
10890       if (AOP_TYPE (right) == AOP_LIT)
10891         {
10892           if (((int) operandLitValue (right)))
10893             aopPut (AOP (result), one, 0);
10894           else
10895             aopPut (AOP (result), zero, 0);
10896
10897           goto release;
10898         }
10899
10900       /* the right is also a bit variable */
10901       if (AOP_TYPE (right) == AOP_CRY)
10902         {
10903           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10904           aopPut (AOP (result), "c", 0);
10905           goto release;
10906         }
10907
10908       /* we need to or */
10909       toBoolean (right);
10910       aopPut (AOP (result), "a", 0);
10911       goto release;
10912     }
10913
10914   /* if they are the same size : or less */
10915   if (AOP_SIZE (result) <= AOP_SIZE (right))
10916     {
10917
10918       /* if they are in the same place */
10919       if (sameRegs (AOP (right), AOP (result)))
10920         goto release;
10921
10922       /* if they in different places then copy */
10923       size = AOP_SIZE (result);
10924       offset = 0;
10925       _startLazyDPSEvaluation ();
10926       while (size--)
10927         {
10928           aopPut (AOP (result),
10929                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10930                   offset);
10931           offset++;
10932         }
10933       _endLazyDPSEvaluation ();
10934       goto release;
10935     }
10936
10937
10938   /* if the result is of type pointer */
10939   if (IS_PTR (ctype))
10940     {
10941
10942       int p_type;
10943       sym_link *type = operandType (right);
10944
10945       /* pointer to generic pointer */
10946       if (IS_GENPTR (ctype))
10947         {
10948           if (IS_PTR (type))
10949             {
10950               p_type = DCL_TYPE (type);
10951             }
10952           else
10953             {
10954 #if OLD_CAST_BEHAVIOR
10955               /* KV: we are converting a non-pointer type to
10956                * a generic pointer. This (ifdef'd out) code
10957                * says that the resulting generic pointer
10958                * should have the same class as the storage
10959                * location of the non-pointer variable.
10960                *
10961                * For example, converting an int (which happens
10962                * to be stored in DATA space) to a pointer results
10963                * in a DATA generic pointer; if the original int
10964                * in XDATA space, so will be the resulting pointer.
10965                *
10966                * I don't like that behavior, and thus this change:
10967                * all such conversions will be forced to XDATA and
10968                * throw a warning. If you want some non-XDATA
10969                * type, or you want to suppress the warning, you
10970                * must go through an intermediate cast, like so:
10971                *
10972                * char _generic *gp = (char _xdata *)(intVar);
10973                */
10974               sym_link *etype = getSpec (type);
10975
10976               /* we have to go by the storage class */
10977               if (SPEC_OCLS (etype) != generic)
10978                 {
10979                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10980                 }
10981               else
10982 #endif
10983                 {
10984                   /* Converting unknown class (i.e. register variable)
10985                    * to generic pointer. This is not good, but
10986                    * we'll make a guess (and throw a warning).
10987                    */
10988                   p_type = FPOINTER;
10989                   werror (W_INT_TO_GEN_PTR_CAST);
10990                 }
10991             }
10992
10993           /* the first two bytes are known */
10994           size = GPTRSIZE - 1;
10995           offset = 0;
10996           _startLazyDPSEvaluation ();
10997           while (size--)
10998             {
10999               aopPut (AOP (result),
11000                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11001                       offset);
11002               offset++;
11003             }
11004           _endLazyDPSEvaluation ();
11005
11006           /* the last byte depending on type */
11007             {
11008                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11009                 char gpValStr[10];
11010             
11011                 if (gpVal == -1)
11012                 {
11013                     // pointerTypeToGPByte will have bitched.
11014                     exit(1);
11015                 }
11016             
11017                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11018                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11019             }
11020           goto release;
11021         }
11022
11023       /* just copy the pointers */
11024       size = AOP_SIZE (result);
11025       offset = 0;
11026       _startLazyDPSEvaluation ();
11027       while (size--)
11028         {
11029           aopPut (AOP (result),
11030                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11031                   offset);
11032           offset++;
11033         }
11034       _endLazyDPSEvaluation ();
11035       goto release;
11036     }
11037
11038   /* so we now know that the size of destination is greater
11039      than the size of the source */
11040   /* we move to result for the size of source */
11041   size = AOP_SIZE (right);
11042   offset = 0;
11043   _startLazyDPSEvaluation ();
11044   while (size--)
11045     {
11046       aopPut (AOP (result),
11047               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
11048               offset);
11049       offset++;
11050     }
11051   _endLazyDPSEvaluation ();
11052
11053   /* now depending on the sign of the source && destination */
11054   size = AOP_SIZE (result) - AOP_SIZE (right);
11055   /* if unsigned or not an integral type */
11056   /* also, if the source is a bit, we don't need to sign extend, because
11057    * it can't possibly have set the sign bit.
11058    */
11059   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11060     {
11061       while (size--)
11062         {
11063           aopPut (AOP (result), zero, offset++);
11064         }
11065     }
11066   else
11067     {
11068       /* we need to extend the sign :{ */
11069       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
11070                         FALSE, FALSE, TRUE);
11071       MOVA (l);
11072       emitcode ("rlc", "a");
11073       emitcode ("subb", "a,acc");
11074       while (size--)
11075         aopPut (AOP (result), "a", offset++);
11076     }
11077
11078   /* we are done hurray !!!! */
11079
11080 release:
11081   freeAsmop (right, NULL, ic, TRUE);
11082   freeAsmop (result, NULL, ic, TRUE);
11083
11084 }
11085
11086 /*-----------------------------------------------------------------*/
11087 /* genDjnz - generate decrement & jump if not zero instrucion      */
11088 /*-----------------------------------------------------------------*/
11089 static int
11090 genDjnz (iCode * ic, iCode * ifx)
11091 {
11092   symbol *lbl, *lbl1;
11093   if (!ifx)
11094     return 0;
11095
11096   /* if the if condition has a false label
11097      then we cannot save */
11098   if (IC_FALSE (ifx))
11099     return 0;
11100
11101   /* if the minus is not of the form
11102      a = a - 1 */
11103   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11104       !IS_OP_LITERAL (IC_RIGHT (ic)))
11105     return 0;
11106
11107   if (operandLitValue (IC_RIGHT (ic)) != 1)
11108     return 0;
11109
11110   /* if the size of this greater than one then no
11111      saving */
11112   if (getSize (operandType (IC_RESULT (ic))) > 1)
11113     return 0;
11114
11115   /* otherwise we can save BIG */
11116   D(emitcode(";", "genDjnz"););
11117
11118   lbl = newiTempLabel (NULL);
11119   lbl1 = newiTempLabel (NULL);
11120
11121   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11122
11123   if (AOP_NEEDSACC(IC_RESULT(ic)))
11124   {
11125       /* If the result is accessed indirectly via
11126        * the accumulator, we must explicitly write
11127        * it back after the decrement.
11128        */
11129       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
11130       
11131       if (strcmp(rByte, "a"))
11132       {
11133            /* Something is hopelessly wrong */
11134            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11135                    __FILE__, __LINE__);
11136            /* We can just give up; the generated code will be inefficient,
11137             * but what the hey.
11138             */
11139            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11140            return 0;
11141       }
11142       emitcode ("dec", "%s", rByte);
11143       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11144       emitcode ("jnz", "!tlabel", lbl->key + 100);
11145   }
11146   else if (IS_AOP_PREG (IC_RESULT (ic)))
11147     {
11148       emitcode ("dec", "%s",
11149                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11150       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
11151       emitcode ("jnz", "!tlabel", lbl->key + 100);
11152     }
11153   else
11154     {
11155       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
11156                 lbl->key + 100);
11157     }
11158   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11159   emitcode ("", "!tlabeldef", lbl->key + 100);
11160   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11161   emitcode ("", "!tlabeldef", lbl1->key + 100);
11162
11163   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11164   ifx->generated = 1;
11165   return 1;
11166 }
11167
11168 /*-----------------------------------------------------------------*/
11169 /* genReceive - generate code for a receive iCode                  */
11170 /*-----------------------------------------------------------------*/
11171 static void
11172 genReceive (iCode * ic)
11173 {
11174
11175     int size = getSize (operandType (IC_RESULT (ic)));
11176     int offset = 0;
11177     int rb1off ;
11178     
11179     D (emitcode (";", "genReceive ");
11180        );
11181
11182   if (ic->argreg == 1) { /* first parameter */
11183       if (isOperandInFarSpace (IC_RESULT (ic)) &&
11184           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11185            IS_TRUE_SYMOP (IC_RESULT (ic))))
11186           {
11187               offset = fReturnSizeDS390 - size;
11188               while (size--)
11189                   {
11190                       emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
11191                                                fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
11192                       offset++;
11193                   }
11194               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11195               size = AOP_SIZE (IC_RESULT (ic));
11196               offset = 0;
11197               while (size--)
11198                   {
11199                       emitcode ("pop", "acc");
11200                       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
11201                   }
11202               
11203           } else {
11204               _G.accInUse++;
11205               aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11206               _G.accInUse--;
11207               assignResultValue (IC_RESULT (ic));
11208           }
11209   } else { /* second receive onwards */
11210       /* this gets a little tricky since unused recevies will be
11211          eliminated, we have saved the reg in the type field . and
11212          we use that to figure out which register to use */
11213       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11214       rb1off = ic->argreg;
11215       while (size--) {
11216           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11217       }
11218       
11219   }
11220   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11221 }
11222
11223 /*-----------------------------------------------------------------*/
11224 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11225 /*-----------------------------------------------------------------*/
11226 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11227 {
11228     operand *from , *to , *count;
11229     symbol *lbl;
11230     bitVect *rsave;
11231     int i;
11232
11233     /* we know it has to be 3 parameters */
11234     assert (nparms == 3);
11235     
11236     rsave = newBitVect(16);
11237     /* save DPTR if it needs to be saved */
11238     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11239             if (bitVectBitValue(ic->rMask,i))
11240                     rsave = bitVectSetBit(rsave,i);
11241     }
11242     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11243                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11244     savermask(rsave);
11245     
11246     to = parms[0];
11247     from = parms[1];
11248     count = parms[2];
11249
11250     aopOp (from, ic->next, FALSE, FALSE);
11251
11252     /* get from into DPTR1 */
11253     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11254     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11255     if (options.model == MODEL_FLAT24) {
11256         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11257     }
11258
11259     freeAsmop (from, NULL, ic, FALSE);
11260     aopOp (to, ic, FALSE, FALSE);
11261     /* get "to" into DPTR */
11262     /* if the operand is already in dptr
11263        then we do nothing else we move the value to dptr */
11264     if (AOP_TYPE (to) != AOP_STR) {
11265         /* if already in DPTR then we need to push */
11266         if (AOP_TYPE(to) == AOP_DPTR) {
11267             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11268             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11269             if (options.model == MODEL_FLAT24)
11270                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11271             emitcode ("pop", "dph");
11272             emitcode ("pop", "dpl");        
11273         } else {
11274             _startLazyDPSEvaluation ();
11275             /* if this is remateriazable */
11276             if (AOP_TYPE (to) == AOP_IMMD) {
11277                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11278             } else {                    /* we need to get it byte by byte */
11279                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11280                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11281                 if (options.model == MODEL_FLAT24) {
11282                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11283                 }
11284             }
11285             _endLazyDPSEvaluation ();
11286         }
11287     }
11288     freeAsmop (to, NULL, ic, FALSE);
11289     _G.dptrInUse = _G.dptr1InUse = 1;
11290     aopOp (count, ic->next->next, FALSE,FALSE);
11291     lbl =newiTempLabel(NULL);
11292
11293     /* now for the actual copy */
11294     if (AOP_TYPE(count) == AOP_LIT && 
11295         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11296         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11297         if (fromc) {
11298             emitcode ("lcall","__bi_memcpyc2x_s");
11299         } else {
11300             emitcode ("lcall","__bi_memcpyx2x_s");
11301         }
11302         freeAsmop (count, NULL, ic, FALSE);
11303     } else {
11304         symbol *lbl1 = newiTempLabel(NULL);
11305         
11306         emitcode (";"," Auto increment but no djnz");
11307         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11308         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11309         freeAsmop (count, NULL, ic, FALSE);
11310         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11311         emitcode ("","!tlabeldef",lbl->key+100);
11312         if (fromc) {
11313             emitcode ("clr","a");
11314             emitcode ("movc", "a,@a+dptr");
11315         } else 
11316             emitcode ("movx", "a,@dptr");
11317         emitcode ("movx", "@dptr,a");
11318         emitcode ("inc", "dptr");
11319         emitcode ("inc", "dptr");
11320         emitcode ("mov","a,b");
11321         emitcode ("orl","a,_ap");
11322         emitcode ("jz","!tlabel",lbl1->key+100);
11323         emitcode ("mov","a,_ap");
11324         emitcode ("add","a,#!constbyte",0xFF);
11325         emitcode ("mov","_ap,a");
11326         emitcode ("mov","a,b");
11327         emitcode ("addc","a,#!constbyte",0xFF);
11328         emitcode ("mov","b,a");
11329         emitcode ("sjmp","!tlabel",lbl->key+100);
11330         emitcode ("","!tlabeldef",lbl1->key+100);
11331     }
11332     emitcode ("mov", "dps,#0"); 
11333     _G.dptrInUse = _G.dptr1InUse = 0;
11334     unsavermask(rsave);
11335
11336 }
11337
11338 /*-----------------------------------------------------------------*/
11339 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11340 /*-----------------------------------------------------------------*/
11341 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11342 {
11343     operand *from , *to , *count;
11344     symbol *lbl,*lbl2;
11345     bitVect *rsave;
11346     int i;
11347
11348     /* we know it has to be 3 parameters */
11349     assert (nparms == 3);
11350     
11351     rsave = newBitVect(16);
11352     /* save DPTR if it needs to be saved */
11353     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11354             if (bitVectBitValue(ic->rMask,i))
11355                     rsave = bitVectSetBit(rsave,i);
11356     }
11357     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11358                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11359     savermask(rsave);
11360     
11361     to = parms[0];
11362     from = parms[1];
11363     count = parms[2];
11364
11365     aopOp (from, ic->next, FALSE, FALSE);
11366
11367     /* get from into DPTR1 */
11368     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11369     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11370     if (options.model == MODEL_FLAT24) {
11371         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11372     }
11373
11374     freeAsmop (from, NULL, ic, FALSE);
11375     aopOp (to, ic, FALSE, FALSE);
11376     /* get "to" into DPTR */
11377     /* if the operand is already in dptr
11378        then we do nothing else we move the value to dptr */
11379     if (AOP_TYPE (to) != AOP_STR) {
11380         /* if already in DPTR then we need to push */
11381         if (AOP_TYPE(to) == AOP_DPTR) {
11382             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11383             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11384             if (options.model == MODEL_FLAT24)
11385                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11386             emitcode ("pop", "dph");
11387             emitcode ("pop", "dpl");        
11388         } else {
11389             _startLazyDPSEvaluation ();
11390             /* if this is remateriazable */
11391             if (AOP_TYPE (to) == AOP_IMMD) {
11392                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11393             } else {                    /* we need to get it byte by byte */
11394                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11395                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11396                 if (options.model == MODEL_FLAT24) {
11397                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11398                 }
11399             }
11400             _endLazyDPSEvaluation ();
11401         }
11402     }
11403     freeAsmop (to, NULL, ic, FALSE);
11404     _G.dptrInUse = _G.dptr1InUse = 1;
11405     aopOp (count, ic->next->next, FALSE,FALSE);
11406     lbl =newiTempLabel(NULL);
11407     lbl2 =newiTempLabel(NULL);
11408
11409     /* now for the actual compare */
11410     if (AOP_TYPE(count) == AOP_LIT && 
11411         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11412         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11413         if (fromc)
11414             emitcode("lcall","__bi_memcmpc2x_s");
11415         else
11416             emitcode("lcall","__bi_memcmpx2x_s");
11417         freeAsmop (count, NULL, ic, FALSE);
11418         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11419         aopPut(AOP(IC_RESULT(ic)),"a",0);
11420         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11421     } else {
11422         symbol *lbl1 = newiTempLabel(NULL);
11423
11424         emitcode("push","ar0");         
11425         emitcode (";"," Auto increment but no djnz");
11426         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11427         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11428         freeAsmop (count, NULL, ic, FALSE);
11429         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11430         emitcode ("","!tlabeldef",lbl->key+100);
11431         if (fromc) {
11432             emitcode ("clr","a");
11433             emitcode ("movc", "a,@a+dptr");
11434         } else 
11435             emitcode ("movx", "a,@dptr");
11436         emitcode ("mov","r0,a");
11437         emitcode ("movx", "a,@dptr");
11438         emitcode ("clr","c");
11439         emitcode ("subb","a,r0");
11440         emitcode ("jnz","!tlabel",lbl2->key+100);
11441         emitcode ("inc", "dptr");
11442         emitcode ("inc", "dptr");
11443         emitcode ("mov","a,b");
11444         emitcode ("orl","a,_ap");
11445         emitcode ("jz","!tlabel",lbl1->key+100);
11446         emitcode ("mov","a,_ap");
11447         emitcode ("add","a,#!constbyte",0xFF);
11448         emitcode ("mov","_ap,a");
11449         emitcode ("mov","a,b");
11450         emitcode ("addc","a,#!constbyte",0xFF);
11451         emitcode ("mov","b,a");
11452         emitcode ("sjmp","!tlabel",lbl->key+100);
11453         emitcode ("","!tlabeldef",lbl1->key+100);
11454         emitcode ("clr","a");
11455         emitcode ("","!tlabeldef",lbl2->key+100);
11456         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11457         aopPut(AOP(IC_RESULT(ic)),"a",0);
11458         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11459         emitcode("pop","ar0");
11460         emitcode ("mov", "dps,#0");      
11461     }
11462     _G.dptrInUse = _G.dptr1InUse = 0;
11463     unsavermask(rsave);
11464
11465 }
11466
11467 /*-----------------------------------------------------------------*/
11468 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11469 /* port, first parameter output area second parameter pointer to   */
11470 /* port third parameter count                                      */
11471 /*-----------------------------------------------------------------*/
11472 static void genInp( iCode *ic, int nparms, operand **parms)
11473 {
11474     operand *from , *to , *count;
11475     symbol *lbl;
11476     bitVect *rsave;
11477     int i;
11478
11479     /* we know it has to be 3 parameters */
11480     assert (nparms == 3);
11481     
11482     rsave = newBitVect(16);
11483     /* save DPTR if it needs to be saved */
11484     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11485             if (bitVectBitValue(ic->rMask,i))
11486                     rsave = bitVectSetBit(rsave,i);
11487     }
11488     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11489                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11490     savermask(rsave);
11491     
11492     to = parms[0];
11493     from = parms[1];
11494     count = parms[2];
11495
11496     aopOp (from, ic->next, FALSE, FALSE);
11497
11498     /* get from into DPTR1 */
11499     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11500     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11501     if (options.model == MODEL_FLAT24) {
11502         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11503     }
11504
11505     freeAsmop (from, NULL, ic, FALSE);
11506     aopOp (to, ic, FALSE, FALSE);
11507     /* get "to" into DPTR */
11508     /* if the operand is already in dptr
11509        then we do nothing else we move the value to dptr */
11510     if (AOP_TYPE (to) != AOP_STR) {
11511         /* if already in DPTR then we need to push */
11512         if (AOP_TYPE(to) == AOP_DPTR) {
11513             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11514             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11515             if (options.model == MODEL_FLAT24)
11516                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11517             emitcode ("pop", "dph");
11518             emitcode ("pop", "dpl");        
11519         } else {
11520             _startLazyDPSEvaluation ();
11521             /* if this is remateriazable */
11522             if (AOP_TYPE (to) == AOP_IMMD) {
11523                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11524             } else {                    /* we need to get it byte by byte */
11525                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11526                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11527                 if (options.model == MODEL_FLAT24) {
11528                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11529                 }
11530             }
11531             _endLazyDPSEvaluation ();
11532         }
11533     }
11534     freeAsmop (to, NULL, ic, FALSE);
11535
11536     _G.dptrInUse = _G.dptr1InUse = 1;
11537     aopOp (count, ic->next->next, FALSE,FALSE);
11538     lbl =newiTempLabel(NULL);
11539
11540     /* now for the actual copy */
11541     if (AOP_TYPE(count) == AOP_LIT && 
11542         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11543         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11544         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11545         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11546         freeAsmop (count, NULL, ic, FALSE);
11547         emitcode ("","!tlabeldef",lbl->key+100);
11548         emitcode ("movx", "a,@dptr");   /* read data from port */
11549         emitcode ("dec","dps");         /* switch to DPTR */
11550         emitcode ("movx", "@dptr,a");   /* save into location */
11551         emitcode ("inc", "dptr");       /* point to next area */
11552         emitcode ("inc","dps");         /* switch to DPTR2 */
11553         emitcode ("djnz","b,!tlabel",lbl->key+100);
11554     } else {
11555         symbol *lbl1 = newiTempLabel(NULL);
11556         
11557         emitcode (";"," Auto increment but no djnz");
11558         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11559         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11560         freeAsmop (count, NULL, ic, FALSE);
11561         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11562         emitcode ("","!tlabeldef",lbl->key+100);
11563         emitcode ("movx", "a,@dptr");
11564         emitcode ("dec","dps");         /* switch to DPTR */
11565         emitcode ("movx", "@dptr,a");
11566         emitcode ("inc", "dptr");
11567         emitcode ("inc","dps");         /* switch to DPTR2 */
11568 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11569 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11570         emitcode ("mov","a,b");
11571         emitcode ("orl","a,_ap");
11572         emitcode ("jz","!tlabel",lbl1->key+100);
11573         emitcode ("mov","a,_ap");
11574         emitcode ("add","a,#!constbyte",0xFF);
11575         emitcode ("mov","_ap,a");
11576         emitcode ("mov","a,b");
11577         emitcode ("addc","a,#!constbyte",0xFF);
11578         emitcode ("mov","b,a");
11579         emitcode ("sjmp","!tlabel",lbl->key+100);
11580         emitcode ("","!tlabeldef",lbl1->key+100);
11581     }
11582     emitcode ("mov", "dps,#0"); 
11583     _G.dptrInUse = _G.dptr1InUse = 0;
11584     unsavermask(rsave);
11585
11586 }
11587
11588 /*-----------------------------------------------------------------*/
11589 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11590 /* port, first parameter output area second parameter pointer to   */
11591 /* port third parameter count                                      */
11592 /*-----------------------------------------------------------------*/
11593 static void genOutp( iCode *ic, int nparms, operand **parms)
11594 {
11595     operand *from , *to , *count;
11596     symbol *lbl;
11597     bitVect *rsave;
11598     int i;
11599
11600     /* we know it has to be 3 parameters */
11601     assert (nparms == 3);
11602     
11603     rsave = newBitVect(16);
11604     /* save DPTR if it needs to be saved */
11605     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11606             if (bitVectBitValue(ic->rMask,i))
11607                     rsave = bitVectSetBit(rsave,i);
11608     }
11609     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11610                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11611     savermask(rsave);
11612     
11613     to = parms[0];
11614     from = parms[1];
11615     count = parms[2];
11616
11617     aopOp (from, ic->next, FALSE, FALSE);
11618
11619     /* get from into DPTR1 */
11620     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
11621     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
11622     if (options.model == MODEL_FLAT24) {
11623         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
11624     }
11625
11626     freeAsmop (from, NULL, ic, FALSE);
11627     aopOp (to, ic, FALSE, FALSE);
11628     /* get "to" into DPTR */
11629     /* if the operand is already in dptr
11630        then we do nothing else we move the value to dptr */
11631     if (AOP_TYPE (to) != AOP_STR) {
11632         /* if already in DPTR then we need to push */
11633         if (AOP_TYPE(to) == AOP_DPTR) {
11634             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11635             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11636             if (options.model == MODEL_FLAT24)
11637                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11638             emitcode ("pop", "dph");
11639             emitcode ("pop", "dpl");        
11640         } else {
11641             _startLazyDPSEvaluation ();
11642             /* if this is remateriazable */
11643             if (AOP_TYPE (to) == AOP_IMMD) {
11644                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11645             } else {                    /* we need to get it byte by byte */
11646                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11647                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11648                 if (options.model == MODEL_FLAT24) {
11649                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11650                 }
11651             }
11652             _endLazyDPSEvaluation ();
11653         }
11654     }
11655     freeAsmop (to, NULL, ic, FALSE);
11656
11657     _G.dptrInUse = _G.dptr1InUse = 1;
11658     aopOp (count, ic->next->next, FALSE,FALSE);
11659     lbl =newiTempLabel(NULL);
11660
11661     /* now for the actual copy */
11662     if (AOP_TYPE(count) == AOP_LIT && 
11663         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11664         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11665         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11666         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11667         emitcode ("","!tlabeldef",lbl->key+100);
11668         emitcode ("movx", "a,@dptr");   /* read data from port */
11669         emitcode ("inc","dps");         /* switch to DPTR2 */
11670         emitcode ("movx", "@dptr,a");   /* save into location */
11671         emitcode ("inc", "dptr");       /* point to next area */
11672         emitcode ("dec","dps");         /* switch to DPTR */
11673         emitcode ("djnz","b,!tlabel",lbl->key+100);
11674         freeAsmop (count, NULL, ic, FALSE);
11675     } else {
11676         symbol *lbl1 = newiTempLabel(NULL);
11677         
11678         emitcode (";"," Auto increment but no djnz");
11679         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11680         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11681         freeAsmop (count, NULL, ic, FALSE);
11682         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11683         emitcode ("","!tlabeldef",lbl->key+100);
11684         emitcode ("movx", "a,@dptr");
11685         emitcode ("inc", "dptr");
11686         emitcode ("inc","dps");         /* switch to DPTR2 */
11687         emitcode ("movx", "@dptr,a");
11688         emitcode ("dec","dps");         /* switch to DPTR */
11689         emitcode ("mov","a,b");
11690         emitcode ("orl","a,_ap");
11691         emitcode ("jz","!tlabel",lbl1->key+100);
11692         emitcode ("mov","a,_ap");
11693         emitcode ("add","a,#!constbyte",0xFF);
11694         emitcode ("mov","_ap,a");
11695         emitcode ("mov","a,b");
11696         emitcode ("addc","a,#!constbyte",0xFF);
11697         emitcode ("mov","b,a");
11698         emitcode ("sjmp","!tlabel",lbl->key+100);
11699         emitcode ("","!tlabeldef",lbl1->key+100);
11700     }
11701     emitcode ("mov", "dps,#0"); 
11702     _G.dptrInUse = _G.dptr1InUse = 0;
11703     unsavermask(rsave);
11704
11705 }
11706
11707 /*-----------------------------------------------------------------*/
11708 /* genSwapW - swap lower & high order bytes                        */
11709 /*-----------------------------------------------------------------*/
11710 static void genSwapW(iCode *ic, int nparms, operand **parms)
11711 {
11712     operand *dest;
11713     operand *src;
11714     assert (nparms==1);
11715
11716     src = parms[0];
11717     dest=IC_RESULT(ic);
11718
11719     assert(getSize(operandType(src))==2);
11720
11721     aopOp (src, ic, FALSE, FALSE);
11722     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,TRUE));
11723     _G.accInUse++;
11724     emitcode ("mov","b,%s",aopGet(AOP(src),1,FALSE,FALSE,FALSE));
11725     _G.accInUse--;
11726     freeAsmop (src, NULL, ic, FALSE);
11727     
11728     aopOp (dest,ic, FALSE, FALSE);
11729     aopPut(AOP(dest),"b",0);
11730     aopPut(AOP(dest),"a",1);
11731     freeAsmop (dest, NULL, ic, FALSE);    
11732 }
11733
11734 /*-----------------------------------------------------------------*/
11735 /* genMemsetX - gencode for memSetX data                           */
11736 /*-----------------------------------------------------------------*/
11737 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11738 {
11739     operand *to , *val , *count;
11740     symbol *lbl;
11741     char *l;
11742     int i;
11743     bitVect *rsave = NULL;
11744
11745     /* we know it has to be 3 parameters */
11746     assert (nparms == 3);
11747     
11748     to = parms[0];
11749     val = parms[1];
11750     count = parms[2];
11751         
11752     /* save DPTR if it needs to be saved */
11753     rsave = newBitVect(16);
11754     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11755             if (bitVectBitValue(ic->rMask,i))
11756                     rsave = bitVectSetBit(rsave,i);
11757     }
11758     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11759                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11760     savermask(rsave);
11761
11762     aopOp (to, ic, FALSE, FALSE);
11763     /* get "to" into DPTR */
11764     /* if the operand is already in dptr
11765        then we do nothing else we move the value to dptr */
11766     if (AOP_TYPE (to) != AOP_STR) {
11767         /* if already in DPTR then we need to push */
11768         if (AOP_TYPE(to) == AOP_DPTR) {
11769             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11770             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11771             if (options.model == MODEL_FLAT24)
11772                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11773             emitcode ("pop", "dph");
11774             emitcode ("pop", "dpl");        
11775         } else {
11776             _startLazyDPSEvaluation ();
11777             /* if this is remateriazable */
11778             if (AOP_TYPE (to) == AOP_IMMD) {
11779                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11780             } else {                    /* we need to get it byte by byte */
11781                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11782                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11783                 if (options.model == MODEL_FLAT24) {
11784                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11785                 }
11786             }
11787             _endLazyDPSEvaluation ();
11788         }
11789     }
11790     freeAsmop (to, NULL, ic, FALSE);
11791
11792     aopOp (val, ic->next->next, FALSE,FALSE);
11793     aopOp (count, ic->next->next, FALSE,FALSE);    
11794     lbl =newiTempLabel(NULL);
11795     /* now for the actual copy */
11796     if (AOP_TYPE(count) == AOP_LIT && 
11797         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11798         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11799         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11800         MOVA(l);
11801         emitcode ("","!tlabeldef",lbl->key+100);
11802         emitcode ("movx", "@dptr,a");
11803         emitcode ("inc", "dptr");
11804         emitcode ("djnz","b,!tlabel",lbl->key+100);
11805     } else {
11806         symbol *lbl1 = newiTempLabel(NULL);
11807         
11808         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11809         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11810         emitcode ("","!tlabeldef",lbl->key+100);
11811         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11812         MOVA(l);
11813         emitcode ("movx", "@dptr,a");
11814         emitcode ("inc", "dptr");
11815         emitcode ("mov","a,b");
11816         emitcode ("orl","a,_ap");
11817         emitcode ("jz","!tlabel",lbl1->key+100);
11818         emitcode ("mov","a,_ap");
11819         emitcode ("add","a,#!constbyte",0xFF);
11820         emitcode ("mov","_ap,a");
11821         emitcode ("mov","a,b");
11822         emitcode ("addc","a,#!constbyte",0xFF);
11823         emitcode ("mov","b,a");
11824         emitcode ("sjmp","!tlabel",lbl->key+100);
11825         emitcode ("","!tlabeldef",lbl1->key+100);
11826     }
11827     freeAsmop (count, NULL, ic, FALSE);
11828     unsavermask(rsave);
11829 }
11830
11831 /*-----------------------------------------------------------------*/
11832 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11833 /*-----------------------------------------------------------------*/
11834 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11835 {
11836         bitVect *rsave ;
11837         operand *pnum, *result;
11838         int i;
11839     
11840         assert (nparms==1);
11841         /* save registers that need to be saved */
11842         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11843                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11844     
11845         pnum = parms[0]; 
11846         aopOp (pnum, ic, FALSE, FALSE);
11847         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11848         freeAsmop (pnum, NULL, ic, FALSE);
11849         emitcode ("lcall","NatLib_LoadPrimitive");
11850         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11851         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11852             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11853                 for (i = (size-1) ; i >= 0 ; i-- ) {
11854                         emitcode ("push","a%s",javaRet[i]);
11855                 }
11856                 for (i=0; i < size ; i++ ) {
11857                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11858                 }
11859         } else {
11860                 for (i = 0 ; i < size ; i++ ) {
11861                         aopPut(AOP(result),javaRet[i],i);
11862                 }
11863         }    
11864         freeAsmop (result, NULL, ic, FALSE);
11865         unsavermask(rsave);
11866 }
11867
11868 /*-----------------------------------------------------------------*/
11869 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11870 /*-----------------------------------------------------------------*/
11871 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11872 {
11873         bitVect *rsave ;
11874         operand *pnum, *result;
11875         int size = 3;
11876         int i;
11877     
11878         assert (nparms==1);
11879         /* save registers that need to be saved */
11880         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11881                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11882     
11883         pnum = parms[0]; 
11884         aopOp (pnum, ic, FALSE, FALSE);
11885         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11886         freeAsmop (pnum, NULL, ic, FALSE);
11887         emitcode ("lcall","NatLib_LoadPointer");
11888         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11889         if (AOP_TYPE(result)!=AOP_STR) {
11890                 for (i = 0 ; i < size ; i++ ) {
11891                         aopPut(AOP(result),fReturn[i],i);
11892                 }
11893         }    
11894         freeAsmop (result, NULL, ic, FALSE);
11895         unsavermask(rsave);
11896 }
11897
11898 /*-----------------------------------------------------------------*/
11899 /* genNatLibInstallStateBlock -                                    */
11900 /*-----------------------------------------------------------------*/
11901 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11902                                        operand **parms, const char *name)
11903 {
11904         bitVect *rsave ;
11905         operand *psb, *handle;
11906         assert (nparms==2);
11907
11908         /* save registers that need to be saved */
11909         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11910                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11911         psb = parms[0];
11912         handle = parms[1];
11913
11914         /* put pointer to state block into DPTR1 */
11915         aopOp (psb, ic, FALSE, FALSE);
11916         if (AOP_TYPE (psb) == AOP_IMMD) {
11917                 emitcode ("mov","dps,#1");
11918                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11919                 emitcode ("mov","dps,#0");
11920         } else {
11921                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11922                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11923                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11924         }
11925         freeAsmop (psb, NULL, ic, FALSE);
11926
11927         /* put libraryID into DPTR */
11928         emitcode ("mov","dptr,#LibraryID");
11929
11930         /* put handle into r3:r2 */
11931         aopOp (handle, ic, FALSE, FALSE);
11932         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11933                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11934                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11935                 emitcode ("pop","ar3");
11936                 emitcode ("pop","ar2");
11937         } else {        
11938                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11939                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11940         }
11941         freeAsmop (psb, NULL, ic, FALSE);
11942
11943         /* make the call */
11944         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11945
11946         /* put return value into place*/
11947         _G.accInUse++;
11948         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11949         _G.accInUse--;
11950         aopPut(AOP(IC_RESULT(ic)),"a",0);
11951         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11952         unsavermask(rsave);
11953 }
11954
11955 /*-----------------------------------------------------------------*/
11956 /* genNatLibRemoveStateBlock -                                     */
11957 /*-----------------------------------------------------------------*/
11958 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11959 {
11960         bitVect *rsave ;
11961
11962         assert(nparms==0);
11963
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         unsavermask(rsave);
11973 }
11974
11975 /*-----------------------------------------------------------------*/
11976 /* genNatLibGetStateBlock -                                        */
11977 /*-----------------------------------------------------------------*/
11978 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11979                                    operand **parms,const char *name)
11980 {
11981         bitVect *rsave ;
11982         symbol *lbl = newiTempLabel(NULL);
11983         
11984         assert(nparms==0);
11985         /* save registers that need to be saved */
11986         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11987                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11988
11989         /* put libraryID into DPTR */
11990         emitcode ("mov","dptr,#LibraryID");
11991         /* make the call */
11992         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11993         emitcode ("jnz","!tlabel",lbl->key+100);
11994
11995         /* put return value into place */
11996         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11997         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11998                 emitcode ("push","ar3");
11999                 emitcode ("push","ar2");
12000                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12001                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12002         } else {
12003                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12004                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12005         }
12006         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12007         emitcode ("","!tlabeldef",lbl->key+100);
12008         unsavermask(rsave);
12009 }
12010
12011 /*-----------------------------------------------------------------*/
12012 /* genMMMalloc -                                                   */
12013 /*-----------------------------------------------------------------*/
12014 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12015                          int size, const char *name)
12016 {
12017         bitVect *rsave ;
12018         operand *bsize;
12019         symbol *rsym;
12020         symbol *lbl = newiTempLabel(NULL);
12021
12022         assert (nparms == 1);
12023         /* save registers that need to be saved */
12024         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12025                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12026         
12027         bsize=parms[0];
12028         aopOp (bsize,ic,FALSE,FALSE);
12029
12030         /* put the size in R4-R2 */
12031         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12032                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12033                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12034                 if (size==3) {
12035                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12036                         emitcode("pop","ar4");
12037                 }
12038                 emitcode("pop","ar3");
12039                 emitcode("pop","ar2");          
12040         } else {
12041                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
12042                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
12043                 if (size==3) {
12044                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
12045                 }
12046         }
12047         freeAsmop (bsize, NULL, ic, FALSE);
12048
12049         /* make the call */
12050         emitcode ("lcall","MM_%s",name);
12051         emitcode ("jz","!tlabel",lbl->key+100);
12052         emitcode ("mov","r2,#!constbyte",0xff);
12053         emitcode ("mov","r3,#!constbyte",0xff);
12054         emitcode ("","!tlabeldef",lbl->key+100);
12055         /* we don't care about the pointer : we just save the handle */
12056         rsym = OP_SYMBOL(IC_RESULT(ic));
12057         if (rsym->liveFrom != rsym->liveTo) {
12058                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12059                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12060                         emitcode ("push","ar3");
12061                         emitcode ("push","ar2");
12062                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
12063                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
12064                 } else {
12065                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12066                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12067                 }
12068                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12069         }
12070         unsavermask(rsave);
12071 }
12072
12073 /*-----------------------------------------------------------------*/
12074 /* genMMDeref -                                                    */
12075 /*-----------------------------------------------------------------*/
12076 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12077 {
12078         bitVect *rsave ;
12079         operand *handle;
12080
12081         assert (nparms == 1);
12082         /* save registers that need to be saved */
12083         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12084                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12085         
12086         handle=parms[0];
12087         aopOp (handle,ic,FALSE,FALSE);
12088
12089         /* put the size in R4-R2 */
12090         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12091                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12092                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12093                 emitcode("pop","ar3");
12094                 emitcode("pop","ar2");          
12095         } else {
12096                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12097                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12098         }
12099         freeAsmop (handle, NULL, ic, FALSE);
12100
12101         /* make the call */
12102         emitcode ("lcall","MM_Deref");
12103         
12104         {
12105                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12106                 if (rsym->liveFrom != rsym->liveTo) {                   
12107                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12108                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12109                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12110                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12111                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12112                         }
12113                 }
12114         }
12115         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12116         unsavermask(rsave);
12117 }
12118
12119 /*-----------------------------------------------------------------*/
12120 /* genMMUnrestrictedPersist -                                      */
12121 /*-----------------------------------------------------------------*/
12122 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12123 {
12124         bitVect *rsave ;
12125         operand *handle;
12126
12127         assert (nparms == 1);
12128         /* save registers that need to be saved */
12129         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12130                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12131         
12132         handle=parms[0];
12133         aopOp (handle,ic,FALSE,FALSE);
12134
12135         /* put the size in R3-R2 */
12136         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12137                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12138                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12139                 emitcode("pop","ar3");
12140                 emitcode("pop","ar2");          
12141         } else {
12142                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12143                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12144         }
12145         freeAsmop (handle, NULL, ic, FALSE);
12146
12147         /* make the call */
12148         emitcode ("lcall","MM_UnrestrictedPersist");
12149
12150         {
12151                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12152                 if (rsym->liveFrom != rsym->liveTo) {   
12153                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12154                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12155                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12156                 }
12157         }
12158         unsavermask(rsave);
12159 }
12160
12161 /*-----------------------------------------------------------------*/
12162 /* genSystemExecJavaProcess -                                      */
12163 /*-----------------------------------------------------------------*/
12164 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12165 {
12166         bitVect *rsave ;
12167         operand *handle, *pp;
12168
12169         assert (nparms==2);
12170         /* save registers that need to be saved */
12171         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12172                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12173         
12174         pp = parms[0];
12175         handle = parms[1];
12176         
12177         /* put the handle in R3-R2 */
12178         aopOp (handle,ic,FALSE,FALSE);
12179         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12180                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12181                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12182                 emitcode("pop","ar3");
12183                 emitcode("pop","ar2");          
12184         } else {
12185                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
12186                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
12187         }
12188         freeAsmop (handle, NULL, ic, FALSE);
12189         
12190         /* put pointer in DPTR */
12191         aopOp (pp,ic,FALSE,FALSE);
12192         if (AOP_TYPE(pp) == AOP_IMMD) {
12193                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
12194         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12195                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12196                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12197                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12198         }
12199         freeAsmop (handle, NULL, ic, FALSE);
12200
12201         /* make the call */
12202         emitcode ("lcall","System_ExecJavaProcess");
12203         
12204         /* put result in place */
12205         {
12206                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12207                 if (rsym->liveFrom != rsym->liveTo) {   
12208                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12209                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12210                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12211                 }
12212         }
12213         
12214         unsavermask(rsave);
12215 }
12216
12217 /*-----------------------------------------------------------------*/
12218 /* genSystemRTCRegisters -                                         */
12219 /*-----------------------------------------------------------------*/
12220 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12221                                   char *name)
12222 {
12223         bitVect *rsave ;
12224         operand *pp;
12225
12226         assert (nparms==1);
12227         /* save registers that need to be saved */
12228         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12229                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12230         
12231         pp=parms[0];
12232         /* put pointer in DPTR */
12233         aopOp (pp,ic,FALSE,FALSE);
12234         if (AOP_TYPE (pp) == AOP_IMMD) {
12235                 emitcode ("mov","dps,#1");
12236                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
12237                 emitcode ("mov","dps,#0");
12238         } else {
12239                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
12240                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
12241                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
12242         }
12243         freeAsmop (pp, NULL, ic, FALSE);
12244
12245         /* make the call */
12246         emitcode ("lcall","System_%sRTCRegisters",name);
12247
12248         unsavermask(rsave);
12249 }
12250
12251 /*-----------------------------------------------------------------*/
12252 /* genSystemThreadSleep -                                          */
12253 /*-----------------------------------------------------------------*/
12254 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12255 {
12256         bitVect *rsave ;
12257         operand *to, *s;
12258
12259         assert (nparms==1);
12260         /* save registers that need to be saved */
12261         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12262                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12263
12264         to = parms[0];
12265         aopOp(to,ic,FALSE,FALSE);
12266         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12267             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12268                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12269                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12270                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12271                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12272                 emitcode ("pop","ar3");
12273                 emitcode ("pop","ar2");
12274                 emitcode ("pop","ar1");
12275                 emitcode ("pop","ar0");
12276         } else {
12277                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
12278                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
12279                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
12280                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
12281         }
12282         freeAsmop (to, NULL, ic, FALSE);
12283
12284         /* suspend in acc */
12285         s = parms[1];
12286         aopOp(s,ic,FALSE,FALSE);
12287         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
12288         freeAsmop (s, NULL, ic, FALSE);
12289
12290         /* make the call */
12291         emitcode ("lcall","System_%s",name);
12292
12293         unsavermask(rsave);
12294 }
12295
12296 /*-----------------------------------------------------------------*/
12297 /* genSystemThreadResume -                                         */
12298 /*-----------------------------------------------------------------*/
12299 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12300 {
12301         bitVect *rsave ;
12302         operand *tid,*pid;
12303
12304         assert (nparms==2);
12305         /* save registers that need to be saved */
12306         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12307                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12308         
12309         tid = parms[0];
12310         pid = parms[1];
12311         
12312         /* PID in R0 */
12313         aopOp(pid,ic,FALSE,FALSE);
12314         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12315         freeAsmop (pid, NULL, ic, FALSE);
12316         
12317         /* tid into ACC */
12318         aopOp(tid,ic,FALSE,FALSE);
12319         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
12320         freeAsmop (tid, NULL, ic, FALSE);
12321         
12322         emitcode ("lcall","System_ThreadResume");
12323
12324         /* put result into place */
12325         {
12326                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12327                 if (rsym->liveFrom != rsym->liveTo) {   
12328                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12329                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12330                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12331                 }
12332         }
12333         unsavermask(rsave);
12334 }
12335
12336 /*-----------------------------------------------------------------*/
12337 /* genSystemProcessResume -                                        */
12338 /*-----------------------------------------------------------------*/
12339 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12340 {
12341         bitVect *rsave ;
12342         operand *pid;
12343
12344         assert (nparms==1);
12345         /* save registers that need to be saved */
12346         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12347                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12348         
12349         pid = parms[0];
12350         
12351         /* pid into ACC */
12352         aopOp(pid,ic,FALSE,FALSE);
12353         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
12354         freeAsmop (pid, NULL, ic, FALSE);
12355         
12356         emitcode ("lcall","System_ProcessResume");
12357
12358         unsavermask(rsave);
12359 }
12360
12361 /*-----------------------------------------------------------------*/
12362 /* genSystem -                                                     */
12363 /*-----------------------------------------------------------------*/
12364 static void genSystem (iCode *ic,int nparms,char *name)
12365 {
12366         assert(nparms == 0);
12367
12368         emitcode ("lcall","System_%s",name);
12369 }
12370
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemPoll -                                                  */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12375 {
12376         bitVect *rsave ;
12377         operand *fp;
12378
12379         assert (nparms==1);
12380         /* save registers that need to be saved */
12381         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12382                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12383
12384         fp = parms[0];
12385         aopOp (fp,ic,FALSE,FALSE);
12386         if (AOP_TYPE (fp) == AOP_IMMD) {
12387                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
12388         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12389                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
12390                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
12391                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
12392         }
12393         freeAsmop (fp, NULL, ic, FALSE);
12394
12395         emitcode ("lcall","System_%sPoll",name);
12396
12397         /* put result into place */
12398         {
12399                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12400                 if (rsym->liveFrom != rsym->liveTo) {   
12401                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12402                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12403                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12404                 }
12405         }
12406         unsavermask(rsave);
12407 }
12408
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemGetCurrentID -                                         */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12413 {
12414         assert (nparms==0);
12415
12416         emitcode ("lcall","System_GetCurrent%sId",name);
12417         /* put result into place */
12418         {
12419                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12420                 if (rsym->liveFrom != rsym->liveTo) {   
12421                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12422                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12423                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12424                 }
12425         }
12426 }
12427
12428 /*-----------------------------------------------------------------*/
12429 /* genBuiltIn - calls the appropriate function to  generating code */
12430 /* for a built in function                                         */
12431 /*-----------------------------------------------------------------*/
12432 static void genBuiltIn (iCode *ic)
12433 {
12434         operand *bi_parms[MAX_BUILTIN_ARGS];
12435         int nbi_parms;
12436         iCode *bi_iCode;
12437         symbol *bif;
12438
12439         /* get all the arguments for a built in function */
12440         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12441
12442         /* which function is it */
12443         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12444         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12445                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12446         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12447                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12448         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12449                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12450         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12451                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12452         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12453                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12454         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12455                 genInp(bi_iCode,nbi_parms,bi_parms);
12456         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12457                 genOutp(bi_iCode,nbi_parms,bi_parms);
12458         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12459                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12460                 /* JavaNative builtIns */               
12461         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12462                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12463         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12464                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12465         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12466                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12467         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12468                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12469         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12470                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12471         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12472                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12473         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12474                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12475         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12476                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12477         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12478                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12479         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12480                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12481         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12482                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12483         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12484                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12485         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12486                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12487         } else if (strcmp(bif->name,"MM_Free")==0) {
12488                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12489         } else if (strcmp(bif->name,"MM_Deref")==0) {
12490                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12491         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12492                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12493         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12494                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12495         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12496                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12497         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12498                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12499         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12500                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12501         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12502                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12503         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12504                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12505         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12506                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12507         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12508                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12509         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12510                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12511         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12512                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12513         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12514                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12515         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12516                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12517         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12518                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12519         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12520                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12521         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12522                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12523         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12524                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12525         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12526                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12527         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12528                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12529         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12530                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12531         } else {
12532                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12533                 return ;
12534         }
12535         return ;    
12536 }
12537
12538 /*-----------------------------------------------------------------*/
12539 /* gen390Code - generate code for Dallas 390 based controllers     */
12540 /*-----------------------------------------------------------------*/
12541 void
12542 gen390Code (iCode * lic)
12543 {
12544   iCode *ic;
12545   int cln = 0;
12546
12547   lineHead = lineCurr = NULL;
12548   dptrn[1][0] = "dpl1";
12549   dptrn[1][1] = "dph1";
12550   dptrn[1][2] = "dpx1";
12551   
12552   if (options.model == MODEL_FLAT24) {
12553     fReturnSizeDS390 = 5;
12554     fReturn = fReturn24;
12555   } else {
12556     fReturnSizeDS390 = 4;
12557     fReturn = fReturn16;
12558     options.stack10bit=0;
12559   }
12560 #if 1
12561   /* print the allocation information */
12562   if (allocInfo)
12563     printAllocInfo (currFunc, codeOutFile);
12564 #endif
12565   /* if debug information required */
12566   if (options.debug && currFunc)
12567     {
12568       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
12569       _G.debugLine = 1;
12570       if (IS_STATIC (currFunc->etype))
12571         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12572       else
12573         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12574       _G.debugLine = 0;
12575     }
12576   /* stack pointer name */
12577   if (options.useXstack)
12578     spname = "_spx";
12579   else
12580     spname = "sp";
12581
12582
12583   for (ic = lic; ic; ic = ic->next)
12584     {
12585
12586       if (ic->lineno && cln != ic->lineno)
12587         {
12588           if (options.debug)
12589             {
12590               _G.debugLine = 1;
12591               emitcode ("", "C$%s$%d$%d$%d ==.",
12592                         FileBaseName (ic->filename), ic->lineno,
12593                         ic->level, ic->block);
12594               _G.debugLine = 0;
12595             }
12596           if (!options.noCcodeInAsm) {
12597             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12598                       printCLine(ic->filename, ic->lineno));
12599           }
12600           cln = ic->lineno;
12601         }
12602       if (options.iCodeInAsm) {
12603         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12604       }
12605       /* if the result is marked as
12606          spilt and rematerializable or code for
12607          this has already been generated then
12608          do nothing */
12609       if (resultRemat (ic) || ic->generated)
12610         continue;
12611
12612       /* depending on the operation */
12613       switch (ic->op)
12614         {
12615         case '!':
12616           genNot (ic);
12617           break;
12618
12619         case '~':
12620           genCpl (ic);
12621           break;
12622
12623         case UNARYMINUS:
12624           genUminus (ic);
12625           break;
12626
12627         case IPUSH:
12628           genIpush (ic);
12629           break;
12630
12631         case IPOP:
12632           /* IPOP happens only when trying to restore a
12633              spilt live range, if there is an ifx statement
12634              following this pop then the if statement might
12635              be using some of the registers being popped which
12636              would destory the contents of the register so
12637              we need to check for this condition and handle it */
12638           if (ic->next &&
12639               ic->next->op == IFX &&
12640               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12641             genIfx (ic->next, ic);
12642           else
12643             genIpop (ic);
12644           break;
12645
12646         case CALL:
12647           genCall (ic);
12648           break;
12649
12650         case PCALL:
12651           genPcall (ic);
12652           break;
12653
12654         case FUNCTION:
12655           genFunction (ic);
12656           break;
12657
12658         case ENDFUNCTION:
12659           genEndFunction (ic);
12660           break;
12661
12662         case RETURN:
12663           genRet (ic);
12664           break;
12665
12666         case LABEL:
12667           genLabel (ic);
12668           break;
12669
12670         case GOTO:
12671           genGoto (ic);
12672           break;
12673
12674         case '+':
12675           genPlus (ic);
12676           break;
12677
12678         case '-':
12679           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12680             genMinus (ic);
12681           break;
12682
12683         case '*':
12684           genMult (ic);
12685           break;
12686
12687         case '/':
12688           genDiv (ic);
12689           break;
12690
12691         case '%':
12692           genMod (ic);
12693           break;
12694
12695         case '>':
12696           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12697           break;
12698
12699         case '<':
12700           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12701           break;
12702
12703         case LE_OP:
12704         case GE_OP:
12705         case NE_OP:
12706
12707           /* note these two are xlated by algebraic equivalence
12708              during parsing SDCC.y */
12709           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12710                   "got '>=' or '<=' shouldn't have come here");
12711           break;
12712
12713         case EQ_OP:
12714           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12715           break;
12716
12717         case AND_OP:
12718           genAndOp (ic);
12719           break;
12720
12721         case OR_OP:
12722           genOrOp (ic);
12723           break;
12724
12725         case '^':
12726           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12727           break;
12728
12729         case '|':
12730           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12731           break;
12732
12733         case BITWISEAND:
12734           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12735           break;
12736
12737         case INLINEASM:
12738           genInline (ic);
12739           break;
12740
12741         case RRC:
12742           genRRC (ic);
12743           break;
12744
12745         case RLC:
12746           genRLC (ic);
12747           break;
12748
12749         case GETHBIT:
12750           genGetHbit (ic);
12751           break;
12752
12753         case LEFT_OP:
12754           genLeftShift (ic);
12755           break;
12756
12757         case RIGHT_OP:
12758           genRightShift (ic);
12759           break;
12760
12761         case GET_VALUE_AT_ADDRESS:
12762           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12763           break;
12764
12765         case '=':
12766           if (POINTER_SET (ic))
12767             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12768           else
12769             genAssign (ic);
12770           break;
12771
12772         case IFX:
12773           genIfx (ic, NULL);
12774           break;
12775
12776         case ADDRESS_OF:
12777           genAddrOf (ic);
12778           break;
12779
12780         case JUMPTABLE:
12781           genJumpTab (ic);
12782           break;
12783
12784         case CAST:
12785           genCast (ic);
12786           break;
12787
12788         case RECEIVE:
12789           genReceive (ic);
12790           break;
12791
12792         case SEND:
12793           if (ic->builtinSEND) genBuiltIn(ic);
12794           else addSet (&_G.sendSet, ic);
12795           break;
12796
12797         case ARRAYINIT:
12798             genArrayInit(ic);
12799             break;
12800             
12801         default:
12802           ic = ic;
12803         }
12804     }
12805
12806
12807   /* now we are ready to call the
12808      peep hole optimizer */
12809   if (!options.nopeep)
12810     peepHole (&lineHead);
12811
12812   /* now do the actual printing */
12813   printLine (lineHead, codeOutFile);
12814   return;
12815 }